@duckmind/dm-windows-x64 0.61.4 → 0.61.9

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/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +211 -67
  3. package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
  4. package/extensions/dm-subagents/agents/claude-code.md +15 -0
  5. package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
  6. package/extensions/dm-subagents/agents/codex-exec.md +15 -0
  7. package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
  8. package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
  9. package/extensions/dm-subagents/agents/delegate.md +3 -2
  10. package/extensions/dm-subagents/agents/oracle.md +10 -5
  11. package/extensions/dm-subagents/agents/researcher.md +2 -2
  12. package/extensions/dm-subagents/agents/reviewer.md +17 -7
  13. package/extensions/dm-subagents/agents/scout.md +5 -5
  14. package/extensions/dm-subagents/agents/worker.md +6 -2
  15. package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
  16. package/extensions/dm-subagents/index.js +4 -0
  17. package/extensions/dm-subagents/inspector-runner.mjs +10 -0
  18. package/extensions/dm-subagents/install.mjs +3 -2
  19. package/extensions/dm-subagents/package.json +2 -2
  20. package/extensions/dm-subagents/prompts/council.md +60 -0
  21. package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
  22. package/extensions/dm-subagents/prompts/review-loop.md +13 -7
  23. package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
  24. package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
  25. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
  26. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
  27. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
  28. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
  29. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
  30. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
  31. package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
  32. package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
  33. package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
  34. package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
  35. package/extensions/dm-subagents/src/agents/agents.js +1447 -299
  36. package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
  37. package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
  38. package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
  39. package/extensions/dm-subagents/src/agents/identity.js +1 -1
  40. package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
  41. package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
  42. package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
  43. package/extensions/dm-subagents/src/agents/skills.js +52 -35
  44. package/extensions/dm-subagents/src/api/agents.js +6 -0
  45. package/extensions/dm-subagents/src/api/background-work.js +151 -0
  46. package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
  47. package/extensions/dm-subagents/src/api/control-channel.js +3 -0
  48. package/extensions/dm-subagents/src/api/delegation.js +5 -0
  49. package/extensions/dm-subagents/src/api/dm-args.js +3 -0
  50. package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
  51. package/extensions/dm-subagents/src/api/external-runs.js +233 -0
  52. package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
  53. package/extensions/dm-subagents/src/api/preflight.js +322 -0
  54. package/extensions/dm-subagents/src/api/project-panes.js +11 -0
  55. package/extensions/dm-subagents/src/api/shared-types.js +4 -0
  56. package/extensions/dm-subagents/src/extension/config.js +175 -0
  57. package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
  58. package/extensions/dm-subagents/src/extension/doctor.js +71 -17
  59. package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
  60. package/extensions/dm-subagents/src/extension/index.js +711 -265
  61. package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
  62. package/extensions/dm-subagents/src/extension/rpc.js +427 -22
  63. package/extensions/dm-subagents/src/extension/schemas.js +158 -65
  64. package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
  65. package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
  66. package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
  67. package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
  68. package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
  69. package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
  70. package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
  71. package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
  72. package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
  73. package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
  74. package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
  75. package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
  76. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
  77. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
  78. package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
  79. package/extensions/dm-subagents/src/missions/actions.js +394 -0
  80. package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
  81. package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
  82. package/extensions/dm-subagents/src/missions/store.js +548 -0
  83. package/extensions/dm-subagents/src/missions/types.js +9 -0
  84. package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
  85. package/extensions/dm-subagents/src/policy/authority.js +37 -0
  86. package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
  87. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
  88. package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
  89. package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
  90. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
  91. package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
  92. package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
  93. package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
  94. package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
  95. package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
  96. package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
  97. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
  98. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
  99. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
  100. package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
  101. package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
  102. package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
  103. package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
  104. package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
  105. package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
  106. package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
  107. package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
  108. package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
  109. package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
  110. package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
  111. package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
  112. package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
  113. package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
  114. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
  115. package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
  116. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
  117. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
  118. package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
  119. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
  120. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
  121. package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
  122. package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
  123. package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
  124. package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
  125. package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
  126. package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
  127. package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
  128. package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
  129. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
  130. package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
  131. package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
  132. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
  133. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
  134. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
  135. package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
  136. package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
  137. package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
  138. package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
  139. package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
  140. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
  141. package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
  142. package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
  143. package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
  144. package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
  145. package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
  146. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
  147. package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
  148. package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
  149. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
  150. package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
  151. package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
  152. package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
  153. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
  154. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
  155. package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
  156. package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
  157. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
  158. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
  159. package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
  160. package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
  161. package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
  162. package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
  163. package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
  164. package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
  165. package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
  166. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
  167. package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
  168. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
  169. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
  170. package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
  171. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
  172. package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
  173. package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
  174. package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
  175. package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
  176. package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
  177. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
  178. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
  179. package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
  180. package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
  181. package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
  182. package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
  183. package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
  184. package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
  185. package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
  186. package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
  187. package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
  188. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
  189. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
  190. package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
  191. package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
  192. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
  193. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
  194. package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
  195. package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
  196. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
  197. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
  198. package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
  199. package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
  200. package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
  201. package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
  202. package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
  203. package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
  204. package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
  205. package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
  206. package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
  207. package/extensions/dm-subagents/src/shared/display-text.js +142 -0
  208. package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
  209. package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
  210. package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
  211. package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
  212. package/extensions/dm-subagents/src/shared/formatters.js +21 -7
  213. package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
  214. package/extensions/dm-subagents/src/shared/model-info.js +10 -5
  215. package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
  216. package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
  217. package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
  218. package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
  219. package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
  220. package/extensions/dm-subagents/src/shared/settings.js +39 -47
  221. package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
  222. package/extensions/dm-subagents/src/shared/status-format.js +9 -2
  223. package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
  224. package/extensions/dm-subagents/src/shared/types.js +47 -7
  225. package/extensions/dm-subagents/src/shared/utf8.js +12 -0
  226. package/extensions/dm-subagents/src/shared/utils.js +151 -131
  227. package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
  228. package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
  229. package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
  230. package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
  231. package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
  232. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
  233. package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
  234. package/extensions/dm-subagents/src/slash/selector.js +101 -0
  235. package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
  236. package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
  237. package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
  238. package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
  239. package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
  240. package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
  241. package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
  242. package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
  243. package/extensions/dm-subagents/src/tui/render.js +1511 -261
  244. package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
  245. package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
  246. package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
  247. package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
  248. package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
  249. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
  250. package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
  251. package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
  252. package/extensions/dm-subagents/src/watchdog/render.js +54 -0
  253. package/extensions/dm-subagents/src/watchdog/review.js +251 -0
  254. package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
  255. package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
  256. package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
  257. package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
  258. package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
  259. package/extensions/dm-subagents/src/watchdog/types.js +29 -0
  260. package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
  261. package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
  262. package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
  263. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
  264. package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
  265. package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
  266. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
  267. package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
  268. package/package.json +4 -3
  269. package/extensions/dm-fff/package.json +0 -21
  270. package/extensions/dm-fff/src/index.js +0 -691
  271. package/extensions/dm-fff/src/query.js +0 -60
  272. package/extensions/dm-subagents/agents/context-builder.md +0 -46
  273. package/extensions/dm-subagents/agents/planner.md +0 -55
  274. package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
  275. package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
  276. package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
  277. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
  278. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
  279. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
