Code Mode dispatch worker stops at sampling end while yielded cells still need subsequent tools
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of Codex CLI is running?
Installed upstream CLI: 0.154.0. Source inspection below is pinned to upstream main 4701aa4b4239c70063ab6f2fcb835324f9c109f4. The end-to-end fix validation was on a local fork; this is not a claim of a fresh stock-0.154.0 runtime reproduction.
What subscription do you have?
ChatGPT Pro
Which model were you using?
The proposed failure mechanism is in the tool dispatch lifecycle, rather than a specific model's output. Model for a fresh upstream reproduction: not yet recorded.
What platform is your computer?
Linux 7.0.0-31-generic x86_64 unknown
What terminal emulator and version are you using (if applicable)?
Not recorded.
Codex doctor report
Not collected for this source-level report.
What issue are you seeing?
A yielded Code Mode cell may remain alive after the assistant ends its turn, but subsequent nested tool calls cannot be dispatched while the thread is idle. The first already-dispatched tool can finish; the next awaited tool then waits for a receive worker from a later sampling request.
This is separate from automatically waking the model: even without any completion wake, the Cell's JavaScript should be able to finish sequential non-interactive tools while idle.
What steps can reproduce the bug?
Suggested minimal reproduction (stock-current-version runtime confirmation still pending):
- In interactive CLI with Code Mode available, ask for one Cell containing the following JavaScript.
- Have the assistant finish its turn after the Cell yields. Do not call wait or send another user message during the sleeps. Ensure each command is permitted without additional approval.
- Observe whether the second command starts after the first returns, without another sampling request.
// @exec: {"yield_time_ms": 1000, "max_output_tokens": 1000}
const first = await tools.exec_command({
cmd: "sleep 8", yield_time_ms: 10000, max_output_tokens: 100
});
text({step: 1, result: first});
const second = await tools.exec_command({
cmd: "sleep 8", yield_time_ms: 10000, max_output_tokens: 100
});
text({step: 2, result: second});
The outer Cell yields after one second, but each inner tool has time to finish before its own yield. A deterministic regression should gate the first tool result until after the parent reaches idle, then assert that the second tool dispatches before any further model request. Our local fork has such an HTTP MCP regression, in addition to a manual two-sleep success test on the patched binary.
What is the expected behavior?
Ordinary nested tools requiring no new approval should continue until the live Cell completes, without keeping the model busy. This does not ask for idle approval UI, unlimited tool timeouts, or an automatic model continuation.
Additional information
Source inspection at the pinned upstream commit:
- Sampling request owns a local _code_mode_worker.
- Worker receive loop exits on shutdown.
- CodeModeDispatchWorker::drop sends shutdown.
These lifetimes explain the observed boundary in our investigation; the suggested stock repro above has not yet been rerun in this reporting session.
A possible approach is to retain the existing dispatch worker while unfinished Cells exist, releasing it on completion/teardown and respecting existing sampling-boundary replacement. Approval provenance and cancellation need explicit handling; retaining the worker alone exposes previously unreachable idle prompt paths.
Reference experiment: fork commit af1f26f725. This sits on top of separate completion-wake changes and is not an independent upstream-ready patch or a PR request.
Related, but distinct:
- #34122 concerns lost Cell handles across native goal continuations.
- #40041 concerns visibility/order of nested command activity.
- #38495 concerns Cell completion push and polling cost.
- #32188 concerns waking on background command completion.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the sampling worker in codex-rs/core/src/session/turn.rs and the receive and drop paths in codex-rs/core/src/tools/code_mode/delegate.rs. Run the suggested two-sleep Code Mode reproduction, then add or run a deterministic regression that gates the first result after the parent becomes idle. Done means sequential non-interactive nested tools dispatch through Cell completion without another sampling request.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100