# Cross-tool memory guarantees — design sketch

**Status:** Sketch, not approved. Captured 2026-05-11 during operational audit.
**Companion docs:** `session-checkpoint-axiom-memory-mcp.md`, `/Users/ben/.claude/projects/-Users-ben-Projects-UT-Computational-NE/memory/project_axi_memory_failure_modes_and_selfheal.md`
**Scope:** What it takes for *any* tool integration (Claude Code, Codex, JetBrains, VS Code, Gemini, ChatGPT Desktop) to be guaranteed-active for memory and to minimize context loss on unexpected restart.

---

## The two guarantees

1. **Active-memory guarantee** — any integrated tool always has a live, registered, writable axiom-memory MCP available to its model loop, *or* a transcript-ingest backstop covering it when the model loop can't reach MCP.
2. **Restart-safety guarantee** — an unexpected host restart (VS Code reboot, OS update, kernel panic, OOM) loses at most bounded context: prior turns survive in the ledger, new sessions resume warm.

Neither guarantee falls out of any single mechanism. Both come from defense in depth across five layers.

## Five loss surfaces

| # | Loss surface | Coverage today | Gap |
|---|---|---|---|
| 1 | MCP unregistered after install/upgrade | claude-code: `register-mcp` + `axi dr` check | no codex/jetbrains/vscode/gemini registrars |
| 2 | Tool registered, handshake stale | none | silent — model thinks MCP works |
| 3 | Model never calls `append` | claude-code: JSONL ingest backstop, foreground only | no daemon; nothing for tools without on-disk transcripts |
| 4 | New session starts cold (no resume) | MCP `instructions` field nudges model to call `recent` | no automatic injection of recent fragments at session start |
| 5 | Long-running silent stop | none | no heartbeat — `axi dr` cannot tell |

## Layered architecture

```mermaid
flowchart TD
  L0[L0 Substrate<br/>CompositionService · audit.jsonl · SQLite · idempotent source_uuid]
  L1[L1 Per-tool registrars<br/>claude-code · codex · jetbrains · vscode · gemini]
  L2[L2 Backstop daemon<br/>launchd/systemd · watches transcript paths · hourly heartbeat]
  L3[L3 Liveness contract<br/>MCP instructions + list_tools probe in axi dr]
  L4[L4 Resume-on-start hook<br/>injects axiom_memory_recent at session start]
  L5[L5 Self-heal<br/>principal-pin reconcile · file-watch · audit replay · RACI]

  L0 --> L1
  L1 --> L2
  L1 --> L3
  L2 --> L4
  L3 --> L5

  style L0 fill:#d4edda,color:#000
  style L1 fill:#fff3cd,color:#000
  style L2 fill:#fff3cd,color:#000
  style L3 fill:#fff3cd,color:#000
  style L4 fill:#fff3cd,color:#000
  style L5 fill:#e1e4e8,color:#000
```

Green = shipped. Yellow = new for this design. Grey = already designed in a follow-on note (see `project_axi_memory_failure_modes_and_selfheal.md`).

## Reuse of core axiom architecture

The design organizes existing capability kinds — it doesn't invent new ones. Every layer maps to an existing AEOS kind, and every "seam" first sketched in this doc collapses onto an existing primitive (RPE, the 4-scope policy engine, RAG hybrid search, the artifact registry, the prompt registry, the trust graph).

### AEOS capability-kind mapping

| Layer / element | AEOS kind |
|---|---|
| SCAN, TIDY, TRIAGE | `agent` |
| `axiom_memory_*` MCP tools | `tool` |
| `axi memory` subcommands | `cmd` |
| L2 ingest daemon | `service` |
| Per-tool transcript parsers (claude-code, codex, jetbrains, vscode, gemini, chatgpt-desktop) | `adapter` |
| L4 resume-on-start hooks | `hook` |
| Per-tool resume skill | `skill` (TBD) |

Six of seven AEOS kinds used. Each per-tool integration is `axi ext init <tool>` away with a declared `axiom-extension.toml` manifest, not a bespoke project.

