fix(server): archive refuses a thread with running delegated tasks#26078

open1
main
GitHub fork: fix/archive-parent-with-active-children
opened14d agobySSouthCarpet
View on GitHubTwo-way sync enabledPR last imported 3h ago

Problem

An idle parent thread can be archived while an app-owned delegated child still runs. When the child completes, planDelegatedCompletionDelivery disposes the result because the parent is archived, so the parent never wakes and nothing is delivered after unarchive. Details and line references are in #26075.

Change

thread.archive is refused when the thread's projection has an app_owned subagent record whose status is active (isOrchestrationV2WorkActive: pending, running or waiting). The guard sits after the "already archived" check and fails with its own OrchestratorDispatchError cause: Thread <id> has running delegated tasks. Wait for them or cancel them before archiving. Completed, failed, cancelled and interrupted tasks do not block, and provider-native subagents are not counted.

No client, contract or delivery change. The existing dispatch-error path already carries the cause to the web toast ("Failed to archive thread"), the mobile alert and the MCP t3_thread_organize result. One sentence in docs/user/thread-sidebar.md tells the user to wait for or cancel delegated tasks before archiving the parent.

Scope and approval

Fixes #26075

A small server guard, 16 lines plus one regression test. #23451 adds an independent guard for the thread's own active run at the same place; both can coexist, and whichever lands second needs a small rebase. #20072 propagates archive to descendants; with this guard a cascade that reaches a child with its own running delegated task is refused, which is noted in #26075 for a policy decision.

Verification

  • New test rejects archiving an idle parent until its delegated child completes in apps/server/src/orchestration-v2/runtimeLayer.test.ts: a parent delegates an app-owned task, its own run completes, thread.archive fails with the exact cause and archivedAt stays null; after the child completes, archive succeeds. With the guard removed the test fails because the archive command is accepted.
  • vp test run src/orchestration-v2/runtimeLayer.test.ts: 90 of 90 passed, including the existing archive, cancellation, replay and unarchive cases.
  • vp run check:changed: format, lint, knip (two passes), graphql, typecheck (server, scripts, evals) and the selected tests (4 files, 103 tests) pass.
  • Not checked: a live app run of the new message in web, mobile or MCP (source read only), combined behaviour with #20072's cascade.

Created with GPT-6.1 Sol in Codex running in T3 Code. Verified with Claude Sonnet 5.5 in Claude Code running in T3 Code.

Fixes pingdotgg/t3code#26075

Checks

20 successful · 12 skipped
All checks passed
9458715

Added 1 commit

  • fix(server): archive refuses a thread with running delegated tasks9458715
Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

Archiving a thread now fails when it has an active app-owned delegated task. The regression test verifies that archiving succeeds after the task completes. The thread sidebar documentation describes the restriction.

Changes: Delegated task archive guard

Layer / File(s)Summary
Check delegated tasks before archiving
apps/server/src/orchestration-v2/Orchestrator.ts, apps/server/src/orchestration-v2/runtimeLayer.test.ts, docs/user/thread-sidebar.md
The orchestrator rejects archiving when an app-owned delegated task is active. The test verifies that the thread remains unarchived until the task completes, then verifies that archiving succeeds. The sidebar documentation says to wait for delegated tasks to finish or cancel them.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested labels: bugfix, size:M

Suggested reviewers: juliusmarminge, t3dotgg, macroscopeapp

Merge Risk: External image Minimal · up to 94587

Archiving is blocked while delegated work is active, and no actionable merge-blocking risk remains after normal checks.

Pre-merge checks: Passed 4

Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main change: preventing archive operations for threads with running delegated tasks.
Linked Issues checkPassedFor #26075, Orchestrator.ts now checks thread.archive after the already-archived check. It rejects an app_owned subagent when isOrchestrationV2WorkActive(task.status) is true. The error cause …
Out of Scope Changes checkPassedThe changes stay within #26075. The server guard implements the selected refusal outcome. The test verifies the guard. The documentation explains the new archive condition. No unrelated product behavi…
Description checkPassedThe description covers the problem, change, scope and approval context, and focused verification. It also states what was not checked.
Full details: Linked Issues check

Explanation

For #26075, Orchestrator.ts now checks thread.archive after the already-archived check. It rejects an app_owned subagent when isOrchestrationV2WorkActive(task.status) is true. The error cause requests completion or cancellation. Provider-native and inactive tasks do not match the guard. The regression test verifies rejection, the exact cause, unchanged archivedAt, and successful archiving after child completion. The documentation states the required user action.

Full details: Out of Scope Changes check

Explanation

The changes stay within #26075. The server guard implements the selected refusal outcome. The test verifies the guard. The documentation explains the new archive condition. No unrelated product behavior or client implementation changes are present.

Finishing Touches

🧪 Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
External image Recent review info

External image Run configuration

External image Commits

Reviewing files that changed from the base of the PR and between d0b81ceb6e225a7386203d590ec84def4abed281 and 9458715adf57359a0452136c1a8d1a0b9c6c4655.

External image Files selected for processing: 3

  • apps/server/src/orchestration-v2/Orchestrator.ts
  • apps/server/src/orchestration-v2/runtimeLayer.test.ts
  • docs/user/thread-sidebar.md

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.