@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,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import * as fs from "node:fs";
3
+ import { isUnexplainedProcessSignal } from "../runs/shared/process-signal.js";
3
4
  import {
4
5
  SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT,
5
6
  SUBAGENT_RESULT_INTERCOM_EVENT
@@ -7,10 +8,16 @@ import {
7
8
  export function resolveSubagentResultStatus(input) {
8
9
  if (input.detached)
9
10
  return "detached";
11
+ if (input.stopped || input.state === "stopped")
12
+ return "stopped";
10
13
  if (input.interrupted || input.state === "paused")
11
14
  return "paused";
12
- if (typeof input.success === "boolean")
13
- return input.success ? "completed" : "failed";
15
+ if (input.success === true)
16
+ return "completed";
17
+ if (isUnexplainedProcessSignal(input) && input.exitCode !== 0)
18
+ return "stopped";
19
+ if (input.success === false)
20
+ return "failed";
14
21
  if (input.state === "complete")
15
22
  return "completed";
16
23
  if (input.state === "failed")
@@ -24,6 +31,7 @@ function countStatuses(children) {
24
31
  completed: 0,
25
32
  failed: 0,
26
33
  paused: 0,
34
+ stopped: 0,
27
35
  detached: 0
28
36
  };
29
37
  for (const child of children) {
@@ -35,15 +43,32 @@ function formatStatusCounts(counts) {
35
43
  const parts = [
36
44
  counts.completed ? `${counts.completed} completed` : undefined,
37
45
  counts.failed ? `${counts.failed} failed` : undefined,
46
+ counts.stopped ? `${counts.stopped} stopped` : undefined,
38
47
  counts.paused ? `${counts.paused} paused` : undefined,
39
48
  counts.detached ? `${counts.detached} detached` : undefined
40
49
  ].filter((part) => Boolean(part));
41
50
  return parts.length ? parts.join(", ") : "0 results";
42
51
  }
52
+ function countOutputStates(children) {
53
+ const counts = { present: 0, absent: 0, unknown: 0 };
54
+ for (const child of children)
55
+ counts[child.outputState ?? "unknown"] += 1;
56
+ return counts;
57
+ }
58
+ function formatOutputCounts(counts) {
59
+ const parts = [
60
+ counts.present ? `${counts.present} present` : undefined,
61
+ counts.absent ? `${counts.absent} absent` : undefined,
62
+ counts.unknown ? `${counts.unknown} unknown` : undefined
63
+ ].filter((part) => Boolean(part));
64
+ return parts.length ? parts.join(", ") : "0 outputs";
65
+ }
43
66
  function resolveGroupedStatus(children) {
44
67
  const counts = countStatuses(children);
45
68
  if (counts.failed > 0)
46
69
  return "failed";
70
+ if (counts.stopped > 0)
71
+ return "stopped";
47
72
  if (counts.paused > 0)
48
73
  return "paused";
49
74
  if (counts.completed > 0)
@@ -66,6 +91,7 @@ function compactNestedRun(run, depth = 0) {
66
91
  })),
67
92
  ...run.asyncDir ? { asyncDir: run.asyncDir } : {},
68
93
  ...run.sessionId ? { sessionId: run.sessionId } : {},
94
+ ...run.sessionName ? { sessionName: run.sessionName } : {},
69
95
  ...run.sessionFile ? { sessionFile: run.sessionFile } : {},
70
96
  ...run.intercomTarget ? { intercomTarget: run.intercomTarget } : {},
71
97
  ...run.ownerIntercomTarget ? { ownerIntercomTarget: run.ownerIntercomTarget } : {},
@@ -75,6 +101,8 @@ function compactNestedRun(run, depth = 0) {
75
101
  state: run.state,
76
102
  ...run.agent ? { agent: run.agent } : {},
77
103
  ...run.agents?.length ? { agents: run.agents.slice(0, 12) } : {},
104
+ ...run.model ? { model: run.model } : {},
105
+ ...run.thinking ? { thinking: run.thinking } : {},
78
106
  ...run.currentStep !== undefined ? { currentStep: run.currentStep } : {},
79
107
  ...run.chainStepCount !== undefined ? { chainStepCount: run.chainStepCount } : {},
80
108
  ...run.parallelGroups?.length ? { parallelGroups: run.parallelGroups.slice(0, 8) } : {},
@@ -92,7 +120,10 @@ function compactNestedRun(run, depth = 0) {
92
120
  ...run.error ? { error: run.error } : {},
93
121
  ...run.steps?.length ? { steps: run.steps.slice(0, 12).map((step) => ({
94
122
  agent: step.agent,
123
+ ...step.sessionName ? { sessionName: step.sessionName } : {},
95
124
  status: step.status,
125
+ ...step.model ? { model: step.model } : {},
126
+ ...step.thinking ? { thinking: step.thinking } : {},
96
127
  ...step.sessionFile ? { sessionFile: step.sessionFile } : {},
97
128
  ...step.activityState ? { activityState: step.activityState } : {},
98
129
  ...step.lastActivityAt !== undefined ? { lastActivityAt: step.lastActivityAt } : {},
@@ -166,14 +197,19 @@ function asyncResumeGuidance(input) {
166
197
  }
167
198
  function formatSubagentResultIntercomMessage(input) {
168
199
  const counts = countStatuses(input.children);
200
+ const outputCounts = countOutputStates(input.children);
169
201
  const lines = [
170
202
  "subagent results",
171
203
  "",
172
204
  `Run: ${input.runId}`,
173
205
  `Mode: ${input.mode}`,
174
- `Status: ${input.status}`,
175
- `Children: ${formatStatusCounts(counts)}`
206
+ `Process status: ${input.status}`,
207
+ `Children: ${formatStatusCounts(counts)}`,
208
+ `Outputs: ${formatOutputCounts(outputCounts)} (semantic adequacy unassessed)`
176
209
  ];
210
+ if (input.children.some((child) => child.status === "failed" && child.outputState === "present")) {
211
+ lines.push("Recovery: At least one failed process produced output. Inspect that output before retrying; output presence does not establish task completion.");
212
+ }
177
213
  if (input.mode === "chain" && typeof input.chainSteps === "number") {
178
214
  lines.push(`Chain steps: ${input.chainSteps}`);
179
215
  }
@@ -181,6 +217,8 @@ function formatSubagentResultIntercomMessage(input) {
181
217
  lines.push(`Async id: ${input.asyncId}`);
182
218
  if (input.asyncDir)
183
219
  lines.push(`Async dir: ${input.asyncDir}`);
220
+ if (input.parallelHandoff)
221
+ lines.push(`Parallel handoff: ${input.parallelHandoff.path}`);
184
222
  const resumeGuidance = asyncResumeGuidance(input);
185
223
  if (resumeGuidance)
186
224
  lines.push(resumeGuidance);
@@ -191,7 +229,7 @@ function formatSubagentResultIntercomMessage(input) {
191
229
  for (let index = 0;index < input.children.length; index++) {
192
230
  const child = input.children[index];
193
231
  lines.push("");
194
- lines.push(`${index + 1}. ${child.agent} — ${child.status}`);
232
+ lines.push(`${index + 1}. ${child.agent} — process ${child.status} · output ${child.outputState ?? "unknown"}`);
195
233
  if (child.intercomTarget)
196
234
  lines.push(`${input.source === "async" ? "Previous intercom target" : "Run intercom target"}: ${child.intercomTarget}`);
197
235
  if (child.artifactPath)
@@ -208,6 +246,7 @@ function formatSubagentResultIntercomMessage(input) {
208
246
  export function buildSubagentResultIntercomPayload(input) {
209
247
  const children = input.children.map((child) => ({
210
248
  ...child,
249
+ outputState: child.outputState ?? "unknown",
211
250
  summary: child.summary.trim() || "(no output)",
212
251
  children: compactNestedResultChildren(child.children)
213
252
  }));
@@ -225,6 +264,7 @@ export function buildSubagentResultIntercomPayload(input) {
225
264
  ...input.asyncId ? { asyncId: input.asyncId } : {},
226
265
  ...input.asyncDir ? { asyncDir: input.asyncDir } : {},
227
266
  ...typeof input.chainSteps === "number" ? { chainSteps: input.chainSteps } : {},
267
+ ...input.parallelHandoff ? { parallelHandoff: input.parallelHandoff } : {},
228
268
  ...firstChild?.agent ? { agent: firstChild.agent } : {},
229
269
  ...firstChild?.index !== undefined ? { index: firstChild.index } : {},
230
270
  ...firstChild?.artifactPath ? { artifactPath: firstChild.artifactPath } : {},
@@ -240,8 +280,6 @@ export async function deliverSubagentResultIntercomEvent(events, payload, timeou
240
280
  export async function deliverSubagentIntercomMessageEvent(events, to, message, timeoutMs = 500, extra = {}) {
241
281
  if (typeof events.on !== "function" || typeof events.emit !== "function")
242
282
  return false;
243
- if (events.listenerCount?.(SUBAGENT_RESULT_INTERCOM_EVENT) === 0)
244
- return true;
245
283
  const requestId = typeof extra.requestId === "string" ? extra.requestId : randomUUID();
246
284
  return new Promise((resolve) => {
247
285
  let settled = false;
@@ -294,6 +332,8 @@ export function formatSubagentResultReceipt(input) {
294
332
  `Run: ${input.runId}`,
295
333
  `Children: ${formatStatusCounts(counts)}`
296
334
  ];
335
+ if (input.payload.parallelHandoff)
336
+ lines.push(`Parallel handoff: ${input.payload.parallelHandoff.path}`);
297
337
  const artifacts = input.payload.children.filter((child) => typeof child.artifactPath === "string");
298
338
  if (artifacts.length > 0) {
299
339
  lines.push("Artifacts:");
@@ -0,0 +1,394 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import {
4
+ MISSION_STATUSES
5
+ } from "./types.js";
6
+ import { missionStatePath } from "./workflow-state.js";
7
+ import {
8
+ createMission,
9
+ listGlobalMissions,
10
+ listMissions,
11
+ missionRecordPath,
12
+ readMission,
13
+ resolveMissionStoreLocation,
14
+ updateMission,
15
+ validateMissionId
16
+ } from "./store.js";
17
+ export const MISSION_ACTIONS = [
18
+ "mission.create",
19
+ "mission.list",
20
+ "mission.show",
21
+ "mission.update",
22
+ "mission.resolve-decision",
23
+ "mission.attach-run",
24
+ "mission.close"
25
+ ];
26
+ function textResult(text, details) {
27
+ return { content: [{ type: "text", text }], details };
28
+ }
29
+ function requireMissionId(params) {
30
+ return validateMissionId(params.missionId, "missionId");
31
+ }
32
+ function validateStatus(value, label) {
33
+ if (typeof value !== "string" || !MISSION_STATUSES.includes(value)) {
34
+ throw new Error(`${label} must be one of ${MISSION_STATUSES.join(", ")}`);
35
+ }
36
+ return value;
37
+ }
38
+ export function validateMissionLaunch(value) {
39
+ if (!value || typeof value !== "object" || Array.isArray(value))
40
+ throw new Error("mission must be an object");
41
+ const input = value;
42
+ for (const key of Object.keys(input)) {
43
+ if (key !== "title" && key !== "summary" && key !== "objective" && key !== "goal" && key !== "budget" && key !== "labels")
44
+ throw new Error(`mission.${key} is unknown`);
45
+ }
46
+ if (input.title !== undefined && input.summary !== undefined)
47
+ throw new Error("mission.title and mission.summary cannot both be set");
48
+ const title = input.title ?? input.summary;
49
+ if (typeof title !== "string" || !title.trim())
50
+ throw new Error("mission.title or mission.summary must be a non-empty string");
51
+ if (input.objective !== undefined && (typeof input.objective !== "string" || !input.objective.trim()))
52
+ throw new Error("mission.objective must be a non-empty string");
53
+ if (input.goal !== undefined && input.goal !== true)
54
+ throw new Error("mission.goal must be true when supplied");
55
+ const budget = input.budget;
56
+ if (budget !== undefined && (!budget || typeof budget !== "object" || Array.isArray(budget) || !Number.isSafeInteger(budget.tokens) || budget.tokens < 1)) {
57
+ throw new Error("mission.budget.tokens must be a positive integer");
58
+ }
59
+ if (input.goal === true && budget === undefined)
60
+ throw new Error("mission.budget is required when mission.goal is true");
61
+ if (input.labels !== undefined && (!Array.isArray(input.labels) || input.labels.some((label) => typeof label !== "string" || !label.trim()))) {
62
+ throw new Error("mission.labels must contain only non-empty strings");
63
+ }
64
+ return {
65
+ title: title.trim(),
66
+ ...typeof input.objective === "string" ? { objective: input.objective.trim() } : {},
67
+ ...input.goal === true ? { goal: true } : {},
68
+ ...budget !== undefined ? { budget: { tokens: budget.tokens } } : {},
69
+ ...input.labels !== undefined ? { labels: input.labels.map((label) => label.trim()) } : {}
70
+ };
71
+ }
72
+ function validateArtifact(value, index) {
73
+ if (!value || typeof value !== "object" || Array.isArray(value))
74
+ throw new Error(`missionUpdate.artifacts[${index}] must be an object`);
75
+ const input = value;
76
+ const kinds = ["status", "output", "patch", "manifest", "review", "note", "other"];
77
+ if (typeof input.kind !== "string" || !kinds.includes(input.kind))
78
+ throw new Error(`missionUpdate.artifacts[${index}].kind is invalid`);
79
+ if (typeof input.path !== "string" || !input.path.trim())
80
+ throw new Error(`missionUpdate.artifacts[${index}].path must be a non-empty string`);
81
+ if (input.description !== undefined && (typeof input.description !== "string" || !input.description.trim()))
82
+ throw new Error(`missionUpdate.artifacts[${index}].description must be a non-empty string`);
83
+ return {
84
+ kind: input.kind,
85
+ path: input.path,
86
+ ...typeof input.description === "string" ? { description: input.description } : {}
87
+ };
88
+ }
89
+ function validateReceipt(value, index) {
90
+ if (!value || typeof value !== "object" || Array.isArray(value))
91
+ throw new Error(`missionUpdate.receipts[${index}] must be an object`);
92
+ const input = value;
93
+ for (const key of Object.keys(input)) {
94
+ if (!["kind", "status", "title", "url", "description"].includes(key))
95
+ throw new Error(`missionUpdate.receipts[${index}].${key} is unknown`);
96
+ }
97
+ const kinds = ["pull_request", "ci", "deployment", "release"];
98
+ const statuses = ["pending", "ready", "succeeded", "failed"];
99
+ if (typeof input.kind !== "string" || !kinds.includes(input.kind))
100
+ throw new Error(`missionUpdate.receipts[${index}].kind is invalid`);
101
+ if (typeof input.status !== "string" || !statuses.includes(input.status))
102
+ throw new Error(`missionUpdate.receipts[${index}].status is invalid`);
103
+ for (const field of ["title", "url"]) {
104
+ if (typeof input[field] !== "string" || !input[field].trim())
105
+ throw new Error(`missionUpdate.receipts[${index}].${field} must be a non-empty string`);
106
+ }
107
+ try {
108
+ new URL(input.url);
109
+ } catch {
110
+ throw new Error(`missionUpdate.receipts[${index}].url must be an absolute URL`);
111
+ }
112
+ if (input.description !== undefined && (typeof input.description !== "string" || !input.description.trim()))
113
+ throw new Error(`missionUpdate.receipts[${index}].description must be a non-empty string`);
114
+ return {
115
+ kind: input.kind,
116
+ status: input.status,
117
+ title: input.title.trim(),
118
+ url: input.url.trim(),
119
+ ...typeof input.description === "string" ? { description: input.description.trim() } : {}
120
+ };
121
+ }
122
+ function validateMissionUpdate(value) {
123
+ if (!value || typeof value !== "object" || Array.isArray(value))
124
+ throw new Error("missionUpdate must be an object");
125
+ const input = value;
126
+ for (const key of Object.keys(input)) {
127
+ if (!["title", "objective", "goal", "budget", "status", "summary", "labels", "artifacts", "receipts", "decisions"].includes(key))
128
+ throw new Error(`missionUpdate.${key} is unknown`);
129
+ }
130
+ const update = {};
131
+ for (const field of ["title", "objective", "summary"]) {
132
+ const candidate = input[field];
133
+ if (candidate === undefined)
134
+ continue;
135
+ if (typeof candidate !== "string" || !candidate.trim())
136
+ throw new Error(`missionUpdate.${field} must be a non-empty string`);
137
+ update[field] = candidate.trim();
138
+ }
139
+ if (input.goal !== undefined) {
140
+ if (typeof input.goal === "boolean")
141
+ update.goal = input.goal ? { status: "active" } : false;
142
+ else {
143
+ if (!input.goal || typeof input.goal !== "object" || Array.isArray(input.goal) || typeof input.goal.paused !== "boolean" || Object.keys(input.goal).some((key) => key !== "paused")) {
144
+ throw new Error("missionUpdate.goal must be boolean or { paused: boolean }");
145
+ }
146
+ update.goal = { status: input.goal.paused ? "paused" : "active" };
147
+ }
148
+ }
149
+ if (input.budget !== undefined) {
150
+ if (!input.budget || typeof input.budget !== "object" || Array.isArray(input.budget) || !Number.isSafeInteger(input.budget.tokens) || input.budget.tokens < 1) {
151
+ throw new Error("missionUpdate.budget.tokens must be a positive integer");
152
+ }
153
+ update.budget = { tokens: input.budget.tokens };
154
+ }
155
+ if (input.status !== undefined)
156
+ update.status = validateStatus(input.status, "missionUpdate.status");
157
+ if (input.labels !== undefined) {
158
+ if (!Array.isArray(input.labels) || input.labels.some((label) => typeof label !== "string" || !label.trim()))
159
+ throw new Error("missionUpdate.labels must contain only non-empty strings");
160
+ update.labels = input.labels;
161
+ }
162
+ if (input.artifacts !== undefined) {
163
+ if (!Array.isArray(input.artifacts))
164
+ throw new Error("missionUpdate.artifacts must be an array");
165
+ update.addArtifacts = input.artifacts.map(validateArtifact);
166
+ }
167
+ if (input.receipts !== undefined) {
168
+ if (!Array.isArray(input.receipts))
169
+ throw new Error("missionUpdate.receipts must be an array");
170
+ update.addReceipts = input.receipts.map(validateReceipt);
171
+ }
172
+ if (input.decisions !== undefined) {
173
+ if (!Array.isArray(input.decisions))
174
+ throw new Error("missionUpdate.decisions must be an array");
175
+ update.addDecisions = input.decisions.map((value, index) => {
176
+ if (!value || typeof value !== "object" || Array.isArray(value))
177
+ throw new Error(`missionUpdate.decisions[${index}] must be an object`);
178
+ const decision = value;
179
+ if (typeof decision.title !== "string" || !decision.title.trim())
180
+ throw new Error(`missionUpdate.decisions[${index}].title must be a non-empty string`);
181
+ if (decision.options !== undefined && (!Array.isArray(decision.options) || decision.options.some((option) => typeof option !== "string" || !option.trim())))
182
+ throw new Error(`missionUpdate.decisions[${index}].options must contain only non-empty strings`);
183
+ return {
184
+ title: decision.title.trim(),
185
+ ...typeof decision.prompt === "string" && decision.prompt.trim() ? { prompt: decision.prompt } : {},
186
+ ...Array.isArray(decision.options) ? { options: decision.options } : {},
187
+ ...typeof decision.recommendation === "string" && decision.recommendation.trim() ? { recommendation: decision.recommendation } : {}
188
+ };
189
+ });
190
+ }
191
+ if (Object.keys(update).length === 0)
192
+ throw new Error("missionUpdate must include at least one supported field");
193
+ return update;
194
+ }
195
+ function refreshLinkedRunStatus(location, record) {
196
+ const warnings = [];
197
+ const updates = record.runs.flatMap((run) => {
198
+ if (!run.asyncDir)
199
+ return [];
200
+ const statusPath = path.join(run.asyncDir, "status.json");
201
+ if (!fs.existsSync(statusPath))
202
+ return [];
203
+ let status;
204
+ try {
205
+ status = JSON.parse(fs.readFileSync(statusPath, "utf-8"));
206
+ } catch (error) {
207
+ warnings.push(`Failed to read linked run status '${statusPath}': ${error instanceof Error ? error.message : String(error)}`);
208
+ return [];
209
+ }
210
+ if (!status || typeof status !== "object" || Array.isArray(status)) {
211
+ warnings.push(`Linked run status '${statusPath}' must be an object`);
212
+ return [];
213
+ }
214
+ const state = status.state;
215
+ if (typeof state !== "string" || !state.trim()) {
216
+ warnings.push(`Linked run status '${statusPath}' is missing state`);
217
+ return [];
218
+ }
219
+ if (state === run.status)
220
+ return [];
221
+ return [{
222
+ ...run,
223
+ status: state,
224
+ ...!["queued", "running"].includes(state) && !run.completedAt ? { completedAt: new Date().toISOString() } : {}
225
+ }];
226
+ });
227
+ if (updates.length === 0)
228
+ return { record, warnings };
229
+ const merged = record.runs.map((run) => updates.find((update) => update.runId === run.runId && update.childIndex === run.childIndex) ?? run);
230
+ const states = merged.map((run) => run.status);
231
+ const status = record.status === "completed" || record.status === "failed" || record.status === "cancelled" ? record.status : record.goal && !states.some((state) => state === "queued" || state === "running" || state === "active") ? "active" : states.some((state) => state === "queued" || state === "running" || state === "active") ? "active" : states.some((state) => state === "paused") ? "waiting" : states.some((state) => state === "failed") ? "failed" : states.some((state) => state === "stopped" || state === "rejected" || state === "cancelled") ? "cancelled" : states.length > 0 && states.every((state) => state === "complete" || state === "completed") ? "completed" : record.status;
232
+ return { record: updateMission(location, record.id, { status, addRuns: updates }), warnings };
233
+ }
234
+ function formatMission(record) {
235
+ const lines = [
236
+ `Mission: ${record.id}`,
237
+ `Title: ${record.title}`,
238
+ `Status: ${record.status}`,
239
+ `Objective: ${record.objective}`,
240
+ `Updated: ${record.updatedAt}`
241
+ ];
242
+ if (record.goal && record.budget)
243
+ lines.push(`Goal mode: ${record.goal.status}`, `Budget: ${record.usage?.tokens ?? 0}/${record.budget.tokens} tokens`);
244
+ if (record.summary)
245
+ lines.push(`Summary: ${record.summary}`);
246
+ if (record.labels?.length)
247
+ lines.push(`Labels: ${record.labels.join(", ")}`);
248
+ if (record.runs.length) {
249
+ lines.push("Runs:");
250
+ for (const run of record.runs)
251
+ lines.push(` ${run.runId} (${run.mode}${run.status ? `, ${run.status}` : ""})${run.asyncDir ? ` — ${run.asyncDir}` : ""}`);
252
+ }
253
+ if (record.workflowChildren.length) {
254
+ lines.push("Workflow children:");
255
+ for (const child of record.workflowChildren) {
256
+ const identity = child.runId ? `${child.key} (${child.runId})` : child.key;
257
+ const heartbeat = child.heartbeat ? `; heartbeat ${child.heartbeat.status ?? child.status}${child.heartbeat.phase ? `/${child.heartbeat.phase}` : ""} at ${child.heartbeat.updatedAt}` : "";
258
+ const recovery = child.sessionPath ? `; session ${child.sessionPath}` : child.artifactPaths.length ? `; artifacts ${child.artifactPaths.length}` : "";
259
+ lines.push(` ${identity}: ${child.status}${child.agent ? ` — ${child.agent}` : ""}${child.phase ? ` [${child.phase}]` : ""}; updated ${child.updatedAt}${heartbeat}${recovery}`);
260
+ }
261
+ }
262
+ if (record.decisions.length) {
263
+ lines.push("Decisions:");
264
+ for (const decision of record.decisions) {
265
+ lines.push(` ${decision.id}: ${decision.status} — ${decision.title}${decision.resolution ? `; resolution: ${decision.resolution}` : ""}`);
266
+ }
267
+ }
268
+ if (record.artifacts.length) {
269
+ lines.push("Artifacts:");
270
+ for (const artifact of record.artifacts)
271
+ lines.push(` ${artifact.kind}: ${artifact.path}`);
272
+ }
273
+ if (record.receipts.length) {
274
+ lines.push("Delivery receipts:");
275
+ for (const receipt of record.receipts)
276
+ lines.push(` ${receipt.kind} (${receipt.status}): ${receipt.title} — ${receipt.url}`);
277
+ }
278
+ return lines.join(`
279
+ `);
280
+ }
281
+ export function handleMissionAction(action, params, ctx) {
282
+ const location = resolveMissionStoreLocation({
283
+ projectRoot: ctx.cwd,
284
+ ...ctx.config ? { config: ctx.config } : {},
285
+ ...ctx.agentDir ? { agentDir: ctx.agentDir } : {}
286
+ });
287
+ if (action === "mission.create") {
288
+ const mission = validateMissionLaunch(params.mission);
289
+ const record = createMission(location, {
290
+ title: mission.title,
291
+ objective: mission.objective ?? mission.title,
292
+ ...mission.goal === true ? { goal: true } : {},
293
+ ...mission.budget ? { budget: mission.budget } : {},
294
+ status: params.missionStatus ? validateStatus(params.missionStatus, "missionStatus") : "planned",
295
+ ...mission.labels ? { labels: mission.labels } : {},
296
+ ...ctx.currentSessionId ? { ownerSessionId: ctx.currentSessionId } : {}
297
+ }, new Date, ctx.config?.retainTerminal);
298
+ return textResult(`Created mission ${record.id}: ${record.title}`, { mode: "management", results: [], missionId: record.id, missionPath: pathFor(record.id), mission: record });
299
+ }
300
+ if (action === "mission.list") {
301
+ if (params.missionScope !== undefined && params.missionScope !== "project" && params.missionScope !== "global") {
302
+ throw new Error('missionScope must be "project" or "global"');
303
+ }
304
+ if (params.missionScope === "global") {
305
+ const listed = listGlobalMissions(location.globalIndexDir);
306
+ const lines = listed.entries.length === 0 ? ["No indexed missions."] : listed.entries.map((entry) => `${entry.missionId} ${entry.status}${entry.stale ? " [stale]" : ""} ${entry.title} ${entry.projectRoot}`);
307
+ if (listed.warnings.length)
308
+ lines.push("", ...listed.warnings.map((warning) => `Warning: ${warning}`));
309
+ return textResult(lines.join(`
310
+ `), { mode: "management", results: [], missions: { globalEntries: listed.entries, warnings: listed.warnings } });
311
+ }
312
+ const listed = listMissions(location);
313
+ const lines = listed.records.length === 0 ? ["No project missions."] : listed.records.map((record) => {
314
+ const open = record.decisions.filter((decision) => decision.status === "open").length;
315
+ const resolved = record.decisions.length - open;
316
+ return `${record.id} ${record.status} ${record.title} ${record.updatedAt}${record.decisions.length ? ` decisions: ${open} open, ${resolved} resolved` : ""}`;
317
+ });
318
+ if (listed.warnings.length)
319
+ lines.push("", ...listed.warnings.map((warning) => `Warning: ${warning}`));
320
+ return textResult(lines.join(`
321
+ `), { mode: "management", results: [], missions: { records: listed.records, warnings: listed.warnings } });
322
+ }
323
+ if (action === "mission.show") {
324
+ const refreshed = refreshLinkedRunStatus(location, readMission(location, requireMissionId(params)));
325
+ const lines = [formatMission(refreshed.record), `State: ${missionStatePath(location, refreshed.record.id)}`];
326
+ if (refreshed.warnings.length)
327
+ lines.push("", ...refreshed.warnings.map((warning) => `Warning: ${warning}`));
328
+ return textResult(lines.join(`
329
+ `), {
330
+ mode: "management",
331
+ results: [],
332
+ missionId: refreshed.record.id,
333
+ missionPath: pathFor(refreshed.record.id),
334
+ mission: refreshed.record,
335
+ missions: { warnings: refreshed.warnings }
336
+ });
337
+ }
338
+ if (action === "mission.update") {
339
+ const record = updateMission(location, requireMissionId(params), validateMissionUpdate(params.missionUpdate));
340
+ return textResult(`Updated mission ${record.id}.
341
+
342
+ ${formatMission(record)}`, { mode: "management", results: [], missionId: record.id, missionPath: pathFor(record.id), mission: record });
343
+ }
344
+ if (action === "mission.resolve-decision") {
345
+ const missionId = requireMissionId(params);
346
+ const decisionId = validateMissionId(params.id, "id");
347
+ if (typeof params.summary !== "string" || !params.summary.trim())
348
+ throw new Error("mission.resolve-decision requires a non-empty summary");
349
+ const record = updateMission(location, missionId, { resolveDecision: { id: decisionId, resolution: params.summary.trim() } });
350
+ return textResult(`Resolved decision ${decisionId} for mission ${record.id}.
351
+
352
+ ${formatMission(record)}`, { mode: "management", results: [], missionId: record.id, missionPath: pathFor(record.id), mission: record });
353
+ }
354
+ if (action === "mission.attach-run") {
355
+ const missionId = requireMissionId(params);
356
+ const runId = params.runId ?? params.id;
357
+ if (typeof runId !== "string" || !runId.trim())
358
+ throw new Error("mission.attach-run requires runId or id");
359
+ const rawMode = params.runMode ?? "external";
360
+ if (!["single", "parallel", "chain", "workflow", "scheduled", "external"].includes(rawMode))
361
+ throw new Error("runMode is invalid");
362
+ const mode = rawMode;
363
+ if (params.dir !== undefined && !params.dir.trim())
364
+ throw new Error("dir must be a non-empty string");
365
+ if (params.runStatus !== undefined && !params.runStatus.trim())
366
+ throw new Error("runStatus must be a non-empty string");
367
+ const record = updateMission(location, missionId, {
368
+ status: "active",
369
+ addRuns: [{
370
+ runId: runId.trim(),
371
+ mode,
372
+ ...params.dir ? { asyncDir: params.dir } : {},
373
+ ...params.agent ? { agent: params.agent } : {},
374
+ ...params.runStatus ? { status: params.runStatus } : {},
375
+ startedAt: new Date().toISOString()
376
+ }]
377
+ });
378
+ return textResult(`Attached run ${runId} to mission ${record.id}.`, { mode: "management", results: [], missionId: record.id, missionPath: pathFor(record.id), mission: record });
379
+ }
380
+ const missionId = requireMissionId(params);
381
+ const status = params.missionStatus ?? "completed";
382
+ if (status !== "completed" && status !== "failed" && status !== "cancelled")
383
+ throw new Error("mission.close missionStatus must be completed, failed, or cancelled");
384
+ if (params.summary !== undefined && !params.summary.trim())
385
+ throw new Error("summary must be a non-empty string");
386
+ const record = updateMission(location, missionId, {
387
+ status,
388
+ ...params.summary !== undefined ? { summary: params.summary.trim() } : {}
389
+ });
390
+ return textResult(`Closed mission ${record.id} as ${record.status}.`, { mode: "management", results: [], missionId: record.id, missionPath: pathFor(record.id), mission: record });
391
+ function pathFor(missionId) {
392
+ return missionRecordPath(location, missionId);
393
+ }
394
+ }