d3ad9f4e73
The no---from/--to fallback in dispatch_generalize probes EACH listed symbol's full archive window (same partial bounds threaded through) and resolves the one shared campaign window as their intersection — latest start, earliest end — instead of symbols[0]'s window alone, so the cross-instrument floor is measured over a genuinely common period. Disjoint archives refuse at runtime (exit 1) naming each symbol's span. The intersect-or-refuse arithmetic lives in the pure intersect_shared_window helper (unit-tested: single symbol, overlapping, disjoint); the explicit --from+--to path stays byte-identical. The superseded shape test is renamed to generalize_without_explicit_window_resolves_a_shared_window_and_completes with its doc comment reworded to the intersection contract. closes #213