Skip to content

Memory Graduation

When a fact in harness memory stops being a private note and starts being load-bearing doctrine cited across the federation, it must move out of harness memory and into the vault — where every CLI, every agent, and the architecture itself can see it. This document is the law for that move.

Cross-link: memory-architecture (the three surfaces and their writers).


The Three Surfaces (recap)

SurfaceLocationAudience
Vault memorymemory/All CLIs + Z2
Commander memory.claude/agent-memory/[Commander]/That commander on its next dispatch
Harness memory~/.claude/projects/-Users-nnamdi-hinata-v2/memory/Claude Code (Hinata) only

Harness memory is Claude-private. It is where Hinata accumulates personal preferences, in-flight project notes, and observed user behaviour. It is not law and other agents cannot see it. That privacy is the feature — until a fact stops being private and becomes doctrine.

Graduation criteria

A harness-memory fact file is a graduation candidate when all of the following hold:

  1. vault_citations >= 3 — the slug is referenced at least three times anywhere under /Users/nnamdi/hinata-v2/ (excluding .git, node_modules, the harness memory dir itself, and the graduation output directory).
  2. agent_spread >= 2 — at least two distinct federation context files cite the slug, evidencing that more than one commander needs the fact.

Thresholds are tunable; they live in memory-graduation-scout.py and may be ratcheted as the corpus matures.

Secondary signals (logged but not gating):

  • age_days — older + still-cited memories are more stable graduation targets than a slug coined yesterday and already heavily cross-referenced.
  • federation_citations — raw count across the federation/ subtree, distinct from spread; weights toward concentration vs distribution.

Proposed targets by type

Memory typeProposed graduation path
feedback_*supreme-court/preferences-styles/
user_*supreme-court/preferences-styles/
reference_*the-government/information_reference/
project_*supreme-court/runtime/ OR the-government/information_reference/ — surfacer offers both, Michael picks

The surfacer never decides between two options for project memories. That call is Michael's.

Surfacer-only — never auto-lift

This is the non-negotiable principle of the graduation pipeline:

  • The surfacer never modifies MEMORY.md. Not even to update a line. Not even when the candidate is unambiguous.
  • The surfacer never writes to supreme-court/ or the-government/. Its only output is a markdown report.
  • The surfacer never deletes the original fact file. Until the lift is ratified and manually performed, the harness memory stays exactly as Hinata wrote it.

Why: auto-lifting doctrine without human review compounds two failure modes — (1) premature canonisation of a fact that turned out to be situational, and (2) silent ownership transfer from "Hinata observed this" to "the federation requires this." Both are worse than a missed candidate.

The workflow

  1. Surfacer runs. memory-graduation-scout.py walks harness memory, scores every fact file, and writes a dated candidate report to /Users/nnamdi/Sandpit/hinata/data/graduation/[YYYY-MM-DD]-candidates.md (plus a JSON sidecar for downstream consumers).
  2. Michael reads the report. Each candidate shows: current MEMORY.md line, citation evidence, federation citers, proposed target path(s), proposed one-liner replacement.
  3. Michael ratifies the lift. Per candidate, he picks: lift (and to which path, for project_*), defer (raise threshold and re-check), or kill (mark as not-for-graduation).
  4. Manual lift. A ratified candidate is moved by hand or by an explicit Hinata dispatch:
    • Create the full doc at the proposed target path with frontmatter (status: law or status: reference), the original body, and cross-links back to [memory-graduation](./memory-graduation.html) and [memory-architecture](./memory-architecture.html).
    • Replace the MEMORY.md line with a one-liner pointer to the new location.
    • Delete the original fact file in harness memory (its content now lives in the vault — duplication violates ../format-design/no-memory-duplication-across-surfaces in spirit).
  5. Audit log. Each graduation is recorded in the relevant audit (/handover-equivalent or daily wrap-up) so the migration is traceable.

The surfacer

ItemDetail
Script/Users/nnamdi/Sandpit/hinata/scripts/memory-graduation-scout.py
Input~/.claude/projects/-Users-nnamdi-hinata-v2/memory/ (Mac-private; sanctioned exception to script-location-doctrine)
Vault scan root/Users/nnamdi/hinata-v2/
Federation scan root/Users/nnamdi/hinata-v2/federation/
Output/Users/nnamdi/Sandpit/hinata/data/graduation/[YYYY-MM-DD]-candidates.md (+ .json sidecar)
Loud-fail conditionsharness memory dir unreadable; MEMORY.md missing; zero fact files found
OwnerJimmy Neutron

