ADR-056: T3 Memory → Worlds routing — `t3_memory_written` event with worlds-local projection
Status: Accepted (2026-04-25) — D3’s SQL grant worlds_t3_reader removed by ADR-063; D3 Protocol-vs-projection sub-decision resolved by ADR-064 D3 (broadened 2026-04-30) in favor of event-driven worlds-local projection; no T3MemoryReader Protocol minted.
Read mechanism superseded by ADR-064 D3. D2’s opaque-pointer payload framing remains, with body content riding the ADR-044 D11 additive payload extension so worlds-side projection does not require a separate body-fetch path.
Context
ADR-018 establishes three-tier memory (T1 short-term in-conversation; T2 working per-session; T3 long-term durable) feeding world-model generation. T3 owner emits memories that feed Worlds for world-model evolution. ADR-058 (TA-12 World Agent memory) and ADR-059 (TA-13 Ops Agent memory) own the storage shape (schema, retention coupling, anchor entities). This ADR disposes the protocol shape — how T3 events reach Worlds, where filtering lives, what auth pattern applies between contexts. Storage details slot in cleanly behind opaque pointers.
Decision
D1 — Push from T3 owner; Worlds applies relevance filter on consume
T3 owner emits t3_memory_written events via the ADR-044 substrate; Worlds consumes; Worlds applies the relevance filter on consume. Push model — not pull-based polling.
Reasoning:
- ADR-044 substrate alignment (LISTEN/NOTIFY + outbox is the event path between contexts)
- Semantic coupling — what counts as “world-gen-relevant” — stays in Worlds where world-model logic lives. Pushing that knowledge into the T3 owner forces semantic spillover across the context boundary.
- T3 owner stays simple — emits “memory was written” as a pure fact.
- Volume concern is deferred — alpha-scale T3 writes are trivial for the substrate; substrate-swap triggers (ADR-044 D15: 5M outbox rows) are far away.
D2 — Payload: opaque pointers
class T3MemoryWrittenPayload(BaseModel): memory_id: UUID embedding_id: UUID workspace_id: UUID recorded_at: datetimeThe payload deliberately carries no memory content — Worlds fetches the actual memory + embedding from T3 storage via the read mechanism between contexts (D3, as reframed by ADR-063). This decouples T3’s storage schema from TA-8’s protocol contract. ADR-058 / ADR-059 may evolve T3’s row shape, retention semantics, or embedding storage strategy without affecting TA-8’s wire format.
D3 — Read of memory body across contexts — superseded by ADR-064 D3
SQL grant superseded by ADR-063; Protocol-vs-projection choice resolved by ADR-064 D3 (broadened 2026-04-30). The original D3 specified a worlds_t3_reader SELECT-only role grant on T3 memory tables; ADR-063 removed inter-context SQL grants. ADR-064 D3 settled the Protocol-vs-projection question in favor of event-driven worlds-local projection: no T3MemoryReader Protocol is minted; worlds consumes via platform.t3_memory.written event + worlds-local projection.
The opaque-pointer payload from D2 evolves under additive-only versioning per ADR-044 D11: under the projection design, the event payload carries enough body content for worlds-side projection without requiring a separate body-fetch path. Producer-side AC + payload-shape evolution owned by SPEC-242; worlds-side projection consumer + replica table owned by SPEC-238.
Context discipline preserved structurally: worlds consumer code (in src/spectral/worlds/) never imports spectral.platform.*; the worlds-side consumer subscribes to the event substrate per ADR-065 D2 + D4 (consumer ACL pattern) and projects into a worlds-local table; reads from that local table are intra-context.
D4 — Consumer invariant: Worlds retains non-promoted memories in observation pool
Structural property of Worlds as a consumer. “Consumed and forgotten” is not a permitted handler outcome. Memories that don’t immediately promote to rule candidates are retained in a Worlds-internal observation pool that accumulates evidence over time toward eventual rule promotion or dismissal per Worlds’ evolution-loop semantics.
Worlds-side handler flow (illustrative; updated for ADR-064 D3 projection):
- Consume
platform.t3_memory.writtenevent; parse with worlds-local ACL model per ADR-065 D4. - Project into worlds-local replica table (sized for evolution-loop needs); body content carried in the event payload per ADR-064 D3 (no separate fetch).
- Apply Worlds-side relevance filter:
- Clearly world-gen-relevant + sufficient evidence → promote to rule candidate.
- Clearly world-gen-relevant + insufficient evidence → add to observation pool with provenance metadata.
- Ambiguous → add to observation pool; lean toward retention.
- Clearly not relevant → discard (audit-record optional).
- Observation pool gains evidence over time; periodic re-evaluation may promote.
- Stale observations expire per ADR-042 retention policy.
TA-8’s commitment is the structural property. Schema, retention policy, embedding-index strategy, and re-evaluation cadence are world-model implementation work — not TA-8’s protocol-shape scope.
D5 — TA-12/13 coupling acknowledgment
T3’s storage shape — schema name (likely platform.t3_* but specifics in implementation), table layout, agent-ownership semantics, retention coupling, embedding-pointer relationship to TA-11 retrievable tables — is ADR-058 / ADR-059 territory. TA-8 commits only to the protocol shape: events flow via ADR-044; payload is opaque pointers; Worlds reads via DI-injected reader.
When ADR-058 / ADR-059 schemas land in implementation epics:
- The actual T3 read API (whether
T3MemoryReader.fetch_bodyqueriesplatform.spectral_agent_memorydirectly, via a view, or via aggregated read across multiple tables) is settled in the implementation. - A T3-side type pre-filter at the publisher (volume tuning) may be added — orthogonal to wire format.
D6 — Embedding strategy: per ADR-038 D9 retrievable-table convention
T3 embeddings live in retrievable tables per ADR-038 D9. Worlds may re-embed for its own observation-pool index using the same canonical embedding profile (ADR-038 D2/D3) — same vector space, hybrid retrieval works (ADR-038 D8 RRF). No re-embedding required if the Worlds observation index reuses T3’s stored embedding directly via the embedding_id pointer.
Alternatives considered
Pull-based: Worlds polls T3 with cursor/watermark. Rejected; polling overhead; cursor management complexity; doesn’t fit the ADR-044 substrate; reactive lag.
Push with T3-side relevance filter. Rejected; couples Worlds’ world-gen semantic to the T3 owner; semantic spillover across the context boundary; T3 doesn’t have world context to decide relevance.
Embed memory content in event payload. Rejected; couples wire format to T3 storage shape; payload size grows with memory size; opaque-pointer pattern is cleaner.
No observation pool (“consumed and forgotten” allowed). Rejected; defeats evidence accumulation; misaligns with evolution-loop semantics.
Combined T3 + failure-cluster signal. Rejected; TA-8 and TA-9 are distinct evidence streams; Worlds aggregates them downstream; protocol-level coupling would force schema gymnastics.
Inter-context SQL grant for body fetch (the original D3). Superseded by ADR-063; Option B (DI-injected reader) is the worked replacement.
Consequences
- Protocol shape decidable independently of T3 storage details.
- ADR-058 / ADR-059 storage decisions slot in cleanly behind the opaque-pointer payload.
- Semantic coupling stays in Worlds where world-gen logic lives.
- ADR-044 substrate native — no new infrastructure.
- Observation pool consumer invariant preserves evolution-loop semantics.
- Worlds must fetch memory content per event (extra DI call; acceptable at alpha volume).
- Filter logic in Worlds may discard memories the T3 owner already considered “potentially relevant” (acceptable; volume tuning available later via T3-side type pre-filter).
- If ADR-058 / ADR-059 schemas land with embedding stored inline (instead of separate-pointer pattern), the payload shape needs revision — schema bump per ADR-044 D11 is non-breaking.
References
- ADR-018 — three-tier memory architecture
- ADR-065 —
spectral.coreadmission discipline - ADR-038 — D9 retrievable-table convention; canonical embedding profile
- ADR-044 — event substrate
- ADR-058 — World Agent memory storage (downstream coupling)
- ADR-059 — Ops Agent memory storage (downstream coupling)
- ADR-060 —
T3MemoryReaderreferenced as inter-context composition reference - ADR-063 — D3 grant removal; DI-injected reader pattern
- TA-8 disposition — SPEC-311 comment
207b3fee - TA-8 verification — SPEC-311 comment
87a91df3 - TA-15 D3 grant removal — SPEC-311 comment
a74f7620 src/spectral/platform/contracts/events/t3_memory_written.py- Codex
system-design/foundations/contract-surfaces/event-substrate.mdx— close-pass updates