generalize no-window semantics: symbols[0] full window is arbitrary #213

Closed
opened 2026-07-06 18:08:47 +02:00 by Brummel · 2 comments
Owner

When aura generalize is invoked without --from/--to, the dissolved path
(dispatch_generalize, main.rs) resolves ONE shared campaign window from the
FIRST listed symbol's full archive geometry (symbols[0].full_window) and
applies it to every instrument — because a CampaignDoc carries a single shared
Window, unlike the old inline run_generalize, which let each instrument
resolve its OWN independent full window.

Picking symbols[0] is arbitrary: if the first symbol's archive is not the
widest, later instruments are clipped to its span, and the grade can differ from
the inline path's per-instrument-full-window result. The only test on this path
(generalize_without_explicit_window_falls_back_to_the_first_symbols_full_window)
asserts shape, not grade — a full-archive value pin is deliberately omitted
because such a grade shifts as the archive grows (unlike the fixed Sept-2024
explicit-window anchor).

Note: the explicit-window path (the common case, both e2e + the exact-grade
anchor) is byte-identical to the inline path — this only affects the no-window
edge.

Reconsider the no-window semantics: the reference-instrument window (current),
the intersection of all instruments' windows (compare over the common period),
the union, or refusing without an explicit window. Ratified as-is for the
generalize dissolution cycle (#210); this tracks the deferred design question.

context: generalize dissolution (#210) architect drift review, [medium]
depends on: nothing (a standalone refinement)

When `aura generalize` is invoked without `--from`/`--to`, the dissolved path (`dispatch_generalize`, main.rs) resolves ONE shared campaign window from the FIRST listed symbol's full archive geometry (`symbols[0].full_window`) and applies it to every instrument — because a `CampaignDoc` carries a single shared `Window`, unlike the old inline `run_generalize`, which let each instrument resolve its OWN independent full window. Picking `symbols[0]` is arbitrary: if the first symbol's archive is not the widest, later instruments are clipped to its span, and the grade can differ from the inline path's per-instrument-full-window result. The only test on this path (`generalize_without_explicit_window_falls_back_to_the_first_symbols_full_window`) asserts shape, not grade — a full-archive value pin is deliberately omitted because such a grade shifts as the archive grows (unlike the fixed Sept-2024 explicit-window anchor). Note: the explicit-window path (the common case, both e2e + the exact-grade anchor) is byte-identical to the inline path — this only affects the no-window edge. Reconsider the no-window semantics: the reference-instrument window (current), the intersection of all instruments' windows (compare over the common period), the union, or refusing without an explicit window. Ratified as-is for the generalize dissolution cycle (#210); this tracks the deferred design question. context: generalize dissolution (#210) architect drift review, [medium] depends on: nothing (a standalone refinement)
Brummel added the idea label 2026-07-06 18:08:47 +02:00
Brummel added this to the Real-project readiness — role-complete research loop (no freeze) milestone 2026-07-10 17:16:15 +02:00
Author
Owner

Decision (2026-07-11): the no-window fallback resolves the shared campaign window as the intersection of the listed symbols' full archive windows, and refuses (runtime exit, both spans named in the message) when the intersection is empty.

Grounds, per the four options enumerated in this issue's body:

  1. Purpose. generalize is the cross-instrument comparison — the worst-case R floor across instruments (#146). A floor pooled over a different period per instrument conflates the instrument axis with the period axis; the common period is the only shared window over which every listed instrument actually has data, so it is the only window that isolates what the verb measures.
  2. Reference-instrument window (current) is arbitrary by this issue's own diagnosis: list order silently picks the span and can clip later instruments.
  3. Union fabricates spans where some instrument has no archive data, producing member-data refusals mid-campaign — structurally broken, not merely arbitrary.
  4. Outright refusal without --from/--to would retract the no-window convenience ratified in the #210 dissolution; only the fallback's semantics were deferred here, not its existence.

Degenerate cases: a single listed symbol resolves to its own full window (the intersection of one — behaviour unchanged); disjoint archives refuse rather than resolve an empty window. The existing shape test (generalize_without_explicit_window_falls_back_to_the_first_symbols_full_window) pins the superseded reference-instrument choice and is re-pinned to the intersection semantics by the delivery. RED-first delivery follows.

Decision (2026-07-11): the no-window fallback resolves the shared campaign window as the **intersection** of the listed symbols' full archive windows, and refuses (runtime exit, both spans named in the message) when the intersection is empty. Grounds, per the four options enumerated in this issue's body: 1. **Purpose.** `generalize` is the cross-instrument comparison — the worst-case R floor across instruments (#146). A floor pooled over a different period per instrument conflates the instrument axis with the period axis; the common period is the only shared window over which every listed instrument actually has data, so it is the only window that isolates what the verb measures. 2. **Reference-instrument window (current)** is arbitrary by this issue's own diagnosis: list order silently picks the span and can clip later instruments. 3. **Union** fabricates spans where some instrument has no archive data, producing member-data refusals mid-campaign — structurally broken, not merely arbitrary. 4. **Outright refusal** without `--from`/`--to` would retract the no-window convenience ratified in the #210 dissolution; only the fallback's semantics were deferred here, not its existence. Degenerate cases: a single listed symbol resolves to its own full window (the intersection of one — behaviour unchanged); disjoint archives refuse rather than resolve an empty window. The existing shape test (`generalize_without_explicit_window_falls_back_to_the_first_symbols_full_window`) pins the superseded reference-instrument choice and is re-pinned to the intersection semantics by the delivery. RED-first delivery follows.
Author
Owner

Delivered (2026-07-11), RED-first per the decision recorded in this thread on 2026-07-11 (intersection of the listed symbols' full archive windows; refuse on an empty intersection): commit bb8c018 pins the contract RED (archive-gated e2e deriving both expected bounds from the live archive via single-symbol probes, AAPL.US listed first so both bounds differ from the superseded symbols[0] window), commit d3ad9f4 turns it green — dispatch_generalize's fallback probes each symbol and reduces through the pure, unit-tested intersect_shared_window (single / overlapping / disjoint); disjoint archives refuse at runtime (exit 1) naming each symbol's span; the explicit --from+--to path is byte-identical; the superseded shape test is renamed with its doc reworded to the intersection contract. Full workspace suite and clippy clean. Closes via commit on merge.

Delivered (2026-07-11), RED-first per the decision recorded in this thread on 2026-07-11 (intersection of the listed symbols' full archive windows; refuse on an empty intersection): commit bb8c018 pins the contract RED (archive-gated e2e deriving both expected bounds from the live archive via single-symbol probes, AAPL.US listed first so both bounds differ from the superseded symbols[0] window), commit d3ad9f4 turns it green — `dispatch_generalize`'s fallback probes each symbol and reduces through the pure, unit-tested `intersect_shared_window` (single / overlapping / disjoint); disjoint archives refuse at runtime (exit 1) naming each symbol's span; the explicit `--from`+`--to` path is byte-identical; the superseded shape test is renamed with its doc reworded to the intersection contract. Full workspace suite and clippy clean. Closes via commit on merge.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#213