claude-skills/engineering/agent-memory
Claude 9f2c50e285
fix(agent-memory): address automated review; harden the session-id fallback
Five of six findings were real. Verified each against the code rather than
taking them at face value; one was wrong and is noted below.

1. validate_examples.py carried a stale header from the spec-only phase --
   "PARKED AS AN ASSET (deliberately not .py yet)... ON IMPLEMENTATION: rename
   to skills/agent-memory/scripts/validate_examples.py". The file is already at
   exactly that path. Rewritten to describe what it now is, keeping the
   substantive part: why it exists, the seven check families, why it compares
   the doc's algorithm by source text rather than exec()-ing a code fence, and
   that nothing runs it automatically.

2. Missing shebang -- added. The same finding also claimed mode 100644; that
   half is wrong, `git ls-files -s` shows 100755 for all five scripts.

3. hooks.json's description still opened "CONTRACT ONLY -- the referenced
   scripts are not yet implemented", true of none of them now. Trimmed to keep
   only the UserPromptSubmit provisionality (9.5 is genuinely still open) and
   to record the measured latency alongside it.

4. The session-id fallback was the finding worth the most. `session_id` is the
   right key -- engineering/security-guidance's shipped hook reads the same one
   -- but the fallback was the CONSTANT "unknown-session", and sessions dedupe
   by value. Had the key ever been absent, every session would collapse onto
   one id, len(set(sessions)) would plateau at 1, and every claim would cap at
   L1 forever with no error anywhere. Now falls back to the transcript's own
   basename, which IS the session id. Verified end-to-end with session_id
   omitted from the payload: the atom records the real session UUID.

5. Dead `now` parameter on _eligible_l1 -- removed.

6. marketplace.json metadata still said 104 agents / 120 slash commands,
   pre-existing drift on a line this branch already edits. Trued up to 110/130.

Re-verified after: 69 checks 0 failures, SKILL.md 6/6 PASS, both blocking gates
still fire by name, check_paths 620 files clean, counters and plugin-json pass,
all 5 scripts --help, all 3 hooks parse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
2026-08-24 18:45:52 +00:00
..
.claude-plugin feat(agent-memory): implement the four-tier memory ladder 2026-08-24 18:23:01 +00:00
agents feat(agent-memory): implement the four-tier memory ladder 2026-08-24 18:23:01 +00:00
commands feat(agent-memory): implement the four-tier memory ladder 2026-08-24 18:23:01 +00:00
hooks fix(agent-memory): address automated review; harden the session-id fallback 2026-08-24 18:45:52 +00:00
skills/agent-memory fix(agent-memory): address automated review; harden the session-id fallback 2026-08-24 18:45:52 +00:00
DESIGN.md feat(agent-memory): implement the four-tier memory ladder 2026-08-24 18:23:01 +00:00
README.md feat(agent-memory): implement the four-tier memory ladder 2026-08-24 18:23:01 +00:00

agent-memory

A four-tier memory ladder for Claude Code. Promotion is earned by recurrence, never asserted by confidence, and nothing reaches a committed file without a human adopting it.

Concept derived from TencentCloud/TencentDB-Agent-Memory (MIT). No upstream code is included — see .claude-plugin/authoring-notes.json for what was taken and what was deliberately rejected.


What it does

Tier Holds Injected Committed
L0 raw session transcripts never already on disk
L1 candidate atoms on relevance, per prompt no (gitignored)
L2 this project's context every session start yes, after adopt
L3 stable cross-project persona always yes, after adopt

L1 → L2 needs ≥ 3 distinct sessions spanning ≥ 2 distinct calendar days. A claim stated outright needs 2 sessions — the day rule still applies. A deterministically verified claim promotes on one observation and is the only day-exempt path. L2 → L3 needs ≥ 2 distinct projects and ≥ 30 days.

Two gates refuse rather than guess: a redacted claim never promotes on evidence alone, and a claim with an open contradiction freezes until a human resolves it.

Install and use

The three hooks in hooks/hooks.json run the loop unattended. Each is disabled independently:

