Appearance
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)
| Surface | Location | Audience |
|---|---|---|
| Vault memory | memory/ | 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:
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).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 thefederation/subtree, distinct from spread; weights toward concentration vs distribution.
Proposed targets by type
| Memory type | Proposed 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/orthe-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
- Surfacer runs.
memory-graduation-scout.pywalks 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). - Michael reads the report. Each candidate shows: current MEMORY.md line, citation evidence, federation citers, proposed target path(s), proposed one-liner replacement.
- 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). - 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: laworstatus: 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).
- Create the full doc at the proposed target path with frontmatter (
- Audit log. Each graduation is recorded in the relevant audit (
/handover-equivalent or daily wrap-up) so the migration is traceable.
The surfacer
| Item | Detail |
|---|---|
| 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 conditions | harness memory dir unreadable; MEMORY.md missing; zero fact files found |
| Owner | Jimmy 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)
- Direct slug grep. The literal slug string (e.g.
feedback_no-auto-vaultwarden-writes) appears in the file. - 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. - 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. Flaggedneeds-description: truein 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 >= 2gate 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); afeedback_*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.mdwhose content is already insupreme-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