@@ -1,24 +1,112 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { formatAsyncRunList, formatAsyncRunOutputPath, formatAsyncRunProgressLabel, listAsyncRuns } from "./async-status.js";
3
+ import { safeTerminalText } from "../../shared/display-text.js";
4
+ import { formatAsyncRunList, formatAsyncRunOutputPath, formatAsyncRunProgressLabel, formatWorkflowStageLine, listAsyncRuns } from "./async-status.js";
4
5
  import { formatAsyncResultTranscript, formatAsyncRunTranscript, formatNestedRunTranscript, inspectSubagentFleet } from "./fleet-view.js";
5
6
  import { formatNestedRunStatusLines } from "../shared/nested-render.js";
6
7
  import { formatModelThinking } from "../../shared/formatters.js";
7
8
  import { formatActivityLabel } from "../../shared/status-format.js";
8
- import { ASYNC_DIR, RESULTS_DIR } from "../../shared/types.js";
9
+ import { DIRS } from "../../shared/types.js";
10
+ import { inspectActiveAsyncCapacityOwner } from "./active-async-capacity.js";
11
+ import { readStatus } from "../../shared/utils.js";
9
12
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.js";
13
+ import { normalizeExternalCliRunnerStatus } from "../shared/external-cli-contract.js";
14
+ import { resolveSubagentResultStatus } from "../../intercom/result-intercom.js";
15
+ import { readProcessTerminal, sanitizeProcessTerminal } from "./process-terminal.js";
16
+ import { formatWaitSubscriptions } from "./wait-subscriptions.js";
10
17
  import { resolveAsyncRunLocation } from "./async-resume.js";
11
18
  import { resolveSubagentRunId } from "./run-id-resolver.js";
12
19
  import { flatToLogicalStepIndex, normalizeParallelGroups } from "./parallel-groups.js";
13
20
  import { reconcileAsyncRun, reconcileNestedAsyncDescendants } from "./stale-run-reconciler.js";
14
21
  import { attachRootChildrenToSteps, findNestedRouteForRootId, projectNestedRegistryForRoot } from "../shared/nested-events.js";
22
+ import { readMissionBinding } from "../../missions/lifecycle.js";
23
+ import { formatWorkflowJsonPreview } from "../../workflows/scripted-workflow.js";
24
+ import { parseWorkflowChildSummary } from "../../workflows/workflow-child-summary.js";
25
+ import { formatWorkflowPreflightPlanSummary, formatWorkflowPreflightWarningSummary } from "../../workflows/workflow-preflight.js";
26
+ import { formatRunFanoutBudget, getRunFanoutBudgetSnapshot, readRunFanoutBudgetDescriptor } from "../shared/run-fanout-budget.js";
27
+ import { workflowGraphStageNodes } from "../shared/workflow-graph.js";
28
+ import { getExternalJobProvider } from "../../api/external-job-provider.js";
29
+ import { formatTimeoutRecoveryLines } from "../shared/mutation-evidence.js";
30
+ function formatProcessTerminal(value) {
31
+ if (!value)
32
+ return "missing";
33
+ return `${value.state}${value.reason ? ` (${value.reason})` : ""}${value.runnerProcessInstanceId ? ` · runner ${value.runnerProcessInstanceId}` : ""}`;
34
+ }
35
+ function debugProcessTerminal(asyncDir, status) {
36
+ const expected = { runId: status.runId, runnerProcessInstanceId: status.processTerminal?.runnerProcessInstanceId };
37
+ return {
38
+ sidecar: readProcessTerminal(asyncDir, expected),
39
+ overlay: sanitizeProcessTerminal(status.processTerminal, expected, path.join(asyncDir, "status.json"))
40
+ };
41
+ }
42
+ function formatCapacityOwner(inspect) {
43
+ if (!inspect.owner)
44
+ return [`Active capacity: ${inspect.release.state} — ${inspect.release.reason}`];
45
+ const owner = inspect.owner;
46
+ return [
47
+ `Active capacity: ${inspect.release.state} — ${inspect.release.reason}`,
48
+ `Capacity owner: ${inspect.relation} slot ${owner.slot}, ${owner.kind}, generation ${owner.generation}`,
49
+ `Capacity session: ${owner.ownerSessionId}`,
50
+ owner.sourceRunId ? `Capacity source run: ${owner.sourceRunId}` : undefined,
51
+ `Capacity async dir: ${owner.asyncDir}`,
52
+ owner.runnerProcessInstanceId ? `Capacity runner: ${owner.runnerProcessInstanceId}` : undefined,
53
+ owner.runnerStartedAt !== undefined ? `Capacity runner started: ${new Date(owner.runnerStartedAt).toISOString()}` : undefined
54
+ ].filter((line) => line !== undefined);
55
+ }
56
+ function formatWorkflowDebug(status) {
57
+ if (status.mode !== "workflow" && !status.parentWorkflowRunId && !status.workflowKey && !status.lane)
58
+ return [];
59
+ const lines = [
60
+ status.parentWorkflowRunId ? `Workflow parent: ${status.parentWorkflowRunId}${status.workflowKey ? ` (${status.workflowKey})` : ""}` : undefined,
61
+ status.mode === "workflow" ? `Workflow children: ${(status.steps ?? []).length}` : undefined,
62
+ status.lane ? `Lane: ${status.lane.key}${status.lane.mode ? ` (${status.lane.mode})` : ""}` : undefined
63
+ ].filter((line) => line !== undefined);
64
+ for (const [index, step] of (status.steps ?? []).entries()) {
65
+ lines.push(` ${index + 1}. key ${step.workflowKey ?? "n/a"} · ${runStatusStepDisplayName(step)} · ${step.status} · async ${step.async === undefined ? "unknown" : step.async ? "yes" : "no"}${step.runId ? ` · run ${step.runId}` : ""}${step.lane ? ` · lane ${step.lane.key}` : ""}${step.worktreePath ? ` · worktree ${step.worktreePath} · branch ${step.branch ?? "unknown"}` : ""}`);
66
+ }
67
+ return lines;
68
+ }
69
+ function formatRunLifecycleDebug(input) {
70
+ const { status, asyncDir, sidecarProcessTerminal, overlayProcessTerminal, capacity } = input;
71
+ const lines = [
72
+ "Run lifecycle debug",
73
+ `Run: ${status.runId}`,
74
+ `Dir: ${asyncDir}`,
75
+ `Status file: ${path.join(asyncDir, "status.json")}`,
76
+ `Process terminal file: ${path.join(asyncDir, "process-terminal.json")}`,
77
+ `Session: ${status.sessionId ?? "unknown"}`,
78
+ `State: ${status.state}`,
79
+ `Mode: ${status.mode}`,
80
+ status.parentWorkflowRunId ? `Workflow parent: ${status.parentWorkflowRunId}` : undefined,
81
+ status.workflowKey ? `Workflow key: ${status.workflowKey}` : undefined,
82
+ status.lane ? `Lane: ${status.lane.key}${status.lane.mode ? ` (${status.lane.mode})` : ""}` : undefined,
83
+ `Status process terminal: ${formatProcessTerminal(overlayProcessTerminal)}`,
84
+ `Sidecar process terminal: ${formatProcessTerminal(sidecarProcessTerminal)}`,
85
+ ...formatCapacityOwner(capacity),
86
+ ...formatWorkflowDebug(status)
87
+ ].filter((line) => line !== undefined);
88
+ return lines.join(`
89
+ `);
90
+ }
15
91
  function hasExistingSessionFile(value) {
16
92
  return typeof value === "string" && fs.existsSync(value);
17
93
  }
