- Reject a non-positive last_price ("bad_price") instead of `last_price or
trigger` coercing 0.0 -> trigger, which silently skipped the extension guard
and sized on a phantom price. (latent: fires() guarantees price>=trigger live,
but submit_breakout_now is public.)
- Extract the halt-gap decision to runtime/halt_guard.is_halt_gap() — pure and
unit-tested (the riskiest heuristic had no coverage). Encodes the fail-safe:
None ages (query glitch / session-date mismatch) -> inert, not mass-block;
global-health gate -> a feed-wide lag can't flag the whole book. 7 cases.
- Honest rationale on the extension ceiling: it measures distance above the ORB
trigger (catches the intraday chase / gap-through / halt re-open); overnight
+100% gappers are already excluded upstream by the trigger book's gap_max. It
is not a day-extension metric (a fuller day-move guard is a possible follow-up).
- Fix stale test docstring (15% not 6%); add bad_price test.
tests/unit: 154 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>