fix(codex): parse the app-server port through ANSI color sequences - #512
fix(codex): parse the app-server port through ANSI color sequences#512chemica-tan wants to merge 1 commit into
Conversation
…odex 0.144+) codex 0.144.1 (npm, updated 2026-07-15) colorizes the app-server startup banner even when stdout is a redirected file (NO_COLOR is ignored). The monitor's port discovery matched the literal "listening on: ws://127.0.0.1:" text, which now carries SGR sequences between the label and the URL, so the sed never matched: every monitored launch burned the 10s poll, killed its own fresh app-server, and failed open to plain codex — no bridge, no delivery. Found live in the chemica.4 E2E (step 3); the fail-open itself worked as designed (loud, non-destructive, verified own-server stop). Strip ANSI SGR sequences in the same sed invocation before matching. The reuse path reads the .port file (bare digits) and `codex --version` prints plain text (od-verified), so this banner sed is the only scrape site. The new test drives the monitor with a fake codex that reproduces the colorized banner verbatim over a node listener — it runs on the Windows runner too, where the python-listener fakes skip (which is exactly why this break was structurally invisible to the suite). Restore-to-FAIL verified: the test fails against the pre-fix monitor. Not a chemica.4 regression: the sed and spawn lines are unchanged since upstream fujibee#170; the 2026-07-15 morning E2E passed on the pre-0.144 codex. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The mechanism and the fix both check out. The One blocking issue, in the new test rather than in the fix. The node fake ends with Nothing is left running afterwards — the process does not leak — but the run itself blocks for the full minute. Since the suite is sharded four ways per OS, that minute is paid on whichever shard holds this file, on every run, on every PR. Could you have the listener exit once the port has been handed off, or have the fixture forward the teardown signal to the node child and wait on it? Either shape keeps the regression coverage and gives the time back. The existing python fake in the same file is a reasonable model — it terminates with its parent rather than on a timer. |
Mechanism
On our Windows 11 + Git Bash host, npm codex-cli 0.144.1 emitted ANSI SGR sequences in the redirected app-server log, with
NO_COLORset (verified withodon the captured log).codex-monitor.shdiscovers the port by matching the literal textlistening on: ws://127.0.0.1:in that log; whenever the banner carries SGR sequences between the label and the URL, the sed never matches.Effect of a non-matching banner on a monitored launch:
codex-monitor:/agmsg:warnings and falls back to a usable plain-codex session, with real-time delivery off for that session.The fail-open works as designed — but because codex itself opens normally, the warning is easy to miss, and the user just stops receiving messages. With #497 making monitor the recommended default, a host whose codex emits the colorized banner loses delivery on every monitored launch until someone reads the log.
Scope honesty: we can attest the colorized-banner emission only for the npm build we measured (0.144.1, Windows). The parser's failure to match any colorized banner is host-independent, and that is the property the new test pins.
Change
Strip ANSI SGR sequences in the same sed invocation before matching — one expression added, no new dependency, bash 3.2-safe. This banner sed is the only scrape site: the reuse path reads the
.portfile (bare digits), andcodex --versionprints plain text.Test
Adds a fake codex that reproduces the colorized banner verbatim over a node listener. The existing python-listener fakes print a plain banner and skip on Windows, which is why this class of breakage was invisible to the suite; the new fake has no Windows skip and passed in our manual Windows run. Note the current windows-latest CI job runs only the Windows-filtered cases of
tests/test_install.bats, so in CI this suite still runs on the Ubuntu/macOS shards. Exact command:Restore-to-FAIL verified on this branch: with the monitor sed reverted, the test fails.
Verification
Found live on Windows 11 + Git Bash + npm codex-cli 0.144.1 (2026-07-16); the fix has been running in our downstream deployment since. Mechanism re-checked against current
main— the banner sed is unchanged (greppable aslistening on: ws://127\.0\.0\.1:). The parser property is verifiable on any host via the test above; the banner emission itself we measured only on the stated Windows host.Note on #505
The text hunks merge cleanly. However, #505 routes the same startup loop's
$!liveness check (server_bg) through a tasklist-only helper, and our Windows probe shows it reports that live MSYS pid dead — we are reporting that on #505 separately. Re-testing the combined head on Windows before merging both is advisable.🤖 Generated with Claude Code
https://claude.ai/code/session_01EjjWN3rwUxE6qWBicECXHC