pi-subagents 0.70.0 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +4 -2
  3. package/agents/claude-code-writer.md +1 -0
  4. package/agents/codex-exec-writer.md +1 -0
  5. package/agents/cursor-agent-writer.md +1 -0
  6. package/agents/worker.md +3 -2
  7. package/docs/agents.md +7 -8
  8. package/docs/configuration.md +17 -1
  9. package/docs/extension-api.md +5 -1
  10. package/docs/models.md +1 -1
  11. package/docs/observability.md +17 -13
  12. package/docs/standalone-background.md +4 -4
  13. package/docs/tool-reference.md +9 -11
  14. package/docs/workflows.md +1 -1
  15. package/inspector-runner.mjs +1 -1
  16. package/package.json +2 -2
  17. package/skills/pi-subagents/SKILL.md +1 -0
  18. package/skills/pi-subagents/references/constraints-and-recipes.md +5 -2
  19. package/skills/pi-subagents/references/execution-controls.md +2 -2
  20. package/skills/pi-subagents/references/management-authoring-rpc.md +3 -3
  21. package/skills/pi-subagents/references/multi-lane-orchestration.md +8 -0
  22. package/skills/pi-subagents/references/prompting-and-roles.md +14 -13
  23. package/src/agents/agent-management.d.ts.map +1 -1
  24. package/src/agents/agent-management.js +11 -25
  25. package/src/agents/agent-management.js.map +1 -1
  26. package/src/agents/agent-serializer.d.ts.map +1 -1
  27. package/src/agents/agent-serializer.js +0 -4
  28. package/src/agents/agent-serializer.js.map +1 -1
  29. package/src/agents/agents.d.ts +17 -4
  30. package/src/agents/agents.d.ts.map +1 -1
  31. package/src/agents/agents.js +39 -22
  32. package/src/agents/agents.js.map +1 -1
  33. package/src/agents/proactive-skills.d.ts +1 -0
  34. package/src/agents/proactive-skills.d.ts.map +1 -1
  35. package/src/agents/proactive-skills.js +3 -1
  36. package/src/agents/proactive-skills.js.map +1 -1
  37. package/src/agents/runtime-agent-registry.d.ts +8 -3
  38. package/src/agents/runtime-agent-registry.d.ts.map +1 -1
  39. package/src/agents/runtime-agent-registry.js +14 -9
  40. package/src/agents/runtime-agent-registry.js.map +1 -1
  41. package/src/agents/skills.d.ts +2 -0
  42. package/src/agents/skills.d.ts.map +1 -1
  43. package/src/agents/skills.js +41 -8
  44. package/src/agents/skills.js.map +1 -1
  45. package/src/api/delegation.d.ts +14 -0
  46. package/src/api/delegation.d.ts.map +1 -1
  47. package/src/extension/index.d.ts.map +1 -1
  48. package/src/extension/index.js +5 -1
  49. package/src/extension/index.js.map +1 -1
  50. package/src/extension/rpc.d.ts +1 -1
  51. package/src/extension/rpc.d.ts.map +1 -1
  52. package/src/extension/rpc.js +11 -1
  53. package/src/extension/rpc.js.map +1 -1
  54. package/src/extension/tool-activation.d.ts +9 -0
  55. package/src/extension/tool-activation.d.ts.map +1 -0
  56. package/src/extension/tool-activation.js +172 -0
  57. package/src/extension/tool-activation.js.map +1 -0
  58. package/src/extension/tool-description.d.ts +4 -4
  59. package/src/extension/tool-description.d.ts.map +1 -1
  60. package/src/extension/tool-description.js +1 -1
  61. package/src/intercom/intercom-bridge.d.ts.map +1 -1
  62. package/src/intercom/intercom-bridge.js +2 -0
  63. package/src/intercom/intercom-bridge.js.map +1 -1
  64. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  65. package/src/runs/background/active-async-capacity.js +4 -33
  66. package/src/runs/background/active-async-capacity.js.map +1 -1
  67. package/src/runs/background/async-execution.d.ts.map +1 -1
  68. package/src/runs/background/async-execution.js +5 -67
  69. package/src/runs/background/async-execution.js.map +1 -1
  70. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  71. package/src/runs/background/async-job-tracker.js +25 -19
  72. package/src/runs/background/async-job-tracker.js.map +1 -1
  73. package/src/runs/background/async-resume.d.ts +1 -1
  74. package/src/runs/background/async-resume.d.ts.map +1 -1
  75. package/src/runs/background/async-resume.js +8 -6
  76. package/src/runs/background/async-resume.js.map +1 -1
  77. package/src/runs/background/async-status.d.ts +1 -0
  78. package/src/runs/background/async-status.d.ts.map +1 -1
  79. package/src/runs/background/async-status.js +1 -0
  80. package/src/runs/background/async-status.js.map +1 -1
  81. package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
  82. package/src/runs/background/binary-bootstrap.js +28 -6
  83. package/src/runs/background/binary-bootstrap.js.map +1 -1
  84. package/src/runs/background/fleet-view.d.ts.map +1 -1
  85. package/src/runs/background/fleet-view.js +26 -7
  86. package/src/runs/background/fleet-view.js.map +1 -1
  87. package/src/runs/background/notify.d.ts +11 -0
  88. package/src/runs/background/notify.d.ts.map +1 -1
  89. package/src/runs/background/notify.js +71 -3
  90. package/src/runs/background/notify.js.map +1 -1
  91. package/src/runs/background/process-terminal-candidate.d.ts +18 -0
  92. package/src/runs/background/process-terminal-candidate.d.ts.map +1 -0
  93. package/src/runs/background/process-terminal-candidate.js +97 -0
  94. package/src/runs/background/process-terminal-candidate.js.map +1 -0
  95. package/src/runs/background/process-terminal.d.ts +3 -15
  96. package/src/runs/background/process-terminal.d.ts.map +1 -1
  97. package/src/runs/background/process-terminal.js +19 -96
  98. package/src/runs/background/process-terminal.js.map +1 -1
  99. package/src/runs/background/retained-children.d.ts.map +1 -1
  100. package/src/runs/background/retained-children.js +3 -2
  101. package/src/runs/background/retained-children.js.map +1 -1
  102. package/src/runs/background/run-child-session.d.ts +1 -0
  103. package/src/runs/background/run-child-session.d.ts.map +1 -1
  104. package/src/runs/background/run-child-session.js.map +1 -1
  105. package/src/runs/background/run-status.d.ts.map +1 -1
  106. package/src/runs/background/run-status.js +11 -5
  107. package/src/runs/background/run-status.js.map +1 -1
  108. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  109. package/src/runs/background/runner-aliases.js +28 -16
  110. package/src/runs/background/runner-aliases.js.map +1 -1
  111. package/src/runs/background/runner-startup-failure.d.ts +14 -0
  112. package/src/runs/background/runner-startup-failure.d.ts.map +1 -0
  113. package/src/runs/background/runner-startup-failure.js +47 -0
  114. package/src/runs/background/runner-startup-failure.js.map +1 -0
  115. package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
  116. package/src/runs/background/stale-run-reconciler.js +9 -1
  117. package/src/runs/background/stale-run-reconciler.js.map +1 -1
  118. package/src/runs/background/subagent-runner-bootstrap.d.ts +14 -0
  119. package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -0
  120. package/src/runs/background/subagent-runner-bootstrap.js +277 -0
  121. package/src/runs/background/subagent-runner-bootstrap.js.map +1 -0
  122. package/src/runs/background/subagent-runner.d.ts +5 -7
  123. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  124. package/src/runs/background/subagent-runner.js +67 -274
  125. package/src/runs/background/subagent-runner.js.map +1 -1
  126. package/src/runs/background/workflow-terminal-proof.d.ts +18 -0
  127. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -0
  128. package/src/runs/background/workflow-terminal-proof.js +68 -0
  129. package/src/runs/background/workflow-terminal-proof.js.map +1 -0
  130. package/src/runs/foreground/execution.d.ts.map +1 -1
  131. package/src/runs/foreground/execution.js +43 -111
  132. package/src/runs/foreground/execution.js.map +1 -1
  133. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  134. package/src/runs/foreground/subagent-executor.js +108 -17
  135. package/src/runs/foreground/subagent-executor.js.map +1 -1
  136. package/src/runs/shared/acceptance.d.ts.map +1 -1
  137. package/src/runs/shared/acceptance.js +7 -40
  138. package/src/runs/shared/acceptance.js.map +1 -1
  139. package/src/runs/shared/child-hooks.d.ts +1 -3
  140. package/src/runs/shared/child-hooks.d.ts.map +1 -1
  141. package/src/runs/shared/child-hooks.js +1 -16
  142. package/src/runs/shared/child-hooks.js.map +1 -1
  143. package/src/runs/shared/child-launch.d.ts +0 -2
  144. package/src/runs/shared/child-launch.d.ts.map +1 -1
  145. package/src/runs/shared/child-launch.js +4 -2
  146. package/src/runs/shared/child-launch.js.map +1 -1
  147. package/src/runs/shared/child-runtime-config.d.ts +4 -0
  148. package/src/runs/shared/child-runtime-config.d.ts.map +1 -1
  149. package/src/runs/shared/child-runtime-config.js.map +1 -1
  150. package/src/runs/shared/child-session.d.ts +8 -9
  151. package/src/runs/shared/child-session.d.ts.map +1 -1
  152. package/src/runs/shared/child-session.js +67 -2
  153. package/src/runs/shared/child-session.js.map +1 -1
  154. package/src/runs/shared/dynamic-fanout.js +1 -1
  155. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  156. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  157. package/src/runs/shared/external-cli-runner.js +3 -1
  158. package/src/runs/shared/external-cli-runner.js.map +1 -1
  159. package/src/runs/shared/git-environment.d.ts +3 -0
  160. package/src/runs/shared/git-environment.d.ts.map +1 -0
  161. package/src/runs/shared/git-environment.js +28 -0
  162. package/src/runs/shared/git-environment.js.map +1 -0
  163. package/src/runs/shared/mcp-config-sources.d.ts +3 -0
  164. package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
  165. package/src/runs/shared/mcp-config-sources.js.map +1 -1
  166. package/src/runs/shared/mcp-direct-tool-allowlist.js +1 -1
  167. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  168. package/src/runs/shared/mcp-direct-tool-grant.d.ts +3 -1
  169. package/src/runs/shared/mcp-direct-tool-grant.d.ts.map +1 -1
  170. package/src/runs/shared/mcp-direct-tool-grant.js +19 -5
  171. package/src/runs/shared/mcp-direct-tool-grant.js.map +1 -1
  172. package/src/runs/shared/parallel-utils.d.ts +0 -1
  173. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  174. package/src/runs/shared/parallel-utils.js.map +1 -1
  175. package/src/runs/shared/pi-spawn.d.ts +10 -1
  176. package/src/runs/shared/pi-spawn.d.ts.map +1 -1
  177. package/src/runs/shared/pi-spawn.js +86 -7
  178. package/src/runs/shared/pi-spawn.js.map +1 -1
  179. package/src/runs/shared/single-output.d.ts.map +1 -1
  180. package/src/runs/shared/single-output.js +10 -2
  181. package/src/runs/shared/single-output.js.map +1 -1
  182. package/src/runs/shared/structured-output.d.ts +7 -0
  183. package/src/runs/shared/structured-output.d.ts.map +1 -1
  184. package/src/runs/shared/structured-output.js +74 -0
  185. package/src/runs/shared/structured-output.js.map +1 -1
  186. package/src/runs/shared/subagent-control.d.ts.map +1 -1
  187. package/src/runs/shared/subagent-control.js +6 -19
  188. package/src/runs/shared/subagent-control.js.map +1 -1
  189. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  190. package/src/runs/shared/subagent-prompt-runtime.js +23 -7
  191. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  192. package/src/runs/shared/tool-availability.js +1 -1
  193. package/src/runs/shared/tool-availability.js.map +1 -1
  194. package/src/shared/child-session-name.d.ts.map +1 -1
  195. package/src/shared/child-session-name.js +4 -2
  196. package/src/shared/child-session-name.js.map +1 -1
  197. package/src/shared/fork-context.d.ts +4 -0
  198. package/src/shared/fork-context.d.ts.map +1 -1
  199. package/src/shared/fork-context.js +9 -4
  200. package/src/shared/fork-context.js.map +1 -1
  201. package/src/shared/launch-contract.d.ts.map +1 -1
  202. package/src/shared/launch-contract.js +0 -1
  203. package/src/shared/launch-contract.js.map +1 -1
  204. package/src/shared/pruned-fork.d.ts +1 -1
  205. package/src/shared/pruned-fork.d.ts.map +1 -1
  206. package/src/shared/pruned-fork.js +70 -65
  207. package/src/shared/pruned-fork.js.map +1 -1
  208. package/src/shared/types.d.ts +32 -13
  209. package/src/shared/types.d.ts.map +1 -1
  210. package/src/shared/types.js +2 -0
  211. package/src/shared/types.js.map +1 -1
  212. package/src/slash/delegation-adapters.d.ts +7 -1
  213. package/src/slash/delegation-adapters.d.ts.map +1 -1
  214. package/src/slash/delegation-adapters.js +17 -0
  215. package/src/slash/delegation-adapters.js.map +1 -1
  216. package/src/slash/prompt-template-bridge.d.ts.map +1 -1
  217. package/src/slash/prompt-template-bridge.js +14 -1
  218. package/src/slash/prompt-template-bridge.js.map +1 -1
  219. package/src/slash/prompt-workflows.d.ts.map +1 -1
  220. package/src/slash/prompt-workflows.js +16 -2
  221. package/src/slash/prompt-workflows.js.map +1 -1
  222. package/src/slash/slash-commands.d.ts.map +1 -1
  223. package/src/slash/slash-commands.js +5 -251
  224. package/src/slash/slash-commands.js.map +1 -1
  225. package/src/slash/subagent-cost.d.ts +29 -0
  226. package/src/slash/subagent-cost.d.ts.map +1 -0
  227. package/src/slash/subagent-cost.js +271 -0
  228. package/src/slash/subagent-cost.js.map +1 -0
  229. package/src/slash/subagents-admin.d.ts.map +1 -1
  230. package/src/slash/subagents-admin.js +4 -5
  231. package/src/slash/subagents-admin.js.map +1 -1
  232. package/src/tui/fleet.d.ts.map +1 -1
  233. package/src/tui/fleet.js +4 -0
  234. package/src/tui/fleet.js.map +1 -1
  235. package/src/tui/render.d.ts.map +1 -1
  236. package/src/tui/render.js +16 -11
  237. package/src/tui/render.js.map +1 -1
  238. package/src/watchdog/diff-tool.d.ts +2 -1
  239. package/src/watchdog/diff-tool.d.ts.map +1 -1
  240. package/src/watchdog/diff-tool.js +9 -3
  241. package/src/watchdog/diff-tool.js.map +1 -1
  242. package/src/watchdog/permission-arbiter.d.ts.map +1 -1
  243. package/src/watchdog/permission-arbiter.js +12 -8
  244. package/src/watchdog/permission-arbiter.js.map +1 -1
  245. package/src/watchdog/register-child.d.ts +3 -1
  246. package/src/watchdog/register-child.d.ts.map +1 -1
  247. package/src/watchdog/register-child.js +12 -3
  248. package/src/watchdog/register-child.js.map +1 -1
  249. package/src/watchdog/review.d.ts +1 -0
  250. package/src/watchdog/review.d.ts.map +1 -1
  251. package/src/watchdog/review.js +12 -6
  252. package/src/watchdog/review.js.map +1 -1
  253. package/src/watchdog/runtime.d.ts +1 -1
  254. package/src/watchdog/runtime.d.ts.map +1 -1
  255. package/src/watchdog/runtime.js +2 -1
  256. package/src/watchdog/runtime.js.map +1 -1
  257. package/src/watchdog/turn-delta.d.ts +5 -1
  258. package/src/watchdog/turn-delta.d.ts.map +1 -1
  259. package/src/watchdog/turn-delta.js +9 -5
  260. package/src/watchdog/turn-delta.js.map +1 -1
  261. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  262. package/src/workflows/scripted-workflow.js +1 -3
  263. package/src/workflows/scripted-workflow.js.map +1 -1
  264. package/src/runs/shared/completion-evidence.d.ts +0 -31
  265. package/src/runs/shared/completion-evidence.d.ts.map +0 -1
  266. package/src/runs/shared/completion-evidence.js +0 -54
  267. package/src/runs/shared/completion-evidence.js.map +0 -1
  268. package/src/runs/shared/completion-guard.d.ts +0 -35
  269. package/src/runs/shared/completion-guard.d.ts.map +0 -1
  270. package/src/runs/shared/completion-guard.js +0 -214
  271. package/src/runs/shared/completion-guard.js.map +0 -1
  272. package/src/runs/shared/llm-intent-arbiter.d.ts +0 -48
  273. package/src/runs/shared/llm-intent-arbiter.d.ts.map +0 -1
  274. package/src/runs/shared/llm-intent-arbiter.js +0 -235
  275. package/src/runs/shared/llm-intent-arbiter.js.map +0 -1
  276. package/src/runs/shared/task-intent.d.ts +0 -38
  277. package/src/runs/shared/task-intent.d.ts.map +0 -1
  278. package/src/runs/shared/task-intent.js +0 -213
  279. package/src/runs/shared/task-intent.js.map +0 -1
