fix(codex-implementer): stop lanes colliding in /tmp and stalling forever - #14
Open
wooter wants to merge 1 commit into
Open
fix(codex-implementer): stop lanes colliding in /tmp and stalling forever#14wooter wants to merge 1 commit into
wooter wants to merge 1 commit into
Conversation
…ever
Three defects, all observed repeatedly across parallel lanes on macOS.
1. `mktemp -t codex-spec.XXXXXX` does not do what it looks like on macOS.
BSD mktemp treats -t's argument as a PREFIX, not a template, so the
literal XXXXXX survives into the filename:
/var/folders/.../codex-spec.XXXXXX.TJEjQBKZt2
Every lane on the host therefore produces a path matching the same
`codex-spec.XXXXXX.*` glob. That is what makes cross-lane pickup
possible — one lane recovered its spec path by globbing and executed a
*different, concurrently running* lane's spec. The block sits directly
under the words "never a fixed path (parallel lanes on fixed paths
corrupt each other)", which is the right intent; the code just did not
deliver it. Passing an explicit template as an operand substitutes the
Xs on BSD and GNU alike.
Switch to one private scratch dir per lane and put spec/final inside it.
2. Document how to carry the path across tool calls. `ls /tmp/codex-spec.*
| tail -1` sorts by random suffix, not mtime. Parking it in a fixed
sidecar (/tmp/.codex_spec_path) is worse — concurrent lanes clobber that
deterministically rather than occasionally.
3. Lanes background `codex exec`, then end the turn "waiting for the
completion notification". Nothing delivers that notification to a
subagent, so the lane waits forever: 60-100k tokens across dozens of
tool calls, empty working tree, no report, while the caller believes
work is in flight. Relatedly, a 600 s shell wrapper is meaningless when
the Bash tool call itself defaults to 120 s — the tool kills the command
long before the documented cap applies.
State both plainly: foreground the call, set the tool timeout to match,
and never end a turn with codex still running.
Verified: the new mktemp form yields distinct dirs on BSD mktemp with the
Xs substituted, and two simulated concurrent lanes keep their own specs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
wooter
force-pushed
the
fix/lane-reliability
branch
from
August 10, 2026 11:17
e92e8b3 to
0bc012a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three defects in the lane, all observed repeatedly across parallel lanes on macOS. Independent of #12 — different hunks, the two merge cleanly in either order.
1.
mktemp -t codex-spec.XXXXXXdoesn't do what it looks like on macOSBSD
mktemptreats-t's argument as a prefix, not a template. The literalXXXXXXsurvives into the filename:So every lane on the host emits a path matching the same
codex-spec.XXXXXX.*glob. That is the enabling condition for cross-lane pickup: a lane recovered its spec path by globbing and ran a different, concurrently executing lane's spec. I found two such stray files sitting inTMPDIRon my machine from real runs.The block sits directly beneath the words "never a fixed path (parallel lanes on fixed paths corrupt each other)" — the intent is already right, the code just doesn't deliver it. Passing an explicit template as an operand substitutes the Xs on BSD and GNU alike.
Fix: one private scratch dir per lane, with
spec.mdandfinal.txtinside it.2. Nothing said how to carry the path across tool calls
$SPEConly lives for one Bash call, so lanes improvise:ls /tmp/codex-spec.* | tail -1— sorts by random suffix, not mtime, so under concurrency it cheerfully returns another lane's spec/tmp/.codex_spec_path— a fixed global sidecar; two lanes clobber it deterministically, not occasionallyBoth are now called out explicitly, with the two safe options (same tool call, or echo the path and copy it forward).
3. Lanes background codex and then wait forever
The dominant failure in my logs — eight separate incidents. A lane launches
codex execas a background task, ends its turn "waiting for the completion notification", and nothing is wired to deliver that notification to a subagent. Observed shape: 60–100k tokens across dozens of tool calls, empty working tree, no report, while the caller believes work is in flight. One session hit it three times.Related: a 600 s shell wrapper is meaningless when the Bash tool call itself defaults to 120 s. The tool kills the command long before the documented cap can apply, so the "ten-minute wall clock" is fiction unless the tool-call timeout is set to match.
Both are now stated plainly in step 2, plus a hard rule: never end your turn with a codex process still running.
Verification
mktemp -d "${TMPDIR:-/tmp}/codex-lane.XXXXXX"on BSD mktempXXXXXXDocs-only change.