ADR-2026-08-31-02 — Three continuity scopes
Status: Accepted
Date: 2026-08-31
Gap: G-01
Related: ADR-2026-08-31-01, ADR-2026-08-31-03
Context
packages/hermes-spine-memory models memory as two scopes:
export type MemoryScope = "personal" | "org"; // types.ts:29
The namespace header describes personal:user:{id} as holding "twin chat history, personal
notes" — one namespace holding two participants' continuity. routeTwinMemory() can only route
Twin into personal or org, so AI has no continuity of its own: its working memory is
stored inside the human's private namespace.
This violates the canon invariant directly. Personal Memory and AI Memory are supposed to be
separate from each other, and neither automatically becomes organizational truth. Today the first
half of that is untrue.
It also blocks Spine Agents (G-05), which cannot have per-agent memory
namespaces while the scope enumeration has no slot for a non-human participant.
Decision
Memory has three scopes, matching the three continuity domains:
| Scope | Holds | Owner |
|---|---|---|
org | Business Context / Organizational Memory — shared organizational reality and durable knowledge | Organization |
personal | Personal Contextual Memory — the human's private continuity | Human |
ai | AI Continuity Memory — AI's own continuing working memory | Twin, Spine Agents |
Twin's continuity moves out of the human's private namespace into its own.
The ai scope is subject-addressed like the others, so a Twin and each Spine Agent get distinct
namespaces rather than sharing one AI pool.
Governed promotion is the only path between scopes. Nothing crosses implicitly. This half is
already correct in code: services/pipeline/src/memory-promoter.ts never auto-promotes
AI-sourced writes into organizational memory — they land in staging pending approval. That
behaviour is preserved unchanged.
Implementation status — landed 2026-08-31
Implemented in packages/hermes-spine-memory:
MemoryScopewidened to"personal" | "org" | "ai", withMemorySubjectTypenaming the
subject each scope addresses (user/tenant/agent).resolveNamespaceand the newsubjectIdForScoperesolve the subject per scope and throw
when it is absent. A fallback would write one participant's continuity into another's database,
so absence is refused rather than defaulted.routeTwinMemorynow defaults Twin to its ownaicontinuity when anagentIdis known,
instead of falling intopersonalororg.- The
aiscope is subject-addressed, so a Twin and each Spine Agent get distinct namespaces. - 27 tests added (
namespaces.test.ts) — the package previously had none.
Round-trip bug fixed in passing. The path grammar was inconsistent: resolveNamespace produced
personal:user:{id} but parseNamespacePath treated user as part of the subject id, so
dbNameFromPath(ns.path) returned iw_mem_personal_user_abc while ns.dbName was
iw_mem_personal_abc — two different databases for one namespace. The grammar is now uniformly
{scope}:{subjectType}:{subjectId} and round-trips are asserted for all three scopes.
No migration is required — correcting an earlier assessment
An earlier draft of this ADR stated that a data migration was required, on the assumption that
existing personal:user:{id} namespaces held commingled human notes and Twin chat history. That
was wrong. Verified:
packages/hermes-spine-memoryhas zero consumers — only its ownpackage.jsonand
index.tsreference it. Nothing has ever written through it.services/continuityno longer uses CouchDB. Itswrangler.tomlbindsenv.DB(D1)
exclusively, andsrc/couchdb.tsno longer exists. TheCOUCHDB_*secrets in itsREADME.md
and inSERVICE_ARCHITECTURE_REPORT.mdare stale documentation.apps/web/lib/core/twin-memory/store.tsis an in-memoryMapimplementation, headed
"Production: Replace with Supabase or database backend."
So no CouchDB memory databases are provisioned, and AI continuity has no persistent home today
at all. This substrate is designed but unwired.
That makes now the cheapest possible moment to correct the scope model: the design is being fixed
before anything depends on it, at zero migration risk. It also reframes the gap — the problem was
never "AI memory sits in the wrong live namespace," it was "the three-domain model was designed
into a substrate that was never wired, with only two domains in it."
Consequences
- The privacy boundary is now structural: a human's personal namespace cannot accumulate AI
working state, because theaiscope refuses to resolve against auserId. - Unblocks
G-05— Spine Agents can hold identity plus an addressable
memory namespace. - A migration becomes required the moment this substrate is wired to a live store. This ADR
records that it is not required now; that changes as soon as anything writes through it. - Stale CouchDB references in
services/continuity/README.mdandSERVICE_ARCHITECTURE_REPORT.md
should be corrected, so the next reader does not conclude a CouchDB deployment exists.
Not decided here
Promotion rules between the three scopes — what qualifies AI continuity or personal context for
promotion into organizational memory, and under whose authority. The existing seven promotion
signals cover Spine → Org Memory. Scope-to-scope promotion needs its own decision.