The script is Mac-local because harness memory lives under ~/.claude/, which is Apple-side per hinata-architecture. This is one of the few sanctioned exceptions to "scripts default to Z2."

Metric hardening (2026-06-14)

First-run finding: the original agent_spread metric was a single-layer slug grep across federation/*.md. It scored zero across the entire corpus because federation context files cite memories by concept name, not by slug — so even legitimately cross-agent doctrine (e.g. feedback_no-auto-vaultwarden-writes, 10 vault citations) read as spread=0 and never surfaced.

Michael ruling (2026-06-14): do NOT lower the threshold. Harden the detector instead. Quality bar is sovereign — all candidates must meet vault_citations >= 3 AND agent_spread >= 2 from this run onwards.

Three signal layers (OR-merged)

  1. Direct slug grep. The literal slug string (e.g. feedback_no-auto-vaultwarden-writes) appears in the file.
  2. Wikilink grep. Either [slug] or [slug-without-type-prefix] (i.e. [no-auto-vaultwarden-writes](../preferences-styles/no-auto-vaultwarden-writes.html)) appears in the file.
  3. Title-fragment grep. Multi-word content phrases derived from the memory's description: frontmatter appear in the file. Phrase extraction strips stop-words (including English stop-words, common Hinata vocabulary like "memory/agent/federation", and federation member names) and emits runs of consecutive content tokens.

Two scan roots (each counted in spread)

  • federation/*.md — each context file = one agent
  • .claude/agent-memory/[Commander]/*.md — each commander directory = one agent (per memory-architecture — commander memory is the second of the three memory surfaces)

agent_spread = |distinct federation files matched| + |distinct commander dirs matched|

Guardrails

  • Minimum phrase length: 3 consecutive content words. 2-token phrases like "main thread" or "entry point" produced unacceptable false positives even after stop-word filtering. The 3-token floor trades recall for precision deliberately — a missed candidate this run can be surfaced next run when new citations accrete; a false positive corrupts trust in the metric immediately.
  • Maximum phrase length: 5 content words. Above 5, recall drops to zero (no federation file uses the full phrase).
  • Empty description: → fallback to slug-only. Flagged needs-description: true in the sidecar so Michael can fix the source memory.
  • Per-memory signal trace logged in JSON sidecar. For every file that matched, the sidecar records which signal layer fired (slug / wikilink / fragment + the specific phrase). No black box — every spread number is auditable.

Verification

The hardened metric scored 3 candidates against 83 memories on 2026-06-14, including the known-good case feedback_no-auto-vaultwarden-writes (spread=3 via slug + wikilink hits in Bulma, Itachi, and Jimmy-Neutron commander memory). Zero false positives observed.

Scheduling

Nightly at 03:00 via launchd (~/Library/LaunchAgents/com.hinata.memory-graduation-scout.plist, loaded 2026-06-14). 03:00 is after token-burn settles and before morning sessions begin. Output rolls into data/graduation/[YYYY-MM-DD]-candidates.md. The principle that the surfacer only surfaces does not change — the launchd hook writes a report; nothing is auto-lifted.

Anti-patterns

  • Auto-promoting based on raw citation count without spread. A slug cited 10 times in one file is not doctrine — it's a heavily-referenced project note. The agent_spread >= 2 gate is what makes a candidate doctrine.
  • Lifting reference memories into preferences. Type-correct targets matter. A reference_* is a fact about reality (where something lives, how something is named); a feedback_* is a behavioural rule. They graduate to different folders for a reason.
  • Forgetting to delete the harness-memory original after lift. Once graduated, the harness copy is duplicative noise. Delete it. See ../format-design/no-memory-duplication-across-surfaces.
  • Re-creating a graduated memory in harness memory. If Hinata writes a new feedback_X.md whose content is already in supreme-court/preferences-styles/X.md, that's drift, not memory — fold and delete on sight.

Cross-links: memory-architecture · ../format-design/no-memory-duplication-across-surfaces · hinata-architecture · runtime_workflow