You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Delegated task reports finished while its child thread still has running work #16603
From a parent thread, delegate_task to a Codex child that starts a long-running shell command (a bot, a test watcher) and ends its turn without waiting for it.
Read task_status, or look at the parent once it settles.
Expected: The task stays in progress (or reports waiting_for_children) while the child's command is still running, and the parent stays Waiting.
Actual: The task finalizes as completed / result_available and the parent can settle to Done, while the child thread still has a running command_execution item and the process is alive. delegatedTaskProgress (SubagentProjection.ts:207-259) checks runs, subagent entities and the provider roster, but not active turn items, and finalizeAppOwnedSubagent (Orchestrator.ts:8472-8488) finalizes on that result.
A related path: t3_thread_send into an already-finalized child (ThreadManagementService.sendToThread) starts new runs there, but the parent task stays completed and its later result is never delivered (OrchestratorMcpService.ts:1058-1077, Orchestrator.ts:8537-8546).
Evidence (0.0.46-nightly.20261004 state DB): 3 of 145 completed delegated tasks since Oct 1 finalized while their child had live command items (2 still running now, one confirmed alive with pgrep). 5 later runs across 3 finalized children.
Possible fix: include pendingBackgroundTurnItems({ turnItems, runs }) in delegatedTaskProgress (and load turn items in both callers), retrying finalization when those items end. For the send path, reject sends into finalized app-owned children or reopen task tracking.
Confirmed on current main: an app-owned delegated task can finalize as result_available / completed while the child still has live background command_execution work.
Main bug
delegatedTaskProgress decides working / waiting_for_children / result_available from:
non-terminal work runs
active child subagents / pending completion delivery
provider-thread pendingBackgroundTasks
It does not look at active turn items. finalizeAppOwnedSubagent loads the child without turnItems, calls that helper, and finalizes as soon as progress.state === "result_available".
So a Codex child that starts a long-lived shell (countsForRun: false / turn ends without waiting) can look “done” to the parent while the process is still alive — matching the state-DB evidence in the report.
The shared pendingBackgroundTurnItems helper already exists and is used elsewhere in the orchestrator (e.g. interrupt cleanup). It is the natural check to fold into delegatedTaskProgress (with callers loading turnItems).
Secondary path (distinct)
t3_thread_send into an already-finalized child can start new runs without reopening parent task tracking / delivering the later result. That overlaps open #13490 and open PR #15004 (follow-up result delivery). Those do not fix the premature-finalize case above.
Loosely related: #13625 (completion sound while background work runs), #15993 (stale background banner).
Fix direction: include pendingBackgroundTurnItems({ turnItems, runs }) in delegatedTaskProgress (and load turn items in both finalize / status callers); keep finalization deferred until those items end. Separately, for send-into-finalized-child, either reject or reopen tracking (coordinate with #15004).
From the original root thread, the remaining descendant activity is not visible, so the delegated workflow appears finished while B continues working.
This is an observation, not an independently reproduced case. It is unclear whether it has the same underlying cause as the command_execution gap described above.
Consolidating the related report from #16902 here to avoid parallel tracking.
Same outcome with a Claude child, on 2026-10-20. The open work here is a native background subagent, not a shell command. The machine's installed runtime is 0.1.1-nightly.20261019.3373.
18:23:32Z: the parent sends the child a follow-up with t3_thread_send. T3 tracks it as a delegated task.
18:24:11Z: the child launches a background subagent. T3 writes a record for it on the child in orchestration_v2_projection_subagents (origin: provider_native, status: running).
18:31:45Z: the child's turn ends with "I'm waiting on two things in the background: the price-research child and a watcher for its output file."
18:31:45Z: T3 finalizes the delegated task and delivers its result to the parent. The record for the child's subagent still reads status: running.
18:35:59Z: the child's subagent completes.
The issue body says delegatedTaskProgress checks subagent entities. This record read status: running when T3 finalized the task. The parent agent learned the work was unfinished only from the child's final text, and sent another follow-up at 18:31:57Z.
Triage read the report and follow-up, scanned all 949 open issues, and inspected current main at a12d6ed942. No earlier duplicate identified; #21837 covers a related follow-up lifecycle. Runtime reproduction was not attempted. This requires maintainer review under the automated triage restriction on MCP tool-surface changes: the requested behavior changes delegated-task completion returned by task_status and follow-up handling through t3_thread_send. No code changes or PR.
Additional observed case on 2 November 2026: a delegated implementation agent displays Done while its required asynchronous review delegate is still running. Adding here because #16902 explicitly consolidated this nested-descendant visibility case into #16603.
Steps observed
An implementation coordinator launches a required asynchronous review with delegate_task.
The host result instructs it: "Completion wakes this thread, so end your turn. Do not wait on it or poll it."
The coordinator ends its turn awaiting that review.
Open Lineage while the review remains active.
These steps describe the supplied live-session evidence. No fresh isolated reproduction was run.
Expected behavior
The aggregate workflow status remains pending, for example Waiting for review/delegates, while a required descendant is active. The parent agent's completed turn can remain visible separately. Active required descendants should remain discoverable from ancestors.
Observable acceptance:
Aggregate status remains pending during required child activity.
It transitions correctly when that child completes, fails, or is cancelled.
A terminal parent-turn status remains distinguishable from completion of the delegated workflow.
Actual behavior and evidence
A screenshot from the implementation conversation shows "Lineage · 1 running", the implementation parent marked Done, and its required Opus review still running at about 16 minutes elapsed.
A separate root-conversation screenshot shows only direct previous agents. This supports a related nested-descendant discoverability concern; it does not establish the same underlying cause as the Done ambiguity.
The main coordinator's read-only T3 thread inspection confirmed an active claudeAgent / claude-opus-5-5 run with a parent relation to the ended implementation delegate. Completed command activity was recorded at 14:01 AEDT, UTC+11, on 2 November 2026. That command completion is not evidence that the review itself completed.
The required source milestone remained pending at observation time.
This is evidence of user-visible pending-work/status ambiguity. It does not establish premature backend task finalization, a reducer defect, lost tasks, cancelled work, or failed completion delivery. Root cause is unknown.
Environment and version limits
T3 Code on Linux, with nested T3 asynchronous delegation and a Claude Agent Opus 5.5 reviewer. Read-only installed metadata identifies CLI runtime 0.1.4-nightly.20261028.3814 and desktop package 0.1.3-nightly.20261023.3566. These are installed versions, not a verified binding of the screenshot or active server to either version; the exact affected running build is unknown.
Impact and workaround
Users can mistake an ended parent turn for finished work and lose visibility of a required pending review. No verified UI workaround. The supplied evidence distinguishes parent-turn completion from outstanding review work; no claim is made that execution stopped.
Related reports and scope
#27126 concerns an async delegate hint stopping otherwise independent work. Here the review is required and ending the turn is expected; this report concerns the displayed aggregate state. #27700 concerns native Claude subagent background commands/monitors. This case uses a required T3 asynchronous review delegate, without assuming the same cause.
Sanitized text only. Private screenshots, transcripts, task identifiers, repository details and machine paths are intentionally omitted. No implementation, task cancellation, restart, or monitoring was performed for this report.
Same bug with a Claude child, on 0.1.7-nightly.20261102.4066 (macOS, Claude Code 2.1.316, Claude Opus 5.5). The report above uses a Codex child.
Steps observed
A Claude parent starts a child with delegate_task, isolation: "worktree", mode: "async".
The child starts a long script with Bash run_in_background and ends its turn with the message "Waiting for background task <id>, the final evidence run."
The parent calls task_status.
Result
While the script was still running, task_status returned:
{
"status": "completed",
"workState": "result_available",
"hasPendingChildRuns": false,
"latestTerminalSummary": "Expect: about 25 minutes and little plan usage. Waiting for background task `<id>`, the final evidence run."
}
At the same moment, on the machine, the script's process and the child's claude process were alive, and the child had not pushed its branch.
The parent was woken with a [completed] message whose whole text was the waiting line. The same thing happens on every turn the child ends while it waits: in this session four workers sent about 15 [completed] messages between them that were not final results. Each background completion starts a new child run through a provider continuation, and that run delivers another [completed].
Impact
A parent has no reliable way to tell a finished child from a waiting one. Here both the parent agent and the person watching the app read a running worker as done. The parent has to inspect the child's checkpoint or processes to find out.
Not tested
I did not check whether calling t3_background_wait inside the child changes this. I did not run a patched build.
Related: #27700 covers the same state for native Claude subagents, and anthropics/claude-code#92952 covers the completed status it comes from.
Same nested case on v0.1.6 (Linux desktop app), with counts from one long-running session. All delegates were started with delegate_task. The parents were Claude Opus 5.5, and the children were a mix of Claude and an ACP provider.
Observed
root: latest run completed, no active run, 72/72 subagent records completed
├─ orchestrator A: latest run completed → review delegate: running
├─ orchestrator B: latest run completed → build delegate: running; review delegate: running
└─ orchestrator C: latest run completed → mapping delegate: running
From the code, the root row should read as finished: its status comes from its own runs and its own unfinished records, and nothing here is active. I read this from the state database and the source, and did not capture the sidebar itself.
Two paths, both in the state database
A follow-up closes while its nested work runs. In finalizeAppOwnedSubagent, only the original task is held back by progress.state. Example from orchestrator C:
12:09:07.563 orchestrator opens a nested delegate
12:09:17.934 orchestrator's run ends
12:09:18.449 root's follow-up record closes as completed; the nested delegate is still running
A run starts with no root record open. Orchestrator A's last root record closed at 10:31:31. A nested completion woke it at 12:06:13, and it opened a new delegate at 12:06:36. The root had no open record for any of this.
Orchestrator
Root records closed while a nested record was open
Runs with no open root record
A
26 of 29
110 of 166
B
10 of 13
49 of 67
C
17 of 21
45 of 96
These compare timestamps across each orchestrator's own records. They count overlaps, and don't show that each overlap was visible in the UI.
Related work
Path 1 looks like what #21877 addresses, and path 2 looks like what #28462 addresses. I have not run a build with either PR, so I can't say whether the two together keep the root in a pending state for this whole tree.
Another case with a Claude child on v0.1.6 on Windows, using mode: "async", isolation: "shared". The child's own final message says it isn't finished, but the task and the thread read as done.
What happened. A child started a background Bash watcher, then ended its turn with this message:
W6 isn't finished: nothing has been submitted yet... Background watcher bqkvktnji checks both local files every 2 minutes, for up to 2 hours, and wakes me when the gate opens, the suite fails or it times out.
The parent received Delegated task ... [completed] with that text. t3_thread_read shows the thread as status: completed, activeRunId: null, runCount: 1, and t3_thread_list with statuses: [running, starting, queued, waiting] doesn't list it, while the watcher it describes is meant to still be alive.
Why the status can't be relied on, in the same session. Two sibling children showed the same completed state after similar turns and then woke up later and did real work:
One submitted 30 cluster jobs under a later provider-continuation task ID, after its original task had reported completed.
Another woke up several more times on its own, reported state changes and resubmitted a failed job.
So completed can mean either "finished" or "waiting on my own background work", and the parent can only tell by reading the child's prose.
The practical cost. A parent seeing completed on unfinished work starts a replacement, which then risks duplicating the original if it wakes. I had to start a replacement for this child with no way to confirm the first wouldn't resume. For long fan-outs this also produces many [completed] notifications carrying interim text such as "Waiting for the retry to report back."
Expected. As this issue describes: waiting_for_children or similar while a child has live background work, including Claude run_in_background commands, and a final completed only when it has really ended.
Same bug with a Claude child on 0.1.6-nightly.20261031.3977 (macOS 27.0.1 arm64, desktop app on a local server). This adds what it does to the parent's Lineage panel.
Observed
A Claude Opus 5.5 parent started a Claude Opus 5.5 child with delegate_task (isolation: "worktree").
The child started long test runs with Bash run_in_background, called t3_background_wait on them, and ended its turn. It woke and carried on each time a run finished.
In orchestration_v2_projection_subagents, every task record for the child read completed / delivered, one per turn. Each was written while the child's background runs were still pending; four of its test processes were alive on the machine at the time.
What the parent's Lineage panel showed
While the child was working, the parent's thread details panel showed no active agent. Lineage showed only a collapsed "Previous agents · 1 failed · 194", with the live child folded in among the finished ones. The child's own panel listed the parent correctly.
From the source (checked against main at c52df24), this follows from the task status:
Between turns the child has no live run, so its activityRunStatus is null. The subagent edge's status in deriveThreadRelationshipGraph (packages/client-runtime/src/state/threadRelationships.ts) then falls back to the child's completed status, because the subagent record is no longer active.
ThreadRelationshipsPanel (apps/web/src/components/chat/ThreadRelationshipsControl.tsx, the groupBy that returns "previous") puts every subagent edge with a settled status under "Previous agents".
So if the subagent record stayed running while the child waits on its own background work, the edge would take that status and the child would stay in the active list. The Lineage symptom should not need a separate client fix.
Observed in a live session, not reproduced in isolation.
Filed by Claude Code (claude-opus-5-5) inside T3 Code, following .github/triage/PLAYBOOK.md.
Still reproducible on t3 v0.1.8 (Claude Code 2.1.322 parent and child), via the follow-up path described above:
The parent sent a follow-up to a finished delegate_task child with t3_thread_send. The answer was delivery: "started" with a new taskId.
The child (run 4) started a long UI-review command in the background and ended its turn with "Waiting for the run's completion notification."
The parent immediately got a completion for the new taskId, with that run-4 text as the result.
The background command exited, and the child woke as run 5 (08:44:27 → 08:46:09 UTC). Run 5 wrote the real report and a commit. That result was never delivered to the parent.
t3_thread_wait(threadId, untilDelegatedWorkSettled: true), called while the background command was still running, also returned resultRun = run 4 (completed, not timed out) before run 5 existed. Only a second t3_thread_wait on run 5's id, then t3_thread_read, got the real report.
I tried to reproduce this on the current build and could not.
Commit 1e438c8 (origin/main). Not run in the live app: no provider on this VM reports server-tracked background commands (Codex and Claude need first-party OAuth, which is unavailable here). Reproduced instead in the real orchestrator with its in-memory event sink. I added the test 'subagent follow-ups > keeps a follow-up running while its child awaits a background command' to apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts. It reuses the startSelfQueuedFollowup fixture: the parent sends a follow-up to a finished delegated child, the follow-up run starts, the child's provider thread records pendingBackgroundTasks [{kind: 'command', awaited: true}], and the follow-up run completes with the text 'Waiting on the test run.'. On main the parent's follow-up subagent task settles with result 'Waiting on the test run.' while the awaited command is still pending. Run with: cd apps/server && vp test run src/orchestration-v2/DelegatedCompletionDelivery.test.ts -t follow-up. Result: 1 failed, 23 passed.
Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.
Still happening on 0.1.9 (desktop app on a local server, macOS arm64, Claude Opus 5.5 parent and children). A unit test reproduces it on current main, and open PR #34958 fixes it in that test.
This case differs from the earlier no-repro test in two ways:
The task that finished early was a t3_thread_send follow-up, not the original delegate_task.
The pending work was a Claude native background subagent (provider_native), not a background command.
Observed (one child, 12 Nov, UTC)
Root thread idle
└─ Child A (delegate_task) 12 app_owned task records on the root, all completed/delivered
│ original task 13:54:02 → 14:49:04; the other 11 are thread-send follow-ups / provider continuations
├─ native subagent B1 (background Agent) running, started 15:10:30, still updating at 16:21
└─ native subagent B2 (background Agent) running, started 16:13:58, still updating at 16:21
Root sends A a follow-up with t3_thread_send (task …thread-send:a84b1471…, run 12 starts 16:13:22).
During run 12, A starts B2 with Claude's background Agent tool at 16:13:58, then ends its turn 8s later, waiting for B2's wake.
At 16:14:06 the follow-up task becomes completed / delivered on the root, while B1 and B2 are running in orchestration_v2_projection_subagents on A's thread.
The root's subagents view lists only its direct children, and all of them are finished. Nothing running shows from the root, although two grandchildren are working.
Expected: the follow-up stays waiting_for_children until the child's subagents settle, and the root shows delegated work still active below it.
Cause
In finalizeAppOwnedSubagent (apps/server/src/orchestration-v2/Orchestrator.ts, same on v0.1.9 and main), delegatedTaskProgress only gates the original task:
Every follow-up skips that check. finalizeAppOwnedSubagentTask then finalizes it from its own run's outcome, without looking at subagents that run started.
Test results
I added a test to DelegatedCompletionDelivery.test.ts under subagent follow-ups. A finished delegated child gets a t3_thread_send follow-up. During that follow-up run the child starts a provider_native subagent (status: running), then ends its turn with an interim reply.
Build
Result
main @ fd8e386f
Fails.the follow-up task settled on its handoff turn while the child's nested subagent was running: expected 'Waiting on the background subagent.' to equal null. The fixture check that the nested subagent is still running passes first.
So #34958 also covers Claude native background subagents, not only the app_owned subagent its own test uses. I haven't run the live app on that branch.
Run: cd apps/server && vp test run src/orchestration-v2/DelegatedCompletionDelivery.test.ts -t "follow-up"
Test (insert before "waits for a run the follow-up's child queued on its own thread")
it.effect("keeps a follow-up running while its child's nested subagent runs",()=>Effect.gen(function*(){constorchestrator=yield*Orchestrator.OrchestratorV2;consteventSink=yield*EventSink.EventSinkV2;constrequests=yield*ProviderContinuationRequests.ProviderContinuationRequests;constnow=yield*DateTime.now;constname="nested-followup";constparentThreadId=ThreadId.make(`thread:${name}-parent`);constprojectId=ProjectId.make(`project:${name}`);constparentRunId=RunId.make(`run:${name}-parent`);constrootNodeId=NodeId.make(`node:${name}-parent`);yield*seedParentWithTerminalTask({threadId: parentThreadId,
projectId,runId: parentRunId,
rootNodeId,taskId: NodeId.make(`node:${name}-seed`),deliveryState: "acknowledged",
now,});constchild=yield*seedRestartCancelledChild({
parentThreadId,
projectId,
parentRunId,
rootNodeId,name: `${name}-child`,completionWake: "always",continuationPending: false,runStatus: "completed",
now,});yield*orchestrator.recoverDelegatedTasks;letfirstWake=yield*requests.take;while(firstWake.threadId!==parentThreadId)firstWake=yield*requests.take;yield*orchestrator.dispatch({type: "delegated_task.completion-delivery.acknowledge",commandId: CommandId.make(`command:${name}-ack`),
parentThreadId,taskId: child.taskId,observedByRunId: parentRunId,});constparentRun=(yield*orchestrator.getThreadProjection(parentThreadId)).runs.find((run)=>run.id===parentRunId,)!;yield*eventSink.write({commandId: reconcileCommandId(`${name}-parent-finished`),events: [{id: EventId.make(`event:${name}-parent-finished`),type: "run.updated",threadId: parentThreadId,runId: parentRunId,occurredAt: now,payload: { ...parentRun,status: "completed",completedAt: now},},],});// The parent sends the finished child a follow-up (t3_thread_send).constfollowupMessageId=MessageId.make(`message:${name}`);yield*orchestrator.dispatch({type: "message.dispatch",createdBy: "agent",creationSource: "mcp",commandId: CommandId.make(`command:${name}`),threadId: child.childThreadId,senderThreadId: parentThreadId,messageId: followupMessageId,text: "Build the codemod.",attachments: [],dispatchMode: {type: "start_immediately"},});constqueuedRun=(yield*orchestrator.getThreadProjection(child.childThreadId)).runs.find((row)=>row.userMessageId===followupMessageId,)!;constfollowupTaskId=queuedRun.delegatedTaskId;assert.isDefined(followupTaskId);constfollowupRun={ ...queuedRun,status: "running"asconst,startedAt: now};// During the follow-up run, the child starts a Claude background subagent.constnested={id: NodeId.make(`node:${name}-nested`),threadId: child.childThreadId,runId: followupRun.id,parentNodeId: NodeId.make(`node:${name}-child-root`),origin: "provider_native"asconst,createdBy: "agent"asconst,
driver,providerInstanceId: modelSelection.instanceId,providerThreadId: null,childThreadId: null,nativeTaskRef: null,prompt: "Nested work",title: null,model: null,status: "running"asconst,result: null,startedAt: now,completedAt: null,updatedAt: now,};yield*eventSink.write({commandId: reconcileCommandId(`${name}-running`),events: [{id: EventId.make(`event:${name}-running`),type: "run.updated",threadId: child.childThreadId,runId: followupRun.id,occurredAt: now,payload: followupRun,},{id: EventId.make(`event:${name}-nested-open`),type: "subagent.updated",threadId: child.childThreadId,runId: followupRun.id,nodeId: nested.id,
driver,providerInstanceId: modelSelection.instanceId,occurredAt: now,payload: nested,},],});// The child ends its turn to wait for the nested subagent's wake.yield*eventSink.write({commandId: reconcileCommandId(`${name}-handoff`),events: [{id: EventId.make(`event:${name}-handoff:result`),type: "message.updated",threadId: child.childThreadId,runId: followupRun.id,occurredAt: now,payload: {id: MessageId.make(`message:${name}-handoff:result`),threadId: child.childThreadId,runId: followupRun.id,nodeId: null,role: "assistant",text: "Waiting on the background subagent.",attachments: [],streaming: false,createdBy: "agent",creationSource: "server",createdAt: now,updatedAt: now,},},{id: EventId.make(`event:${name}-handoff:finished`),type: "run.updated",threadId: child.childThreadId,runId: followupRun.id,occurredAt: now,payload: { ...followupRun,status: "completed",startedAt: now,completedAt: now},},],});yield*orchestrator.recoverDelegatedTasks;constchildProjection=yield*orchestrator.getThreadProjection(child.childThreadId);assert.equal(childProjection.subagents.find((task)=>task.id===nested.id)?.status,"running","fixture: the nested subagent is still running on the child",);constfollowup=(yield*orchestrator.getThreadProjection(parentThreadId)).subagents.find((task)=>task.id===followupTaskId,)!;assert.isNull(followup.result,"the follow-up task settled on its handoff turn while the child's nested subagent was running",);assert.notEqual(followup.status,"completed");}),);
Open question
Claude starts the child's wake after a native subagent finishes, not a server delegatedCompletion, so #34958's delegatedTaskRuns won't attach that wake to the follow-up. In this database those wakes appear on the parent as separate provider-continuation tasks, so the final reply probably still arrives, as its own task. Not verified.
Related: #16902 (same Root → A → B shape, merged into this one), #29128.
Triaged with Claude Code (Claude Opus 5.5) via T3 Code triage.
Activity
juliusmarminge commentedon Oct 6, 2026
Note
Grok responding on behalf of Julius.
Confirmed on current
main: an app-owned delegated task can finalize asresult_available/completedwhile the child still has live backgroundcommand_executionwork.Main bug
delegatedTaskProgressdecidesworking/waiting_for_children/result_availablefrom:pendingBackgroundTasksIt does not look at active turn items.
finalizeAppOwnedSubagentloads the child withoutturnItems, calls that helper, and finalizes as soon asprogress.state === "result_available".So a Codex child that starts a long-lived shell (
countsForRun: false/ turn ends without waiting) can look “done” to the parent while the process is still alive — matching the state-DB evidence in the report.The shared
pendingBackgroundTurnItemshelper already exists and is used elsewhere in the orchestrator (e.g. interrupt cleanup). It is the natural check to fold intodelegatedTaskProgress(with callers loadingturnItems).Secondary path (distinct)
t3_thread_sendinto an already-finalized child can start new runs without reopening parent task tracking / delivering the later result. That overlaps open #13490 and open PR #15004 (follow-up result delivery). Those do not fix the premature-finalize case above.Loosely related: #13625 (completion sound while background work runs), #15993 (stale background banner).
Fix direction: include
pendingBackgroundTurnItems({ turnItems, runs })indelegatedTaskProgress(and load turn items in both finalize / status callers); keep finalization deferred until those items end. Separately, for send-into-finalized-child, either reject or reopen tracking (coordinate with #15004).Labeling
bug+via-triage.emilvakhitov commentedon Oct 7, 2026
Additional user-observed scenario with nested subagents:
From the original root thread, the remaining descendant activity is not visible, so the delegated workflow appears finished while B continues working.
This is an observation, not an independently reproduced case. It is unclear whether it has the same underlying cause as the
command_executiongap described above.Consolidating the related report from #16902 here to avoid parallel tracking.
jamesvillarrubia commentedon Oct 20, 2026
Same outcome with a Claude child, on 2026-10-20. The open work here is a native background subagent, not a shell command. The machine's installed runtime is 0.1.1-nightly.20261019.3373.
t3_thread_send. T3 tracks it as a delegated task.orchestration_v2_projection_subagents(origin: provider_native,status: running).status: running.The issue body says
delegatedTaskProgresschecks subagent entities. This record readstatus: runningwhen T3 finalized the task. The parent agent learned the work was unfinished only from the child's final text, and sent another follow-up at 18:31:57Z.juliusmarminge commentedon Oct 22, 2026
Triage read the report and follow-up, scanned all 949 open issues, and inspected current main at a12d6ed942. No earlier duplicate identified; #21837 covers a related follow-up lifecycle. Runtime reproduction was not attempted. This requires maintainer review under the automated triage restriction on MCP tool-surface changes: the requested behavior changes delegated-task completion returned by
task_statusand follow-up handling throught3_thread_send. No code changes or PR.seankoji commentedon Nov 2, 2026
Additional observed case on 2 November 2026: a delegated implementation agent displays Done while its required asynchronous review delegate is still running. Adding here because #16902 explicitly consolidated this nested-descendant visibility case into #16603.
Steps observed
delegate_task.These steps describe the supplied live-session evidence. No fresh isolated reproduction was run.
Expected behavior
The aggregate workflow status remains pending, for example Waiting for review/delegates, while a required descendant is active. The parent agent's completed turn can remain visible separately. Active required descendants should remain discoverable from ancestors.
Observable acceptance:
Actual behavior and evidence
claudeAgent/claude-opus-5-5run with a parent relation to the ended implementation delegate. Completed command activity was recorded at 14:01 AEDT, UTC+11, on 2 November 2026. That command completion is not evidence that the review itself completed.This is evidence of user-visible pending-work/status ambiguity. It does not establish premature backend task finalization, a reducer defect, lost tasks, cancelled work, or failed completion delivery. Root cause is unknown.
Environment and version limits
T3 Code on Linux, with nested T3 asynchronous delegation and a Claude Agent Opus 5.5 reviewer. Read-only installed metadata identifies CLI runtime
0.1.4-nightly.20261028.3814and desktop package0.1.3-nightly.20261023.3566. These are installed versions, not a verified binding of the screenshot or active server to either version; the exact affected running build is unknown.Impact and workaround
Users can mistake an ended parent turn for finished work and lose visibility of a required pending review. No verified UI workaround. The supplied evidence distinguishes parent-turn completion from outstanding review work; no claim is made that execution stopped.
Related reports and scope
#27126 concerns an async delegate hint stopping otherwise independent work. Here the review is required and ending the turn is expected; this report concerns the displayed aggregate state. #27700 concerns native Claude subagent background commands/monitors. This case uses a required T3 asynchronous review delegate, without assuming the same cause.
Sanitized text only. Private screenshots, transcripts, task identifiers, repository details and machine paths are intentionally omitted. No implementation, task cancellation, restart, or monitoring was performed for this report.
vilmerfrost commentedon Nov 2, 2026
Same bug with a Claude child, on
0.1.7-nightly.20261102.4066(macOS, Claude Code 2.1.316, Claude Opus 5.5). The report above uses a Codex child.Steps observed
delegate_task,isolation: "worktree",mode: "async".run_in_backgroundand ends its turn with the message "Waiting for background task<id>, the final evidence run."task_status.Result
While the script was still running,
task_statusreturned:{ "status": "completed", "workState": "result_available", "hasPendingChildRuns": false, "latestTerminalSummary": "Expect: about 25 minutes and little plan usage. Waiting for background task `<id>`, the final evidence run." }At the same moment, on the machine, the script's process and the child's
claudeprocess were alive, and the child had not pushed its branch.The parent was woken with a
[completed]message whose whole text was the waiting line. The same thing happens on every turn the child ends while it waits: in this session four workers sent about 15[completed]messages between them that were not final results. Each background completion starts a new child run through a provider continuation, and that run delivers another[completed].Impact
A parent has no reliable way to tell a finished child from a waiting one. Here both the parent agent and the person watching the app read a running worker as done. The parent has to inspect the child's checkpoint or processes to find out.
Not tested
I did not check whether calling
t3_background_waitinside the child changes this. I did not run a patched build.Related: #27700 covers the same state for native Claude subagents, and anthropics/claude-code#92952 covers the
completedstatus it comes from.Written with Claude Opus 5.5 in T3 Code.
hishamank commentedon Nov 2, 2026
Same nested case on v0.1.6 (Linux desktop app), with counts from one long-running session. All delegates were started with
delegate_task. The parents were Claude Opus 5.5, and the children were a mix of Claude and an ACP provider.Observed
From the code, the root row should read as finished: its status comes from its own runs and its own unfinished records, and nothing here is active. I read this from the state database and the source, and did not capture the sidebar itself.
Two paths, both in the state database
A follow-up closes while its nested work runs. In
finalizeAppOwnedSubagent, only the original task is held back byprogress.state. Example from orchestrator C:A run starts with no root record open. Orchestrator A's last root record closed at 10:31:31. A nested completion woke it at 12:06:13, and it opened a new delegate at 12:06:36. The root had no open record for any of this.
These compare timestamps across each orchestrator's own records. They count overlaps, and don't show that each overlap was visible in the UI.
Related work
Path 1 looks like what #21877 addresses, and path 2 looks like what #28462 addresses. I have not run a build with either PR, so I can't say whether the two together keep the root in a pending state for this whole tree.
Written with Claude Opus 5.5 in T3 Code.
jamesdchen commentedon Nov 2, 2026
Another case with a Claude child on v0.1.6 on Windows, using
mode: "async",isolation: "shared". The child's own final message says it isn't finished, but the task and the thread read as done.What happened. A child started a background Bash watcher, then ended its turn with this message:
The parent received
Delegated task ... [completed]with that text.t3_thread_readshows the thread asstatus: completed,activeRunId: null,runCount: 1, andt3_thread_listwithstatuses: [running, starting, queued, waiting]doesn't list it, while the watcher it describes is meant to still be alive.Why the status can't be relied on, in the same session. Two sibling children showed the same
completedstate after similar turns and then woke up later and did real work:provider-continuationtask ID, after its original task had reportedcompleted.So
completedcan mean either "finished" or "waiting on my own background work", and the parent can only tell by reading the child's prose.The practical cost. A parent seeing
completedon unfinished work starts a replacement, which then risks duplicating the original if it wakes. I had to start a replacement for this child with no way to confirm the first wouldn't resume. For long fan-outs this also produces many[completed]notifications carrying interim text such as "Waiting for the retry to report back."Expected. As this issue describes:
waiting_for_childrenor similar while a child has live background work, including Clauderun_in_backgroundcommands, and a finalcompletedonly when it has really ended.test(server): reproduce a follow-up task finishing while the child's …
fix(server): keep follow-up tasks pending until nested work finishes
dpearson2699 commentedon Nov 6, 2026
Same bug with a Claude child on
0.1.6-nightly.20261031.3977(macOS 27.0.1 arm64, desktop app on a local server). This adds what it does to the parent's Lineage panel.Observed
delegate_task(isolation: "worktree").run_in_background, calledt3_background_waiton them, and ended its turn. It woke and carried on each time a run finished.orchestration_v2_projection_subagents, every task record for the child readcompleted/delivered, one per turn. Each was written while the child's background runs were still pending; four of its test processes were alive on the machine at the time.What the parent's Lineage panel showed
While the child was working, the parent's thread details panel showed no active agent. Lineage showed only a collapsed "Previous agents · 1 failed · 194", with the live child folded in among the finished ones. The child's own panel listed the parent correctly.
From the source (checked against
mainat c52df24), this follows from the task status:activityRunStatusisnull. The subagent edge'sstatusinderiveThreadRelationshipGraph(packages/client-runtime/src/state/threadRelationships.ts) then falls back to the child'scompletedstatus, because the subagent record is no longer active.ThreadRelationshipsPanel(apps/web/src/components/chat/ThreadRelationshipsControl.tsx, thegroupBythat returns"previous") puts every subagent edge with a settled status under "Previous agents".So if the subagent record stayed
runningwhile the child waits on its own background work, the edge would take that status and the child would stay in the active list. The Lineage symptom should not need a separate client fix.Observed in a live session, not reproduced in isolation.
Filed by Claude Code (claude-opus-5-5) inside T3 Code, following
.github/triage/PLAYBOOK.md.test(server): reproduce a follow-up task finishing while the child's …
fix(server): keep follow-up tasks pending until nested work finishes
8 remaining items
fix(server): keep follow-up tasks pending until nested work finishes
Possemaster commentedon Nov 10, 2026
Still reproducible on t3 v0.1.8 (Claude Code 2.1.322 parent and child), via the follow-up path described above:
delegate_taskchild witht3_thread_send. The answer wasdelivery: "started"with a newtaskId.taskId, with that run-4 text as the result.t3_thread_wait(threadId, untilDelegatedWorkSettled: true), called while the background command was still running, also returnedresultRun= run 4 (completed, not timed out) before run 5 existed. Only a secondt3_thread_waiton run 5's id, thent3_thread_read, got the real report.So the parent sees a progress note as the final result, and
untilDelegatedWorkSettleddoes not wait for the pending background-exit wake either (the same gap as [Bug]: Original delegate_task task finalizes on a stale result in the gap before the child's background-exit wake turn #24297, on the follow-up task).test(server): reproduce a follow-up task finishing while the child's …
fix(server): keep follow-up tasks pending until nested work finishes
test(server): reproduce a follow-up task finishing while the child's …
fix(server): keep follow-up tasks pending until nested work finishes
juliusmarminge commentedon Nov 12, 2026
I tried to reproduce this on the current build and could not.
Commit 1e438c8 (origin/main). Not run in the live app: no provider on this VM reports server-tracked background commands (Codex and Claude need first-party OAuth, which is unavailable here). Reproduced instead in the real orchestrator with its in-memory event sink. I added the test 'subagent follow-ups > keeps a follow-up running while its child awaits a background command' to apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts. It reuses the startSelfQueuedFollowup fixture: the parent sends a follow-up to a finished delegated child, the follow-up run starts, the child's provider thread records pendingBackgroundTasks [{kind: 'command', awaited: true}], and the follow-up run completes with the text 'Waiting on the test run.'. On main the parent's follow-up subagent task settles with result 'Waiting on the test run.' while the awaited command is still pending. Run with: cd apps/server && vp test run src/orchestration-v2/DelegatedCompletionDelivery.test.ts -t follow-up. Result: 1 failed, 23 passed.
Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.
sammyhass commentedon Nov 12, 2026
Still happening on 0.1.9 (desktop app on a local server, macOS arm64, Claude Opus 5.5 parent and children). A unit test reproduces it on current main, and open PR #34958 fixes it in that test.
This case differs from the earlier no-repro test in two ways:
t3_thread_sendfollow-up, not the originaldelegate_task.provider_native), not a background command.Observed (one child, 12 Nov, UTC)
t3_thread_send(task…thread-send:a84b1471…, run 12 starts 16:13:22).Agenttool at 16:13:58, then ends its turn 8s later, waiting for B2's wake.completed/deliveredon the root, while B1 and B2 arerunninginorchestration_v2_projection_subagentson A's thread.Expected: the follow-up stays
waiting_for_childrenuntil the child's subagents settle, and the root shows delegated work still active below it.Cause
In
finalizeAppOwnedSubagent(apps/server/src/orchestration-v2/Orchestrator.ts, same on v0.1.9 and main),delegatedTaskProgressonly gates the original task:Every follow-up skips that check.
finalizeAppOwnedSubagentTaskthen finalizes it from its own run's outcome, without looking at subagents that run started.Test results
I added a test to
DelegatedCompletionDelivery.test.tsundersubagent follow-ups. A finished delegated child gets at3_thread_sendfollow-up. During that follow-up run the child starts aprovider_nativesubagent (status: running), then ends its turn with an interim reply.fd8e386fthe follow-up task settled on its handoff turn while the child's nested subagent was running: expected 'Waiting on the background subagent.' to equal null. The fixture check that the nested subagent is stillrunningpasses first.ac7bb5f2-t "follow-up".So #34958 also covers Claude native background subagents, not only the
app_ownedsubagent its own test uses. I haven't run the live app on that branch.Run:
cd apps/server && vp test run src/orchestration-v2/DelegatedCompletionDelivery.test.ts -t "follow-up"Test (insert before "waits for a run the follow-up's child queued on its own thread")
Open question
Claude starts the child's wake after a native subagent finishes, not a server
delegatedCompletion, so #34958'sdelegatedTaskRunswon't attach that wake to the follow-up. In this database those wakes appear on the parent as separateprovider-continuationtasks, so the final reply probably still arrives, as its own task. Not verified.Related: #16902 (same Root → A → B shape, merged into this one), #29128.
Triaged with Claude Code (Claude Opus 5.5) via T3 Code triage.
test(server): reproduce a follow-up task finishing while the child's …
fix(server): keep follow-up tasks pending until nested work finishes
test(server): reproduce a follow-up task finishing while the child's …
test(server): follow-up tasks stay pending until nested work finishes
test(server): reproduce a follow-up task finishing while the child's …
test(server): follow-up tasks stay pending until nested work finishes