fix(memory): stage() mirrors manual lessons into AGENT_LEARNINGS.jsonl#57
Open
diazMelgarejo wants to merge 2 commits into
Open
fix(memory): stage() mirrors manual lessons into AGENT_LEARNINGS.jsonl#57diazMelgarejo wants to merge 2 commits into
diazMelgarejo wants to merge 2 commits into
Conversation
The manual-stage path in .agent/tools/learn.py writes a candidate with evidence_ids: [now], promising an episodic record exists at that timestamp — but never writes one. The auto-derived candidate path mirrors to AGENT_LEARNINGS.jsonl correctly; the manual path does not. The result is a referential-integrity gap: a graduated lesson's evidence_ids points at a timestamp with no matching episodic record. Fix: add _append_episodic_mirror(), called right after the candidate file is written, using the same 'now' timestamp so evidence_ids[0] always resolves. Fail-open on OSError so a mirror-write failure never blocks staging. Minimal and additive — stdlib only, no new dependencies, no change to the auto-derived path. Found and fixed downstream in Perpetua-Tools (which vendors this project); contributing back per that project's dogfooding practice.
Standalone stdlib unittest (no third-party test dependency) since this project currently ships no test harness — intended as the first test file. Kept as a SEPARATE commit from the fix so it can be cherry-picked out if the maintainer prefers to merge the fix alone. Adapted from the downstream Perpetua-Tools suite that proved this fix. Covers: stage() writes exactly one matching episodic mirror; the candidate's evidence_ids[0] resolves to exactly one episodic record (the regression this targets); and _append_episodic_mirror fails open on write error. Run: python3 -m unittest .agent/tools/test_learn_episodic_mirror.py
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Atomic PR 01 of 3
Summary
stage()'s manual-lesson path writes a candidate withevidence_ids: [now], promising an episodic record exists at that timestamp inAGENT_LEARNINGS.jsonl— but never writes one. The auto-derived candidate path mirrors correctly; the manual path doesn't. Result: a graduated lesson'sevidence_idscan point at a timestamp with no matching episodic record.Fix
Adds
_append_episodic_mirror(), called right after the candidate file is written, using the same timestamp soevidence_ids[0]always resolves.Fail-open on
OSError— a mirror-write failure never blocks staging.Minimal, additive, stdlib-only.
Verification
master@00eda65c, syntax-checked.stage()now writes exactly one episodic mirror whose timestamp equals the candidate'sevidence_ids[0].vendor/agentic-stack). Validated there in two ways: 3 unit tests, and 6 real, non-test invocations of the fixedlearn.py— all 6 evidence_ids verified programmatically to resolve to exactly one matching episodic record. Both are on PTmain, commits95f047f(fix) and61dee0d(real-world validation), if useful cross-reference.Two commits, intentionally separate
fix(memory): ...— the fix alone.test(memory): ...— a standaloneunittest(no pytest or other third-party dependency, since this project doesn't currently ship a test harness). Kept as a separate commit specifically so you can cherry-pick it out if you'd rather merge the fix without introducing the project's first test file this way.Question for you: would you like the test included as-is, dropped, or adapted to a different location/convention? Fully open to whatever fits this project, this is offered as a starting point, not a requirement.
Background check
Searched open/closed issues and PRs for
episodic,evidence_ids,mirror, no duplicate report. (#13 is a related-but-different gap: adapters not auto-populating the episodic log at all; this fix is about the manual-stage path specifically not mirroring.)Note on this PR and its siblings
This is PR 1 of 3 prepared together as a small, related set (each stacked on the previous: #2 will be based on this branch, #3 on #2), separated so each can be reviewed and merged on its own merit, but designed as a set. (My own personal working patch on top of your latest release!)
Opening this one first; happy to hold 2 and 3 until this lands, or just open them now for visibility from my end, and mentioned here for transparency rather than surprising you with a queue later on. They can also all land together, whichever you prefer.
Thank you,
ALL THE BEST!
P.S.: your 0.19 draft spec looks exciting 💪🏼
Note
Mirror manual
stage()calls intoAGENT_LEARNINGS.jsonlas episodic records_append_episodic_mirrorin learn.py that writes a JSONL entry tomemory/episodic/AGENT_LEARNINGS.jsonlwhenever a lesson is manually staged, using the same timestamp as the candidate file.manual-stage:{cid}, pain score, importance, confidence, and evidence IDs linking back to the candidate.Macroscope summarized a3d5139.