### MIRIX cognitive-type tagging

Not every write is `episodic`. The L0 write path tags fragments with their cognitive type so downstream queries (RPE, RAG) can scope correctly:

| Write source | MIRIX type |
|---|---|
| L2 transcript ingest, MCP `append` per-turn | `episodic` |
| Provider-memory mirror (e.g., Anthropic memory tool, Cursor) — extracted facts | `semantic` |
| Sensitive content flagged by policy | `vault` |
| Identity / principal facts | `core` |
| How-to / skill content (rare today) | `procedural` |
| File / artifact references | `resource` |

### Primitive reuse per layer

| Layer | Reused primitive | What that gives us |
|---|---|---|
| L2 privacy filter on transcripts | 4-scope policy engine | scope-based deny rules, sensitive-content routing |
| L3 MCP `instructions` payload | prompt registry | versioning, eval, per-tool swap |
| L2 daemon state (position, lag, last error) | artifact registry | observable state SCAN + TRIAGE can read |
| L4 resume hydration | RPE intent (e.g., `resume.task_context`) + RAG hybrid search | relevance + recency mix, addressable via `axiom://` URIs |
| L5 escalate-vs-auto-fix decision | policy engine | escalation thresholds declarative, not coded |
| L5 peer reputation in A2A phase | trust graph (ADR-028) | EigenTrust-style peer trust, dispute resolution |
| TIDY retention | policy engine (importance-weighted scope) | importance + age + size as one rule set |

The implication: cross-tool memory work is mostly **wiring**, not **invention**. The only genuinely new things across all seven layers are (a) per-tool adapter parsers (claude-code shipped; five stubs to fill in) and (b) one schema field — see §Classifier-pluggable seam.

## Where each guarantee comes from

**Active-memory guarantee** is delivered by L1 + L3 for MCP-capable tools, and L2 for transcript-only tools. Editor-side inline AI with no persistent transcript (some Copilot inline modes) is **unaddressable without tool cooperation** — must be documented as an explicit limit.

**Restart-safety guarantee** is delivered by:
- per-turn `append` discipline (L3 soft-pushes the model)
- L2 daemon folding any turns the model missed (idempotent on `source_uuid`)
- L4 hook injecting `recent` into the new session at start
- L5 heartbeat making silent stops visible in `axi dr`

## Three windows of work

1. **Today (cheap, low-risk operational):**
   - Idempotent re-ingest of recent Claude Code transcripts to close the live ledger gap
   - `axi agents start` (and fix the LLM-gateway provider gap separately)
   - File the `axiom_memory_search`-without-`principal_id` empty-result anomaly
2. **First post-delivery-window sprint:** L2 daemon + L5 #1 heartbeat. Single highest-leverage piece — closes the model-discipline gap and silent-daemon-stop for any tool with on-disk transcripts.
3. **Milestone-sized:** L1 multi-tool registrars (codex first — already validated via the green-dragon/purple-unicorn cross-tool test) and L4 resume-on-start hook (per-host hook surface investigation).

## Per-tool integration matrix (draft)

| Tool | MCP-native | On-disk transcript | Session-start hook | Notes |
|---|---|---|---|---|
| Claude Code | yes | yes (`~/.claude/projects/.../*.jsonl`) | yes (`SessionStart`) | reference implementation |
| Codex | yes | yes (TBD path) | TBD | bidi memory already validated |
| JetBrains AI | via MCP plugin (TBD) | TBD | TBD | needs plugin survey |
| VS Code Copilot Chat | via MCP extension (TBD) | TBD | TBD | inline-mode likely unaddressable |
| Gemini CLI | yes (when MCP-enabled) | yes (TBD) | TBD | parser stub exists |
| ChatGPT Desktop | no MCP | yes (TBD path) | no | L2-only coverage |

## Reconciliation with provider memory

axiom-memory is canonical master per ADR-026; provider memory is a **peer with delegated rights**, never a competing master. Reconciliation is sync, not competition.

