fix #83830: [Bug]: Dreaming diary repeats "first day" narrative every sweep — same early memories dominate snippets#91225
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 12, 2026, 12:00 PM ET / 16:00 UTC. Summary PR surface: Source +168, Tests +200. Total +368 across 5 files. Reproducibility: yes. The current-main limit-first ranking is a deterministic reproduction path, and the supplied controlled production-path proof shows the high-recall first-day snippet winning before the patch and a later snippet winning afterward. Review metrics: none identified. Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this bounded memory-core fix after an area owner confirms the diary-coverage ranking policy; keep selection before the phase limit, optional context fail-open, and managed writes strict. Do we have a high-confidence way to reproduce the issue? Yes. The current-main limit-first ranking is a deterministic reproduction path, and the supplied controlled production-path proof shows the high-recall first-day snippet winning before the patch and a later snippet winning afterward. Is this the best way to solve the issue? Yes. The narrowest maintainable fix is to incorporate recent diary coverage at the light-dream selection owner boundary before the configured limit, while keeping prompt continuity and optional file-read degradation in their existing owners. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 8673c65c6bad. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +168, Tests +200. Total +368 across 5 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
31a7570 to
1859b8c
Compare
|
One actionable finding from my local review before it goes to memory-core owner review: |
fa916c1 to
1eb48a6
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
9977e88 to
62db365
Compare
|
Land-ready maintainer pass complete. What changed:
Verification:
Known proof gap: the pre-push remote Best-fix judgment: yes. The bounded full-store stable partition removes the starvation case completely instead of tuning another candidate multiplier, while preserving the existing ranking order within fresh and diary-covered groups. |
Prevent repeated first-day Dream Diary narratives by prioritizing fresh recall snippets across the bounded short-term store and adding recent diary context to narrative generation. Keep diary reads best-effort and reject symlink/non-file inputs. Fixes openclaw#83830. Thanks @mushuiyu886. Co-authored-by: 杨浩宇0668001029 <[email protected]>
Prevent repeated first-day Dream Diary narratives by prioritizing fresh recall snippets across the bounded short-term store and adding recent diary context to narrative generation. Keep diary reads best-effort and reject symlink/non-file inputs. Fixes openclaw#83830. Thanks @mushuiyu886. Co-authored-by: 杨浩宇0668001029 <[email protected]>
Prevent repeated first-day Dream Diary narratives by prioritizing fresh recall snippets across the bounded short-term store and adding recent diary context to narrative generation. Keep diary reads best-effort and reject symlink/non-file inputs. Fixes openclaw#83830. Thanks @mushuiyu886. Co-authored-by: 杨浩宇0668001029 <[email protected]>
Prevent repeated first-day Dream Diary narratives by prioritizing fresh recall snippets across the bounded short-term store and adding recent diary context to narrative generation. Keep diary reads best-effort and reject symlink/non-file inputs. Fixes openclaw#83830. Thanks @mushuiyu886. Co-authored-by: 杨浩宇0668001029 <[email protected]>
Summary
readRecentDreamDiaryEntries()now treats unreadable optionalDREAMS.mdcontext as empty history, including permission/safe-read failures such asEACCESandEPERM, so light dreaming does not abort before staging/reporting.DREAMS.mdwrite path are unchanged.DREAMS.mdis unreadable.Fixes #83830
Maintainer-ready notes
DREAMS.mdupdates still go through the existingupdateDreamsFile()path and still reject unreadable files.extensions/memory-core/src/dreaming-phases.ts; prompt/DREAMS.md context remains owned byextensions/memory-core/src/dreaming-narrative.ts; shared path/read/write safety remains owned byextensions/memory-core/src/dreaming-dreams-file.ts.Real behavior proof
DREAMS.mdpreviously won the light phase's limited snippet slot because selection sorted by recent recall time and recall count before the phase limit. The latest review finding covered the follow-up path: recent diary history is optional prompt context, but an unreadableDREAMS.mdcould abort the required light-dreaming path before staging/reporting./media/vdc/code/ai/aispace/openclaw-worktrees/pr-91225, branchrepair/pr-91225, latest HEAD1eb48a6c6c311e2ba8325b0f7343a6ca3ebc5786. The latest proof uses real local filesystem permissions (chmod 000) through the production memory-core diary context reader and the productionDREAMS.mdupdate helper.{ "head": "1eb48a6c6c311e2ba8325b0f7343a6ca3ebc5786", "proofScope": "real local filesystem permissions through production memory-core diary context and DREAMS.md update helpers", "readableContext": { "returnedEntries": 1, "firstEntry": "The old routing memory stayed available for the next light sweep." }, "unreadableOptionalContext": { "chmod": "000", "returnedEntries": 0, "lightDreamingContextContinuesAsEmptyHistory": true }, "strictWritePath": { "chmod": "000", "rejectedCode": "EACCES", "writePathStillStrict": true } }Existing broader source-runtime proof from the earlier revision also showed the original diary-repeat fix: with
light.limit=1, the old limit-first ranking selected the already-written first-day snippet withrecallCount=4; after the patch, the production light sweep selected the later routing snippet as the memory fragment, kept the first-day text only as recent diary context, wrote the fresh candidate into the light block, and appended a new diary entry while preserving the existing first-day entry as history.DREAMS.mdexists but is unreadable on the local filesystem,readRecentDreamDiaryEntries()returns empty history instead of throwing, so light dreaming can continue. The same unreadable file still causes the managed write path to reject withEACCES, proving the optional prompt-context fallback did not loosenupdateDreamsFile()safety.Main sync conflict verification
origin/mainmovedDREAMS.mdpath and locking helpers intodreaming-dreams-file.ts; this update keepsreadRecentDreamDiaryEntries()on that source-of-truth by importingresolveDreamsPath()andreadDreamsFile()instead of reintroducing private path/file helpers.1eb48a6c6c311e2ba8325b0f7343a6ca3ebc5786.Test Files 1 passed (1); Tests 58 passed (58).Review findings addressed
sallyom: unreadable optionalDREAMS.mdhistory now degrades to empty recent diary context for light dreaming, while the strict managedDREAMS.mdwrite path remains unchanged and still rejects unreadable files.DREAMS.mdhelper and safe file-read boundary; symlinked and non-fileDREAMS.mdpaths return empty recent diary context before target contents can reachbuildNarrativePrompt().Regression Test Plan
extensions/memory-core/src/dreaming-narrative.test.ts,extensions/memory-core/src/dreaming-phases.test.ts,extensions/memory-core/src/short-term-promotion.test.ts.DREAMS.mdalready contains the first-day snippet, and a light dreaming sweep withlimit=1sends the newer snippet to the narrative prompt while keeping the first-day text only as diary history. The latest follow-up adds coverage that unreadableDREAMS.mdprompt context resolves to empty history.DREAMS.mdread path, unreadable optional context, and unchanged strict write path without changing config/schema or relying on provider-specific prose output.Merge risk
DREAMS.mdfile shape and readability determine whether text may enter prompt context. Availability applies because unreadable optional diary history should not abort light dreaming. Compatibility risk is low because public config, file markers, store schema, plugin SDK API, provider routing, and append/dedupe commands are unchanged.readRecentDreamDiaryEntries(), where diary history is optional context. It does not changereadDreamsFile()globally and does not relaxupdateDreamsFile(); proof shows the write path still rejects an unreadableDREAMS.mdwithEACCES.appendNarrativeEntry(), does not change external provider/model behavior, does not migrateDREAMS.mdor short-term recall state, does not change public dreaming defaults, and does not relax managed write safety checks.Root Cause
runLightDreaming()sorted live short-term recall entries bylastRecalledAtandrecallCount, sliced to the phase limit, and only then generated the diary prompt. Because Dream Diary had no feedback into that selection step, an early first-day memory that was repeatedly recalled could keep winning the limited input slot even afterDREAMS.mdalready contained that same memory. The latest reviewer finding exposed a separate optional-context availability boundary:readRecentDreamDiaryEntries()could let an unreadableDREAMS.mdabort light dreaming even though diary history is only prompt continuity context.readRecentDreamDiaryEntries()catches read/permission/safe-read failures and returns empty history, while leaving managed writes strict.extensions/memory-core/src/dreaming-phases.tsfor light snippet selection,extensions/memory-core/src/dreaming-narrative.tsfor prompt/DREAMS.md context, andextensions/memory-core/src/dreaming-dreams-file.tsfor sharedDREAMS.mdpath/read/write safety. Public contract scope is narrow: no SDK/API/config/protocol/schema/default migration changed.