v0.7.0 ships 6 of 6 of Batman's write-time-investment forms + the 7th (substrate-authority at write). All IMPLEMENTED. None active by default. This page is the operator-facing recipe to take a fresh install from Batman-capable to Batman-active — and make it survive reboot.
Batman is the published 6-form write-time-investment framework. Memory quality is set at WRITE time, not retrieval time. No amount of rerank fixes a substrate that ingested duplicates, un-atomized blobs, untyped facts, no provenance, no confidence, and no governance. ai-memory v0.7.0 implements all 6 + adds a 7th (substrate-authority over agent-EXTERNAL actions). On a default install the cognitive forms in the write path are on the moment you launch with --tier autonomous; the governance + namespace-policy forms are opt-in and need this recipe.
| Form | What it does | Default | Activation gate |
|---|---|---|---|
| Form 1 | Online dedup-and-synthesis (one batch action-emitting LLM call BEFORE write — add/update/delete/no-op verb vocabulary) | ACTIVE | Autonomous tier; on by default in MCP write path |
| Form 2 | Synchronous atomise-before-embed (source decomposed into atoms BEFORE embedding) | ACTIVE | On by default in MCP write path |
| Form 3 | Multi-step ingest orchestrator (prompt-cache reuse + explicit-trust deterministic-then-LLM helpers) | ACTIVE | On by default in MCP write path |
| Form 4 | Fact-provenance: citations field + source-as-URI + atom-grain span |
ACTIVE | Schema-level; always on at v0.7.0 |
| Form 5 | Auto-confidence + shadow-mode calibration + freshness decay | OPT-IN | Process env vars — AI_MEMORY_AUTO_CONFIDENCE=1 / AI_MEMORY_CONFIDENCE_SHADOW=1 / AI_MEMORY_CONFIDENCE_DECAY=1 — + curator daemon |
| Form 6 | MemoryKind vocabulary (Concept / Entity / Claim / Relation / Event / Conversation / Decision / Observation / Reflection / Persona) | OPT-IN | Per-namespace auto_classify_kind policy ("regex_then_llm" / "regex_only") + curator backfills |
| 7th | Substrate-authority at write — check_agent_action at Bash / Filesystem / Network / Spawn boundaries; refuses per signed operator rules |
OPT-IN | Operator key + R001–R004 signed + enabled |
Form 7 at v0.7.0 wires substrate-internal write paths (any caller of memory_store / memory_link / memory_delete / memory_archive / memory_consolidate / memory_replay). Agent-EXTERNAL Layer-4 (Bash / FilesystemWrite outside substrate / NetworkRequest / ProcessSpawn) is callable_now=false until the v0.8.0 harness-boundary wiring lands (#697). Operators can already enforce the same rules at the harness boundary themselves via a PreToolUse hook that shells out to ai-memory rules check.
A fresh v0.7.0 install with --tier autonomous --profile full running gives you Forms 1–4 the moment the MCP server boots. Everything else is dormant by design. The recipe below activates Forms 5, 6, 7 and makes the activation survive reboot.
Online dedup, synchronous atomise-before-embed, multi-step ingest, fact-provenance. Six cognitive transforms before a row hits SQL.
Form 5 freshness decay + shadow-mode are process env vars on the MCP server + curator daemon; Form 6 auto-classify is a per-namespace policy. Default off so operators choose the LLM-call surface.
Operator-signed seed rules R001–R004 ship in the table at enabled=0, attest_level='unsigned'. Until the operator signs + enables them, the governance gate is dormant.
Set the DB path once and the rest of the commands inherit it:
ai-memory rules keygen wrote the operator key to <config-dir>/operator.key while the mutation verbs only looked under <config-dir>/keys/. Fixed (#800 Gap #6 / #822): load_operator_signing_key_from_dir now resolves the key across all three layouts (legacy keys/operator.priv+.pub, staged keys/operator.key+.pub, and the parent-dir singleton keygen writes). No mv workaround is needed.
Without it, rules enable / disable / remove / add all refuse with governance.no_operator_key. Read-only verbs (list, check) work unsigned.
R001–R004 ship in the governance_rules table with enabled=0 and attest_level='unsigned'. sign-seed populates signature_b64 and lifts attest_level to operator_signed. It does not enable them.
Seed rules: R001 refuses filesystem_write under /tmp/**, R002 under /var/tmp/**, R003 under /private/tmp/** (macOS realpath), R004 refuses process_spawn of cargo when free disk is under 20 GiB.
enabled=0 → 1 per rule.--sign is mandatory for mutation verbs.
The curator runs Form 1 background dedup sweeps on rows the in-process write-path already saw, Form 5 freshness-decay sweeps, Form 6 auto-classify backfills, and Rule-5 consolidation. --max-ops caps LLM-invoking operations per cycle.
For permanence across reboot, skip this manual launch and use the OS service manager — see the next section.
Reflection memories from co-recalled Observation clusters.Per-namespace max_reflection_depth is enforced on top — --max-depth refuses to propose reflections that would exceed an operator-supplied cap so the curator never burns an LLM round-trip on a doomed write.
Form 5 lives on the MCP server + curator daemon process environment. Forms 2 + 6 live in a standard memory's metadata.governance, bound via memory_namespace_set_standard (MCP) or ai-memory namespace set-standard (CLI):
Operator key, signed/enabled rules, and namespace policies all live on disk or in SQLite and survive reboot. The curator daemon does not — it needs the OS service manager. The full plist / unit / scheduler XML lives in the markdown companion; here is the shape:
~/Library/LaunchAgents/dev.alphaone.ai-memory.curator.plist with RunAtLoad=true, KeepAlive on Crashed=true, ProcessType=Background, Nice=5. Load with launchctl bootstrap gui/$(id -u) ....
~/.config/systemd/user/ai-memory-curator.service, Restart=on-failure, RestartSec=30s, Nice=5. Pair with loginctl enable-linger $USER for headless hosts.
New-ScheduledTask -Trigger AtLogOn with -RestartCount 3, -RestartInterval 1m, -StartWhenAvailable.
Cloud-LLM key wiring. A service manager does not inherit your login-shell exports: launchd's GUI domain and systemd service units never see an OPENROUTER_API_KEY / XAI_API_KEY you export from ~/.zshrc. A curator daemon that can't resolve its key reports key_source=error and every cycle silently logs tagged=0. Prefer [llm].api_key_file = "…/openrouter-api.key" (mode 0400) in config.toml — env-independent and identical across launchd/systemd — or declare the key var inside the plist EnvironmentVariables dict / unit Environment= line.
The operator key on disk is left alone — keep it, rotate it via a fresh ai-memory rules keygen if you suspect compromise, or rm it if you genuinely want to retire the operator role on this node. Disabled rules remain in the database with signatures intact; enable flips them back on without re-signing.