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
Copy file name to clipboardExpand all lines: .changeset/422-claude-spawn-confirmation.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,4 +3,4 @@
3
3
"agent-bundle": patch
4
4
---
5
5
6
-
Take Claude Code's own word for a subagent's parent: the parent's `Agent` `PostToolUse` carries the spawn `tool_use_id` and `tool_response.agentId`, the child's `agent_id`, so the lineage registry behind `request.lineage` now confirms the edge it matched from spawn-call ordering, fills in `subagent.toolCallId` for siblings it had claimed blind, places a `SubagentStart` no spawn window could (none open, or two parents with one — the start's id, type, time and stop are kept meanwhile), moves a child it had filed under the wrong parent and re-bases that child's descendants, and holds a child the host names before its start arrives. Add `'confirmed'` to `AgentLineageResolution` (`@agent-bundle/runtime`, `RequestLineageProvenance` in `agent-bundle`): a subagent's `parent`/`root`/`depth` resolve `confirmed` once every edge up to the root is host-named — right after `SubagentStart` for a background spawn, after `SubagentStop` for a foreground one — and stay `registry` otherwise. The Claude capability table's `lineage.parent`/`lineage.depth` rows record the confirmation and its timing, and the generated hosts page gains a "Conversation lineage" section rendered from every host's `lineage` rows. (#422)
6
+
Take Claude Code's own word for a subagent's parent: the parent's `Agent` `PostToolUse` carries the spawn `tool_use_id` and `tool_response.agentId`, the child's `agent_id`, so the lineage registry behind `request.lineage` now confirms the edge it matched from spawn-call ordering, fills in `subagent.toolCallId` for siblings it had claimed blind, places a `SubagentStart` no spawn window could (none open, or two parents with one — the start's id, type, time, stop, and any confirmations it issued for its own children are kept meanwhile, so a missed spawn hook at one level does not lose the subtree beneath it), moves a child it had filed under the wrong parent and re-bases that child's descendants, and holds a child the host names before its start arrives. Add `'confirmed'` to `AgentLineageResolution` (`@agent-bundle/runtime`, `RequestLineageProvenance` in `agent-bundle`): a subagent's `parent`/`root`/`depth` resolve `confirmed` once every edge up to the root is host-named — right after `SubagentStart` for a background spawn, after `SubagentStop` for a foreground one — and stay `registry` otherwise. The Claude capability table's `lineage.parent`/`lineage.depth` rows record the confirmation and its timing, and the generated hosts page gains a "Conversation lineage" section rendered from every host's `lineage` rows. (#422)
| Claude | Yes — `session_id` on every event is the root session (re-verified live: all 42 + 46 + 127 hook payloads across the three runs carry the root id — through resumed turns and a compaction too — and `CLAUDE_CODE_SESSION_ID` in every plugin process is the root id) | Only through the runtime's registry (inferred at `SubagentStart`); nothing in the child's payload |
324
+
| Claude | Yes — `session_id` on every event is the root session (re-verified live: all 42 + 46 + 127 hook payloads across the three runs carry the root id — through resumed turns and a compaction too — and `CLAUDE_CODE_SESSION_ID` in every plugin process is the root id) | Only through the runtime's registry (placed at `SubagentStart`, confirmed by the parent's `Agent` PostToolUse); nothing in the child's payload |
325
325
| Codex | Yes — `session_id` is the root thread on every event, and `_meta.x-codex-turn-metadata.session_id` on MCP calls | Yes on MCP calls (`parent_thread_id`); on hooks only through the registry (or the parent rollout at `SubagentStop`) |
326
326
| Cursor | Only through the registry — a child's payload carries neither root nor parent | Only through the registry (ordering-bound) |
327
327
@@ -354,7 +354,7 @@ root, and the parent-of-subagent chain — is the only identity-adjacent surface
354
354
| Roots first seen on a tool hook (Cursor restart or plugin load mid-conversation) | Cursor | §9 | Ours: workspace-scoped child binding plus correction (subtree re-rooted) when a bound conversation later carries a root-only event (`beforeSubmitPrompt`, `stop`, `sessionEnd`, `preCompact`) |
355
355
| Cursor CLI not exercised | Cursor | table above | Needs a signed-in `cursor-agent`; not attempted on the operator's account |
356
356
|~~Claude session used a scripted model~~| Claude | §8 | Closed 2026-09-03: two live-model sessions replace the stand-in fixture; every stand-in claim held, see §8 |
357
-
| Claude `PostToolUse(Agent).tool_response.agentId` not consumed by the registry | Claude | §1, §2 |The registry claims the newest unclaimed spawn under the root at `SubagentStart` and marks same-parent sibling cohorts `siblingsUncertain`; the parent's `Agent` PostToolUse could later firm those up. Not needed for any live run: even the orchestration run's two parallel spawns arrived serialised (`SubagentStart`before the next `Agent``PreToolUse`), so every claim was certain; left as an improvement|
357
+
|~~Claude `PostToolUse(Agent).tool_response.agentId` not consumed by the registry~~| Claude | §1, §2 |Closed 2026-09-03 (#422 follow-up PR): the registry now treats the parent's `Agent` PostToolUse as the host's word on the edge — it confirms the spawn-window match (`resolution: confirmed` once every edge to the root is host-named), fills in sibling `toolCallId`s claimed blind, places a `SubagentStart` no window could (an unplaced start keeps id/type/time/stop, and any confirmations it issued for its own children, until its edge is known), moves a child filed under the wrong parent and re-bases its descendants, and holds a child named before its start (orchestration row 13 → 14). Replays of the orchestration capture with row 64 or row 81 withheld recover the sequential agent and the depth-2 child from rows 99/101 alone|
358
358
|~~Claude interactive OAuth session expired; refresh fails~~| Claude | header table | Closed 2026-09-03: after the operator signed in again, the unmodified harness (`probe:install claude` byte-for-byte copy of `~/.claude/.credentials.json`) produced the signed-in 2.1.259 orchestration session. The two 2.1.257 runs had used a one-off re-seed of the isolated `.credentials.json` outside the harness (`docs/audits/2026-09-03-claude-live-session-proofs.md`); no credential-handling code was ever added |
359
359
|`stream-json` shows depth-1 subagent traffic only | Claude | §1 (orchestration run) | The nested agent's 7 tool calls appear in hooks (with its `agent_id`) but in no stream envelope; `task_started` still announces it with `spawn_depth: 2`. Hooks remain the only complete lineage source; recorded, no framework impact |
360
360
| Auto-compaction (`PreCompact trigger: "auto"`) not induced | Claude | §1 (orchestration run) | Manual `/compact` as a resumed `-p` prompt fires `PreCompact` → `SessionStart source: compact` → `PostCompact`; the automatic path would need a session near the context limit and was not attempted |
Copy file name to clipboardExpand all lines: packages/agent-bundle/src/adapters/capabilities/claude-2.1.250.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -177,7 +177,7 @@
177
177
"reason": "live model 2026-09-03, Claude Code 2.1.257 and 2.1.259: no hook payload a subagent itself emits names its parent (#422: SubagentStart carries only the child agent_id and agent_type, and a subagent's own hooks carry session_id + agent_id; the hooks reference's common input fields list session_id, transcript_path, cwd, permission_mode, agent_id and agent_type, no parent). The runtime registry places the child under the Agent/Task PreToolUse that is the newest unclaimed spawn when SubagentStart fires (resolution: registry) — exact for sequential spawns and for the 2.1.259 parallel pair (the host serialises SubagentStart before the next Agent PreToolUse), verified at depth 1 and 2 in background, foreground and parallel spawn paths, refused as id-not-resolvable when two parents have unclaimed spawns, toolCallId withheld when siblings from one parent were claimed blind — and then takes the host's own word for the edge: the parent's Agent PostToolUse carries the spawn tool_use_id, the parent's identity and tool_response.agentId, the child. That hook confirms the edge (resolution: confirmed once every edge up to the root is host-named), fills in the sibling→tool_use_id assignment, places a start the window could not, and moves a child the window filed under the wrong parent, re-basing its descendants. It arrives right after SubagentStart for a background spawn (status async_launched; in 2.1.259 even before it) but only after the child's SubagentStop for a foreground one (status completed), so a foreground child's own events resolve as registry for their whole life. The host's stream-json task_started envelope (task_id, tool_use_id, spawn_depth) agrees with every placement but is not delivered to plugins.",
178
178
"evidence": [
179
179
"live model 2026-09-03, Claude Code 2.1.257 (fixtures/host-lineage/claude-2.1.257.ndjson rows 17 and 41; claude-2.1.257-foreground.ndjson rows 47 and 49): the parent's Agent PostToolUse tool_response is {isAsync: true, status: \"async_launched\", agentId} for a background spawn and {status: \"completed\", agentId, agentType, content[]} for a foreground one; agentId equals the agent_id on the child's SubagentStart, SubagentStop and every hook the child fired.",
180
-
"live model 2026-09-03, Claude Code 2.1.259 (fixtures/host-lineage/claude-2.1.259-orchestration.ndjson): all four Agent PostToolUse payloads name their child — rows 13 and 17 (background Explore and general-purpose, async_launched; row 13 fires before that child's SubagentStart at row 14, so the registry holds the node by the host's word and the start adds its agent_type), row 99 (the depth-1 agent's own PostToolUse, carrying its agent_id, names the depth-2 child, completed) and row 101 (the root's, naming the depth-1 agent, completed); the depth-2 child's SubagentStart (row 82) and every hook it fires carry only its own agent_id and the root session_id, nothing that names the depth-1 parent.",
180
+
"live model 2026-09-03, Claude Code 2.1.259 (fixtures/host-lineage/claude-2.1.259-orchestration.ndjson): all four Agent PostToolUse payloads name their child — rows 13 and 17 (background Explore and general-purpose, async_launched; row 13 fires before that child's SubagentStart at row 14, so the registry holds the node by the host's word and the start adds its agent_type), row 99 (the depth-1 agent's own PostToolUse, carrying its agent_id, names the depth-2 child, completed) and row 101 (the root's, naming the depth-1 agent, completed); the depth-2 child's SubagentStart (row 82) and every hook it fires carry only its own agent_id and the root session_id, nothing that names the depth-1 parent. Replays of that capture with the root's spawn PreToolUse (row 64) or the depth-1 agent's (row 81) withheld leave the affected starts unplaced until rows 99/101 place them — the sequential agent under the root and the depth-2 child under it, with the start and stop times the hooks carried (packages/rsc-runtime/tests/lineage-registry.test.ts). The child's SubagentStop agent_transcript_path is <session>/subagents/agent-<agent_id>.jsonl for depth-1 and depth-2 children alike (rows 57, 61, 98, 100), and Stop/SubagentStop background_tasks[] entries carry id, type, status, description and agent_type but no tool_use_id or parent, so neither path nor list can bind a nested child to its parent.",
181
181
"uploaded 2026-09-03, Claude Code docs hooks reference (hooks-2.md, \"Common input fields\": agent_id and agent_type are the only subagent fields hooks add, no parent; \"SubagentStart\"/\"SubagentStop\": agent_id, agent_type, agent_transcript_path under the parent's transcript folder, background_tasks scoped to the parent session; \"PostToolUse\": tool_name, tool_input, tool_response, tool_use_id) and sub-agents reference (sub-agents-3.md, \"Resume subagents\": when a subagent completes Claude receives its agent ID — the id the registry matches to agent_id — and the one-shot built-in Explore and Plan agents return no agent ID to Claude, so a spawn whose tool_response omits agentId keeps the registry's own match; observed 2.1.259 background Explore responses did carry agentId)."
0 commit comments