Stale MultiAgentV2 branch in legacy completion watcher obscures the active completion path
Summary
The legacy subagent completion watcher still contains a MultiAgentV2 delivery branch, even though normal V2 spawn/resume paths intentionally do not start that watcher. The active V2 completion path now lives in the session terminal-turn lifecycle instead.
This leaves a semantically stale branch and a direct unit test that can make changes appear correct without exercising production V2 routing.
Current behavior on main
AgentControl::maybe_start_completion_watchercontains achild_uses_multi_agent_v2branch that sends anInterAgentCommunicationmessage.- Normal V2 spawn and resume paths skip
maybe_start_completion_watcher. - V2 child completion is actually forwarded by the session terminal-turn path (
maybe_notify_parent_of_terminal_turn/forward_child_completion_to_parent). multi_agent_v2_completion_queues_message_for_direct_parentcalls the private watcher directly, so it covers a synthetic path rather than the normal V2 lifecycle.
I confirmed the mismatch by changing only the watcher's V2 trigger_turn behavior: the direct watcher unit test passed, while an integration test that spawned a real V2 child and completed its turn did not observe the corresponding automatic parent turn. The integration path only changed behavior when the session terminal-turn forwarding path was changed.
The watcher itself is not dead code: V1 still uses it. The concern is specifically the V2 branch inside the legacy watcher and the misleading V2 unit coverage around it.
Why this matters
- It is easy to patch the wrong completion path when investigating V2 notification or wake-up bugs.
- The watcher and session implementations can drift in delivery semantics such as
trigger_turn. - A passing direct unit test can give false confidence while the production V2 path remains unchanged.
- This obscures work on #15723, where the desired wake-up behavior needs to be implemented on the active path.
Related history and issues
- #15570 introduced the custom MultiAgent V2 watcher.
- #16308 added one-shot end-of-turn forwarding in the session lifecycle, which is now the active V2 completion path.
- #15723 requests durable completion notification and wake-up behavior.
- #33061 reports the opposite failure mode: a late subagent completion causing an extra user-visible response even with
trigger_turn: false.
Proposed direction
- Make
maybe_start_completion_watcherexplicitly V1-only and remove its V2-specific branch, arguments, imports, and direct V2 watcher test where they are no longer needed. - Replace the synthetic V2 watcher test with integration coverage that exercises spawn -> child terminal turn -> parent delivery through the session path.
- If V1 and V2 need shared code, share construction of a bounded, idempotent completion receipt rather than duplicating lifecycle ownership.
- Treat wake-up policy as a separate decision from this cleanup. A possible policy is:
- enqueue one durable terminal receipt;
- wake only when the parent is idle and has expressed that it is waiting for child work;
- defer or coalesce while the parent is busy;
- avoid unconditional
trigger_turn: true, given the duplicate-response scenario in #33061.
Design questions
- Should completion wake-up depend on explicit parent wait/join state rather than a fixed
trigger_turnvalue? - Should V1 watcher delivery and V2 session delivery share a
CompletionReceiptabstraction while keeping their lifecycle triggers separate?
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