@@ -53,8 +53,7 @@ import { normalizeExtensionBindings } from "../shared/extension-bindings.js";
53
53
  import { resolveRequiredChildExtensions } from "../../shared/required-child-extensions.js";
54
54
  import { finalizeSingleOutput, injectSingleOutputInstruction, normalizeSingleOutputOverride, outputPathMappingFromTask, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.js";
55
55
  import { assertJsonSchemaObject, cleanupStructuredOutputRuntime, createStructuredOutputRuntime } from "../shared/structured-output.js";
56
- import { compactForegroundDetails, getSingleResultOutput, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage, toAgentToolUsage } from "../../shared/utils.js";
57
- import { createTaskMutationArbiter } from "../shared/llm-intent-arbiter.js";
56
+ import { compactForegroundDetails, getSingleResultOutput, PROMPT_REDACTED, readStatus, resolveChildCwd, sumResultsCost, sumResultsUsage, toAgentToolUsage } from "../../shared/utils.js";
58
57
  import { discardPreservedWorktrees, formatParallelHandoffError, formatParallelHandoffReference, formatStoredParallelHandoffCleanup, parallelHandoffPath, readParallelHandoffManifest, recordParallelHandoffMerge, recordParallelHandoffSupersession, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
59
58
  import { summarizeContextModes } from "../shared/context-mode.js";
60
59
  import { attachNestedChildrenToResultChildren, buildSubagentResultIntercomPayload, deliverSubagentResultIntercomEvent, formatSubagentResultReceipt, resolveSubagentResultStatus, stripDetailsOutputsForIntercomReceipt, } from "../../intercom/result-intercom.js";
@@ -101,7 +100,7 @@ import { deepFreezeWorkflowArgs, normalizeWorkflowArgs, resolveWorkflowResource
101
100
  import { stableJsonDigest } from "../../shared/launch-contract.js";
102
101
  import { cleanupWorktrees, createWorktrees, preflightWorktreeSource, withWorktreeTransaction, diffWorktrees, formatWorktreeDiffSummary, } from "../shared/worktree.js";
103
102
  import { createWorktreeCleanupPlan, formatWorktreeCleanupPlan } from "../shared/worktree-cleanup-plan.js";
104
- import { DIRS, DEFAULT_ARTIFACT_CONFIG, DEFAULT_FORK_PREAMBLE, SUBAGENT_ACTIONS, SUBAGENT_CONTROL_EVENT, SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, checkSubagentDepth, resolveChildMaxSubagentDepth, resolveCurrentMaxSubagentDepth, resolveMaxSubagentSpawnsPerRun, wrapForkTask, } from "../../shared/types.js";
103
+ import { DIRS, DEFAULT_ARTIFACT_CONFIG, DEFAULT_FORK_PREAMBLE, SUBAGENT_ACTIONS, SUBAGENT_ASYNC_STARTED_EVENT, SUBAGENT_CHILD_STATUS_EVENT, SUBAGENT_CONTROL_EVENT, SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, SUBAGENT_LIFECYCLE_ARTIFACT_VERSION, checkSubagentDepth, resolveChildMaxSubagentDepth, resolveCurrentMaxSubagentDepth, resolveMaxSubagentSpawnsPerRun, wrapForkTask, } from "../../shared/types.js";
105
104
  import { deriveChildSessionName } from "../../shared/child-session-name.js";
106
105
  const MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete", "eject", "disable", "enable", "reset", "grant-spawn-budget", "watchdog.configure", "mission.create", "mission.update", "mission.resolve-decision", "mission.attach-run", "mission.close", "inspector.open", "inspector.close", "project.open", "project.close", "worktree.discard", "worktree.cleanup", "lane.recordMerge", "lane.recordSupersession", "refine", "refine.rollback", "dismiss", "schedule.create", "schedule.pause", "schedule.resume", "schedule.run", "schedule.run-due", "schedule.delete"]);
107
106
  const DESTRUCTIVE_MANAGEMENT_ACTIONS = new Set(["delete", "eject", "disable", "reset", "mission.close", "worktree.discard", "refine.rollback", "inspector.close", "project.close", "stop", "interrupt", "schedule.delete"]);
@@ -1517,7 +1516,7 @@ async function resumeAsyncRun(input) {
1517
1516
  const discoveredAgents = discovered.agents;
1518
1517
  const unknownAgentDiagnosticContext = diagnosticContextFromDiscovery(discovered, effectiveCwd, scope);
1519
1518
  const modelScope = discovered.modelScope;
1520
- const sessionName = resolveIntercomSessionTarget(input.deps.pi.getSessionName(), input.ctx.sessionManager.getSessionId());
1519
+ const sessionName = resolveIntercomSessionTarget(input.deps.childRuntime?.intercomSessionName ?? input.deps.pi.getSessionName(), input.ctx.sessionManager.getSessionId());
1521
1520
  const recoveryDescriptor = "recoveryDescriptor" in target ? target.recoveryDescriptor : undefined;
1522
1521
  const recoveryContext = recoveryDescriptor?.context ?? (input.params.context === "profile" ? undefined : input.params.context);
1523
1522
  const intercomBridge = resolveIntercomBridge({
@@ -1559,7 +1558,7 @@ async function resumeAsyncRun(input) {
1559
1558
  if (target.source === "async" && target.runner?.type === "external-job") {
1560
1559
  if (attachChain)
1561
1560
  return { content: [{ type: "text", text: "External-job follow-up does not support chain attachment. Use action='resume' with message instead." }], isError: true, details: { mode: "management", results: [] } };
1562
- return resumeExternalJobFollowUp({
1561
+ const resumed = await resumeExternalJobFollowUp({
1563
1562
  target,
1564
1563
  followUp,
1565
1564
  baseAgentConfig,
@@ -1573,6 +1572,10 @@ async function resumeAsyncRun(input) {
1573
1572
  parentSessionFile,
1574
1573
  absoluteDeadlineAt: input.absoluteDeadlineAt,
1575
1574
  });
1575
+ const resumedRunId = resumed.details.runId ?? resumed.details.asyncId;
1576
+ if (!resumed.isError && resumedRunId)
1577
+ input.onLaunch?.({ agent: target.agent, async: true, runId: resumedRunId });
1578
+ return resumed;
1576
1579
  }
1577
1580
  if (attachChain) {
1578
1581
  if (target.source !== "async") {
@@ -1680,6 +1683,7 @@ async function resumeAsyncRun(input) {
1680
1683
  return result;
1681
1684
  }
1682
1685
  const attachedId = result.details.asyncId ?? runId;
1686
+ input.onLaunch?.({ agent: target.agent, ...(target.sessionFile ? { sessionFile: target.sessionFile } : {}), async: true, runId: attachedId });
1683
1687
  const lines = [
1684
1688
  `Attached async subagent ${target.runId} as the first step of a new chain.`,
1685
1689
  `Chain run: ${attachedId}`,
@@ -1696,11 +1700,14 @@ async function resumeAsyncRun(input) {
1696
1700
  if (!revivalSessionFile) {
1697
1701
  return { content: [{ type: "text", text: `Async run '${target.runId}' child ${target.index} does not have a persisted session file to resume from.` }], isError: true, details: { mode: "management", results: [] } };
1698
1702
  }
1703
+ if (input.params.baseRef !== undefined && "managedWorktree" in target && target.managedWorktree === true) {
1704
+ return { content: [{ type: "text", text: "Cannot resume with baseRef: retained managed-worktree children continue in their existing worktree. Start a new worktree run from that base ref instead." }], isError: true, details: { mode: "management", results: [] } };
1705
+ }
1699
1706
  if (target.source === "async" && asyncReviveRequiresRecoveryDescriptor(target)) {
1700
1707
  return { content: [{ type: "text", text: `Async child '${target.runId}' is missing its required run fan-out recovery identity. Start a new run instead.` }], isError: true, details: { mode: "management", results: [] } };
1701
1708
  }
1702
- if (input.params.baseRef !== undefined && "managedWorktree" in target && target.managedWorktree === true) {
1703
- return { content: [{ type: "text", text: "Cannot resume with baseRef: retained managed-worktree children continue in their existing worktree. Start a new worktree run from that base ref instead." }], isError: true, details: { mode: "management", results: [] } };
1709
+ if (target.source === "nested" && !target.recoveryDescriptor) {
1710
+ return { content: [{ type: "text", text: `Nested child '${target.runId}' is missing its required recovery identity. Start a new run instead.` }], isError: true, details: { mode: "management", results: [] } };
1704
1711
  }
1705
1712
  const recoveryAgentConfig = recoveryDescriptor ? applySteeringRecoveryAgentConfig(baseAgentConfig, recoveryDescriptor) : baseAgentConfig;
1706
1713
  const agentConfig = intercomBridge.active ? applyIntercomBridgeToAgent(recoveryAgentConfig, intercomBridge) : recoveryAgentConfig;
@@ -1822,15 +1829,19 @@ async function resumeAsyncRun(input) {
1822
1829
  ...(input.params.timeoutMs !== undefined ? { timeoutMs: input.params.timeoutMs } : {}),
1823
1830
  ...(input.absoluteDeadlineAt !== undefined ? { absoluteDeadlineAt: input.absoluteDeadlineAt } : {}),
1824
1831
  ...(input.params.toolBudget !== undefined ? { toolBudget: input.params.toolBudget } : {}),
1825
- capabilityCeiling: intersectSubagentCapabilityCeilings("capabilityCeiling" in target ? target.capabilityCeiling : undefined, recoveryDescriptor?.capabilityCeiling, resolveCurrentSubagentCapabilityCeiling(input.deps.state.currentSessionId)),
1832
+ // Recovery descriptors, remembered foreground runs, and current workflow roots
1833
+ // preserve parent authority before the selected agent's descendant ceiling.
1834
+ capabilityCeiling: intersectSubagentCapabilityCeilings(recoveryDescriptor?.capabilityCeiling ?? (target.source === "foreground" || (target.source === "async" && target.mode === "workflow") ? target.capabilityCeiling : undefined), resolveCurrentSubagentCapabilityCeiling(input.deps.state.currentSessionId)),
1826
1835
  runFanoutBudget: input.params.runFanoutBudget ?? recoveryDescriptor?.runFanoutBudget ?? createRunFanoutBudget(runId, resolveMaxSubagentSpawnsPerRun(input.deps.config.maxSubagentSpawnsPerRun)),
1827
1836
  parentWorkflowRunId: input.params.workflowParentRunId,
1828
1837
  workflowKey: input.params.workflowKey,
1829
1838
  activeAsyncCapacity,
1830
1839
  }));
1840
+ const notifyLaunch = () => input.onLaunch?.({ agent: target.agent, sessionFile: revivalSessionFile, async: true, runId });
1831
1841
  if (result.isError) {
1832
1842
  const startedStatus = readStatus(revivalAsyncDir);
1833
1843
  if (input.params.workflowParentRunId !== undefined && startedStatus?.runId === runId && startedStatus.processTerminal?.runnerProcessInstanceId) {
1844
+ notifyLaunch();
1834
1845
  return {
1835
1846
  ...result,
1836
1847
  details: {
@@ -1845,6 +1856,7 @@ async function resumeAsyncRun(input) {
1845
1856
  activeAsyncCapacity?.rollback();
1846
1857
  return result;
1847
1858
  }
1859
+ notifyLaunch();
1848
1860
  for (const brief of queuedBriefs)
1849
1861
  fs.rmSync(brief.path, { force: true });
1850
1862
  if (queuedBriefs.length > 0 && sourceAsyncDir) {
@@ -2148,11 +2160,15 @@ function projectEffectiveAcceptanceSchemas(params, agents) {
2148
2160
  }
2149
2161
  function validateExecutionInput(params, agents, hasChain, hasTasks, hasSingle, allowClarifyTaskPrompt, context) {
2150
2162
  if (Number(hasChain) + Number(hasTasks) + Number(hasSingle) !== 1) {
2163
+ const agentList = agents.map((a) => a.name).join(", ") || "none";
2164
+ const noMode = !hasChain && !hasTasks && !hasSingle;
2151
2165
  return {
2152
2166
  content: [
2153
2167
  {
2154
2168
  type: "text",
2155
- text: `Provide exactly one mode. Agents: ${agents.map((a) => a.name).join(", ") || "none"}`,
2169
+ text: noMode && typeof params.workflowKey === "string"
2170
+ ? `Workflow child '${params.workflowKey}' has no agent. Pass { key, agent, task }. Agents: ${agentList}`
2171
+ : `Provide exactly one mode. Agents: ${agentList}`,
2156
2172
  },
2157
2173
  ],
2158
2174
  isError: true,
@@ -3465,7 +3481,6 @@ async function runSinglePath(data, deps) {
3465
3481
  runtimeSnapshotHost: deps.pi,
3466
3482
  parentSessionId: ctx.sessionManager.getSessionId() ?? undefined,
3467
3483
  requiredExtensions,
3468
- llmIntentArbiter: createTaskMutationArbiter({ model: ctx.model, modelRegistry: ctx.modelRegistry, sessionId: ctx.sessionManager.getSessionId() }),
3469
3484
  childRuntime: deps.childRuntime,
3470
3485
  onChildSession: (controls) => { childSessionControls = controls; },
3471
3486
  context: data.contextPolicy.contextForAgent(params.agent),
@@ -4664,6 +4679,7 @@ export function createSubagentExecutor(deps) {
4664
4679
  ...(workflowSessionRoot ? { sessionRoot: workflowSessionRoot } : {}),
4665
4680
  ...(requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {}),
4666
4681
  pid: process.pid,
4682
+ ...(workflowCapabilityCeiling ? { admissionCapabilityCeiling: workflowCapabilityCeiling } : {}),
4667
4683
  steps: [],
4668
4684
  ...(workflowPreflight ? { preflight: workflowPreflight } : {}),
4669
4685
  workflow: { trace: [], emits: [], console: [], ...(workflowArgsEvidence ?? {}), ...(workflowResource ? { resource: workflowResource.provenance } : {}) },
@@ -4732,11 +4748,15 @@ export function createSubagentExecutor(deps) {
4732
4748
  deps.refreshResultDelivery?.();
4733
4749
  return false;
4734
4750
  };
4751
+ const pendingWorkflowChildAnnouncements = new Map();
4752
+ let announcePersistedWorkflowChildren = () => { };
4735
4753
  const runPersistence = createCapacityResilientJsonWriter({
4736
4754
  keepAlive: true,
4737
4755
  onSuccess: (filePath, payload) => {
4738
- if (filePath === statusPath)
4756
+ if (filePath === statusPath) {
4757
+ announcePersistedWorkflowChildren();
4739
4758
  queueActiveRunIndex(payload);
4759
+ }
4740
4760
  if (filePath === resultPath)
4741
4761
  settleResultPublication?.(true);
4742
4762
  },
@@ -4777,7 +4797,8 @@ export function createSubagentExecutor(deps) {
4777
4797
  else if (options.tolerateStatusWriteFailure) {
4778
4798
  try {
4779
4799
  runPersistence.write(statusPath, { ...status });
4780
- statusPersistenceDegraded = false;
4800
+ if (runPersistence.pendingCount() === 0)
4801
+ statusPersistenceDegraded = false;
4781
4802
  }
4782
4803
  catch (error) {
4783
4804
  const message = `Failed to persist async workflow state ${statusPath}: ${error instanceof Error ? error.message : String(error)}`;
@@ -4873,6 +4894,25 @@ export function createSubagentExecutor(deps) {
4873
4894
  return { content: [{ type: "text", text: `Failed to create async workflow storage: ${error instanceof Error ? error.message : String(error)}` }], isError: true, details: { mode: "workflow", results: [] } };
4874
4895
  }
4875
4896
  appendWorkflowEvent({ type: "subagent.workflow.started", ...(workflowArgsDigest ? { argsDigest: workflowArgsDigest } : {}) });
4897
+ try {
4898
+ deps.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
4899
+ lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
4900
+ id: workflowRunId,
4901
+ asyncDir,
4902
+ cwd: workflowCwd,
4903
+ ...(workflowSessionRoot ? { sessionRoot: workflowSessionRoot } : {}),
4904
+ pid: process.pid,
4905
+ sessionId: currentSessionId ?? undefined,
4906
+ completionOwnerId,
4907
+ mode: "workflow",
4908
+ agent: "workflow",
4909
+ goal: derivedObjective.trim() ? PROMPT_REDACTED : undefined,
4910
+ ...(timeout !== undefined ? { timeoutMs: timeout, deadlineAt: startedAt + timeout } : {}),
4911
+ });
4912
+ }
4913
+ catch (error) {
4914
+ console.error("Failed to emit async workflow start event:", error);
4915
+ }
4876
4916
  // The runner does not execute workflow scripts: this active owner must consume its own
4877
4917
  // durable steer inbox, deliver through in-process child controls, and persist receipts.
4878
4918
  const emitWorkflowSteerEvent = (type, requestId, index, extra = {}) => {
@@ -5041,6 +5081,44 @@ export function createSubagentExecutor(deps) {
5041
5081
  const childOutputClaimPaths = new Map();
5042
5082
  const producedChildOutputPaths = new Set();
5043
5083
  const workflowSteps = new Map();
5084
+ const announcedWorkflowChildren = new Set();
5085
+ const announceWorkflowChild = (key, step) => {
5086
+ if (announcedWorkflowChildren.has(key))
5087
+ return;
5088
+ announcedWorkflowChildren.add(key);
5089
+ const stepIndex = status.steps?.indexOf(step);
5090
+ const childEvent = {
5091
+ type: "subagent.child-status",
5092
+ version: 1,
5093
+ runId: workflowRunId,
5094
+ childId: key,
5095
+ status: "started",
5096
+ ts: Date.now(),
5097
+ source: "async",
5098
+ asyncDir,
5099
+ ...(stepIndex !== undefined ? { stepIndex } : {}),
5100
+ agent: step.agent,
5101
+ ...(step.runId ? { childRunId: step.runId } : {}),
5102
+ workflowKey: key,
5103
+ ...(step.phase ? { phase: step.phase } : {}),
5104
+ ...(step.label ? { label: step.label } : {}),
5105
+ };
5106
+ appendWorkflowEvent({ ...childEvent });
5107
+ try {
5108
+ deps.pi.events.emit(SUBAGENT_CHILD_STATUS_EVENT, childEvent);
5109
+ }
5110
+ catch (error) {
5111
+ console.error("Failed to emit workflow child status event:", error);
5112
+ }
5113
+ };
5114
+ announcePersistedWorkflowChildren = () => {
5115
+ for (const [key, step] of pendingWorkflowChildAnnouncements) {
5116
+ if (!step.runId)
5117
+ continue;
5118
+ announceWorkflowChild(key, step);
5119
+ pendingWorkflowChildAnnouncements.delete(key);
5120
+ }
5121
+ };
5044
5122
  const runHostCommand = workflowHostCommandRunner({
5045
5123
  workflowCwd,
5046
5124
  artifactsDir: workflowArtifactsDir,
@@ -5282,6 +5360,8 @@ export function createSubagentExecutor(deps) {
5282
5360
  step.runId = launch.runId;
5283
5361
  if (childRequest.lane)
5284
5362
  step.lane = childRequest.lane;
5363
+ if (step.runId)
5364
+ pendingWorkflowChildAnnouncements.set(key, step);
5285
5365
  persist({ tolerateStatusWriteFailure: true });
5286
5366
  }
5287
5367
  recordMissionWorkflowChild(missionBinding, workflowRunId, key, { status: "running", agent: launch.agent, ...(launch.sessionFile ? { sessionPath: launch.sessionFile } : {}) });
@@ -5378,7 +5458,7 @@ export function createSubagentExecutor(deps) {
5378
5458
  catch (receiptError) {
5379
5459
  appendWorkflowEvent({ type: "subagent.workflow.receipt_write_failed", error: `Failed to persist async workflow receipt: ${receiptError instanceof Error ? receiptError.message : String(receiptError)}` });
5380
5460
  }
5381
- if (!writeWorkflowResult({ id: workflowRunId, runId: workflowRunId, toolCallId, agent: "workflow", mode: "workflow", success: true, state: "complete", summary: resultSummary, output: resultSummary, workflowChildren, results: workflowResultChildren(workflow.children, status, false), workflow: status.workflow, ...(workflowReceipt ? { workflowReceipt } : {}), asyncDir, cwd: workflowCwd, sessionId: currentSessionId, completionOwnerId, ...(requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {}), timestamp: Date.now(), durationMs: Date.now() - startedAt }))
5461
+ if (!writeWorkflowResult({ id: workflowRunId, runId: workflowRunId, toolCallId, agent: "workflow", mode: "workflow", success: true, state: "complete", summary: resultSummary, output: resultSummary, workflowChildren, results: workflowResultChildren(workflow.children, status, false), workflow: status.workflow, ...(workflowCapabilityCeiling ? { admissionCapabilityCeiling: workflowCapabilityCeiling } : {}), ...(workflowReceipt ? { workflowReceipt } : {}), asyncDir, cwd: workflowCwd, sessionId: currentSessionId, completionOwnerId, ...(requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {}), timestamp: Date.now(), durationMs: Date.now() - startedAt }))
5382
5462
  return;
5383
5463
  if (pendingResultPublication && !await pendingResultPublication)
5384
5464
  return;
@@ -5435,7 +5515,7 @@ export function createSubagentExecutor(deps) {
5435
5515
  catch (receiptError) {
5436
5516
  appendWorkflowEvent({ type: "subagent.workflow.receipt_write_failed", error: `Failed to persist async workflow receipt: ${receiptError instanceof Error ? receiptError.message : String(receiptError)}` });
5437
5517
  }
5438
- if (!writeWorkflowResult({ id: workflowRunId, runId: workflowRunId, toolCallId, agent: "workflow", mode: "workflow", success: status.state === "complete", state: status.state, summary: resultSummary, error: status.state === "complete" ? undefined : status.error, stopped: status.stopped, activityState: status.activityState, workflowChildren, ...(terminalOutcome ? { terminalOutcome } : {}), results: workflowResultChildren(partial.children, status, true), workflow: status.workflow, ...(workflowReceipt ? { workflowReceipt } : {}), asyncDir, cwd: workflowCwd, sessionId: currentSessionId, completionOwnerId, ...(requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {}), timestamp: Date.now(), durationMs: Date.now() - startedAt }))
5518
+ if (!writeWorkflowResult({ id: workflowRunId, runId: workflowRunId, toolCallId, agent: "workflow", mode: "workflow", success: status.state === "complete", state: status.state, summary: resultSummary, error: status.state === "complete" ? undefined : status.error, stopped: status.stopped, activityState: status.activityState, workflowChildren, ...(terminalOutcome ? { terminalOutcome } : {}), results: workflowResultChildren(partial.children, status, true), workflow: status.workflow, ...(workflowCapabilityCeiling ? { admissionCapabilityCeiling: workflowCapabilityCeiling } : {}), ...(workflowReceipt ? { workflowReceipt } : {}), asyncDir, cwd: workflowCwd, sessionId: currentSessionId, completionOwnerId, ...(requestParams.scheduleOrigin ? { scheduleOrigin: requestParams.scheduleOrigin } : {}), timestamp: Date.now(), durationMs: Date.now() - startedAt }))
5439
5519
  return;
5440
5520
  if (pendingResultPublication && !await pendingResultPublication)
5441
5521
  return;
@@ -6037,7 +6117,7 @@ export function createSubagentExecutor(deps) {
6037
6117
  }
6038
6118
  let orchestratorTarget;
6039
6119
  try {
6040
- orchestratorTarget = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
6120
+ orchestratorTarget = resolveIntercomSessionTarget(deps.childRuntime?.intercomSessionName ?? deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
6041
6121
  }
6042
6122
  catch (error) {
6043
6123
  if (!sessionError)
@@ -6119,7 +6199,18 @@ export function createSubagentExecutor(deps) {
6119
6199
  return withBudget(inspectSubagentStatus(paramsWithResolvedCwd, omitUndefinedProperties({ state: deps.state, nested: nestedScope, sessionRoots, abandonedSlotReleaseAfterMs: resolveAbandonedSlotReleaseAfterMs(deps.config.capacity?.abandonedSlotReleaseAfterMs) })));
6120
6200
  }
6121
6201
  if (action === "resume") {
6122
- return resumeAsyncRun(omitUndefinedProperties({ params: paramsWithResolvedCwd, requestCwd, ctx, deps, parentModel: requestParentModel, signal }));
6202
+ return resumeAsyncRun(omitUndefinedProperties({
6203
+ params: paramsWithResolvedCwd,
6204
+ requestCwd,
6205
+ ctx,
6206
+ deps,
6207
+ parentModel: requestParentModel,
6208
+ signal,
6209
+ ...(workflowLaunchObserver ? { onLaunch: (launch) => {
6210
+ workflowLaunchObservers.delete(params);
6211
+ workflowLaunchObserver(launch);
6212
+ } } : {}),
6213
+ }));
6123
6214
  }
6124
6215
  if (action === "steer") {
6125
6216
  if (paramsWithResolvedCwd.mode !== undefined && resolveSteerDeliveryMode(paramsWithResolvedCwd.mode) === undefined) {
@@ -6470,7 +6561,7 @@ export function createSubagentExecutor(deps) {
6470
6561
  return buildRequestedModeError(effectiveParams, contextPolicyResult.error);
6471
6562
  const contextPolicy = contextPolicyResult;
6472
6563
  effectiveParams = contextPolicy.params;
6473
- const sessionName = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
6564
+ const sessionName = resolveIntercomSessionTarget(deps.childRuntime?.intercomSessionName ?? deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
6474
6565
  const intercomBridge = resolveIntercomBridge({
6475
6566
  config: deps.config.intercomBridge,
6476
6567
  override: effectiveParams.intercomBridge,