Skip to main content

Module replay

Module replay 

Source
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§

ReplayEntry
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_id the 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_on edges to depth hops.