Pin the IC offline-join duplicate-timestamp semantics #294

Open
opened 2026-07-20 16:43:05 +02:00 by claude · 1 comment
Collaborator

Latent: undefended duplicate-timestamp assumption in the IC offline join

information_coefficient (crates/aura-cli/src/main.rs, let sig_at: HashMap<i64, f64> = signal.iter().map(|(t, v)| (t.0, *v)).collect();) keys the signal series by epoch-ns timestamp and aligns the forward-return series to it by exact-ts match. Building the map with .collect() makes duplicate timestamps last-wins, silently — the code comments the assumption "a tap fires at most once per ts", but nothing defends or tests it.

Claim (latent, not currently reachable via a shipped path): under C4 a single timestamp can carry multiple distinct cycles (same-timestamp multi-source records break by source declaration order), so a tap CAN emit more than one value at one ts. A measurement blueprint fed such a multi-source stream would produce a persisted trace with duplicate ts[] entries, and the join would silently drop all but the last — a wrong IC, not a crash. No shipped path exercises this today: the only measurement blueprints in the tree tap a single per-bar synthetic stream (one value per ts), so this is a latent correctness gap, not an observed bug.

Why it is filed, not fixed now: the correct duplicate-ts semantics for an IC join (drop, error, first-wins, or aggregate) is itself a design question that belongs with the measurement-metric path — see #147 item 2 (how measurement metrics enter the family/deflation machinery) and #290 (where the IC reduction landed). Surfaced by the #290 cycle-close audit; the recommendation was to pin this before measurement gains a second metric consumer.

When fixed: RED-first — construct a persisted trace with duplicate timestamps on the signal tap and assert the chosen (defined) semantics, rather than the current silent last-wins.

## Latent: undefended duplicate-timestamp assumption in the IC offline join `information_coefficient` (crates/aura-cli/src/main.rs, `let sig_at: HashMap<i64, f64> = signal.iter().map(|(t, v)| (t.0, *v)).collect();`) keys the signal series by epoch-ns timestamp and aligns the forward-return series to it by exact-ts match. Building the map with `.collect()` makes duplicate timestamps **last-wins, silently** — the code comments the assumption "a tap fires at most once per ts", but nothing defends or tests it. **Claim (latent, not currently reachable via a shipped path):** under C4 a single timestamp can carry multiple distinct cycles (same-timestamp multi-source records break by source declaration order), so a tap CAN emit more than one value at one ts. A measurement blueprint fed such a multi-source stream would produce a persisted trace with duplicate `ts[]` entries, and the join would silently drop all but the last — a wrong IC, not a crash. No shipped path exercises this today: the only measurement blueprints in the tree tap a single per-bar synthetic stream (one value per ts), so this is a latent correctness gap, not an observed bug. **Why it is filed, not fixed now:** the *correct* duplicate-ts semantics for an IC join (drop, error, first-wins, or aggregate) is itself a design question that belongs with the measurement-metric path — see #147 item 2 (how measurement metrics enter the family/deflation machinery) and #290 (where the IC reduction landed). Surfaced by the #290 cycle-close audit; the recommendation was to pin this before measurement gains a second metric consumer. When fixed: RED-first — construct a persisted trace with duplicate timestamps on the signal tap and assert the chosen (defined) semantics, rather than the current silent last-wins.
Author
Collaborator

Re-anchoring after the #295 extraction: information_coefficient and the sig_at join described here no longer live in crates/aura-cli/src/main.rs. They moved verbatim to crates/aura-measurement/src/ic.rs (the HashMap<i64, f64> collect/last-wins join is now at ic.rs:80, inside the function starting at ic.rs:70; the doc comment at ic.rs:62-69 still asserts EXACT-timestamp alignment without defending the duplicate case). crates/aura-cli/src/main.rs:2132 is now only a call site (function imported at main.rs:40). The latent gap itself is untouched by the move — no duplicate-timestamp test or handling exists anywhere in the tree today.

The issue's blocking reference to #147 item 2 is also stale: #147 closed on 2026-07-20 (0651e16, 2cf4574), shortly after this issue was filed. That closure answered how measurement metrics enter the family/deflation machinery (the MetricVocabulary trait), which was never actually a hard prerequisite for choosing the join's duplicate-ts semantics — the two questions are orthogonal. #147's closure does not resolve this issue.

When picked up, the RED-first test and fix belong in crates/aura-measurement/src/ic.rs, not aura-cli.

Re-anchoring after the #295 extraction: `information_coefficient` and the `sig_at` join described here no longer live in `crates/aura-cli/src/main.rs`. They moved verbatim to `crates/aura-measurement/src/ic.rs` (the `HashMap<i64, f64>` collect/last-wins join is now at `ic.rs:80`, inside the function starting at `ic.rs:70`; the doc comment at `ic.rs:62-69` still asserts EXACT-timestamp alignment without defending the duplicate case). `crates/aura-cli/src/main.rs:2132` is now only a call site (function imported at `main.rs:40`). The latent gap itself is untouched by the move — no duplicate-timestamp test or handling exists anywhere in the tree today. The issue's blocking reference to #147 item 2 is also stale: #147 closed on 2026-07-20 (0651e16, 2cf4574), shortly after this issue was filed. That closure answered how measurement metrics enter the family/deflation machinery (the `MetricVocabulary` trait), which was never actually a hard prerequisite for choosing the join's duplicate-ts semantics — the two questions are orthogonal. #147's closure does not resolve this issue. When picked up, the RED-first test and fix belong in `crates/aura-measurement/src/ic.rs`, not `aura-cli`.
claude added this to the Measurement reachable — measure ic end-to-end on robust signals milestone 2026-07-23 13:42:58 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#294