Deliver to matching-surface Codex idle instead of treating it as errored

Merged
JI
2mo ago
+401-22

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 StateErrored like StateUnknown in 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 errored does not veto that proof; foreign Working / awaiting / shell still veto.
  • Requires ComposerCleared at the final disposition gate when the proof is selected Codex.
  • Does not change Codex Assess or detector status, so a sibling Codex seat that is genuinely errored stays errored/codex. Detector idle-override remains Unknown-only.

Test plan

  • go test ./cmd/flotilla/ -count=1 in isolate (includes new officer-route cases)
  • Matching-surface Codex errored + idle-cleared composer delivers
  • Codex errored without cleared composer refuses
  • Grok errored still refuses
  • Foreign Working still vetoes; foreign errored does 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 + ComposerCleared counts 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 StateErrored as an idle-proof gap.
  • CODEX_HOME lookup is shared between trust seeding and session liveness via codextrust.Home, defaulting to ~/.codex when unset.
  • Foreign drivers reporting errored no longer veto that proof; foreign Working / awaiting / shell still veto.
  • Final disposition gate requires ComposerCleared when the proof is selected Codex.
  • No live install changes; Assess and detector status are untouched.