| Provider | Memory surface | Access | Bridge strategy |
|---|---|---|---|
| Anthropic Claude (memory tool, 4.x) | sandboxed FS in-conversation | model-callable tool | **Proxy MCP** — wrap memory_tool calls; mirror writes to axiom; serve reads from axiom when project context matches |
| OpenAI ChatGPT memory | opaque server-side | none (UI only) | **out of scope** — document as unaddressable until API opens |
| Google Gemini memory | opaque server-side | none | same as ChatGPT |
| Cursor memories | `.cursor/` files | filesystem | **L2 ingest** with parser |
| Codex CLI | `~/.codex/` + JSONL | filesystem | **L2 ingest** (parser stub exists) |
| GitHub Copilot Chat | session-only, no persistence | none | **L2 if transcript exists**, else unaddressable |
| JetBrains AI Assistant | per-plugin TBD | TBD | survey before commitment |

One-liner: **provider memory = fast local cache; axiom-memory = durable canonical ledger; the bridge is a sync.**

For tools whose memory is opaque server-side, the honest position is: no guarantee. A false guarantee is worse than a documented limit.

## How A2A changes the architecture

A2A reframes "build N per-tool registrars" as "advertise one capability set; agents discover and subscribe."

```mermaid
flowchart TD
  AM[axiom-memory<br/>canonical master · A2A peer]
  CC[Claude Code agent]
  CX[Codex agent]
  JB[JetBrains AI agent]
  VS[VS Code agent]
  PM[Provider memory peers<br/>Anthropic · Cursor · Codex local]

  CC -- A2A subscribe --> AM
  CX -- A2A subscribe --> AM
  JB -- A2A subscribe --> AM
  VS -- A2A subscribe --> AM
  AM -- recent · hydrate-on-resume --> CC
  AM -- recent · hydrate-on-resume --> CX
  PM -. federated peer · delegated rights .-> AM

  style AM fill:#d4edda,color:#000
  style CC fill:#cfe2ff,color:#000
  style CX fill:#cfe2ff,color:#000
  style JB fill:#cfe2ff,color:#000
  style VS fill:#cfe2ff,color:#000
  style PM fill:#fff3cd,color:#000
```

A2A's contributions:

1. **Discovery replaces registrars.** Cohort registry; no per-tool config writer.
2. **Subscriptions replace polling.** Agent loop publishes turn events; axiom subscribes. Closes the model-discipline gap structurally — the *agent loop* publishes whether or not the *model* called `append`.
3. **Capability negotiation gives the guarantee teeth.** A tool advertises `memory.write per turn`; `axi dr` verifies via signed A2A traffic, not best-effort inspection.
4. **Multi-sig provenance answers "who wrote this?"** Every fragment carries a signed chain (tool, user, agent, runtime).
5. **Federation handles provider peers natively.** Anthropic's memory tool = federated peer with delegated rights, not a special-case shim.

L1–L5 restated in A2A terms:

| Layer | Pre-A2A | A2A-native |
|---|---|---|
| L1 registrars | per-tool config writers | cohort discovery, no writers |
| L2 daemon | polls transcript paths | subscribes to turn events |
| L3 liveness | `list_tools` roundtrip in `axi dr` | A2A capability heartbeat |
| L4 resume hook | session-start hook injects `recent` | agent subscribes to `memory.recent` at start; auto-hydrates |
| L5 self-heal | principal-pin reconcile + file-watch | multi-sig chain verification + trust-graph dispute |

Transition path: build the proxy + L2 daemon for what exists today; migrate to A2A as more tools become A2A peers. L2 isn't replaced by A2A — it *becomes* A2A once the ecosystem catches up.

## Resilience moves

Resilience is what the system does when **its own parts** fail — distinct from the loss-surface table above. Eight moves, by leverage:

