aura-ingest/aura-engine: join multi-tap recorder traces on timestamp, not by index #93
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Surfaced building the GER40 real-data example (commit
5b5f034,crates/aura-ingest/examples/ger40_breakout_real.rs).When a graph taps several
Recordersinks to build a per-bar trace, thesinks do not all fire on the same cardinality:
Gttap downstream ofDelay(1)is one row shorter —Delayis cold onthe first bar and emits nothing, so everything downstream skips that cycle;
Sessiontap filters bars that precede a session open (emitsNoneout of session).
So the recorded channels have different lengths and different firing
instants. Fusing them positionally (zip by index) misaligns the columns or
panics outright — the example's first cut did exactly that and panicked.
A correct multi-sink trace must join on the recorded timestamp, not by
position. The example fixed it with a ts-keyed join (
drain_trace/BarTraceinexamples/shared/breakout_real.rs), defaulting side-taps wherethey did not fire that bar.
Proposed: either a documented note on the sink/Recorder API ("taps fire at
their own node's cadence; join multi-tap traces on ts, never by index") or a
small shipped
join_on_tshelper, so the next consumer does not rediscoverthis via a panic. Non-blocking. Relates to C8/C18 (a sink is the only
observable surface).
Design reconciliation (specify, in-context entry)
Spec:
0053-multi-tap-ts-join. The fork below is still listed open on thisissue; it was resolved in the in-context design discussion (brainstorm).
join_on_tsreturnsVec<Option<Vec<Scalar>>>for the side taps — the enginereports presence (
Nonewhere a tap did not fire at a ts), and the consumerinterprets absence (the
0.0/-1/falsedefaults stay caller-side, since theyare consumer interpretations of "Gt didn't fire" / "before session open", never
engine truths). Rejected: per-side caller-supplied default-row (bakes "absence
has a default" into the engine API), and doc-note-only (delivers no reuse).
Provenance: user selected "Option je Seite (empfohlen)" in the brainstorm
approach-choice question, 2026-06-18.
Resolved in cycle 0053. A reusable, spine-anchored
join_on_ts(spine, sides) -> Vec<JoinedRow>helper now lives inaura-engine's report layer (sibling ofsummarize/f64_field), fusing N recorded(Timestamp, Vec<Scalar>)tap streams on the recorded timestamp — Option-per-side, so the engine reports presence and the consumer interprets absence.drain_traceis refactored onto it (the hand-rolled_by_tsHashMaps are gone), and theRecorderdoc now states the cadence/join rule ("join multi-tap traces on ts, never by index").Commits:
74324d1feat(aura-engine): join_on_ts helper + JoinedRow + two RED unit tests + lib.rs re-export35c5adcrefactor(aura-ingest): drain_trace fused via join_on_ts + Recorder prose cadence note7deb38echore: cycle 0053 close (audit clean)Verified: workspace build/test/clippy clean; the gated GER40 byte-identity tests stay green against the real archive (drain_trace's trace is byte-preserved across the refactor).