generalize no-window semantics: symbols[0] full window is arbitrary #213
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?
When
aura generalizeis invoked without--from/--to, the dissolved path(
dispatch_generalize, main.rs) resolves ONE shared campaign window from theFIRST listed symbol's full archive geometry (
symbols[0].full_window) andapplies it to every instrument — because a
CampaignDoccarries a single sharedWindow, unlike the old inlinerun_generalize, which let each instrumentresolve its OWN independent full window.
Picking
symbols[0]is arbitrary: if the first symbol's archive is not thewidest, 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)
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:
generalizeis 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.--from/--towould 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.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
bb8c018pins 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), commitd3ad9f4turns it green —dispatch_generalize's fallback probes each symbol and reduces through the pure, unit-testedintersect_shared_window(single / overlapping / disjoint); disjoint archives refuse at runtime (exit 1) naming each symbol's span; the explicit--from+--topath 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.