fix(memory): skip raw snippets during promotion (#94636)

This commit is contained in:
tayoun
2026-07-01 04:57:27 -04:00
committed by GitHub
parent 9bf338f3a1
commit 5bbd74266d
2 changed files with 111 additions and 1 deletions
@@ -459,6 +459,71 @@ describe("short-term promotion", () => {
});
});
it("ignores raw session and transcript snippets when recording short-term recalls", async () => {
await withTempWorkspace(async (workspaceDir) => {
await recordShortTermRecalls({
workspaceDir,
query: "session recap",
results: [
{
path: "memory/2026-06-18.md",
source: "memory",
startLine: 1,
endLine: 1,
score: 0.92,
snippet:
"Session: 2026-06-18 10:37:05 EDT; Session Key: agent:cody:discord:channel:1502199757592989836; Session ID: 6d52b6a2-a2e1-4839-a69a-a532b9090a6d; Source: discord",
},
{
path: "memory/2026-06-18.md",
source: "memory",
startLine: 2,
endLine: 2,
score: 0.91,
snippet: "Conversation Summary: assistant: Traced all three. No changes made.",
},
{
path: "memory/2026-06-18.md",
source: "memory",
startLine: 3,
endLine: 3,
score: 0.9,
snippet:
"user: Save important context from this session to the daily memory file. STRICT RULES: 1. The file MUST be named exactly memory/2026-06-18.md",
},
],
});
const store = await testing.readRecallStore(workspaceDir, new Date().toISOString());
expect(store.version).toBe(1);
expect(store.entries).toEqual({});
});
});
it("ignores already-promoted score metadata snippets when recording short-term recalls", async () => {
await withTempWorkspace(async (workspaceDir) => {
await recordShortTermRecalls({
workspaceDir,
query: "promotion metadata",
results: [
{
path: "memory/2026-06-18.md",
source: "memory",
startLine: 1,
endLine: 1,
score: 0.94,
snippet:
"2026-06-13 09:20 America/New_York - Polycore PR #112 re-review... [score=0.837 recalls=0 avg=0.620 source=memory/2026-06-13.md:10-12]",
},
],
});
const store = await testing.readRecallStore(workspaceDir, new Date().toISOString());
expect(store.version).toBe(1);
expect(store.entries).toEqual({});
});
});
it("keeps ordinary snippets that only quote dreaming prompt markers", async () => {
await withTempWorkspace(async (workspaceDir) => {
await recordShortTermRecalls({
@@ -1595,6 +1660,38 @@ describe("short-term promotion", () => {
).toBe(true);
});
it("treats raw session metadata snippets as contaminated", () => {
expect(
testing.isContaminatedDreamingSnippet(
"Session: 2026-06-18 10:37:05 EDT; Session Key: agent:cody:discord:channel:1502199757592989836; Session ID: 6d52b6a2-a2e1-4839-a69a-a532b9090a6d; Source: discord",
),
).toBe(true);
});
it("treats raw conversation summaries as contaminated", () => {
expect(
testing.isContaminatedDreamingSnippet(
"Conversation Summary: assistant: Traced all three. No changes made.",
),
).toBe(true);
});
it("treats raw transcript turns as contaminated", () => {
expect(
testing.isContaminatedDreamingSnippet(
"user: Save important context from this session to the daily memory file. STRICT RULES: 1. The file MUST be named exactly memory/2026-06-18.md",
),
).toBe(true);
});
it("treats promotion score metadata as contaminated", () => {
expect(
testing.isContaminatedDreamingSnippet(
"Polycore PR #112 re-review... [score=0.837 recalls=0 avg=0.620 source=memory/2026-06-13.md:10-12]",
),
).toBe(true);
});
it("does not treat prose that mentions the word Candidate as contaminated", () => {
expect(
testing.isContaminatedDreamingSnippet(
@@ -74,6 +74,14 @@ const PHASE_SIGNAL_REM_BOOST_MAX = 0.09;
const PHASE_SIGNAL_HALF_LIFE_DAYS = 14;
const DREAMING_TRANSCRIPT_PROMPT_LINE_RE =
/\[[^\]]*dreaming-narrative[^\]]*]\s*(?:User|Assistant):\s*Write a dream diary entry from these memory fragments:?/i;
const RAW_SESSION_METADATA_RE =
/\bSession Key\b.{0,260}\bSession ID\b|\bSession ID\b.{0,260}\bSession Key\b/i;
const RAW_CONVERSATION_SUMMARY_RE = /^(?:[-*+]\s*)?Conversation Summary:/i;
const RAW_TRANSCRIPT_TURN_RE = /^(?:[-*+]\s*)?(?:user|assistant):\s/i;
const MEMORY_FLUSH_PROMPT_RE =
/Save important context from this session to the daily memory file\.\s*STRICT RULES:/i;
const PROMOTION_SCORE_METADATA_RE =
/\[\s*score=\d+(?:\.\d+)?\s+recalls=\d+\s+avg=\d+(?:\.\d+)?\s+source=memory\//i;
const DREAMING_DIFF_PREFIX_RE = /@@\s*-\d+(?:,\d+)?\s+[-*+]\s+/iy;
const GENERIC_DAY_HEADING_RE =
/^(?:(?:mon|monday|tue|tues|tuesday|wed|wednesday|thu|thur|thurs|thursday|fri|friday|sat|saturday|sun|sunday)(?:,\s+)?)?(?:(?:jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|sept|september|oct|october|nov|november|dec|december)\s+\d{1,2}(?:st|nd|rd|th)?(?:,\s*\d{4})?|\d{1,2}[/-]\d{1,2}(?:[/-]\d{2,4})?|\d{4}[/-]\d{2}[/-]\d{2})$/i;
@@ -409,7 +417,12 @@ function isContaminatedDreamingSnippet(raw: string): boolean {
}
if (
/<!--\s*openclaw-memory-promotion:/i.test(snippet) ||
DREAMING_TRANSCRIPT_PROMPT_LINE_RE.test(snippet)
DREAMING_TRANSCRIPT_PROMPT_LINE_RE.test(snippet) ||
RAW_SESSION_METADATA_RE.test(snippet) ||
RAW_CONVERSATION_SUMMARY_RE.test(snippet) ||
RAW_TRANSCRIPT_TURN_RE.test(snippet) ||
MEMORY_FLUSH_PROMPT_RE.test(snippet) ||
PROMOTION_SCORE_METADATA_RE.test(snippet)
) {
return true;
}