Three defects that kept a converged run bouncing forever, found by
replaying the issue #10 timeline against the real engine:
- follow-up routing did not exclude terminal cards: a FAILED
final-decider was clobbered to PENDING and then blew up the whole
resume turn with InvalidPhaseTransition: failed -> ready. Filter
FAILED/CANCELLED at selection and refuse terminal targets in
_prepare_company_followup_target (DONE stays eligible - the
approved -> rework reopen has a dedicated legal store op).
- with every routable decider terminal, the suspend checkpoint parked
pending forever and dead-ended each message on the same error.
Degrade to a plain runtime resume so the run converges and the
checkpoint drains, with an explanatory note.
- startup reconcile classified suspend-hold residue on terminal cards
as an interruption, rebuilding a pending company_runtime_interrupted
checkpoint on every boot. Scrub the residue instead so restarts are
idempotent.
scripts/verify_issue10_e2e.py replays the reporter's full timeline
(kill -> restart -> resume cycles, all external agents disabled) against
the real engine/store/dispatcher: startup only suspends, the codex-pinned
card fails closed with zero attempts burned, restarts stay converged with
idle CPU ~0%, and the kill loop terminalizes at the ledger limit. 11/11.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>