Repository navigation
bug(codex): nullable wait/close results leave completed subagents running (0.14.0) #8262
Description
What's broken
Two native Codex subagents remain “2 running” in Paseo after they have completed and been closed. The parent has finished, and each child's last Codex turn is completed. Restoring the same parent history reproduces the incorrect status.
This is a fresh 0.14.0 macOS reproduction of the symptom tracked in #4538, with additional evidence of a nullable-field parsing gap and live control-item reconciliation. Related proposal: #5314. That PR is still open; this report does not claim the older issue was fixed and then regressed upstream.
Expected: the original spawn cards and provider-subagent descriptors become completed, running indicators stop, and “Archive finished” becomes available. Actually: the original descriptors/cards remain running.
Steps to reproduce
- In a Codex parent session, spawn two native subagents.
- Wait for each to finish and close them. Codex
thread/readreturnscollabAgentToolCallitems:spawnAgentsnapshots withpendingInit, followed bywait/closeAgentsnapshots withcompleted; those control items containprompt: null. - Open the parent's subagents menu. In the affected persisted session, it shows two running children.
- Replay that parent's history through
CodexAppServerAgentSession: stock 0.14.0 reconstructs both children asrunning. Applying terminal control snapshots to the original spawn entries reconstructs both ascompleted.
The affected existing session and a deterministic provider regression test reproduce this. The entire original model-driven conversation has not been recreated from a fresh profile.
Where did this happen
Desktop (Electron), with the desktop-managed daemon on the same Mac.
Paseo version
0.14.0. Also observed on 0.13.2. Current upstream main tested at 9c7925d.
OS version
macOS 27.0.1, Apple Silicon.
Agent provider
Codex app-server, via a custom provider extending Codex.
Provider configuration
Codex CLI 0.164.0 at verification time. The CLI version at the original spawn time was not captured. The custom model endpoint and credentials are omitted. The deterministic reproduction uses the shared Codex provider implementation and does not require the custom endpoint or a model request.
Logs and raw evidence
The following are selected fields from a new, read-only thread/read capture of the affected real conversation. IDs are consistently replaced, prompt strings are redacted, and unrelated message fields are omitted. Statuses and null values are preserved.
{"type":"collabAgentToolCall","id":"CALL_1","tool":"spawnAgent","status":"completed","prompt":"[redacted]","receiverThreadIds":["CHILD_1"],"agentsStates":{"CHILD_1":{"status":"pendingInit"}}}
{"type":"collabAgentToolCall","id":"CALL_5","tool":"wait","status":"completed","prompt":null,"receiverThreadIds":["CHILD_1"],"agentsStates":{"CHILD_1":{"status":"completed"}}}
{"type":"collabAgentToolCall","id":"CALL_13","tool":"closeAgent","status":"completed","prompt":null,"receiverThreadIds":["CHILD_1"],"agentsStates":{"CHILD_1":{"status":"completed"}}}Child thread reads:
[
{"id":"CHILD_1","lastTurnStatus":"completed"},
{"id":"CHILD_2","lastTurnStatus":"completed"}
]All selected collaboration items, including both children and intervening sendInput calls.
Stock packaged-provider replay, before applying the local fix:
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
[
+ 'running',
+ 'running'
- 'completed',
- 'completed'
]
After applying the local packaged-provider reconciliation and replaying the same unmodified Codex history:
{
actualHistoricalChildStatuses: [ 'completed', 'completed' ],
runningChildren: 0
}
The live daemon reconciliation returned:
{
sessions: 1,
before: [ 'running', 'running' ],
updated: true,
after: [ 'completed', 'completed' ]
}
Code paths verified independently of the explanation:
CodexCollabAgentToolCallItemSchema.promptaccepts an optional string but rejectsnull.- History indexes the original spawn snapshot, without folding subsequent per-child
agentsStatescontrol results onto it. handleRegisteredSubAgentActivityhandlessubAgentActivitybut not legacy collaboration control results.
The source regression test fails on unmodified main with running/running, and passes with the proposed fix. A companion mapper test covers prompt: null directly.
Screenshots or video
Original report, cropped to the status badge to exclude conversation content (2 个运行中 = “2 running”):
After the equivalent local reconciliation was applied to the packaged 0.14.0 daemon, the original desktop conversation was opened and its subagents menu inspected: the badge changed to “2 个 subagent”, both spinning indicators disappeared, and “归档已完成的 subagent” (“Archive finished”) appeared. Neither child was archived to obtain that result. The live daemon was not restarted during this repair.
The local packaged-provider patch and GUI check are separate from the upstream TypeScript checkout's automated tests; no claim is made that a new desktop application was built from the proposed branch.

Activity
paseo-bot commentedon Oct 30, 2026
Thanks for the report and the capture, @popstk. This is #4538, so I've added your report there, with a link to PR #8263, and I'm closing this one as a duplicate. Updates go on #4538.