Repository navigation
Conversation
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — The existing Stop path now performs orphan repair and enqueues recursive delegated-task stopping, which can affect active child workflows across threads rather than only correcting stale status. Tests cover the repair and unreadable-child cases, but the broader production side effect warrants human review. You can add or adjust custom eligibility rules. Learn more. |
|
Here is a data point from a real client for this PR, on State (read-only from
What Stop did I clicked Stop 14 times at 17:55:30–17:55:39 UTC while the thread was idle.
Two silent returns in
Two other routes don't reach these orphans either:
Not verified: which branch returns, or a fix. Investigated with Claude Code (Opus 5.5) in T3 Code. |
Problem
#20310 added a repair that cancels app-owned follow-ups left
runningafter losing their child-run binding (the #19002 bug; #19019 prevents new ones). The repair only runs onthread.stop, an internal command the server sends to delegated child threads. The Stop a user presses sendsrun.interruptwithholdQueue: true, so it never reaches the repair for the thread being stopped. Onmain, Stop interrupts the orphan's turn item and clears the waiting banner, but the task and its node stayrunning. Lineage can keep showing the agent as Running, andtask_statuskeeps reporting it as running.Change
cancelIdleOrphansmoves out ofdispatchThreadStopwith its guards and events unchanged, sorun.interruptwithholdQueue: truecan also run it on the stopped thread.thread.stopkeeps its two call sites, and each Stop path runs the repair once.On the user's Stop, the repair writes to its own copy of the pending events, and they are merged only if it succeeds. Otherwise it logs a warning, so a child that can't be read does not make Stop itself fail.
thread.stopkeeps its existing error behavior.Scope and approval
Refs #19002. In the maintainer triage, the fix includes letting "Stop settle stuck app-owned nodes whose child is idle". #20310 implemented this for
thread.stop; this PR applies the same repair to the Stop users press. Server only; no contract or client change.Verification
macOS arm64, base
1451e7cb.Stop clears an orphaned follow-up only when its child is finished (idle via run.interrupt)inThreadStop.test.ts. It reuses the fix(server): parent Stop clears orphaned delegated follow-ups #20310 fixture and dispatches the client's Stop command on the completed parent run. Onmainit fails withexpected 'running' to equal 'cancelled'; with this change it passes. The 12 existingthread.stopcases are unchanged apart from their titles.Stop still stops the thread when a delegated child cannot be read. Without the isolation it fails withOrchestratorProjectionError; it passes with the change, and onmain.vp test runforThreadStop,BackgroundWorkStop.integration,DelegatedCompletionDelivery,OrchestratorMcpToolkit.integration,SteeringCompletion.integration, andProjectionRecovery: 6 files, 95 tests pass.vp fmt --check,t3typecheck, andgit diff --checkpass.vp lintreports only the two warnings already onmain(the movedSchema.isand the unusedlayerUnavailable).main, the five turn items becameinterruptedwhile the five tasks and nodes stayedrunning. With this change, exactly those five tasks, nodes, and turn items becamecancelled, and the thread's other 36 tasks did not change.Not checked: a live provider session or a pass in a real client.
Model and harness: GPT-6.1-Sol in Codex (investigation, implementation, and review), coordinated by Claude Opus 5.5 in Claude Code, running in T3 Code.