18
- function formatResumeGuidance(runId, children, fallbackSessionFile) {
94
+ function formatResumeGuidance(runId, children, fallbackSessionFile, options = {}) {
95
+ if (options.stopped)
96
+ return "Resume: unavailable; stopped runs are not resumable. Start a new run instead.";
19
97
  const knownChildren = children.map((child, index) => ({ child, index })).filter(({ child }) => typeof child.agent === "string");
20
98
  if (!runId || knownChildren.length === 0)
21
99
  return "Resume: unavailable; no child session file was persisted.";
100
+ const workflowChildren = knownChildren.filter(({ child }) => typeof child.runId === "string" && child.runId.trim() && hasExistingSessionFile(child.sessionFile));
101
+ const supervisorDetachedWorkflowChildren = workflowChildren.filter(({ child }) => child.status === "paused" && child.activityState === "needs_attention");
102
+ const resumableWorkflowChildren = workflowChildren.filter(({ child }) => !(child.status === "paused" && child.activityState === "needs_attention"));
103
+ if (workflowChildren.length > 0) {
104
+ return [
105
+ ...supervisorDetachedWorkflowChildren.map(({ child }) => `Recovery workflow child${typeof child.workflowKey === "string" && child.workflowKey.trim() ? ` '${child.workflowKey}'` : ""}: reply to the supervisor request first, then wait with bg_wait({ id: "${child.runId}" }). Use subagent({ action: "status", id: "${child.runId}" }) to recover the result; do not resume or launch a replacement while it remains detached.`),
106
+ ...resumableWorkflowChildren.map(({ child }) => `Revive workflow child${typeof child.workflowKey === "string" && child.workflowKey.trim() ? ` '${child.workflowKey}'` : ""}: subagent({ action: "resume", id: "${child.runId}", message: "..." })`)
107
+ ].join(`
108
+ `);
109
+ }
22
110
  const singleSessionFile = knownChildren[0]?.child.sessionFile ?? fallbackSessionFile;
23
111
  if (children.length === 1 && knownChildren.length === 1 && hasExistingSessionFile(singleSessionFile)) {
24
112
  return `Revive: subagent({ action: "resume", id: "${runId}", message: "..." })`;
@@ -33,6 +121,8 @@ function stepLineLabel(status, index) {
33
121
  const steps = status.steps ?? [];
34
122
  if (status.mode === "parallel")
35
123
  return `Agent ${index + 1}/${steps.length || 1}`;
124
+ if (status.mode === "workflow")
125
+ return `Workflow child ${steps[index]?.workflowKey ?? index + 1}`;
36
126
  if (status.mode === "chain") {
37
127
  const chainStepCount = status.chainStepCount ?? (steps.length || 1);
38
128
  const groups = normalizeParallelGroups(status.parallelGroups, steps.length, chainStepCount);
@@ -43,7 +133,12 @@ function stepLineLabel(status, index) {
43
133
  }
44
134
  return `Step ${index + 1}`;
45
135
  }
136
+ function runStatusStepDisplayName(step) {
137
+ return step.sessionName?.trim() || (step.label ? `${step.label} (${step.agent})` : step.agent);
138
+ }
46
139
  function nestedRunDisplayName(run) {
140
+ if (run.sessionName?.trim())
141
+ return run.sessionName.trim();
47
142
  if (run.agent)
48
143
  return run.agent;
49
144
  if (run.agents?.length)
@@ -51,15 +146,21 @@ function nestedRunDisplayName(run) {
51
146
  return run.id;
52
147
  }
53
148
  function formatSteeringSummary(input) {
54
- const parts = [];
55
- if (input.steerCount !== undefined)
56
- parts.push(`${input.steerCount} steer${input.steerCount === 1 ? "" : "s"}`);
57
- if (typeof input.lastSteerAt === "number" && Number.isFinite(input.lastSteerAt))
58
- parts.push(`last ${new Date(input.lastSteerAt).toISOString()}`);
59
- return parts.length ? parts.join(", ") : undefined;
149
+ const steering = input.steering;
150
+ if (!steering || steering.requested === 0)
151
+ return;
152
+ const lateAcknowledgments = steering.recent.reduce((count, request) => count + request.targets.filter((target) => target.lateDeliveredAt !== undefined).length, 0);
153
+ return `${steering.requested} requested, ${steering.scheduled} scheduled, ${steering.pending} pending, ${steering.delivered} delivered, ${steering.failed} failed, ${steering.recovered} recovered${lateAcknowledgments ? `, ${lateAcknowledgments} late acknowledged` : ""}`;
154
+ }
155
+ function externalJobFollowUpSupported(provider) {
156
+ try {
157
+ return typeof getExternalJobProvider(provider)?.followUp === "function";
158
+ } catch {
159
+ return false;
160
+ }
60
161
  }
61
162
  function rememberedForegroundChildOutput(child) {
62
- const outputPath = child.artifactPaths?.outputPath;
163
+ const outputPath = child.artifactPaths?.outputPath ?? child.savedOutputPath;
63
164
  if (outputPath && fs.existsSync(outputPath)) {
64
165
  try {
65
166
  const artifactOutput = fs.readFileSync(outputPath, "utf-8").trim();
@@ -80,9 +181,11 @@ function formatRememberedForegroundStatus(run) {
80
181
  for (const child of run.children) {
81
182
  const output = rememberedForegroundChildOutput(child).trim().split(/\r?\n/).find((line) => line.trim());
82
183
  const parts = [
83
- `${child.index + 1}. ${child.agent} ${child.status}`,
184
+ `${child.index + 1}. ${child.sessionName?.trim() || child.agent} ${child.status}`,
84
185
  child.exitCode !== undefined ? `exit ${child.exitCode}` : undefined,
85
186
  child.detachedReason ? `detached: ${child.detachedReason}` : undefined,
187
+ child.acceptance ? `acceptance: ${child.acceptance.status}` : undefined,
188
+ child.error ? `error: ${child.error}` : undefined,
86
189
  output ? `output: ${output.slice(0, 160)}` : undefined
87
190
  ].filter(Boolean);
88
191
  lines.push(parts.join(", "));
@@ -92,6 +195,10 @@ function formatRememberedForegroundStatus(run) {
92
195
  lines.push(` Transcript: ${child.transcriptPath}`);
93
196
  if (child.artifactPaths?.outputPath)
94
197
  lines.push(` Output: ${child.artifactPaths.outputPath}`);
198
+ if (child.savedOutputPath && child.savedOutputPath !== child.artifactPaths?.outputPath)
199
+ lines.push(` Saved output: ${child.savedOutputPath}`);
200
+ if (child.outputSaveError)
201
+ lines.push(` Output warning: ${child.outputSaveError}`);
95
202
  if (child.transcriptError)
96
203
  lines.push(` Transcript warning: ${child.transcriptError}`);
97
204
  }
@@ -100,11 +207,12 @@ function formatRememberedForegroundStatus(run) {
100
207
  lines.push(`Transcript: subagent({ action: "status", id: "${run.runId}", view: "transcript" })`);
101
208
  else
102
209
  lines.push(`Transcript: subagent({ action: "status", id: "${run.runId}", index: 0, view: "transcript" })`);
103
- const resumable = run.children.find((child) => child.status !== "detached" && hasExistingSessionFile(child.sessionFile));
104
- if (resumable) {
210
+ const detached = run.children.some((child) => child.status === "detached");
211
+ const resumable = run.children.find((child) => hasExistingSessionFile(child.sessionFile));
212
+ if (detached) {
213
+ lines.push(`Recovery: reply to the supervisor request first, then wait with bg_wait({ id: "${run.runId}" }); do not resume or launch a replacement while any child remains detached.`);
214
+ } else if (resumable) {
105
215
  lines.push(run.children.length === 1 ? `Revive: subagent({ action: "resume", id: "${run.runId}", message: "..." })` : `Revive child: subagent({ action: "resume", id: "${run.runId}", index: ${resumable.index}, message: "..." })`);
106
- } else if (run.children.some((child) => child.status === "detached")) {
107
- lines.push("Recovery: child detached for intercom coordination; status will show recovered output after the child exits when DM can observe it.");
108
216
  } else {
109
217
  lines.push("Resume: unavailable; no child session file was persisted.");
110
218
  }
@@ -127,10 +235,12 @@ function formatRememberedForegroundTranscript(run, options) {
127
235
  const lines = [
128
236
  `Run: ${run.runId}`,
129
237
  `State: ${child.status}`,
130
- `Child: ${index} (${child.agent})`,
238
+ `Child: ${index} (${child.sessionName?.trim() || child.agent})`,
131
239
  child.sessionFile ? `Session: ${child.sessionFile}` : undefined,
132
240
  child.transcriptPath ? `Transcript: ${child.transcriptPath}` : undefined,
133
- child.artifactPaths?.outputPath ? `Output: ${child.artifactPaths.outputPath}` : undefined
241
+ child.artifactPaths?.outputPath ? `Output: ${child.artifactPaths.outputPath}` : undefined,
242
+ child.savedOutputPath && child.savedOutputPath !== child.artifactPaths?.outputPath ? `Saved output: ${child.savedOutputPath}` : undefined,
243
+ child.outputSaveError ? `Output warning: ${child.outputSaveError}` : undefined
134
244
  ].filter((line) => Boolean(line));
135
245
  lines.push("Result transcript tail:");
136
246
  if (outputLines.length === 0)
@@ -138,7 +248,7 @@ function formatRememberedForegroundTranscript(run, options) {
138
248
  else
139
249
  for (const line of outputLines)
140
250
  lines.push(` ${line}`);
141
- return lines.join(`
251
+ return lines.map((line) => safeTerminalText(line)).join(`
142
252
  `);
143
253
  }
144
254
  function formatNestedExactStatus(rootRunId, run) {
@@ -164,7 +274,7 @@ function formatNestedExactStatus(rootRunId, run) {
164
274
  for (const [index, step] of run.steps.entries()) {
165
275
  const activity = step.status === "running" ? formatActivityLabel(step.lastActivityAt, step.activityState) : undefined;
166
276
  const budget = step.turnBudget ? `, turn budget: ${step.turnBudget.turnCount}/${step.turnBudget.maxTurns}+${step.turnBudget.graceTurns} (${step.turnBudget.outcome})` : "";
167
- lines.push(` ${index + 1}. ${step.agent} ${step.status}${activity ? `, ${activity}` : ""}${budget}${step.error ? `, error: ${step.error}` : ""}`);
277
+ lines.push(` ${index + 1}. ${step.sessionName?.trim() || step.agent} ${step.status}${activity ? `, ${activity}` : ""}${budget}${step.error ? `, error: ${step.error}` : ""}`);
168
278
  lines.push(...formatNestedRunStatusLines(step.children, { indent: " ", commandHints: true }));
169
279
  }
170
280
  }
@@ -174,8 +284,8 @@ function formatNestedExactStatus(rootRunId, run) {
174
284
  `);
175
285
  }
176
286
  export function inspectSubagentStatus(params, deps = {}) {
177
- const asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;
178
- const resultsDir = deps.resultsDir ?? RESULTS_DIR;
287
+ const asyncDirRoot = deps.asyncDirRoot ?? DIRS.async;
288
+ const resultsDir = deps.resultsDir ?? DIRS.results;
179
289
  const currentSessionId = deps.state?.currentSessionId ?? undefined;
180
290
  if (params.view && params.view !== "fleet" && params.view !== "transcript") {
181
291
  return {
@@ -206,8 +316,11 @@ export function inspectSubagentStatus(params, deps = {}) {
206
316
  details: { mode: "single", results: [] }
207
317
  };
208
318
  }
319
+ const waitSubscriptions = deps.state ? formatWaitSubscriptions(deps.state, deps.now?.() ?? Date.now()) : undefined;
209
320
  return {
210
- content: [{ type: "text", text: formatAsyncRunList(runs) }],
321
+ content: [{ type: "text", text: [formatAsyncRunList(runs), waitSubscriptions].filter(Boolean).join(`
322
+
323
+ `) }],
211
324
  details: { mode: "single", results: [] }
212
325
  };
213
326
  } catch (error) {
@@ -222,7 +335,9 @@ export function inspectSubagentStatus(params, deps = {}) {
222
335
  let location;
223
336
  try {
224
337
  const requestedId = params.id ?? params.runId;
225
- if (!params.dir && requestedId) {
338
+ if (params.action === "debug.run") {
339
+ location = resolveAsyncRunLocation(params, asyncDirRoot, resultsDir);
340
+ } else if (!params.dir && requestedId) {
226
341
  const resolved = resolveSubagentRunId(requestedId, { asyncDirRoot, resultsDir, state: deps.state, nested: deps.nested });
227
342
  if (resolved?.kind === "foreground") {
228
343
  const run = deps.state?.foregroundRuns?.get(resolved.id);
@@ -276,6 +391,7 @@ export function inspectSubagentStatus(params, deps = {}) {
276
391
  };
277
392
  }
278
393
  if (asyncDir) {
394
+ const diskStatus = readStatus(asyncDir);
279
395
  let reconciliation;
280
396
  try {
281
397
  reconciliation = reconcileAsyncRun(asyncDir, { resultsDir, kill: deps.kill, now: deps.now });
@@ -288,10 +404,45 @@ export function inspectSubagentStatus(params, deps = {}) {
288
404
  };
289
405
  }
290
406
  const status = reconciliation.status;
407
+ if (!status && diskStatus?.displayDismissedAt !== undefined) {
408
+ if (params.action === "debug.run") {
409
+ const { sidecar, overlay } = debugProcessTerminal(asyncDir, diskStatus);
410
+ const capacity = inspectActiveAsyncCapacityOwner({ runId: diskStatus.runId, sessionId: diskStatus.sessionId, asyncDir }, { rootDir: deps.activeCapacityRoot, liveWorkflowRunIds: new Set(deps.state?.workflowControllers?.keys() ?? []), abandonedSlotReleaseAfterMs: deps.abandonedSlotReleaseAfterMs });
411
+ return {
412
+ content: [{ type: "text", text: formatRunLifecycleDebug({ status: diskStatus, asyncDir, sidecarProcessTerminal: sidecar, overlayProcessTerminal: overlay, capacity }) }],
413
+ details: { mode: "single", results: [], ...sidecar ?? overlay ? { lifecycleStatus: { processTerminal: sidecar ?? overlay } } : {} }
414
+ };
415
+ }
416
+ if (params.view === "transcript") {
417
+ if (currentSessionId && diskStatus.sessionId !== currentSessionId) {
418
+ return {
419
+ content: [{ type: "text", text: "Transcript view is only available for async runs owned by the current session." }],
420
+ isError: true,
421
+ details: { mode: "single", results: [] }
422
+ };
423
+ }
424
+ return { content: [{ type: "text", text: formatAsyncRunTranscript(diskStatus, asyncDir, { index: params.index, lines: params.lines, sessionRoots: deps.sessionRoots }) }], details: { mode: "single", results: [] } };
425
+ }
426
+ return {
427
+ content: [{ type: "text", text: `Run: ${diskStatus.runId}
428
+ State: display-dismissed
429
+ Dismissed: ${new Date(diskStatus.displayDismissedAt).toISOString()}
430
+ No running work was terminated.` }],
431
+ details: { mode: "single", results: [] }
432
+ };
433
+ }
291
434
  const effectiveRunId = status?.runId ?? resolvedId ?? "unknown";
292
435
  const logPath = path.join(asyncDir, `subagent-log-${effectiveRunId}.md`);
293
436
  const eventsPath = path.join(asyncDir, "events.jsonl");
294
437
  if (status) {
438
+ if (params.action === "debug.run") {
439
+ const { sidecar, overlay } = debugProcessTerminal(asyncDir, status);
440
+ const capacity = inspectActiveAsyncCapacityOwner({ runId: status.runId, sessionId: status.sessionId, asyncDir }, { rootDir: deps.activeCapacityRoot, liveWorkflowRunIds: new Set(deps.state?.workflowControllers?.keys() ?? []), abandonedSlotReleaseAfterMs: deps.abandonedSlotReleaseAfterMs });
441
+ return {
442
+ content: [{ type: "text", text: formatRunLifecycleDebug({ status, asyncDir, sidecarProcessTerminal: sidecar, overlayProcessTerminal: overlay, capacity }) }],
443
+ details: { mode: "single", results: [], ...sidecar ?? overlay ? { lifecycleStatus: { processTerminal: sidecar ?? overlay } } : {} }
444
+ };
445
+ }
295
446
  if (params.view === "transcript") {
296
447
  if (currentSessionId && status.sessionId !== currentSessionId) {
297
448
  return {
@@ -325,19 +476,43 @@ export function inspectSubagentStatus(params, deps = {}) {
325
476
  currentStep: status.currentStep,
326
477
  chainStepCount: status.chainStepCount,
327
478
  parallelGroups: status.parallelGroups,
479
+ workflowGraph: status.workflowGraph,
328
480
  steps: (status.steps ?? []).map((step, index) => ({ index, agent: step.agent, status: step.status }))
329
481
  });
330
482
  const started = new Date(status.startedAt).toISOString();
331
483
  const updated = status.lastUpdate ? new Date(status.lastUpdate).toISOString() : "n/a";
332
484
  const statusActivityText = status.state === "running" ? formatActivityLabel(status.lastActivityAt, status.activityState) : undefined;
333
485
  const steeringText = formatSteeringSummary(status);
486
+ const processTerminal = readProcessTerminal(asyncDir, { runId: status.runId, runnerProcessInstanceId: status.processTerminal?.runnerProcessInstanceId }) ?? sanitizeProcessTerminal(status.processTerminal, { runId: status.runId, runnerProcessInstanceId: status.processTerminal?.runnerProcessInstanceId }, path.join(asyncDir, "status.json"));
487
+ const runFanoutBudgetDescriptor = readRunFanoutBudgetDescriptor(asyncDir);
488
+ const runFanoutBudget = runFanoutBudgetDescriptor ? getRunFanoutBudgetSnapshot(runFanoutBudgetDescriptor) : status.runFanoutBudget;
489
+ let missionId;
490
+ try {
491
+ missionId = readMissionBinding(asyncDir)?.missionId;
492
+ } catch (error) {
493
+ nestedWarning = `${nestedWarning ? `${nestedWarning}; ` : ""}Mission binding unavailable: ${error instanceof Error ? error.message : String(error)}`;
494
+ }
495
+ const workflowReturnPreview = status.workflow?.value !== undefined ? formatWorkflowJsonPreview(status.workflow.value, 240) : undefined;
496
+ const workflowEmitPreview = status.workflow?.emits.length ? formatWorkflowJsonPreview(status.workflow.emits.at(-1), 240) : undefined;
334
497
  const lines = [
335
498
  `Run: ${status.runId}`,
499
+ status.toolCallId ? `Tool call: ${status.toolCallId}` : undefined,
500
+ missionId ? `Mission: ${missionId}` : undefined,
336
501
  `State: ${status.state}`,
502
+ processTerminal ? `Process terminal: ${processTerminal.state}${processTerminal.reason ? ` (${processTerminal.reason})` : ""}` : undefined,
503
+ status.capabilityCeiling ? `Capability ceiling: ${status.capabilityCeiling.allowedTools === undefined ? "names unrestricted" : status.capabilityCeiling.allowedTools.length === 0 ? "none" : status.capabilityCeiling.allowedTools.join(", ")}
504
+ Extensions denied: ${status.capabilityCeiling.denyExtensions ? "yes" : "no"} (sources: ${status.capabilityCeiling.sources.join(", ")})` : undefined,
505
+ status.capabilityAudit ? `Capability audit: ${status.capabilityAudit.removedTools.length} tools removed, ${status.capabilityAudit.removedExtensionCount} extension entries removed` : undefined,
337
506
  status.error ? `Error: ${status.error}` : undefined,
338
507
  statusActivityText ? `Activity: ${statusActivityText}` : undefined,
339
508
  steeringText ? `Steering: ${steeringText}` : undefined,
340
509
  `Mode: ${status.mode}`,
510
+ ...status.preflight ? [formatWorkflowPreflightPlanSummary(status.preflight)] : [],
511
+ ...status.workflow?.preflightWarnings?.length ? [formatWorkflowPreflightWarningSummary(status.workflow.preflightWarnings)] : [],
512
+ runFanoutBudget ? formatRunFanoutBudget(runFanoutBudget) : undefined,
513
+ status.parentWorkflowRunId ? `Workflow parent: ${status.parentWorkflowRunId}${status.workflowKey ? ` (${status.workflowKey})` : ""}` : undefined,
514
+ status.mode === "workflow" && workflowReturnPreview !== undefined ? `Return: ${workflowReturnPreview}` : undefined,
515
+ status.mode === "workflow" && workflowEmitPreview !== undefined ? `Latest emit: ${workflowEmitPreview}` : undefined,
341
516
  `Progress: ${progressLabel}`,
342
517
  status.pendingAppends ? `Pending appends: ${status.pendingAppends}` : undefined,
343
518
  `Started: ${started}`,
@@ -345,9 +520,12 @@ export function inspectSubagentStatus(params, deps = {}) {
345
520
  status.turnBudget ? `Turn budget: ${status.turnBudget.turnCount}/${status.turnBudget.maxTurns}+${status.turnBudget.graceTurns} (${status.turnBudget.outcome})` : undefined,
346
521
  `Dir: ${asyncDir}`,
347
522
  outputPath ? `Output: ${outputPath}` : undefined,
523
+ status.parallelHandoff ? `Parallel handoff: ${status.parallelHandoff.path}` : undefined,
348
524
  reconciliation.message ? `Diagnosis: ${reconciliation.message}` : undefined,
349
525
  reconciliation.resultPath && fs.existsSync(reconciliation.resultPath) ? `Result: ${reconciliation.resultPath}` : undefined
350
526
  ].filter((line) => Boolean(line));
527
+ const liveWorkflowControls = status.mode === "workflow" && deps.state?.currentSessionId === status.sessionId && deps.state?.workflowControllers?.has(status.runId) ? [...deps.state?.foregroundControls.values() ?? []].filter((control) => control.parentWorkflowRunId === status.runId && control.sessionId === status.sessionId && Boolean(control.workflowSteeringDir && fs.existsSync(control.workflowSteeringDir)) && (control.activeChildren?.size ?? 0) > 0) : [];
528
+ let hasExternalJobFollowUpHint = false;
351
529
  for (const [index, step] of (status.steps ?? []).entries()) {
352
530
  const stepActivityText = step.status === "running" ? formatActivityLabel(step.lastActivityAt, step.activityState) : undefined;
353
531
  const modelThinking = formatModelThinking(step.model, step.thinking);
@@ -357,39 +535,114 @@ export function inspectSubagentStatus(params, deps = {}) {
357
535
  const errorText = step.error ? `, error: ${step.error}` : "";
358
536
  const acceptanceText = step.acceptance?.status ? `, acceptance: ${step.acceptance.status}` : "";
359
537
  const budgetText = step.turnBudget ? `, turn budget: ${step.turnBudget.turnCount}/${step.turnBudget.maxTurns}+${step.turnBudget.graceTurns} (${step.turnBudget.outcome})` : "";
360
- const display = step.label ? `${step.label} (${step.agent})` : step.agent;
538
+ const display = runStatusStepDisplayName(step);
361
539
  const phase = step.phase ? `[${step.phase}] ` : "";
362
540
  lines.push(`${stepLineLabel(status, index)}: ${phase}${display} ${step.status}${modelText}${stepActivityText ? `, ${stepActivityText}` : ""}${steeringSuffix}${acceptanceText}${budgetText}${errorText}`);
541
+ lines.push(...formatTimeoutRecoveryLines(step.timeoutRecovery, " "));
542
+ if (step.runner?.type === "external-cli") {
543
+ const runner = normalizeExternalCliRunnerStatus(step.runner);
544
+ if (runner) {
545
+ lines.push(` Runner: external-cli (${runner.command}${runner.args.length ? ` ${runner.args.join(" ")}` : ""})`);
546
+ lines.push(` Adapter: ${runner.adapter.id} v${runner.adapter.version} (${runner.adapter.executionMode})`);
547
+ if (runner.safety) {
548
+ if ("approvalPolicy" in runner.safety)
549
+ lines.push(` Safety: ${"access" in runner.safety ? `access=${runner.safety.access}, ` : ""}sandbox=${runner.safety.sandbox}, approval=${runner.safety.approvalPolicy}, ephemeral=${runner.safety.ephemeral}`);
550
+ else if ("mode" in runner.safety)
551
+ lines.push(` Safety: access=${runner.safety.access}, auth=${runner.safety.authentication}, mode=${runner.safety.mode}, sandbox=${runner.safety.sandbox}, workspaceTrust=${runner.safety.workspaceTrust}, sessionReuse=${runner.safety.sessionReuse}`);
552
+ else if ("authentication" in runner.safety)
553
+ lines.push(` Safety: access=${runner.safety.access}, auth=${runner.safety.authentication}, permission=${runner.safety.permissionMode}, tools=${runner.safety.tools}, mcp=${runner.safety.mcp}, settings=${runner.safety.settingSources}, settingsTrust=${runner.safety.userSettingsTrust}, persistence=${runner.safety.sessionPersistence}`);
554
+ else
555
+ lines.push(` Safety: access=read-only, permission=${runner.safety.permissionMode}, tools=${runner.safety.tools}, mcp=${runner.safety.mcp}, settings=${runner.safety.settingSources}, persistence=${runner.safety.sessionPersistence}`);
556
+ }
557
+ lines.push(` Capabilities: stop=${runner.capabilities.stop}, steer=false, resume=false, structuredOutput=false, toolEvents=false, supervisor=unsupported, forkContext=false, extensionBindings=false`);
558
+ lines.push(` Unsupported steer: ${runner.unsupportedReasons.steer}`);
559
+ lines.push(` Unsupported resume: ${runner.nonResumableReason}`);
560
+ lines.push(` Unsupported supervisor: ${runner.unsupportedReasons.supervisor}`);
561
+ lines.push(` Context handoff: fresh only (${runner.unsupportedReasons.forkContext})`);
562
+ } else {
563
+ lines.push(" Runner: external-cli (invalid persisted runner metadata)");
564
+ }
565
+ if (step.externalProcess?.pid !== undefined)
566
+ lines.push(` Process: ${step.externalProcess.pid}`);
567
+ if (step.externalProcess) {
568
+ lines.push(` Stdout: ${step.externalProcess.stdoutPath}`, ` Stderr: ${step.externalProcess.stderrPath}`);
569
+ if (step.externalProcess.finalOutputPath)
570
+ lines.push(` Final output: ${step.externalProcess.finalOutputPath}`);
571
+ }
572
+ } else if (step.runner?.type === "external-job") {
573
+ lines.push(` Runner: external-job (${step.runner.provider})`);
574
+ if (step.externalJob?.providerJobId)
575
+ lines.push(` Provider job: ${step.externalJob.providerJobId}`);
576
+ if (step.externalJob?.state)
577
+ lines.push(` Provider state: ${step.externalJob.state}`);
578
+ if (step.externalJob?.conversationUrl)
579
+ lines.push(` Conversation: ${step.externalJob.conversationUrl}`);
580
+ if (step.externalJob?.resultArtifactPath)
581
+ lines.push(` Result artifact: ${step.externalJob.resultArtifactPath}`);
582
+ if ((step.status === "complete" || step.status === "completed") && step.externalJob?.state === "completed" && step.externalJob.providerJobId && externalJobFollowUpSupported(step.runner.provider)) {
583
+ hasExternalJobFollowUpHint = true;
584
+ lines.push(` Follow-up: subagent({ action: "resume", id: "${status.runId}", index: ${index}, message: "..." })`);
585
+ }
586
+ }
363
587
  lines.push(...formatNestedRunStatusLines(step.children, { indent: " ", commandHints: true, maxLines: 20 }));
364
588
  const stepOutputPath = path.join(asyncDir, `output-${index}.log`);
365
589
  if (stepOutputPath !== outputPath && fs.existsSync(stepOutputPath))
366
590
  lines.push(` Output: ${stepOutputPath}`);
367
- if (step.status === "running") {
591
+ if (step.status === "running" && step.runner?.type !== "external-cli" && step.runner?.type !== "external-job" && status.mode !== "workflow") {
368
592
  lines.push(` Intercom target: ${resolveSubagentIntercomTarget(status.runId, step.agent, index)} (if registered)`);
369
593
  lines.push(` Steer: subagent({ action: "steer", id: "${status.runId}", index: ${index}, message: "..." })`);
594
+ } else if (step.status === "running" && (step.runner?.type === "external-cli" || step.runner?.type === "external-job")) {
595
+ lines.push(" Steer: unavailable; external runners do not accept live messages.");
370
596
  }
371
597
  }
598
+ const loadedWorkflowKeys = new Set((status.steps ?? []).flatMap((step) => step.workflowKey ? [step.workflowKey] : []));
599
+ const graphStages = status.mode === "workflow" ? workflowGraphStageNodes(status.workflowGraph) : [];
600
+ for (const [index, node] of graphStages.entries()) {
601
+ if (!loadedWorkflowKeys.has(node.id))
602
+ lines.push(` ${formatWorkflowStageLine(node, index, graphStages.length)}`);
603
+ }
372
604
  const attached = new Set((status.steps ?? []).flatMap((step) => step.children?.map((child) => child.id) ?? []));
373
605
  const unattached = nestedChildren.filter((child) => !attached.has(child.id));
374
606
  lines.push(...formatNestedRunStatusLines(unattached, { indent: "", commandHints: true, maxLines: 20 }));
607
+ if (status.mode === "workflow" && status.state === "running") {
608
+ if (liveWorkflowControls.length === 0)
609
+ lines.push("Steer: unavailable; no live foreground route is registered in the active session.");
610
+ else
611
+ for (const control of liveWorkflowControls) {
612
+ for (const index of [...control.activeChildren.keys()].sort((left, right) => left - right)) {
613
+ lines.push(`Steer live foreground child: subagent({ action: "steer", id: "${control.runId}", index: ${index}, message: "..." })`);
614
+ }
615
+ }
616
+ }
375
617
  if (nestedWarning)
376
618
  lines.push(`Warning: ${nestedWarning}`);
377
619
  if (status.sessionFile)
378
620
  lines.push(`Session: ${status.sessionFile}`);
379
- if (status.state === "running")
621
+ const allExternal = (status.steps?.length ?? 0) > 0 && status.steps.every((step) => step.runner?.type === "external-cli" || step.runner?.type === "external-job");
622
+ if (status.state === "running" && !allExternal && status.mode !== "workflow")
380
623
  lines.push(`Steer running child: subagent({ action: "steer", id: "${status.runId}", message: "..." })`);
381
624
  if (status.state !== "running") {
382
- lines.push(formatResumeGuidance(status.runId, status.steps ?? [], status.sessionFile));
625
+ lines.push(allExternal ? hasExternalJobFollowUpHint ? "Resume: use the external-job follow-up hint above." : "Resume: unavailable; external runners do not persist DM sessions." : formatResumeGuidance(status.runId, status.steps ?? [], status.sessionFile, { stopped: status.state === "stopped" || status.stopped === true }));
383
626
  }
384
627
  if (fs.existsSync(logPath))
385
628
  lines.push(`Log: ${logPath}`);
386
629
  if (fs.existsSync(eventsPath))
387
630
  lines.push(`Events: ${eventsPath}`);
631
+ const workflowChildren = parseWorkflowChildSummary(status.workflowChildren);
632
+ if (workflowChildren && workflowChildren.workflowRunId !== status.runId)
633
+ throw new Error("workflowChildren.workflowRunId does not match async status runId.");
388
634
  return { content: [{ type: "text", text: lines.join(`
389
- `) }], details: { mode: "single", results: [] } };
635
+ `) }], details: { mode: "single", results: [], ...status.preflight ? { preflight: status.preflight } : {}, ...status.workflow?.preflightWarnings?.length ? { preflightWarnings: status.workflow.preflightWarnings } : {}, ...workflowChildren ? { workflowChildren } : {}, ...runFanoutBudget ? { runFanoutBudget } : {}, ...processTerminal ? { lifecycleStatus: { processTerminal } } : {} } };
390
636
  }
391
637
  }
392
638
  if (resultPath) {
639
+ if (params.action === "debug.run") {
640
+ return {
641
+ content: [{ type: "text", text: "Run lifecycle debug needs an async run directory with status.json." }],
642
+ isError: true,
643
+ details: { mode: "single", results: [] }
644
+ };
645
+ }
393
646
  try {
394
647
  const raw = fs.readFileSync(resultPath, "utf-8");
395
648
  const data = JSON.parse(raw);
@@ -401,15 +654,33 @@ export function inspectSubagentStatus(params, deps = {}) {
401
654
  return { content: [{ type: "text", text: message }], isError: true, details: { mode: "single", results: [] } };
402
655
  }
403
656
  }
404
- const status = data.success ? "complete" : data.state === "paused" || data.exitCode === 0 ? "paused" : "failed";
657
+ const childStatuses = Array.isArray(data.results) ? data.results.map((child) => resolveSubagentResultStatus({
658
+ success: child.success,
659
+ state: child.state,
660
+ interrupted: child.interrupted,
661
+ timedOut: child.timedOut,
662
+ stopped: child.stopped,
663
+ turnBudgetExceeded: child.turnBudgetExceeded,
664
+ processSignal: child.processSignal,
665
+ exitCode: typeof child.exitCode === "number" ? child.exitCode : undefined
666
+ })) : [];
667
+ const status = data.state === "stopped" || data.stopped === true || childStatuses.includes("stopped") ? "stopped" : data.success ? "complete" : data.state === "paused" || data.exitCode === 0 ? "paused" : "failed";
405
668
  const runId = data.runId ?? data.id ?? resolvedId;
406
- const lines = [`Run: ${runId}`, `State: ${status}`, `Result: ${resultPath}`];
669
+ const lines = [`Run: ${runId}`, data.toolCallId ? `Tool call: ${data.toolCallId}` : undefined, `State: ${status}`, `Result: ${resultPath}`].filter((line) => Boolean(line));
670
+ if (data.parallelHandoff?.path)
671
+ lines.push(`Parallel handoff: ${data.parallelHandoff.path}`);
407
672
  const children = Array.isArray(data.results) ? data.results : data.agent ? [{ agent: data.agent, sessionFile: data.sessionFile }] : [];
408
- lines.push(formatResumeGuidance(runId, children, data.sessionFile));
673
+ lines.push(...formatTimeoutRecoveryLines(data.timeoutRecovery, " "));
674
+ for (const child of children)
675
+ lines.push(...formatTimeoutRecoveryLines(child.timeoutRecovery, " "));
676
+ lines.push(formatResumeGuidance(runId, children, data.sessionFile, { stopped: status === "stopped" }));
409
677
  if (data.summary)
410
678
  lines.push("", data.summary);
679
+ const workflowChildren = parseWorkflowChildSummary(data.workflowChildren);
680
+ if (workflowChildren && workflowChildren.workflowRunId !== runId)
681
+ throw new Error("workflowChildren.workflowRunId does not match the result run id.");
411
682
  return { content: [{ type: "text", text: lines.join(`
412
- `) }], details: { mode: "single", results: [] } };
683
+ `) }], details: { mode: "single", results: [], ...workflowChildren ? { workflowChildren } : {} } };
413
684
  } catch (error) {
414
685
  const message = error instanceof Error ? error.message : String(error);
415
686
  return {