We built the pre-flight conflict check, and it answers the brief on both halves at once: it grades information rather than dumping it, and it moves every disagreement between data sources to before the click instead of after the wait.
Here is what happens now. An operator selects a storm and presses Run. Before a single frame is processed, GET /api/preflight/{storm_id} inspects the exact caches the run will read, computes conflicts with the same parsers the pipeline itself uses, and returns a verdict in under half a second. The console then shows one headline sentence and a row of severity pills. That is the whole first layer. An operator who trusts the system reads eleven words and presses Start run. An operator who wants the evidence opens a <details> block and gets the finding IDs, the numbers that disagree, and the tolerance each rule applied. A third layer sits underneath in the raw JSON for anyone auditing the call. Three depths, one screen, no modal stack, and the operator chooses how far down to go rather than having the choice made for them.
The conflict rules are the substance. Preflight cross-checks the committed stub against real 2024 DONKI records and fires stub_donki_speed_mismatch when the two disagree beyond twenty-five percent, stub_donki_arrival_mismatch when ballistic arrival estimates drift past twelve hours, and it checks flare class against R-scale, Bz sign against G-scale, and quota headroom against what a full advisory pass actually costs. On a fresh clone the G5 storm fires at sixty-five percent drift while G4 stays silent at twelve percent, so the panel is genuinely different run to run instead of decorative. It also knows what it cannot know: NOAA's L1 and GOES endpoints are real-time only, so those caches hold the wrong epoch, and preflight withholds them from the cross-source rules rather than reporting a false disagreement between instruments. Reporting a known-bad source as a conflict would have been the easy win and the dishonest one.
Why this is the right shape rather than merely a working one comes down to three decisions we refused to compromise on. First, preflight never blocks. It warns, it estimates the sixty-five to eighty second commitment, and it hands the decision back. A gate that stops a run on a heuristic teaches operators to click through gates, and in this domain that habit costs more than any single bad run. If the preflight call itself fails, the run starts anyway. Second, it is stat-first and read-only on the storm caches, because a check that fetches or mutates the thing it is checking is not a check. We found and documented the one place that claim was not literally true, the health probe that loads models and touches Chroma, and we fixed the cost with a thirty-second TTL cache that took a cold nine-point-seven second click down to zero-point-three-one seconds live. Third, the conflict findings demote themselves from warn to info when cv_stub_replay fires, because the detector returns the stub before it ever reads DONKI, flare, or L1, so a disagreement between those three cannot change the output. Reporting it as a warning would be technically correct and operationally false.
The scope landed exactly where the brief asked. No layer was rebuilt. Preflight reuses the pipeline's own parsers, the existing rate limiter's read-only peek path, and the health collector that was already there. It ships as one backend module, one endpoint, one frontend gate component, and full test coverage across peek, cache, conflict rules, and end-to-end. Two hundred eighty-four backend tests and both frontend test groups pass green, and we verified the whole thing live against a running instance producing four advisories with zero errors. The feature is complete, it is honest about its own limits, and every claim in this paragraph is pinned by a test.