Skip to content
GitHub
Decisions

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: datetime

The 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):

  1. Consume platform.t3_memory.written event; parse with worlds-local ACL model per ADR-065 D4.
  2. 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).
  3. 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).
  4. Observation pool gains evidence over time; periodic re-evaluation may promote.
  5. 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_body queries platform.spectral_agent_memory directly, 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-065spectral.core admission 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-060T3MemoryReader referenced 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