Away mode: recognize parked usage-limit and update menus, clear them safely, and audit every clear #33

Merged
john merged 6 commits from fm/fm-modal-aware-recovery into main 2026-09-24 10:14:52 +00:00
Owner

What was wrong

Workers that hit a harness menu sat there indefinitely while looking alive. A Claude usage-limit modal ("1. Stop and wait for limit to reset / 2. Upgrade your plan …") or Codex's self-update prompt parks the worker until someone presses a key. On 2026-08-16 two Claude workers sat on that menu for about 15 hours, through two window resets, and endpoint liveness reported them healthy the whole time.

What changed

  • The away-mode supervisor now recognizes these menus by anchored structural matching, not by loose text. It is locale-safe and uses fixtures captured from real panes.
  • Claude usage-limit menu: the supervisor selects "wait" only after an independent quota-axi read confirms the five-hour window has actually reset below the threshold. It never selects an upgrade or purchase option. A test proves it.
  • Codex self-update prompt: skipped with Escape.
  • Every clear is recorded in a separate audit record, state/<task>.recovery-log, never in the task's status log, per the captain's decision A (09/23). A worker whose last state was done, paused or waiting on a decision keeps exactly that last line, and a test proves it. Each clear is still surfaced through the normal escalation digest, so it is never silent.
  • An unchanged modal is suppressed, so the same menu is not re-cleared on every tick.

Validation

The no-mistakes pipeline passed at 3044be5. Its review round anchored the detector, fixed C-locale matching and shared the quota reads. There are fixtures for the Claude modal, the Codex update prompt and a clean busy pane, plus new daemon tests. An earlier pushed head wrote the recovery event into the status log (option C). It was sent back before any PR was opened, and this head is the corrected one.

Open

Nothing. This is the firstmate repo, so there is no Plane story. It overlaps bin/fm-supervise-daemon.sh with #32 (away-mode watcher handoff); whichever lands second rebases.

## What was wrong Workers that hit a harness menu sat there indefinitely while looking alive. A Claude usage-limit modal ("1. Stop and wait for limit to reset / 2. Upgrade your plan …") or Codex's self-update prompt parks the worker until someone presses a key. On 2026-08-16 two Claude workers sat on that menu for about 15 hours, through two window resets, and endpoint liveness reported them healthy the whole time. ## What changed - **The away-mode supervisor now recognizes these menus** by anchored structural matching, not by loose text. It is locale-safe and uses fixtures captured from real panes. - **Claude usage-limit menu:** the supervisor selects "wait" only after an independent `quota-axi` read confirms the five-hour window has actually reset below the threshold. **It never selects an upgrade or purchase option.** A test proves it. - **Codex self-update prompt:** skipped with Escape. - **Every clear is recorded in a separate audit record, `state/<task>.recovery-log`, never in the task's status log**, per the captain's decision A (09/23). A worker whose last state was done, paused or waiting on a decision keeps exactly that last line, and a test proves it. Each clear is still surfaced through the normal escalation digest, so it is never silent. - An unchanged modal is suppressed, so the same menu is not re-cleared on every tick. ## Validation The no-mistakes pipeline passed at `3044be5`. Its review round anchored the detector, fixed C-locale matching and shared the quota reads. There are fixtures for the Claude modal, the Codex update prompt and a clean busy pane, plus new daemon tests. An earlier pushed head wrote the recovery event into the status log (option C). It was sent back before any PR was opened, and this head is the corrected one. ## Open Nothing. This is the firstmate repo, so there is no Plane story. It overlaps `bin/fm-supervise-daemon.sh` with #32 (away-mode watcher handoff); whichever lands second rebases.
no-mistakes(document): Reattach recover_modal doc comment to its function
All checks were successful
CI / Test coverage guard (pull_request) Successful in 12s
CI / Lint shell scripts (pull_request) Successful in 4m37s
CI / Behavior portable parallel 1 (pull_request) Successful in 3m14s
CI / Behavior portable parallel 2 (pull_request) Successful in 3m0s
CI / Behavior portable serial 4 (pull_request) Successful in 9m17s
CI / Behavior portable serial 1 (pull_request) Successful in 14m20s
CI / Behavior portable serial 3 (pull_request) Successful in 13m54s
CI / Behavior portable serial 2 (pull_request) Successful in 17m46s
CI / Repo invariants (pull_request) Successful in 5s
CI / Behavior tests (Herdr) (pull_request) Successful in 7m36s
3044be536c
john merged commit b85c94c505 into main 2026-09-24 10:14:52 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
john/firstmate!33
No description provided.