Deliver to matching-surface Codex idle instead of treating it as errored
Operator summary
Before
Watch could see a Codex desk that was alive and sitting at an empty prompt, then still refuse to deliver. The fallback path treated that idle Codex session as broken, so messages queued instead of landing.
Change
When the live surface is Codex and the empty prompt is independently proven, that idle session is no longer treated as broken. A different Codex desk that really is in a dead-end error stays reported as errored. Overlay-first driver selection is unchanged.
After
Matching-surface Codex idle can receive watch delivery. Genuine Codex error seats stay errored. No live install in this change.
Identifiers
- Issue: #1066
- Branch:
agent/officer-route-codex-idle
Summary
Watch officer-route (the fallback that delivers after confirmed delivery returns a transient classifier miss) refused matching-surface Codex idle because idle-proof samples treated Assess=errored as not-idle. Confirmed delivery already maps errored to ErrTransient and then asks officer-route to prove the pane independently idle; officer-route vetoed the same errored sample.
This change:
- Treats matching-surface Codex
StateErroredlikeStateUnknownin idle-proof: neither positive-idle evidence nor a veto. The stable cursor/capture plus empty-main-composer proof decides. - Accepts selected Codex idle+cleared as empty-main-composer proof (Codex analog of selected Grok). Foreign
erroreddoes not veto that proof; foreign Working / awaiting / shell still veto. - Requires
ComposerClearedat the final disposition gate when the proof is selected Codex. - Does not change Codex
Assessor detector status, so a sibling Codex seat that is genuinelyerroredstayserrored/codex. Detector idle-override remainsUnknown-only.
Test plan
-
go test ./cmd/flotilla/ -count=1in isolate (includes new officer-route cases) - Matching-surface Codex
errored+ idle-cleared composer delivers - Codex
erroredwithout cleared composer refuses - Grok
erroredstill refuses - Foreign Working still vetoes; foreign
erroreddoes not veto selected Codex proof
Summary by cubic
Fixes watch delivery to a live, idle Codex desk that previously got treated as errored. Matching-surface Codex StateErrored is now treated like StateUnknown in the idle proof only when a PID/session-store liveness check passes, so the empty-composer proof decides. Genuine Codex error seats still stay errored, and other driver behavior is unchanged.
- Selected Codex
Idle+ComposerClearedcounts as empty-composer proof, mirroring Grok. - Requires the pane PID to be running and the Codex session store to hold an open rollout for that PID before treating
StateErroredas an idle-proof gap. - CODEX_HOME lookup is shared between trust seeding and session liveness via
codextrust.Home, defaulting to~/.codexwhen unset. - Foreign drivers reporting
erroredno longer veto that proof; foreign Working / awaiting / shell still veto. - Final disposition gate requires
ComposerClearedwhen the proof is selected Codex. - No live install changes;
Assessand detector status are untouched.