@@ -203,6 +203,95 @@ describe("short-term promotion", () => {
203203 } ) ;
204204 } ) ;
205205
206+ it ( "ignores contaminated dreaming snippets when recording short-term recalls" , async ( ) => {
207+ await withTempWorkspace ( async ( workspaceDir ) => {
208+ await recordShortTermRecalls ( {
209+ workspaceDir,
210+ query : "action preference" ,
211+ results : [
212+ {
213+ path : "memory/2026-04-03.md" ,
214+ source : "memory" ,
215+ startLine : 1 ,
216+ endLine : 1 ,
217+ score : 0.92 ,
218+ snippet :
219+ "Candidate: Default to action. confidence: 0.76 evidence: memory/.dreams/session-corpus/2026-04-08.txt:1-1 recalls: 3 status: staged" ,
220+ } ,
221+ ] ,
222+ } ) ;
223+
224+ expect (
225+ JSON . parse ( await fs . readFile ( resolveShortTermRecallStorePath ( workspaceDir ) , "utf-8" ) ) ,
226+ ) . toMatchObject ( {
227+ version : 1 ,
228+ entries : { } ,
229+ } ) ;
230+ } ) ;
231+ } ) ;
232+
233+ it ( "ignores bullet-prefixed dreaming snippets when recording short-term recalls" , async ( ) => {
234+ await withTempWorkspace ( async ( workspaceDir ) => {
235+ await recordShortTermRecalls ( {
236+ workspaceDir,
237+ query : "action preference" ,
238+ results : [
239+ {
240+ path : "memory/2026-04-03.md" ,
241+ source : "memory" ,
242+ startLine : 1 ,
243+ endLine : 5 ,
244+ score : 0.92 ,
245+ snippet : [
246+ "- Candidate: Default to action." ,
247+ " - confidence: 0.76" ,
248+ " - evidence: memory/.dreams/session-corpus/2026-04-08.txt:1-1" ,
249+ " - recalls: 3" ,
250+ " - status: staged" ,
251+ ] . join ( "\n" ) ,
252+ } ,
253+ ] ,
254+ } ) ;
255+
256+ expect (
257+ JSON . parse ( await fs . readFile ( resolveShortTermRecallStorePath ( workspaceDir ) , "utf-8" ) ) ,
258+ ) . toMatchObject ( {
259+ version : 1 ,
260+ entries : { } ,
261+ } ) ;
262+ } ) ;
263+ } ) ;
264+
265+ it ( "keeps ordinary snippets that only quote dreaming prompt markers" , async ( ) => {
266+ await withTempWorkspace ( async ( workspaceDir ) => {
267+ await recordShortTermRecalls ( {
268+ workspaceDir,
269+ query : "debug note" ,
270+ results : [
271+ {
272+ path : "memory/2026-04-03.md" ,
273+ source : "memory" ,
274+ startLine : 1 ,
275+ endLine : 1 ,
276+ score : 0.75 ,
277+ snippet :
278+ "Debug note: quote Write a dream diary entry from these memory fragments for docs, but do not use dreaming-narrative-like labels in production." ,
279+ } ,
280+ ] ,
281+ } ) ;
282+
283+ const store = JSON . parse (
284+ await fs . readFile ( resolveShortTermRecallStorePath ( workspaceDir ) , "utf-8" ) ,
285+ ) as { entries : Record < string , { snippet : string } > } ;
286+ expect ( Object . values ( store . entries ) ) . toEqual ( [
287+ expect . objectContaining ( {
288+ snippet :
289+ "Debug note: quote Write a dream diary entry from these memory fragments for docs, but do not use dreaming-narrative-like labels in production." ,
290+ } ) ,
291+ ] ) ;
292+ } ) ;
293+ } ) ;
294+
206295 it ( "records recalls and ranks candidates with weighted scores" , async ( ) => {
207296 await withTempWorkspace ( async ( workspaceDir ) => {
208297 await recordShortTermRecalls ( {
@@ -940,6 +1029,86 @@ describe("short-term promotion", () => {
9401029 } ) ;
9411030 } ) ;
9421031
1032+ it ( "does not rank contaminated dreaming snippets from an existing short-term store" , async ( ) => {
1033+ await withTempWorkspace ( async ( workspaceDir ) => {
1034+ const storePath = resolveShortTermRecallStorePath ( workspaceDir ) ;
1035+ await fs . writeFile (
1036+ storePath ,
1037+ JSON . stringify (
1038+ {
1039+ version : 1 ,
1040+ updatedAt : "2026-04-04T00:00:00.000Z" ,
1041+ entries : {
1042+ contaminated : {
1043+ key : "contaminated" ,
1044+ path : "memory/2026-04-03.md" ,
1045+ startLine : 1 ,
1046+ endLine : 1 ,
1047+ source : "memory" ,
1048+ snippet :
1049+ "Reflections: Theme: assistant. confidence: 1.00 evidence: memory/.dreams/session-corpus/2026-04-08.txt:2-2 recalls: 4 status: staged" ,
1050+ recallCount : 4 ,
1051+ dailyCount : 0 ,
1052+ groundedCount : 0 ,
1053+ totalScore : 3.6 ,
1054+ maxScore : 0.95 ,
1055+ firstRecalledAt : "2026-04-03T00:00:00.000Z" ,
1056+ lastRecalledAt : "2026-04-04T00:00:00.000Z" ,
1057+ queryHashes : [ "a" , "b" ] ,
1058+ recallDays : [ "2026-04-03" , "2026-04-04" ] ,
1059+ conceptTags : [ "assistant" ] ,
1060+ } ,
1061+ } ,
1062+ } ,
1063+ null ,
1064+ 2 ,
1065+ ) ,
1066+ "utf-8" ,
1067+ ) ;
1068+
1069+ const ranked = await rankShortTermPromotionCandidates ( {
1070+ workspaceDir,
1071+ minScore : 0 ,
1072+ minRecallCount : 0 ,
1073+ minUniqueQueries : 0 ,
1074+ } ) ;
1075+
1076+ expect ( ranked ) . toEqual ( [ ] ) ;
1077+ } ) ;
1078+ } ) ;
1079+
1080+ it ( "treats diff-prefixed dreaming snippets as contaminated" , ( ) => {
1081+ expect (
1082+ __testing . isContaminatedDreamingSnippet (
1083+ "@@ -1,1 - Candidate: Default to action. confidence: 0.76 evidence: memory/.dreams/session-corpus/2026-04-08.txt:1-1 recalls: 3 status: staged" ,
1084+ ) ,
1085+ ) . toBe ( true ) ;
1086+ } ) ;
1087+
1088+ it ( "treats bracket-prefixed dreaming snippets as contaminated" , ( ) => {
1089+ expect (
1090+ __testing . isContaminatedDreamingSnippet (
1091+ "([ Candidate: Default to action. confidence: 0.76 evidence: memory/.dreams/session-corpus/2026-04-08.txt:1-1 recalls: 3 status: staged" ,
1092+ ) ,
1093+ ) . toBe ( true ) ;
1094+ } ) ;
1095+
1096+ it ( "does not treat ordinary candidate notes with daily-memory evidence as contaminated" , ( ) => {
1097+ expect (
1098+ __testing . isContaminatedDreamingSnippet (
1099+ "Candidate: move backups weekly. confidence: 0.76 evidence: memory/2026-04-08.md:1-1" ,
1100+ ) ,
1101+ ) . toBe ( false ) ;
1102+ } ) ;
1103+
1104+ it ( "treats transcript-style dreaming prompt echoes as contaminated" , ( ) => {
1105+ expect (
1106+ __testing . isContaminatedDreamingSnippet (
1107+ "[main/dreaming-narrative-light.jsonl#L1] User: Write a dream diary entry from these memory fragments:" ,
1108+ ) ,
1109+ ) . toBe ( true ) ;
1110+ } ) ;
1111+
9431112 it ( "skips direct candidates that exceed maxAgeDays during apply" , async ( ) => {
9441113 await withTempWorkspace ( async ( workspaceDir ) => {
9451114 const applied = await applyShortTermPromotions ( {
@@ -987,6 +1156,53 @@ describe("short-term promotion", () => {
9871156 } ) ;
9881157 } ) ;
9891158
1159+ it ( "does not append contaminated dreaming snippets during direct apply" , async ( ) => {
1160+ await withTempWorkspace ( async ( workspaceDir ) => {
1161+ const applied = await applyShortTermPromotions ( {
1162+ workspaceDir,
1163+ minScore : 0 ,
1164+ minRecallCount : 0 ,
1165+ minUniqueQueries : 0 ,
1166+ candidates : [
1167+ {
1168+ key : "memory:memory/2026-04-03.md:1:1" ,
1169+ path : "memory/2026-04-03.md" ,
1170+ startLine : 1 ,
1171+ endLine : 1 ,
1172+ source : "memory" ,
1173+ snippet :
1174+ "Candidate: Default to action. confidence: 0.76 evidence: memory/.dreams/session-corpus/2026-04-08.txt:1-1 recalls: 3 status: staged" ,
1175+ recallCount : 4 ,
1176+ avgScore : 0.97 ,
1177+ maxScore : 0.97 ,
1178+ uniqueQueries : 2 ,
1179+ firstRecalledAt : "2026-04-03T00:00:00.000Z" ,
1180+ lastRecalledAt : "2026-04-04T00:00:00.000Z" ,
1181+ ageDays : 0 ,
1182+ score : 0.99 ,
1183+ recallDays : [ "2026-04-03" , "2026-04-04" ] ,
1184+ conceptTags : [ "assistant" ] ,
1185+ components : {
1186+ frequency : 1 ,
1187+ relevance : 1 ,
1188+ diversity : 1 ,
1189+ recency : 1 ,
1190+ consolidation : 1 ,
1191+ conceptual : 1 ,
1192+ } ,
1193+ } ,
1194+ ] ,
1195+ } ) ;
1196+
1197+ expect ( applied . applied ) . toBe ( 0 ) ;
1198+ await expect (
1199+ fs . readFile ( path . join ( workspaceDir , "MEMORY.md" ) , "utf-8" ) ,
1200+ ) . rejects . toMatchObject ( {
1201+ code : "ENOENT" ,
1202+ } ) ;
1203+ } ) ;
1204+ } ) ;
1205+
9901206 it ( "applies promotion candidates to MEMORY.md and marks them promoted" , async ( ) => {
9911207 await withTempWorkspace ( async ( workspaceDir ) => {
9921208 await writeDailyMemoryNote ( workspaceDir , "2026-04-01" , [
0 commit comments