Expand description
v0.7.0 L2-4 — transcript replay extended to the reflection union.
§What this module owns
memory_replay (v0.7.0 I4) originally returned the transcripts linked
to a single memory id via the I2 join table. L2-4 (issue #669)
generalises the read: when the memory is a Reflection
(memory_kind = 'reflection', L1-1), the replay must reconstruct the
union of every transcript reachable from the reflection by
walking reflects_on edges backward to the source observations.
The walk is BFS over the reflects_on adjacency (source_id ->
target_id). Each visited memory contributes its own
transcripts_for_memory rows; the final entry list is deduplicated
by transcript id (first-seen wins so the closest ancestor’s span
metadata is preferred when the same transcript is reachable through
more than one path) and sorted by created_at ascending. Ties on
created_at fall back to transcript_id so two transcripts minted
in the same RFC3339 millisecond still produce a deterministic
ordering — same tie-break the I4 handler used.
§Depth contract
Callers may cap the BFS at depth hops via the depth parameter
threaded through memory_replay(depth=N). None (the default)
means “walk the full chain” — every transitively-reachable ancestor.
Some(0) means “self only” (skip the union; same shape as the
pre-L2-4 I4 read). Some(N>=1) means “self plus N hops of
ancestors”. This matches the depth-counting convention used by
reflection_depth on the memory row.
§Non-Reflection passthrough
When the input memory is MemoryKind::Observation (or the row
cannot be loaded — substrate may have GC’d it between the
permission check and now), the walk is skipped entirely and the
result is exactly what transcripts_for_memory returns for the
single memory id. This is the explicit “non-reflection
memory_replay MUST be unchanged” acceptance criterion from #669.
§Cycle safety
L1-2 (#659) already refuses to add a reflects_on edge that
would close a cycle. The walk here still maintains a visited
set on memory_id so a stale cycle that slipped past the
anti-cycle guard (e.g. via direct SQL writes from a legacy
migration) cannot induce an infinite loop. Cycle detection is
a hard safety net, not a correctness shortcut.
Structs§
- Replay
Entry - One row of the L2-4 union replay stream. Carries both the transcript
metadata (compressed/original size, namespace, created_at) and the
I2 link span — plus the
memory_idthe link was discovered through, which the I4 handler returns to operators so they can see which ancestor in the chain contributed each transcript.
Functions§
- replay_
transcript_ union - Replay a memory’s transcripts. When the memory is a reflection,
gather the union of every transcript reachable by walking
reflects_onedges todepthhops.