fix(codex): arm the transcript monitor's watch before it reads
Summary
The Codex transcript monitor could miss a rollout write and publish a Codex question or completion up to 30 seconds late. The monitor read the transcript, then opened a new DispatchSource for its wait. A write that landed between the read and the asynchronous source registration was never reported, so the monitor slept until its 30 s backstop.
test_codex_monitor_memory.py and test_codex_permission_prompt_notification.py wait 5 s per checkpoint and hit this window on main since the CLI lanes began running in parallel (https://github.com/manaflow-ai/cmux/pull/14990, lanes moved to the CLI product job in https://github.com/manaflow-ai/cmux/pull/15177). They failed together in 4 of the last main full runs ("monitor did not publish parser checkpoint"). The race itself dates from the first transcript monitor.
CodexTranscriptChangeWatcher (in CMUXAgentLaunch) keeps one kqueue registration per watched file for the monitor's lifetime. kevent registers synchronously and EV_CLEAR keeps a write pending until the next wait, so the monitor arms before each read and no write is lost. A replaced or late-created transcript is registered again on the next arm; the lease file stays watched for retirement.
test_hermes_wrapper_hooks.py and test_claude_wrapper_mutual_shim_loop.py, the other flaky tests in this job, are already addressed on main by first-exec priming (https://github.com/manaflow-ai/cmux/pull/15768) and serial = true (https://github.com/manaflow-ai/cmux/pull/15240). This PR's full CI run is the evidence for all four.
Testing
swift test --filter CodexTranscriptChangeWatcherinPackages/macOS/CMUXAgentLaunch: 7 tests pass locally, including a write between arm and wait, a write during the read after a wake, replacement by rename, a late-created transcript and lease deletion.python3 scripts/verify-local.py: swift-syntax, package-groups and feature-flags pass.- No red commit: the fix adds a new type, and the monitor race depends on scheduling, so no deterministic failing test exists for the old code. The Python regressions above were the red signal on
main. - Full
ci.ymlrun on this branch: see the PR comments.
Changelog
Fixed: Codex questions and turn completions no longer reach the sidebar up to 30 seconds late
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by cubic
Fixes the Codex transcript monitor's lost-wakeup race so Codex questions and turn completions no longer publish up to 30 seconds late.
- The monitor read the transcript and then opened a new
DispatchSourcefor the wait; a write landing between the two was never reported. - Replaces that with
CodexTranscriptChangeWatcher, which keeps one kqueue registration per watched file and is armed before each read. - Adds unit tests covering writes between arm and wait, file replacement, late-created transcripts, and lease deletion.
Summary by CodeRabbit
- Bug Fixes
- Improved the CLI’s detection of Codex transcript and lease changes, including when files are created, replaced, or removed.
- The CLI responds more reliably while waiting for Codex activity, including when updates occur between checks or after monitoring resumes.
- Waits continue to respect existing time limits, keeping the CLI responsive when no relevant changes occur.