<!-- memorylayer:start -->
# Memory (MemoryLayer)
You have persistent memory + code intelligence via MemoryLayer (MCP).
The UserPromptSubmit hook injects instructions each turn — follow them exactly.
Skipping them means answering without project history, prior decisions, or code knowledge.

## Every turn

1. Load schemas with ToolSearch (first turn only — deferred tools need this).
2. Load priority memories with recall(tags=["rule","constraint","guide"], match="any") (first turn only) — follow them. (match="any" = OR; tags default to AND and would match only memories carrying all three.)
3. Recall from configured namespace with recall(query, namespace).
4. code_ingest: check ingest-registry memory first; hook tells you if git SHA unchanged → SKIP.
5. Match scenario to the right tool (hook injects "Scenario detected" — follow it):
   - **Caller/import** ("what calls X?", "imports"): recall — auto-routes to triple lookup
   - **Closed relational** ("does A call B?", "is A a B?"): recall answers proven-first — trust `confidence` (proven > retrieved); add `require_proof: true` when you need certainty (it abstains instead of guessing)
   - **High-stakes single claim** (about to act on it, or the user is challenging it): prove({ claim }) for a formal proof certificate — stronger than "retrieved", use before risky actions or when precision matters more than speed
   - **Symbol lookup** ("find X", "where is X"): code(locate) → code(grep) → recall(find_symbol)
   - **Broad investigation** ("how does X work?"): recall(explore:true) → code(locate) → code(impact)
   - **Error/bug**: recall(tags=["error"]) first — known fix may exist; remember [error][open] if new
   - **Before Edit/Write**: code(impact, symbolName) — check callers + blast radius first
   - **New project/session, architectural contracts exist** (.domain files, invariants, compliance rules): domain({ action: "load", source: "<path>" }) at session start so violations get caught immediately
   - **Learned a reusable formula or step-by-step procedure**: consolidate({ action: "teach", ... }) so it's queryable later instead of re-derived each time; chain related taught procedures with consolidate({ action: "compose", ... })
   - **CI / pre-merge / "check nothing broke" request** against a loaded domain: audit({ domain }) — batch-checks every axiom, returns exit_code for scripting
   Only fall back to Read/Bash if all memory tools return answer_kind="empty".
6. Before writing ANY new memory, look it up first (see "Before every remember" below) — do not skip straight to remember.
7. After significant work, save with remember (after the lookup step).
8. Before stating something as settled fact in your response (especially anything you'll repeat, hand to a subagent, or act on), run verify({ text }) on the claim — don't rely on recall's retrieval alone for high-stakes statements.

## Tool priority ladder

  1. recall(answer/search) — check memory first
  2. code(locate/impact/grep) — code intelligence
  3. Read — targeted (use offset+limit, never read whole file blindly)
  4. Grep/Glob/Bash — last resort only

## Before every remember — mandatory lookup first

remember()'s automatic dedup only catches near-identical wording — it does NOT
reliably catch "same fact, restated differently," which is how stale duplicate
memories accumulate over a long-running project. Before calling remember():

1. recall({ query: "<the fact/topic>", namespace }) first. If an existing
   memory already covers this topic:
   - Same fact, still true → do nothing (do not create a duplicate).
   - Fact changed / superseded → remember({ action: "update", id: "<existing id>", content: "<new content>" })
     to update it IN PLACE. Do not leave the old one behind.
   - Directly contradicts an existing memory → resolve the contradiction:
     keep whichever is current/correct, update it in place, and if genuinely
     unsure which is right, say so in the updated content rather than storing
     both as separate unreconciled facts.
2. Only call remember() as a fresh upsert when the lookup found nothing
   relevant — this is a NEW fact, not a restatement of something already known.
3. If step 1 turns up two or more memories that look like stale/duplicate
   variants of the same fact (not just one you're updating), that namespace
   has drifted — run consolidate({ action: "ripple", namespace }) to derive
   what's actually current, surface the contradiction, and clean it up before
   adding anything new.

## Tool selection

  recall      → read: search · answer · weave · list · load (intent-routed)
  remember    → write: upsert · update · delete · chunk (param-routed) — ALWAYS recall first, see above
  code        → code: ingest · locate · impact · grep (action-routed)
  consolidate → maintenance: TTL prune · replay-and-derive (ripple) · contradiction detection · ACT-R compose/teach
  verify      → hallucination gate: split text into claims, check each against stored knowledge — use before stating facts
  audit       → batch Z3 invariant check across a loaded domain (CI gate)
  domain      → formal domain: load · export · status · set_mode — load architectural contracts at session start
  prove       → Z3 formal proof for a single claim — use for high-stakes/authoritative statements

## Error lifecycle

- Hit error → recall(tags=["error"], query="<error>") — check if known
- New error → remember({ content: "<error+context>", tags: ["error","open"], priority: 7 })
- Fix found → update SAME memory → tags: ["error","fixed","solution"] + root cause + fix steps
- ONE memory per error — update in place, never open two for the same error

## Before any Edit/Write

1. code(impact, symbolName, depth=2) — callers, callees, test files
2. recall(tags=["error"], query="<symbol>") — known issues with this code
3. Edit with confidence — you know the blast radius

## Ingest rules

- recall(tags=["ingest-registry"]) BEFORE calling code(ingest) — hook does git SHA check
- git SHA unchanged (hook says SKIP) → do NOT call code_ingest
- Repo >500 files → ASK USER first, suggest ingesting a sub-directory
- After ingest → remember({ content: "ingest: path=<p> ns=<ns> git_sha=<sha> reason=<why>", tags: ["ingest-registry","namespace:<ns>"], priority: 6 })
- Task touches a separately ingested repo → query BOTH namespaces in parallel

## Session lifecycle (hooks fire automatically)

- SessionStart → namespace + priority memories loaded; $MEMORYLAYER_NAMESPACE set
- PreCompact → flush decisions/errors/guides to memory BEFORE context is trimmed
- PostCompact → reload priority memories after context is trimmed
- SubagentStop / TaskCompleted → capture anything the subagent/task discovered
- SessionEnd → consolidation: save learnings, close errors, consolidate(), sync push

## When to store

Save with remember (it dedupes; never use memory_store directly):

  remember({ content, namespace, tags?, priority? })

Store whenever:
  - User says "remember this", "save that", "don't forget"
  - User states a preference, decision, or constraint
  - User corrects your behavior — save the rule (priority: 9)
  - You understand how a module or pattern works
  - You hit an error → error lifecycle above
  - Session ends → learnings, how-to guides

## Memory tagging schema

  [error][open|fixed][solution]     — errors + fixes
  [guide][how-to][workflow]         — step-by-step guides
  [arch][decision][pattern]         — architecture insights
  [rule][constraint][priority-10]   — hard rules (always loaded first)
  [ingest-registry][namespace:<ns>] — ingest tracking

## Priority

  5 (default) — general context
  7 — errors, guides, how-tos
  8–10 — must-not-miss: rules, constraints, landmines, key decisions
<!-- memorylayer:end -->