AGENT_MEMORY_SESSIONSTART=0      # stop injecting L2 + L3
AGENT_MEMORY_USERPROMPTSUBMIT=0  # stop L1 recall
AGENT_MEMORY_SESSIONEND=0        # stop capture
cd skills/agent-memory/scripts
python3 memory_inspect.py --tier L1              # what's stuck, and why
python3 memory_inspect.py --why "<claim>"        # full provenance + source line
python3 memory_inspect.py --contested            # disputed claims, both directions
python3 memory_promote.py                        # dry-run the gates; writes nothing
python3 validate_examples.py                     # 69 checks over the spec + schema

Every script takes --sample and --output json. /cs:memory wraps all of it; /cs:memory adopt is the only path that writes to a CLAUDE.md, and it backs both files up first.

Contents

DESIGN.md                       the spec: schema, gates, hook contracts, open decisions
hooks/hooks.json                three hook contracts
hooks/session_start.py          inject L3 + L2, mark cross-tier conflicts
hooks/user_prompt_submit.py     recall L1 on a 100 ms internal budget
hooks/session_end.py            capture, redact, detect, merge, stage
skills/agent-memory/SKILL.md    6/6 PASS on the write-a-skill checklist
  scripts/memory_core.py        shared: ids, redaction, locking, contradictions
  scripts/memory_extract.py     L0 → L1, rule-based, no LLM
  scripts/memory_promote.py     L1 → L2 → L3, stages proposals
  scripts/memory_inspect.py     read-only: --tier / --contested / --why
  scripts/validate_examples.py  69 checks in seven families
  assets/memory_schema.json     13 required fields, five conditionals
  references/                   three references, 67 sources each
agents/cs-memory-curator.md     refuses to adopt what it cannot cite
commands/cs-memory.md           status | why | contested | adopt | forget

Deviations from DESIGN.md

DESIGN.md was written before the implementation and reviewed at length. Where the built thing differs from the planned thing, this list is authoritative.

  1. memory_core.py exists. §10's planned tree lists four scripts and no shared module. Building it that way would have duplicated the redaction patterns, the id algorithm and the lock protocol across seven files — which is precisely the drift class the spec exists to prevent. The module has no CLI and is not a plugin-facing tool.
  2. The tool count in §10.1 is wrong. It says +6 (3 scripts + 3 hooks). The delivered surface is 5 scripts + 3 hooks = 8. Corrected in the counters; §10.1's text is left as the historical record of the estimate.
  3. mark_contradictions() was added to the core. §4.2.1 specifies detection running at merge time in SessionEnd but assigns it to no file. It lives in the core so the promoter and the inspector share one definition of "open contradiction" rather than three.
  4. Cross-tier conflict marking marks both sides. §5.1 requires that an L2 and an L3 claim colliding must not both appear as plain assertions, and says all three candidate policies satisfy it. The implementation marks both and picks no winner — the least committal option, and the one that does not have to be undone if the open decision lands on specificity-wins.
  5. The 100 ms recall budget is met, on this machine. §9.5 asserted the budget without measurement and offered dropping the hook as option (c). Measured: spawn-plus-recall p50 ≈ 29 ms, p95 ≈ 31 ms, max ≈ 35 ms against a populated store; the scoring pass itself 23 ms over 500 atoms. Interpreter start-up is the whole cost. This does not close §9.5 — one machine is not a portability claim, and a slower host may still force option (c).
  6. --why quotes the source line. Not specified anywhere; added because "cite, don't invent" is unfalsifiable if a human cannot see the cited line. It prints nothing when the back-pointer resolves ambiguous.

What would make this worth deleting

Stated plainly because §9.3 permits it and the trial is the point:

  • Recall is too low to matter. Rule-based extraction is deliberately high-precision. If a two-week trial produces a handful of atoms and none reach L2, the honest response is to remove the folder — not to loosen gates until something passes.
  • Nobody reviews the staged promotions. The entire security argument rests on a human at the adopt gate. If staged items are accepted unread, the gate is theatre.
  • --why is never run. Provenance nobody checks is provenance nobody needs.

License

MIT. Concept attribution: TencentDB-Agent-Memory (MIT, © Tencent). See ../../LICENSE.