Same bug here with Claude (Fable 5.2, then Opus 5.5) on a three-level delegate_task chain, main @ 6c9adfb273. Adding it because it shows the gap isn't Codex-specific, and that it covers grandchildren started from follow-ups, not only a single resumed child.
Setup. A (top-level coordinator) delegated to B; B delegated to C1 and C2. All app-owned, all on one machine. A's original delegate_task for B had finished the day before, so everything below runs through follow-ups.
What I saw. For over an hour, A showed as Done in the sidebar, chat, and mobile while C1 and C2 were working and B kept waking up to send them more work. Nothing on A said anything was still running, and A's lineage row for B said Done. A's agent was never woken again either, so it never heard about the later results (that half looks like #21837).
Timeline (UTC, 2026-11-10, from a read-only copy of the state DB):
| 1 | 11:45:08-11:45:45 A gets a follow-up row for a B run (a "Background command finished" notification). |
| 2 | It closes when that run ends, while C1 (since 11:32) and C2 (since 11:40) keep running. |
| 3 | From here on A shows nothing for them. |
| 4 | 11:53-12:09 Usage limit hits all four threads. Each automatic "Continue where you left off." |
| 5 | gets a (failed) row in its parent, so that part is tracked fine. |
| 6 | 12:11 A messages B after I switched to Opus -> row in A, closes 12:15 |
| 7 | 12:14 B messages C1 and C2 -> rows in B |
| 8 | 12:45:51-12:46:02 A's last follow-up row for B (another background-command notification run) closes. |
| 9 | 12:46:04 A's turn ends. |
| 10 | 12:46:19 C2 completes -> B woken by a delegatedCompletion run. No row in A. |
| 11 | 12:46:26 B sends C2 another pass -> row in B |
| 12 | 13:16:26 Another delegatedCompletion wake in B, no row in A. B sends C1 another pass at 13:16:37. |
| 13 | ~13:54 Chain finishes. A showed no running work from 12:46 on, and never ran again. |
Why (agrees with the diagnosis above):
- Only the original task waits for nested work before it finalizes (
finalizeAppOwnedSubagent). A follow-up task finalizes as soon as its bound run ends, even when that run left subagents running. - B's later runs are delegatedCompletion wakes (agent/server, no notification, no sender), which
mayStartSubagentFollowupandrecordSubagentFollowupnever turn into a parent row. - On the client, thread shells are per thread. Approvals already roll up the chain (
pendingSubagentRequestsByThread), but running work doesn't, so A has nothing to show once its own rows close.
From reading the code, a subagent picked back up after a server restart (restartContinuationOfRunId) is excluded the same way. I haven't reproduced that one.
Steps to reproduce (any provider; these mirror the live incident, I haven't run them in isolation):
- In thread A,
delegate_taskan async child B with a trivial task. Let A and B both finish, so the original task is done. - From A,
t3_thread_sendto B: "Use delegate_task to start two async subagents. Each runssleep 120in the foreground and replies DONE. After dispatching, end your turn without waiting or polling. When a completion wakes you, reply GOT_ONE." - Let A end its turn.
- While the grandchildren sleep: A shows Done in the sidebar, chat, and mobile thread list, with no background-work indicator, and A's lineage row for B says Done. B shows Waiting; the grandchildren show Working.
- When the first grandchild finishes, B wakes and runs. A still shows nothing and gets no row for that run.
Expected: A shows that work is still running below it until the last descendant ends, as it already does while the original task is open. The sidebar docs say subagents keep a thread in Working.
Fix. I have a fix ready. It's a client-side roll-up in client-runtime that does for running work what pendingSubagentRequestsByThread already does for approvals. A thread lists a subagent child as background work while that child, or anything under it, is still running and the thread's own rows no longer cover it. The entry clears when the last descendant ends. It covers web, desktop, and mobile, has tests that fail on main, and is running on my machine now against the chain above.
It's around 230 lines across client-runtime, web, and mobile, so I wanted to ask first: would you take it as a PR? Or would you rather fix this on the server by keeping follow-up tasks open until nested work settles? That route would also cover task_status and result delivery (#21837), which a client-side roll-up doesn't.
Investigated with Claude Opus 5.5 (Claude Code in T3 Code).