1. **Audit log is source of truth; SQLite is a rebuildable view.** WAL-style append with fsync; SQLite rebuilds from audit on corruption. Promote from theoretical to tested code path.
2. **Local write-queue with retry.** When MCP/daemon unreachable, tool writes to `~/.axi/queue/<uuid>.json`; next reachable session drains.
3. **Hash-chained fragments.** Each fragment carries `prev_hash`. Tamper-evident; bad fragments quarantinable.
4. **Multi-tier liveness watchdog.** MCP → hourly heartbeat. Daemon → checks heartbeat freshness. launchd/systemd KeepAlive → checks daemon. Push notification → when outermost tier fails.
5. **Ledger replication to a second peer.** Personal cohort = laptop + desktop + optional trusted cloud peer. CRDT-merge on conflicts. Survives single-host disk loss.
6. **Capability isolation per principal/cohort.** Misbehaving tool corrupts only its own scope.
7. **Backpressure, not silent drop.** L2 daemon lag emitted in heartbeat metadata; SCAN flags lag > threshold.
8. **Tested rebuild drill.** Monthly `axi dr --drill` rebuilds SQLite from audit in a temp dir and diffs.

Unifying principle: **every failure is either auto-recoverable (1, 2, 5) or loudly visible (4, 7, 8). No silent loss.**

## Axiom agent allocation

| Agent | Memory-resilience role |
|---|---|
| **SCAN** (diagnostics) | **highest immediate leverage.** Promote `axi dr` from one-shot to always-on. Owns heartbeat-freshness, principal-pin reconcile, MCP liveness probe, daemon lag, audit/SQLite divergence detection. Closes resilience moves #4 and #7. |
| **TIDY** (hygiene) | audit-log compaction, SQLite vacuum, duplicate-source_uuid tombstoning, expired-fragment GC. Service exists; redirect job list at memory. |
| **TRIAGE** | escalation bridge when self-heal can't auto-fix (RACI-escalate, self-heal #6). |
| **WARDEN** (Vega) | A2A multi-sig phase: signature-chain verification, peer impersonation detection, trust-graph dispute. Design target, not immediate — Vega is pre-extraction. |
| AXI | orchestrates the loop. |
| PRESS, CURIO, CHALKE | not memory-resilience work. |

**Resilience loop:**

```
SCAN (detect drift) ──► TRIAGE (escalate if unfixable) ──► operator action
            │
            └─► TIDY (routine compact / vacuum / dedup)

[post-A2A]  WARDEN verifies signatures on every cross-peer write
```

**Immediate pick: SCAN, now.** Single agent whose extension delivers the most resilience per unit of work. Catches the silent-stop class structurally — not by hope. TIDY runs alongside. TRIAGE comes online once SCAN has detections worth escalating. WARDEN is the long-arc target for the A2A phase.

## Classifier-pluggable seam

The only genuinely new interface across the whole design is one optional schema field:

| Seam | Default today | Pluggable for |
|---|---|---|
| `fragment.classification` (optional, versioned) | unset / null | sensitivity score, importance, topic tags, derived facts |

A classifier produces signals; those signals **feed existing primitives** — RPE intents for ranking, 4-scope policy for filtering, MIRIX type promotion (`episodic → semantic`), retention policy for importance-weighted GC. See §Reuse of core axiom architecture.

Memory core stays classifier-agnostic; no classifier code or import in `src/axiom/memory/`. The classifier is named only when (and if) it's brought into official production; until then the field sits dormant.

## Decision points to lock before implementing

- Strictness of "guaranteed": strict (per-turn attestable, requires A2A multi-sig) vs strong (eventual, bounded delay) vs pragmatic (no gap > 1h).
- Daemon scope: per-user launchd/systemd unit only, or also a foreground fallback in `axi chat` startup?
- Registrar surface: `axi memory register-mcp --tool <t>` per tool, or a unified `axi install --with-memory` that fans out?
- Privacy boundary: does L2 respect a per-tool deny-list for transcript paths (e.g., projects flagged sensitive)?
- Provider-bridge proxy: where does it live — a shim MCP that fronts both, or two registered MCPs with a sync agent?
- Replication topology: laptop ↔ desktop only, or include a hosted trusted peer?

---

_Draft sketch. Implementation queued behind the current delivery window per `feedback_freeze_foundation_during_delivery`._
