[Bug]: Archiving an idle parent thread drops the result of its running delegated child#26075
Before submitting
- I searched existing issues and did not find a duplicate. (#15135 and #23451 cover archiving a thread during its own turn; this report is about an idle parent whose delegated child still runs.)
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Start a parent thread and let it delegate an asynchronous task with
delegate_task(an app-owned child on any provider). - Let the parent finish its turn while the child keeps working.
- Archive the parent from the sidebar, or from another thread with
t3_thread_organizeandaction: "archive". - Let the child complete.
Expected behavior
Either the archive is refused while delegated work is still active, or the child's result still reaches the parent after it is unarchived.
Actual behavior
The archive succeeds. When the child completes, its result is disposed and the parent never wakes. After unarchive nothing is delivered again. The result stays only in the task record, readable through task_status, which the agent never calls because it got no wake. A child's question is skipped the same way.
Checked on main 7873f53ada:
apps/server/src/orchestration-v2/Orchestrator.ts:2944rejectsthread.archiveonly when the thread is already archived. Nothing checks active delegated tasks.Orchestrator.ts:10971(planDelegatedCompletionDelivery): whenparentProjection.thread.archivedAt !== null, the task'scompletionDeliverybecomesdisposedandofferisfalse.apps/server/src/orchestration-v2/DelegatedTaskQuestionReactor.ts:67skips questions for an archived parent.packages/client-runtime/src/state/models.ts:118(threadRuntimeCanArchive) checks only the parent's own runtime, so web and mobile offer Archive while children run.
Impact
Minor bug or occasional failure
Version or commit
main at 7873f53ada; also present in 0.1.4-nightly.20261027.3770.
Environment
Windows 11, desktop app as host; parent on the Claude provider, children on Claude and Codex.
Workaround
None in the UI. After unarchive, the parent can be told to call task_status on the task id by hand.
Proposed fix
Reject thread.archive when the thread's projection has an app_owned subagent record with an active status (pending, running or waiting), with its own OrchestratorDispatchError cause that tells the caller to wait for or cancel those tasks. Completed and cancelled tasks do not block. The existing dispatch-error path already shows the cause in the web toast, the mobile alert and the MCP result. A pull request with this guard and a regression test follows.
Related: #23451 adds a guard for the thread's own active run at the same place; the two guards are independent and can coexist. #20072 propagates archive to descendants; with this guard, a cascade that reaches a child with its own running delegated task would be refused, which the maintainers may want to decide as a policy.