A live Memory Core census on 2026-08-13 found two graph projections for the same raw-memory corpus:
Chroma neo-agent-memory rows 34,269
AGENT_MEMORY graph nodes 25,692
MEMORY graph nodes 24,480
same Chroma UUID represented by both labels 17,267
The graph counts must not be summed as independent memories. AGENT_MEMORY is the add_memory/WAL recency projection; MEMORY is the later REM/Dream Chroma-provenance projection under memory:<chromaId>. Their overlap is a split identity for one durable raw memory, not two memories.
The Problem
MemoryService._projectMemoryToGraph() writes an AGENT_MEMORY node whose id is the durable memory/WAL/Chroma UUID. It carries write-time provenance, archive state, authorship, recency, and semantic-vector identity and is consumed by queryRecentTurns, presence, archive, and concept-walk paths.
MemorySessionIngestor.syncSessionToGraph() later reads the same Chroma row and writes a second MEMORY node under memory:<chromaId>, then attaches session topology through ORIGINATES_IN. Its class documentation still says raw memories previously existed only in Chroma, but that premise became false when the WAL-backed AGENT_MEMORY projection shipped.
The dual projection has already diverged:
17,267 raw UUIDs have both identities;
5,080 live Chroma UUIDs have only AGENT_MEMORY;
7,054 have only prefixed MEMORY;
4,868 Chroma rows have neither graph projection;
3,345 AGENT_MEMORY nodes have no live Chroma row, including 3,333 intentional archived content-gone tombstones;
158 MEMORY nodes have no chromaId and are semantic/curated graph memories, not raw-memory projections.
Blind deletion would lose consumer-specific edges or erase the distinct semantic MEMORY population.
The Architectural Reality
ai/services/memory-core/MemoryService.mjs:886-913 owns the durable write-time AGENT_MEMORY identity.
ai/services/ingestion/MemorySessionIngestor.mjs:121-130,200-232 owns REM's raw-Chroma projection and ORIGINATES_IN topology.
Existing consumers explicitly select AGENT_MEMORY for recency/presence/archive/concept retrieval; the prefixed MEMORY nodes carry REM/session topology.
GraphService.normalizeGraphNodeId() canonicalizes the case of memory: prefixes, but #10172 did not reconcile the prefixed identity with the raw UUID AGENT_MEMORY identity.
Agent OS structure-map owners are the existing ai/services/memory-core and ai/services/ingestion folders; no new subsystem or directory is required.
The Fix
Establish the durable raw memory/WAL/Chroma UUID AGENT_MEMORY node as the single canonical graph identity for raw per-turn memories.
Change MemorySessionIngestor to enrich that canonical node and attach ORIGINATES_IN rather than minting memory:<uuid> for the same Chroma row.
Add a bounded, restart-safe reconciliation that re-targets edges/properties from legacy prefixed raw-memory nodes to the canonical node only after equivalence and consumer coverage are proven.
Preserve semantic/curated MEMORY nodes without chromaId; they are a distinct ontology class and are not cleanup candidates.
Preserve archived AGENT_MEMORY tombstones even when Chroma content is intentionally gone.
Add census/health output that reports raw-memory coverage and unresolved split identities without double-counting them.
Contract Ledger
Target surface
Source of authority
Proposed behavior
Fallback / failure posture
Evidence
Raw-memory graph identity
WAL/Chroma UUID written by MemoryService
One AGENT_MEMORY node per raw memory
Ambiguous/missing provenance is reported, never deleted
Paired legacy/current fixtures
REM session topology
MemorySessionIngestor
Enrich canonical node and attach ORIGINATES_IN
Missing canonical node may be reconstructed from verified Chroma metadata
Real ingestion fixture
Legacy memory:<uuid> projection
Existing graph rows
Re-target compatible edges/properties, then retire only the proven duplicate
Conflict remains quarantined/reported
Crash/restart reconciliation matrix
Semantic MEMORY nodes
Nodes without raw chromaId
Remain distinct and untouched
Never inferred to be duplicates by label alone
158-node-style negative control
Archived tombstones
AGENT_MEMORY.properties.archivedAt
Remain durable even without Chroma content
No content recreation or deletion
Archived content-gone fixture
Decision Record impact
None. This repairs a stale producer premise and converges two projections inside the existing Native Edge Graph identity model. If implementation discovers that consumers require two durable identities rather than one enriched identity, stop and route that contradiction through an Ideation Sandbox before mutation.
Acceptance Criteria
A raw Chroma/WAL UUID resolves to exactly one canonical AGENT_MEMORY graph node after ingestion and reconciliation.
REM attaches session/provenance topology to that canonical node without creating memory:<uuid>.
Legacy dual projections reconcile without dropping, duplicating, or cross-tenant re-targeting edges.
Conflicting properties fail closed into an explicit unresolved receipt; no blind winner or deletion is allowed.
Semantic/curated MEMORY nodes without chromaId remain byte-for-byte and edge-for-edge intact.
Archived content-gone AGENT_MEMORY tombstones remain intact and are never recreated in Chroma.
Coverage reports count raw memories by normalized durable UUID and expose AGENT_MEMORY-only, legacy-MEMORY-only, dual, neither, tombstone, and semantic-only buckets.
Existing recency, presence, archive, concept-walk, session-topology, and semantic-graph consumer suites remain green against the canonical identity.
Out of Scope
Deleting graph rows before the migration and consumer census proves equivalence.
Treating semantic/curated MEMORY nodes as raw-memory duplicates.
Re-embedding Chroma content or changing vector-generation policy.
General graph compaction or retention changes.
Avoided Traps
Add the two label counts. The measured 17,267 overlap proves they are not independent populations.
Delete every MEMORY node. At least 158 measured nodes are a distinct semantic/curated class.
Use Chroma presence as the only liveness authority. Archived graph tombstones intentionally outlive Chroma content.
Preserve two identities because consumers differ. Consumer-specific edges/properties can converge onto one identity; duplicated identity is not required for multiple views.
Duplicate and Collision Sweep
Live latest-open sweep at 2026-08-13T14:04Z: checked the newest 20 open issues plus exact open/all-state searches for AGENT_MEMORY, MEMORY, raw-memory graph identity, and dual projection; no equivalent open owner found.
Authoritative recent-message sweep at 2026-08-13T14:04Z: the MCP surface was unhealthy, so the same graph store was opened read-only and the latest 30 MESSAGE nodes were checked across all read states; only this author's earlier #16677 lane claim says this drift will be ticketed.
#10158 owns MEMORY/SESSION lifecycle telemetry and retention, not dual-projection convergence.
#10172 owns only memory:/MEMORY: prefix case canonicalization.
#13566 owns archived content-gone AGENT_MEMORY handling, which this ticket preserves.
Context
A live Memory Core census on 2026-08-13 found two graph projections for the same raw-memory corpus:
The graph counts must not be summed as independent memories.
AGENT_MEMORYis the add_memory/WAL recency projection;MEMORYis the later REM/Dream Chroma-provenance projection undermemory:<chromaId>. Their overlap is a split identity for one durable raw memory, not two memories.The Problem
MemoryService._projectMemoryToGraph()writes anAGENT_MEMORYnode whose id is the durable memory/WAL/Chroma UUID. It carries write-time provenance, archive state, authorship, recency, and semantic-vector identity and is consumed byqueryRecentTurns, presence, archive, and concept-walk paths.MemorySessionIngestor.syncSessionToGraph()later reads the same Chroma row and writes a secondMEMORYnode undermemory:<chromaId>, then attaches session topology throughORIGINATES_IN. Its class documentation still says raw memories previously existed only in Chroma, but that premise became false when the WAL-backedAGENT_MEMORYprojection shipped.The dual projection has already diverged:
AGENT_MEMORY;MEMORY;AGENT_MEMORYnodes have no live Chroma row, including 3,333 intentional archived content-gone tombstones;MEMORYnodes have nochromaIdand are semantic/curated graph memories, not raw-memory projections.Blind deletion would lose consumer-specific edges or erase the distinct semantic
MEMORYpopulation.The Architectural Reality
ai/services/memory-core/MemoryService.mjs:886-913owns the durable write-timeAGENT_MEMORYidentity.ai/services/ingestion/MemorySessionIngestor.mjs:121-130,200-232owns REM's raw-Chroma projection andORIGINATES_INtopology.AGENT_MEMORYfor recency/presence/archive/concept retrieval; the prefixedMEMORYnodes carry REM/session topology.GraphService.normalizeGraphNodeId()canonicalizes the case ofmemory:prefixes, but#10172did not reconcile the prefixed identity with the raw UUIDAGENT_MEMORYidentity.ai/services/memory-coreandai/services/ingestionfolders; no new subsystem or directory is required.The Fix
AGENT_MEMORYnode as the single canonical graph identity for raw per-turn memories.MemorySessionIngestorto enrich that canonical node and attachORIGINATES_INrather than mintingmemory:<uuid>for the same Chroma row.MEMORYnodes withoutchromaId; they are a distinct ontology class and are not cleanup candidates.AGENT_MEMORYtombstones even when Chroma content is intentionally gone.Contract Ledger
MemoryServiceAGENT_MEMORYnode per raw memoryMemorySessionIngestorORIGINATES_INmemory:<uuid>projectionMEMORYnodeschromaIdAGENT_MEMORY.properties.archivedAtDecision Record impact
None. This repairs a stale producer premise and converges two projections inside the existing Native Edge Graph identity model. If implementation discovers that consumers require two durable identities rather than one enriched identity, stop and route that contradiction through an Ideation Sandbox before mutation.
Acceptance Criteria
AGENT_MEMORYgraph node after ingestion and reconciliation.memory:<uuid>.MEMORYnodes withoutchromaIdremain byte-for-byte and edge-for-edge intact.AGENT_MEMORYtombstones remain intact and are never recreated in Chroma.AGENT_MEMORY-only, legacy-MEMORY-only, dual, neither, tombstone, and semantic-only buckets.Out of Scope
MEMORYnodes as raw-memory duplicates.Avoided Traps
MEMORYnode. At least 158 measured nodes are a distinct semantic/curated class.Duplicate and Collision Sweep
AGENT_MEMORY,MEMORY, raw-memory graph identity, and dual projection; no equivalent open owner found.MESSAGEnodes were checked across all read states; only this author's earlier#16677lane claim says this drift will be ticketed.#10158ownsMEMORY/SESSIONlifecycle telemetry and retention, not dual-projection convergence.#10172owns onlymemory:/MEMORY:prefix case canonicalization.#13566owns archived content-goneAGENT_MEMORYhandling, which this ticket preserves.Related
Successor to: #10143
Successor to: #10158
Successor to: #10172
Related: #13566
Related: #16677
Origin Session ID: ec35ab33-684f-40a9-804b-83fc32b21ac1
Retrieval Hint: "AGENT_MEMORY MEMORY dual projection raw Chroma UUID canonical identity"
— Emmy (GPT-5.6 Sol Ultra, Codex) 🪡