Repository navigation
FIX: keep session recovery controls available after errors - #93
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
A moderate active issue can leave SessionPrompt empty indefinitely after a preflight recovery is invalidated, preventing users from recovering.
1 open issue
What changed in this PR
This pull request makes confirmed systemError sessions recoverable through the shared Go adapter, terminal UI, and writable browser controls while preserving safeguards for active, unknown, disconnected, and uncertain states.
Changes:
- Enables explicit follow-ups, supported settings changes, and directory recovery after stopped errors.
- Clears stale turn capabilities and adds attempt-scoped preflight and concurrency protections.
- Updates terminal/browser guidance, README documentation, regression tests, and embedded web assets.
- Addresses a moderate capability-lifecycle issue before approval: a preflight-invalidated attempt can leave the composer permanently spent.
This pull request requires changes.
| File | Description |
|---|---|
web/tests/browser.spec.ts |
Adds browser coverage for recovery composers and /model discovery after stopped errors. |
web/src/Sessions.svelte |
Updates browser error guidance for supported recovery actions. |
README.md |
Documents stopped-error recovery requirements and safety limits. |
internal/web/session_failure_test.go |
Tests browser recovery offers, explicit follow-ups, replay protection, and command discovery. |
internal/web/dist/index.html |
References the regenerated browser JavaScript bundle. |
internal/web/dist/assets/index-CoCF2Nd3.js |
Regenerated browser bundle containing updated error guidance. |
internal/ui/monitor_failure_test.go |
Tests terminal recovery composers and slash-command discovery across detail modes. |
internal/codex/session_turn_unix.go |
Prevents active-turn controls from surviving ended failures. |
internal/codex/session_recovery_unix_test.go |
Adds recovery, preflight, stale-attempt, runtime, and settings tests. |
internal/codex/session_prompt_unix.go |
Enables safe follow-ups for failed runtimes and scopes capability cleanup to attempts. |
internal/codex/session_prompt_unix_test.go |
Extends prompt fixtures with preflight failures and race scenarios. |
internal/codex/session_directory_unix.go |
Allows verified directory changes in stopped error states. |
internal/codex/session_context_daemon.go |
Tracks prompt attempts and clears stale capabilities after definitive failures. |
internal/codex/session_commands_unix.go |
Allows idle-only settings actions for stopped error runtimes. |
internal/codex/daemon_status.go |
Recognizes systemError and defines accepted follow-up runtime states. |
internal/codex/daemon_status_test.go |
Covers systemError parsing and follow-up eligibility. |
Review effort: Lite
|
CI follow-up: the macOS timeout in TestAppServerReadLoopAndClose exposed an existing transport race, fixed separately in 45fbff9. If the error branch drained a final buffered response, it discarded EOF/the decoder error and the next read could block indefinitely. The fix retains that terminal signal while preserving message order. A deterministic regression reproduced both EOF and non-EOF loss before the fix; the transport tests now pass 100 race-enabled Linux runs and 100 native Windows runs. The original close test now has a bounded context, with all assertions retained and no increased CI timeout. Full core race/coverage tests and vet pass. The earlier review issue is fixed in 4a87795; waiting for fresh CI on the latest head before merging. |

Why
A stopped Codex turn can report
systemErrorafter model capacity, availability or other failures. Codexometer treated that runtime as unknown and restricted settings choices toidle, hiding the follow-up composer and blocking/modelprecisely when the user needed recovery. A terminal error without a later completion event could also retain a consumed editor or obsolete active-turn controls.Recovery in the shared Go adapter
systemErroras a confirmed failed, non-running runtime, not unknown or WORKING. Preserve the ERRORS category, attention pills and observed explanation.idleorsystemError, and accept those same states in the freshthread/readpreflight before an explicitturn/start.Capability lifetime and safety
turn/completedevent follows. Ended turns cannot receive stale steering/queue/interrupt requests.turn/startis dispatched, uncertain writes remain consumed and are never automatically retried.idle/systemErrorarrives, but the same notifications cannot revive uncertain dispatched writes.Interface and documentation
Transport race found during CI
Validation
go test -race -cover -timeout 10m -skip '^TestLocalisedScreens$' ./...); the unchanged all-locale screen matrix remains covered separately by CI./modeldiscovery cases.The official app-server runtime-status documentation distinguishes
idle,systemError,notLoadedandactive; this change does not treat arbitrary error labels or unknown states as permission to write.