From store to archived (or purged) — every state a memory can hold, every transition between them, every MCP tool that drives the change. Six stages. One narrative. The lifecycle that makes "memory that doesn't drown you" possible.
An illustrative example: a memory enters at Mid tier, gets accessed twice (each access bumps the TTL), gets linked to a related memory, gets consolidated with siblings into a Long-tier retro, the original ages into the archive, and finally gets purged after a 30-day compliance window.
memories. Validators run, governance gate runs, federation fanout writes to W of N peers, FTS5 indexes the title+content, HNSW vector inserted (if embedder loaded). The created_at timestamp is permanent — it never updates after this.memory_get, recall hit, and search hit bumps access_count and last_accessed_at. Mid-tier memories also get their expires_at bumped forward by mid_extend_secs (default 1 day). Memories that get used earn more time. Updates (memory_update) preserve created_at but bump updated_at. KG edges added via memory_link at any time.memory_consolidate takes 2-100 source memories and produces a derived memory (LLM-summarized at smart/autonomous tier, plain-text-concatenated at lower tiers). Each source gets a derived_from KG edge to the new memory — provenance chain stays intact even though the consolidated row is the canonical one going forward.memory_promote moves a memory from Mid to Long, clearing expires_at and routing through governance. Outcomes: Allow → promoted immediately. Pending(id) → queued for approval; replays automatically once approved. Deny(reason) → 403 with the reason.memories and lands in archived_memories with full metadata + a reason ("ttl_expired" / "manual" / "forget_pattern"). FTS index updated; HNSW vector evicted. Recall + search exclude archived rows. Restorable via memory_archive_restore until purged.archived_memories. No way back. Federation fanout removes peer copies. Useful for compliance regimes that require erasure after a defined retention window — soft-delete first, hard-delete on a schedule.memory_archive_restore brings an archived row back to memories. expires_at is cleared on restore so a stale timestamp doesn't immediately re-expire. FTS5 + HNSW are rebuilt for the row.expires_at = NULL. GC's WHERE expires_at < now() never matches it. Only explicit memory_delete or memory_forget ever removes it.memory_delete + archive_on_gc=false in config produces irreversible erasure on the spot. Rare; usually only seen in regulated environments where archive itself is considered retention.memory_forget sweeps a namespace + FTS pattern + optional tier filter. Each match goes through stage 5 (archived). Use the broom when you don't want to wait for TTL.created_at preserved. Validators run again on the receiver — peer trust is at the mTLS layer, but content correctness is locally re-verified.There is no stage transition that doesn't write something queryable. Operators (or auditors) can reconstruct the full history of any memory by joining a few tables.