@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
@@ -3,90 +3,101 @@ import * as path from "node:path";
3
3
  import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
4
4
  const CUSTOM_TOOL_DESCRIPTION_FILE = "subagent-tool-description.md";
5
5
  const CUSTOM_TOOL_DESCRIPTION_MAX_BYTES = 50 * 1024;
6
+ const EXTERNAL_CLI_RUNNER_GUIDANCE = "External CLI agents (codex-exec, codex-exec-writer, claude-code, claude-code-writer, cursor-agent, cursor-agent-writer) use their own runner contract and do not support native DM child options such as model override, structured output, acceptance/agent contract, tool budget, fast mode, fork context, skills, or native DM tools unless the runner explicitly implements them.";
7
+ const WORKFLOW_RESUME_KEY_GUIDANCE = "Each workflow key identifies one result lane: use a new stable workflow key for every distinct retained resume pass; same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected.";
8
+ const WORKFLOW_OUTPUT_BINDING_GUIDANCE = "For durable workflow child files, set output on runs.run/runs.all; task filename prose is not an output declaration, and return the child's outputReference, outputPathMapping, or artifactPaths instead of inventing a literal path.";
9
+ const WORKFLOW_LANES_GUIDANCE = "For bounded parallel sequential chains, use runs.lanes([{key,stages:[{key,agent,task},{key,resume:'previous',task},...]}]); first stages run together, later stages sequence per lane, and the bounded board reports lane-local failures. Only an explicit structuredOutput.verdict === 'blocked' blocks a successful stage; reviewer prose is not parsed.";
10
+ const WORKFLOW_SCRIPT_PORTABILITY_GUIDANCE = "workflowScript rejects nested async function, arrow, and method helpers; use top-level await, plain helper functions that return runs.run(...), or explicit Promise chains instead.";
11
+ const WORKFLOW_HOST_GUIDANCE = "For one non-interactive operator-owned command, await runs.host(key,{kind:'command',command,timeoutMs,output?,role?,provider?}). runs.host has no per-step cwd: commands and relative output paths use the workflow cwd; set cwd on the outer subagent request instead (for example, {cwd:'/path/to/worktree',workflowScript:'...'}), or put a trusted directory change in the command (for example, 'cd /path/to/worktree && npm test'). v1 supports only command steps; output is bounded and command failure fails the workflow.";
12
+ const AGENT_CAPABILITY_GUIDANCE = 'For capability selection, use { action: "list", capabilities: true } for compact prompt-free rows.';
13
+ export const DEFAULT_SUBAGENT_TOOL_DESCRIPTION = `Delegate to configured subagents. For execution, omit action and use {agent, task?} for one child, workflowScript for inline orchestration, or workflowScriptPath to load a script from the request cwd. The script inputs are mutually exclusive. Use action:'validate' with either script input to check it without launching children. For multi-step or parallel work, make exactly one top-level subagent call with async:true; launch children only inside that workflow and do not make another top-level call for them. Use runs.run('key',{agent,task}) for one child, await runs.all([{key:'a',agent:'reviewer',task:'...'},{key:'b',agent:'reviewer',task:'...'}]) for ordinary parallel children, and read its ordered array result with indexes, destructuring, or .map(...), not by key property. ${WORKFLOW_SCRIPT_PORTABILITY_GUIDANCE} ${WORKFLOW_LANES_GUIDANCE} ${WORKFLOW_HOST_GUIDANCE} ${EXTERNAL_CLI_RUNNER_GUIDANCE} Use action only for management/control. Use guide or the dm-subagents skill for advanced workflow details.`;
14
+ export const SUBAGENT_TOOL_PROMPT_SNIPPET = "Delegate to subagents; orchestrate in one workflowScript call.";
15
+ export const SUBAGENT_TOOL_PROMPT_GUIDELINES = [
16
+ `Use subagent only when delegation is needed. Before executing, call { action: "list" } and run only executable, non-disabled agents. ${AGENT_CAPABILITY_GUIDANCE}`,
17
+ "Omit action for execution. Use { agent, task? } only for one child; use workflowScript for multi-step or parallel work.",
18
+ "workflowScript means exactly one top-level subagent tool call with async:true. Inside it, use runs.run/runs.all to launch children; do not make another top-level subagent call for those children.",
19
+ WORKFLOW_SCRIPT_PORTABILITY_GUIDANCE,
20
+ WORKFLOW_LANES_GUIDANCE,
21
+ WORKFLOW_HOST_GUIDANCE,
22
+ WORKFLOW_RESUME_KEY_GUIDANCE,
23
+ WORKFLOW_OUTPUT_BINDING_GUIDANCE,
24
+ "For ordinary parallel work, use await runs.all([{key,agent,task}, ...]); it resolves to an ordered array, not a key map, so use results[0], destructuring, or results.map(...), not results.<key>. Do not read .output from unawaited runs.run launches. Stored runs.run promises are only for advanced rolling fanout and each must later be observed with direct await, Promise.race, or Promise.all.",
25
+ "Keep one writer per cwd/worktree unless writers run in isolated worktrees.",
26
+ `To pass an explicit model to a child, first call { action: "models" } and copy an exact provider/id (e.g. provider/model-id); bare ids resolve only when unique in the registry, and agent names (gpt-pro, advisor) are not model ids. Set per-run thinking with a suffix on the model string (e.g. provider/model-id:high; off/minimal/low/medium/high/xhigh/max); the suffix wins over the agent's thinking default. The thinking field only applies to action='watchdog.configure' and is ignored on dispatch.`,
27
+ EXTERNAL_CLI_RUNNER_GUIDANCE,
28
+ "Use guide or the dm-subagents skill for advanced scheduling, missions, steering, and retention."
29
+ ];
6
30
  export const SUBAGENT_SAFETY_GUIDANCE = `SAFETY-CRITICAL SUBAGENT GUIDANCE:
7
- • Use { action: "list" } before execution and only run executable/non-disabled agents or chains.
8
- • Keep execution and management separate: omit action for SINGLE/PARALLEL/CHAIN execution; use action only for list/get/models/create/update/delete/status/interrupt/resume/append-step/doctor.
9
- • Async/background runs: launch with async:true only when work can proceed independently. Do not sleep or poll status just to wait; if this turn must block, use the wait tool. Otherwise continue useful work or respond and let completion notifications arrive.
10
- • Child-safety boundary: ordinary child subagents are not orchestrators and must not run subagents. Only explicitly configured fanout children may use the child-safe subagent tool, still bounded by depth/session limits.
11
- • Writing/review safety: keep one writer for the same cwd/worktree. Use fresh-context read-only reviewers/validators for independent review, then have the parent synthesize and apply fixes as the sole writer unless an isolated worktree was intentionally requested.
12
- • Artifacts/status essentials: chain outputs live under {chain_dir}; async runs expose asyncId/asyncDir with status.json, events.jsonl, output logs, and status via { action: "status", id }. Include output paths and residual risks when reporting results.`;
13
- export const FULL_SUBAGENT_TOOL_DESCRIPTION = `Delegate to subagents or manage agent definitions.
31
+ • Use { action: "list" } before execution and only run executable/non-disabled agents.
32
+ • Keep execution and management separate: omit action for structured single-child or workflowScript execution; use action only for management/control.
33
+ • Async/background runs are the normal default unless config sets asyncByDefault:false; set async:true explicitly when async behavior matters. Use async:false only when the parent must block until completion. Async mode still shows progress. Final reviews and gate checks stay async; needing a result is not a blocking reason. After an async launch, continue independent work only until its next dependency barrier; consume the result before work that depends on it. Ordinary async subagents notify this session natively, so return control and do not call bg_wait merely to get a completion wake. Do not sleep or poll status just to wait; use bg_wait only for provider, detached, or other background work without a native notification when this turn must receive its result.
34
+ • ${WORKFLOW_RESUME_KEY_GUIDANCE}
35
+ • ${WORKFLOW_OUTPUT_BINDING_GUIDANCE}
36
+ • ${WORKFLOW_HOST_GUIDANCE}
37
+ • Ordinary child subagents are not orchestrators. Only explicitly configured fanout children may use the child-safe subagent tool, still bounded by depth/session limits.
38
+ • Oracle/advisor consultations should use supervisor dialogue for material unknowns when available; request one-shot only when desired.
39
+ • Keep one writer for the same cwd/worktree. Use fresh-context read-only reviewers for independent review, then have the parent synthesize and apply fixes.
40
+ • Async runs expose asyncId/asyncDir with status.json, events.jsonl, output logs, status via { action: "status", id }, and lifecycle diagnostics via { action: "debug.run", id }. Include output paths and residual risks when reporting results.`;
41
+ export const FULL_SUBAGENT_TOOL_DESCRIPTION = `Run one child with { agent, task? }; use { workflowScript } for inline orchestration or { workflowScriptPath } to load it from the request cwd. The script inputs are mutually exclusive. Omit action for execution. Use action only for management/control actions.
14
42
 
15
- EXECUTION (use exactly ONE mode):
16
- • Before executing, use { action: "list" } to inspect configured agents/chains. Only execute agents listed as executable/non-disabled.
17
- • SINGLE: { agent, task? } - one task; omit task for self-contained agents
18
- • CHAIN: { chain: [{agent:"agent-a"}, {parallel:[{agent:"agent-b",count:3}]}] } - sequential pipeline with optional parallel fan-out
19
- • PARALLEL: { tasks: [{agent,task,count?,output?,reads?,progress?}, ...], concurrency?: number, worktree?: true } - concurrent execution (worktree: isolate each task in a git worktree)
20
- • Optional context: { context: "fresh" | "fork" } (explicit value overrides every child; when omitted, each requested agent uses its own defaultContext, otherwise "fresh"; inspect agent defaults via { action: "list" })
21
- • Optional timeout: { timeoutMs } or { maxRuntimeMs } sets a run-level max runtime for foreground and async/background runs
22
- • If { action: "list" } shows proactive skill subagent suggestions, consider a small fresh-context fanout for broad tasks where one of those skills would materially help
43
+ EXECUTION:
44
+ • ${EXTERNAL_CLI_RUNNER_GUIDANCE}
45
+ • Before executing, use { action: "list" } and run only executable/non-disabled configured agents.
46
+ • When passing an explicit model to a child (on the call or a runs.run/runs.all item), first call { action: "models" } and copy an exact provider/id; bare ids resolve only when unique in the registry, and agent names (e.g. gpt-pro, advisor) are not model ids. Set per-run thinking with a suffix on the model string (e.g. provider/id:high; off/minimal/low/medium/high/xhigh/max); the suffix wins over the agent's thinking default. The thinking field only applies to action='watchdog.configure' and is ignored on dispatch.
47
+ • SINGLE CHILD: { agent:"worker", task:"..." }. This structured form starts exactly one direct child. Fields such as model, context, cwd, worktree, output, budgets, acceptance, and async apply to that child. Do not combine agent/task with action, workflowScript, or workflowScriptPath.
48
+ • WORKFLOW SCRIPT: { workflowScript: "return runs.run('main', {agent:'worker', task:'...'})" }. Use stable-key runs.run for one child and await runs.all([{key,agent,task}, ...]) for ordinary parallel children. runs.all resolves to an ordered array, not a key map, so use results[0], array destructuring, or results.map((result) => result.output), not results.<key>. Do not read .output from unawaited runs.run launches. Stored runs.run promises are only for advanced rolling fanout and each must later be observed with direct await, Promise.race, or Promise.all. Ordinary JavaScript provides sequence, branching, filtering, retries, and aggregation. workflowScript is an ordinary JavaScript statement body, so use an explicit return for a useful result. Use top-level await, plain helper functions, or explicit Promise chains; nested async function, arrow, and method helpers are rejected. For task text with Markdown fences or shell blocks, build quoted lines instead of nesting raw template literals: \`const task=["Run:","\`\`\`bash","npm test","\`\`\`"].join("\\n")\`. Scripts normally start async unless config sets asyncByDefault:false; set async:true explicitly when async behavior matters. Pass async:false only when the parent must block until completion, never for final reviews or gates. Same-repo blocking workflows default to a live in-chat card; explicit live-card requires same-repository async:false, so async workflows should omit chatProgress or use auto/off. Workflow-level child controls default onto each runs.run launch, and explicit child fields override them. Use {action:"children.list"} to list recent retained workflow children with resumable/not-resumable reasons. Resume only rows reported resumable. For a simple follow-up or implementation challenge, use {action:"resume", id:"run-id", message:"..."}. Resume keeps the stored agent/model/tool contract. If no resumable child is listed, launch a same-role fallback challenge and label it as fallback. Inside workflowScript, continue one with runs.run(key, {resume:"run-id", task:"follow-up"}); workflow resumes wait for completed output, and loops must continue from each latest returned runId. Await runs.steer(key, message, {mode?, index?, ackTimeoutMs?}) to guide a prior keyed child without exposing its run id; receipts are queued, delivered, missed, or failed. Always await or return runs.steer. For repository mutation lanes, set worktree:true on the workflow or individual runs.run/runs.all item for managed isolation; each parallel child gets a separate worktree and handoff artifact. A workflow usageBudget is enforced once across the workflow. Available globals are runs.run, runs.all, runs.steer, runs.status, runs.ref/refs, emit, console, and standard JavaScript only. Workflows get async state.get(key) and state.set(key, JSONValue) through their automatic or explicit mission; mission:false workflows do not have a state global. Scripts cannot access filesystem, shell, arbitrary DM tools, or host globals.
49
+ • ${WORKFLOW_LANES_GUIDANCE}
50
+ • FILE SCRIPT: { workflowScriptPath:"workflows/review.js" }. Relative paths resolve against the request cwd. The host reads the file before the filesystem-free workflow sandbox starts. Do not combine this field with workflowScript.
51
+ • Sequential example: { workflowScript: "const a = await runs.run('analyze', {agent:'agent-a', task:'Analyze the request'}); return (await runs.run('plan', {agent:'agent-b', task:'Plan from: '+a.output})).output" }
52
+ • Parallel example: { workflowScript: "const [a,b] = await runs.all([{key:'correctness',agent:'agent-a',task:'Review correctness'},{key:'tests',agent:'agent-b',task:'Review tests'}]); return {correctness:a.output,tests:b.output}" }
53
+ • Optional context is "fresh", "fork", or "profile". profile requires the selected agent's declared defaultContext and ignores config defaultSubagentContext. Explicit fresh/fork wins. When omitted, config defaultSubagentContext wins over agent defaultContext. Config forkContext can summarize transcript overflow with stable recovery refs before spawn without adding another public context value. timeoutMs/maxRuntimeMs apply to foreground and async workflows; foreground workflows default to 30 minutes and async workflows have no default timeout. Omit acceptance for reviewer/read-only calls; evidence levels end at verified, and acceptance.review.required requests independent writer review.
54
+ • Durable mission attachment is automatic by default. Use missionId to attach an existing mission, mission:{...} to override auto-create, or mission:false for ephemeral work. A mission object needs exactly one non-empty title or summary; objective and labels are optional. goal may only be true and requires budget:{tokens}.
23
55
 
24
- CHAIN TEMPLATE VARIABLES (use in task strings):
25
- • {task} - The original task/request from the user
26
- • {previous} - Text response from the previous step (empty for first step)
27
- • {chain_dir} - Shared directory for chain files (e.g., <tmpdir>/dm-subagents-<scope>/chain-runs/abc123/)
28
-
29
- Example: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {agent:"agent-b", task:"Plan based on {previous}"}] }
30
-
31
- MANAGEMENT (use action field, omit agent/task/chain/tasks):
32
- • { action: "list" } - discover executable agents/chains
33
- • { action: "get", agent: "name" } - full detail; packaged agents use dotted runtime names like "package.agent"
34
- • { action: "models", agent?: "name" } - show the runtime-loaded builtin subagent model mapping, optionally filtered to one builtin
35
- • { action: "create", config: { name: "custom-agent", package: "code-analysis", systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext, ... } }
36
- • { action: "update", agent: "code-analysis.custom-agent", config: { package: "analysis", ... } } - merge
37
- • { action: "delete", agent: "code-analysis.custom-agent" }
38
- • { action: "eject", agent: "reviewer", agentScope?: "user" | "project" } - copy a bundled/package agent to user/project scope as an editable custom file that shadows the original (default scope: user)
39
- • { action: "disable", agent: "reviewer", agentScope?: "user" | "project" } - hide any agent from runtime discovery via a reversible settings override (default scope: user)
40
- • { action: "enable", agent: "reviewer", agentScope?: "user" | "project" } - remove a disabled override and restore discovery
41
- • { action: "reset", agent: "reviewer", agentScope?: "user" | "project" } - delete the scope's custom agent file and/or settings override, restoring the bundled default
42
- • Use chainName for chain operations; packaged chains also use dotted runtime names
43
-
44
- CONTROL:
45
- • { action: "status", id: "..." } - inspect an async/background run by id or prefix
46
- • { action: "status", view: "fleet" } - read-only active foreground/async fleet view with transcript commands
47
- • { action: "status", id: "...", view: "transcript", index?: 0, lines?: 80 } - tail a run or child output/session transcript
48
- • { action: "interrupt", id?: "..." } - soft-interrupt the current child turn and leave the run paused
49
- • { action: "resume", id: "...", message: "...", index?: 0 } - interrupt then follow up with a live async child, or revive a completed async/foreground child from its session
50
- • { action: "steer", id: "...", message: "...", index?: 0 } - queue non-terminal guidance for a live/queued async DM child when supported
51
- • { action: "append-step", id: "...", chain: [{agent:"agent-c", task:"Use {previous}"}] } - append one step to the tail of a running async chain
52
-
53
- SCHEDULE (opt-in; requires { "scheduledRuns": { "enabled": true } } in config.json):
54
- • { action: "schedule", agent, task?, schedule: "+10m" | "2030-01-01T09:00:00Z", scheduleName? } - defer a subagent launch until a future time. Also accepts tasks[] or chain[]. Scheduled runs always launch async with fresh context; they become normal tracked async runs once they fire. Only schedule explicit delayed runs the user asked for.
55
- • { action: "schedule-list" } - list scheduled runs for this session
56
- • { action: "schedule-status", id: "..." } - inspect one scheduled run
57
- • { action: "schedule-cancel", id: "..." } - cancel a scheduled run before it fires
58
-
59
- DIAGNOSTICS:
60
- • { action: "doctor" } - read-only report for runtime paths, discovery, sessions, and intercom
56
+ MANAGEMENT / CONTROL (use action; omit execution fields):
57
+ • validate checks workflowScript or workflowScriptPath syntax and statically decidable structure without launching children. list, get, models, guide, children.list, create, update, delete, eject, disable, enable, reset, status, debug.run, doctor, grant-spawn-budget, worktree.discard, worktree.cleanup (plan-only), lane.status, lane.recordMerge, lane.recordSupersession, refine/refine.show/refine.rollback, mission.create/list/show/update/resolve-decision/attach-run/close, inspector.open/status/close, project.open/status/close, and watchdog actions remain available. Use {action:"guide", topic:"overview"} for packaged current-version help; topics are overview, workflows, agents, missions, observability, tool-reference, configuration, models, watchdog, and extension-api.
58
+ • status, interrupt, stop, resume, and steer manage live or persisted runs. Use status view:"fleet" for an overview or view:"transcript" with id and optional index to tail output.
59
+ • Create durable project schedules with { action:"schedule.create", id?, name?, at:"+10m" | ISO, workflowScript:"return runs.run('main', {agent:'worker', task:'...'})" }, or use workflowScriptPath instead. Manage them with schedule.list/show/history/pause/resume/run/run-due/delete. This first slice supports fixed intervals; calendar schedules and schedule mission attachment are deferred.
61
60
 
62
61
  ${SUBAGENT_SAFETY_GUIDANCE}`;
63
- export const COMPACT_SUBAGENT_TOOL_DESCRIPTION = `Delegate to subagents or manage definitions. Use exactly one mode per call.
62
+ export const COMPACT_SUBAGENT_TOOL_DESCRIPTION = `Run one child with { agent, task? }; use { workflowScript } for inline orchestration or { workflowScriptPath } to load it from the request cwd. The script inputs are mutually exclusive. Omit action for execution. Use action only for management/control actions.
64
63
 
65
64
  EXECUTE:
66
- • Before execution, call { action: "list" }; run only executable/non-disabled configured agents/chains.
67
- • SINGLE {agent, task?}; PARALLEL {tasks:[{agent,task,count?,output?,reads?,progress?}], concurrency?, worktree?}; CHAIN {chain:[{agent,task?},{parallel:[...]}]}.
68
- • context can be "fresh" or "fork"; omitted uses each agent defaultContext, otherwise fresh. timeoutMs/maxRuntimeMs apply to foreground and async/background runs.
69
- • Chain templates may use {task}, {previous}, {chain_dir}, and named outputs. Parallel worktree isolation requires a clean git repo.
70
- • If list shows proactive skill subagent suggestions, use a small fresh-context fanout only when the task is broad enough.
65
+ • ${EXTERNAL_CLI_RUNNER_GUIDANCE}
66
+ • Call { action:"list" } first and use only executable/non-disabled agents.
67
+ • Passing an explicit model? Call {action:"models"} first and copy an exact provider/id; bare ids resolve only when unique in the registry; agent names (e.g. gpt-pro, advisor) are not model ids. Per-run thinking is a suffix on the model string (provider/id:high; off/minimal/low/medium/high/xhigh/max), and the suffix wins over the agent's thinking default; the thinking field only applies to action='watchdog.configure' and is ignored on dispatch.
68
+ • SINGLE {agent:"worker",task:"..."} starts exactly one direct child. Fields apply to that child. Do not combine agent/task with action, workflowScript, or workflowScriptPath.
69
+ • SCRIPT {workflowScript:"return runs.run('main', {agent:'worker', task:'...'})"}. Use stable-key runs.run for one child and await runs.all([{key,agent,task}, ...]) for ordinary parallel work. runs.all resolves to an ordered array, not a key map; use results[0], destructuring, or results.map(...), not results.<key>. Do not read .output from unawaited runs.run launches. Stored runs.run promises are only for advanced rolling fanout and each must later be observed with direct await, Promise.race, or Promise.all. Await runs.steer(key,message,options?) to guide a prior keyed child; it returns queued, delivered, missed, or failed and never accepts a raw run id. Always await or return steering calls. Use {action:"children.list"} for recent retained workflow children and resume only rows reported resumable. Use {action:"resume",id:"run-id",message:"..."} for a simple follow-up or challenge; resume keeps the stored agent/model/tool contract. If none is resumable, launch a same-role fallback challenge and label it as fallback. Inside workflowScript use runs.run(key,{resume:"run-id",task:"follow-up"}) when the script must wait for completion and continue from the latest returned runId. Workflows get async state.get/state.set through their automatic or explicit mission; mission:false does not. Scripts are ordinary JavaScript statement bodies; use explicit return for a useful result. Use top-level await, plain helper functions, or explicit Promise chains; nested async function, arrow, and method helpers are rejected. For task text with Markdown fences or shell blocks, build quoted lines instead of nesting raw template literals: \`const task=["Run:","\`\`\`bash","npm test","\`\`\`"].join("\\n")\`. Use JavaScript for sequence, branching, retries, and aggregation. For repository mutation lanes, use worktree:true on the workflow or runs.run/runs.all item for managed isolation. Scripts normally start async unless config sets asyncByDefault:false; set async:true explicitly when async behavior matters. async:false blocks the parent until completion and auto-enables a same-repo live chat card unless chatProgress is off; explicit live-card requires same-repository async:false, so async workflows should omit chatProgress or use auto/off.
70
+ • ${WORKFLOW_LANES_GUIDANCE}
71
+ • FILE SCRIPT {workflowScriptPath:"workflows/review.js"} loads the script on the host relative to the request cwd before sandbox execution. Do not combine it with workflowScript.
72
+ • Example: {workflowScript:"const [a,b]=await runs.all([{key:'a',agent:'agent-a',task:'Implement A',worktree:true},{key:'b',agent:'agent-b',task:'Implement B',worktree:true}]); return [a.output,b.output]"}
73
+ • context can be fresh, fork, or profile. profile requires the selected agent's declared defaultContext and ignores defaultSubagentContext. Explicit fresh/fork wins; omitted context follows defaultSubagentContext before agent defaultContext. Config forkContext can summarize transcript overflow with stable recovery refs before spawn without adding another public context value. timeoutMs/maxRuntimeMs apply to foreground and async workflows; foreground workflows default to 30 minutes and async workflows have no default timeout. Omit acceptance for reviewer/read-only calls.
71
74
 
72
75
  MANAGE / CONTROL:
73
- • Use action without execution fields: list, get, models, create, update, delete, eject, disable, enable, reset, doctor.
74
- • Async control actions: status, interrupt, resume, steer, append-step. Use status view:"fleet" for active-run overview, view:"transcript" to tail child output, and steer for non-terminal live guidance. Use id/runId prefixes carefully; use index for a specific child.
75
- • Opt-in schedule actions: schedule, schedule-list, schedule-status, schedule-cancel. Schedule only explicit delayed runs the user asked for.
76
+ • Use action without execution fields for list/get/models/guide/authoring, refine/refine.show/refine.rollback, mission, watchdog, status, interrupt, stop, resume, steer, worktree.cleanup (mode:'plan' only), script-only scheduling, diagnostics, and other management actions. guide reads shipped current-version docs by topic.
77
+ • A mission object needs exactly one non-empty title or summary; objective and labels are optional. goal may only be true and requires budget:{tokens}.
76
78
 
77
- ASYNC / WAIT:
78
- • async:true detaches background work. Do not sleep or poll just to wait; use the wait tool only when this turn must block. Otherwise continue useful work or respond and let completion notifications arrive.
79
- • Status and artifacts live under asyncId/asyncDir with status.json, events.jsonl, output logs, session files, and { action:"status", id:"..." }.
80
-
81
- SAFETY:
82
- • Ordinary child subagents are not orchestrators and must not run subagents. Only explicit fanout children may use child-safe subagent, still bounded by depth/session limits.
83
- • Keep one writer per cwd/worktree. Use fresh read-only review/validation fanout, then synthesize and apply fixes from the parent unless isolated worktrees were intentionally requested.`;
79
+ ASYNC / SAFETY:
80
+ • Omitted async follows asyncByDefault config; set async:true explicitly when async behavior matters. Continue independent work only until its next dependency barrier; consume the result before work that depends on it. Ordinary async subagents notify this session natively, so return control and do not call bg_wait merely to get a completion wake. Do not sleep or poll merely to wait; use bg_wait only for provider, detached, or other background work without a native notification when this turn must receive its result.
81
+ • ${WORKFLOW_RESUME_KEY_GUIDANCE}
82
+ • ${WORKFLOW_OUTPUT_BINDING_GUIDANCE}
83
+ • ${WORKFLOW_HOST_GUIDANCE}
84
+ • Ordinary children are not orchestrators. Keep one writer per cwd/worktree and use fresh read-only reviewers for independent checks.
85
+ • Oracle/advisor consultations use available supervisor dialogue for material unknowns; request one-shot when desired.
86
+ • Status and artifacts live under asyncId/asyncDir with status.json, events.jsonl, output logs, and {action:"status",id:"..."}.`;
84
87
  function isToolDescriptionMode(value) {
85
88
  return value === "full" || value === "compact" || value === "custom";
86
89
  }
87
90
  function warn(options, message) {
88
91
  (options?.warn ?? console.warn)(`[dm-subagents] ${message}`);
89
92
  }
93
+ export function buildSubagentToolPromptMetadata(config = {}) {
94
+ if (config.toolDescriptionMode !== undefined)
95
+ return {};
96
+ return {
97
+ promptSnippet: SUBAGENT_TOOL_PROMPT_SNIPPET,
98
+ promptGuidelines: SUBAGENT_TOOL_PROMPT_GUIDELINES
99
+ };
100
+ }
90
101
  export function resolveToolDescriptionMode(config, options) {
91
102
  const mode = config.toolDescriptionMode;
92
103
  if (mode === undefined)
@@ -172,14 +183,21 @@ function withMandatorySafetyGuidance(description) {
172
183
  ${SUBAGENT_SAFETY_GUIDANCE}` : SUBAGENT_SAFETY_GUIDANCE;
173
184
  }
174
185
  export function buildSubagentToolDescription(config = {}, options) {
186
+ if (config.toolDescriptionMode === undefined)
187
+ return DEFAULT_SUBAGENT_TOOL_DESCRIPTION;
175
188
  const mode = resolveToolDescriptionMode(config, options);
189
+ let description;
176
190
  if (mode === "compact")
177
- return COMPACT_SUBAGENT_TOOL_DESCRIPTION;
178
- if (mode === "custom") {
191
+ description = COMPACT_SUBAGENT_TOOL_DESCRIPTION;
192
+ else if (mode === "custom") {
179
193
  const custom = loadCustomToolDescription(options);
180
194
  if (custom)
181
- return withMandatorySafetyGuidance(custom);
182
- warn(options, `${CUSTOM_TOOL_DESCRIPTION_FILE} was not found or valid for toolDescriptionMode "custom"; using full description.`);
183
- }
184
- return FULL_SUBAGENT_TOOL_DESCRIPTION;
195
+ description = withMandatorySafetyGuidance(custom);
196
+ else {
197
+ warn(options, `${CUSTOM_TOOL_DESCRIPTION_FILE} was not found or valid for toolDescriptionMode "custom"; using full description.`);
198
+ description = FULL_SUBAGENT_TOOL_DESCRIPTION;
199
+ }
200
+ } else
201
+ description = FULL_SUBAGENT_TOOL_DESCRIPTION;
202
+ return description;
185
203
  }
@@ -0,0 +1,7 @@
1
+ export function finalizeToolResult(result) {
2
+ if (result.isError !== true)
3
+ return result;
4
+ const message = result.content.flatMap((item) => item.type === "text" && typeof item.text === "string" ? [item.text] : []).join(`
5
+ `).trim();
6
+ throw new Error(message || "dm-subagents reported a logical tool failure.");
7
+ }
@@ -0,0 +1,218 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { readMissionBinding } from "../../missions/lifecycle.js";
5
+ import { listMissions, missionRecordPath, resolveMissionStoreLocation } from "../../missions/store.js";
6
+ import { resolveAuthorityDecision } from "../../policy/authority.js";
7
+ import { writeAtomicJson } from "../../shared/atomic-json.js";
8
+ import { DIRS } from "../../shared/types.js";
9
+ import { readStatus } from "../../shared/utils.js";
10
+ import { resolveSubagentRunId } from "../../runs/background/run-id-resolver.js";
11
+ import { resolveNodeExecutable } from "../../shared/node-executable.js";
12
+ import { createHerdrClient, detectHerdr } from "./client.js";
13
+ import { encodeSessionRoots } from "./session-roots-codec.js";
14
+ import { formatShellCommand } from "./shell-command.js";
15
+ export const HERDR_INSPECTOR_ACTIONS = ["inspector.open", "inspector.status", "inspector.close"];
16
+ function result(text, isError = false) {
17
+ return { content: [{ type: "text", text }], ...isError ? { isError: true } : {}, details: { mode: "management", results: [] } };
18
+ }
19
+ function formatHerdrError(input) {
20
+ return `Herdr inspector error (${input.code}): ${input.message}`;
21
+ }
22
+ function bindingPath(asyncDir, index) {
23
+ return path.join(asyncDir, "inspectors", `herdr${index === undefined ? "" : `-${index}`}.json`);
24
+ }
25
+ function parseBinding(value) {
26
+ if (!value || typeof value !== "object" || Array.isArray(value))
27
+ return;
28
+ const input = value;
29
+ if (input.schemaVersion !== 1 || input.kind !== "herdr-inspector")
30
+ return;
31
+ if (typeof input.runId !== "string" || typeof input.asyncDir !== "string" || typeof input.paneId !== "string" || typeof input.openedAt !== "string" || typeof input.command !== "string")
32
+ return;
33
+ if (input.childIndex !== undefined && (!Number.isInteger(input.childIndex) || input.childIndex < 0))
34
+ return;
35
+ return input;
36
+ }
37
+ export function readHerdrInspectorBinding(asyncDir, index) {
38
+ try {
39
+ return parseBinding(JSON.parse(fs.readFileSync(bindingPath(asyncDir, index), "utf-8")));
40
+ } catch {
41
+ return;
42
+ }
43
+ }
44
+ function extractPaneId(value) {
45
+ if (!value || typeof value !== "object" || Array.isArray(value))
46
+ return;
47
+ const record = value;
48
+ const pane = record.pane && typeof record.pane === "object" && !Array.isArray(record.pane) ? record.pane : record;
49
+ for (const key of ["pane_id", "paneId", "id"])
50
+ if (typeof pane[key] === "string")
51
+ return pane[key];
52
+ return;
53
+ }
54
+ function inspectorCommand(input) {
55
+ const args = [input.runnerPath, "--async-dir", input.asyncDir, "--run-id", input.runId, "--allow-steer", String(input.allowSteer), "--allow-stop", String(input.allowStop), "--session-roots", encodeSessionRoots(input.sessionRoots)];
56
+ if (input.index !== undefined)
57
+ args.push("--index", String(input.index));
58
+ if (input.missionPath)
59
+ args.push("--mission-path", input.missionPath);
60
+ return formatShellCommand(resolveNodeExecutable(), args);
61
+ }
62
+ function missionForRun(asyncDir, cwd, config, runId) {
63
+ try {
64
+ const binding = readMissionBinding(asyncDir);
65
+ if (binding)
66
+ return { id: binding.missionId, path: missionRecordPath(binding.location, binding.missionId) };
67
+ const location = resolveMissionStoreLocation({ projectRoot: cwd, ...config ? { config } : {} });
68
+ const mission = listMissions(location).records.find((record) => record.runs.some((run) => run.runId === runId));
69
+ return mission ? { id: mission.id, path: missionRecordPath(location, mission.id) } : undefined;
70
+ } catch {
71
+ return;
72
+ }
73
+ }
74
+ function pathWithin(base, candidate) {
75
+ const resolvedBase = path.resolve(base);
76
+ const resolvedCandidate = path.resolve(candidate);
77
+ return resolvedCandidate === resolvedBase || resolvedCandidate.startsWith(`${resolvedBase}${path.sep}`);
78
+ }
79
+ function herdrSessionRoots(target, deps) {
80
+ const roots = deps.sessionRoots ?? deps.state?.trustedSessionRoots ?? [];
81
+ const job = deps.state?.asyncJobs.get(target.runId) ?? deps.state?.fleetJobs?.get(target.runId);
82
+ return [...new Set([...roots, ...job?.sessionRoot ? [job.sessionRoot] : []])];
83
+ }
84
+ function isTrustedAsyncDir(asyncDir, deps) {
85
+ try {
86
+ if (fs.lstatSync(asyncDir).isSymbolicLink() || !fs.statSync(asyncDir).isDirectory())
87
+ return false;
88
+ const realDir = fs.realpathSync(asyncDir);
89
+ const registered = [...deps.state?.asyncJobs.values() ?? []].some((job) => {
90
+ try {
91
+ return fs.realpathSync(job.asyncDir) === realDir;
92
+ } catch {
93
+ return false;
94
+ }
95
+ });
96
+ if (registered)
97
+ return true;
98
+ const root = deps.asyncDirRoot ?? DIRS.async;
99
+ if (!fs.existsSync(root) || !pathWithin(root, asyncDir))
100
+ return false;
101
+ return pathWithin(fs.realpathSync(root), realDir);
102
+ } catch {
103
+ return false;
104
+ }
105
+ }
106
+ function resolveAsyncTarget(params, deps) {
107
+ const requestedId = params.id ?? params.runId;
108
+ if (params.dir) {
109
+ const asyncDir = path.resolve(params.dir);
110
+ if (!isTrustedAsyncDir(asyncDir, deps))
111
+ return { error: `Async run directory '${asyncDir}' is outside trusted run roots.` };
112
+ const status = readStatus(asyncDir);
113
+ if (!status)
114
+ return { error: `No async run status found in '${asyncDir}'.` };
115
+ if (requestedId && requestedId !== status.runId && !status.runId.startsWith(requestedId))
116
+ return { error: `Run '${requestedId}' does not match status run '${status.runId}'.` };
117
+ return { runId: status.runId, asyncDir };
118
+ }
119
+ if (!requestedId)
120
+ return { error: "Herdr inspector actions require id or dir." };
121
+ try {
122
+ const resolved = resolveSubagentRunId(requestedId, { state: deps.state, asyncDirRoot: deps.asyncDirRoot ?? DIRS.async, resultsDir: deps.resultsDir ?? DIRS.results });
123
+ if (!resolved)
124
+ return { error: `No subagent run found for '${requestedId}'.` };
125
+ if (resolved.kind !== "async" || !resolved.location.asyncDir)
126
+ return { error: `Run '${resolved.id}' is not an inspectable async run with lifecycle artifacts.` };
127
+ return { runId: resolved.id, asyncDir: resolved.location.asyncDir };
128
+ } catch (cause) {
129
+ return { error: cause instanceof Error ? cause.message : String(cause) };
130
+ }
131
+ }
132
+ async function paneExists(client, paneId, signal) {
133
+ return client.run(["pane", "get", paneId], { timeoutMs: 5000, signal });
134
+ }
135
+ export async function handleHerdrInspectorAction(action, params, deps) {
136
+ const target = resolveAsyncTarget(params, deps);
137
+ if ("error" in target)
138
+ return result(target.error, true);
139
+ const status = readStatus(target.asyncDir);
140
+ if (!status)
141
+ return result(`No lifecycle status exists for async run '${target.runId}'.`, true);
142
+ if (params.index !== undefined && (params.index < 0 || params.index >= (status.steps?.length ?? 0))) {
143
+ return result(`Async run '${target.runId}' has ${status.steps?.length ?? 0} children. Index ${params.index} is out of range.`, true);
144
+ }
145
+ const existing = readHerdrInspectorBinding(target.asyncDir, params.index);
146
+ const client = deps.client ?? createHerdrClient();
147
+ if (action === "inspector.status") {
148
+ if (!existing)
149
+ return result(`No Herdr inspector binding exists for async run ${target.runId}${params.index === undefined ? "" : ` child ${params.index}`}.`);
150
+ const live = await paneExists(client, existing.paneId, deps.signal);
151
+ if (live.ok === false)
152
+ return result(`${formatHerdrError(live.error)}
153
+ Binding: ${bindingPath(target.asyncDir, params.index)}
154
+ Run state remains authoritative: ${status.state}.`, true);
155
+ return result(`Herdr inspector ${existing.paneId} is open for async run ${target.runId}.
156
+ Run state: ${status.state}
157
+ Binding: ${bindingPath(target.asyncDir, params.index)}`);
158
+ }
159
+ if (action === "inspector.close") {
160
+ if (!existing)
161
+ return result(`No Herdr inspector binding exists for async run ${target.runId}.`);
162
+ const closed = await client.run(["pane", "close", existing.paneId], { timeoutMs: 1e4, signal: deps.signal });
163
+ if (closed.ok === false && closed.error.code !== "NOT_FOUND" && closed.error.code !== "PANE_GONE")
164
+ return result(formatHerdrError(closed.error), true);
165
+ fs.rmSync(bindingPath(target.asyncDir, params.index), { force: true });
166
+ return result(`Closed Herdr inspector pane ${existing.paneId} for async run ${target.runId}. The subagent run was not stopped.`);
167
+ }
168
+ const detected = await detectHerdr(client, deps.signal);
169
+ if (detected.ok === false)
170
+ return result(formatHerdrError(detected.error), true);
171
+ if (existing) {
172
+ const live = await paneExists(client, existing.paneId, deps.signal);
173
+ if (live.ok)
174
+ return result(`Herdr inspector pane ${existing.paneId} is already open for async run ${target.runId}.${params.focus ? " Herdr cannot refocus an arbitrary raw pane id; select it in the Herdr UI." : ""}`);
175
+ }
176
+ const splitArgs = ["pane", "split", "--current", "--direction", "right", "--cwd", status.cwd ?? deps.cwd];
177
+ splitArgs.push(params.focus === true ? "--focus" : "--no-focus");
178
+ const split = await client.run(splitArgs, { timeoutMs: 15000, signal: deps.signal });
179
+ if (split.ok === false)
180
+ return result(formatHerdrError(split.error), true);
181
+ const paneId = extractPaneId(split.data);
182
+ if (!paneId)
183
+ return result("Herdr inspector error (PANE_GONE): pane split returned no pane id.", true);
184
+ const mission = missionForRun(target.asyncDir, deps.cwd, deps.missions, target.runId);
185
+ const runnerPath = deps.runnerPath ?? fileURLToPath(new URL("../../../inspector-runner.mjs", import.meta.url));
186
+ const command = inspectorCommand({
187
+ runnerPath,
188
+ asyncDir: target.asyncDir,
189
+ runId: target.runId,
190
+ index: params.index,
191
+ missionPath: mission?.path,
192
+ allowSteer: resolveAuthorityDecision({ action: "steerRun", policy: deps.authorityPolicy }) === "auto",
193
+ allowStop: resolveAuthorityDecision({ action: "stopRun", policy: deps.authorityPolicy }) === "auto",
194
+ sessionRoots: herdrSessionRoots(target, deps)
195
+ });
196
+ const started = await client.run(["pane", "run", paneId, command], { timeoutMs: 15000, signal: deps.signal });
197
+ if (started.ok === false) {
198
+ await client.run(["pane", "close", paneId], { timeoutMs: 5000 });
199
+ return result(formatHerdrError(started.error), true);
200
+ }
201
+ const now = (deps.now?.() ?? new Date).toISOString();
202
+ const binding = {
203
+ schemaVersion: 1,
204
+ kind: "herdr-inspector",
205
+ runId: target.runId,
206
+ asyncDir: target.asyncDir,
207
+ ...params.index !== undefined ? { childIndex: params.index } : {},
208
+ ...mission ? { missionId: mission.id, missionPath: mission.path } : {},
209
+ paneId,
210
+ openedAt: now,
211
+ ...params.focus === true ? { lastFocusedAt: now } : {},
212
+ herdrVersion: detected.data.versionText,
213
+ command
214
+ };
215
+ writeAtomicJson(bindingPath(target.asyncDir, params.index), binding);
216
+ return result(`Opened read-only Herdr inspector pane ${paneId} for async run ${target.runId}. Closing the pane does not stop the run.
217
+ Controls inside the pane: steer <message>, stop, status.`);
218
+ }
@@ -0,0 +1,123 @@
1
+ import { spawn } from "node:child_process";
2
+ function error(code, message, details) {
3
+ return { ok: false, error: { code, message, ...details !== undefined ? { details } : {} } };
4
+ }
5
+ function parseLastJson(value) {
6
+ const trimmed = value.trim();
7
+ if (!trimmed)
8
+ return;
9
+ try {
10
+ return JSON.parse(trimmed);
11
+ } catch {}
12
+ for (const line of trimmed.split(/\r?\n/).reverse()) {
13
+ try {
14
+ return JSON.parse(line);
15
+ } catch {}
16
+ }
17
+ return;
18
+ }
19
+ function normalizeCode(raw) {
20
+ const code = String(raw ?? "").toLowerCase();
21
+ if (code.includes("timeout") || code.includes("timed_out"))
22
+ return "TIMEOUT";
23
+ if (code.includes("gone"))
24
+ return "PANE_GONE";
25
+ if (code.includes("not_found") || code.includes("not-found") || code === "no_such_pane")
26
+ return "NOT_FOUND";
27
+ return "VALIDATION_ERROR";
28
+ }
29
+ export function createHerdrClient(options = {}) {
30
+ const bin = options.bin ?? process.env.HERDR_BIN ?? "herdr";
31
+ const spawnImpl = options.spawn ?? spawn;
32
+ return {
33
+ run(args, runOptions = {}) {
34
+ return new Promise((resolve) => {
35
+ let child;
36
+ try {
37
+ child = spawnImpl(bin, args, { shell: false, windowsHide: true, env: process.env });
38
+ } catch (cause) {
39
+ const code = cause?.code;
40
+ resolve(error("HERDR_UNAVAILABLE", code === "ENOENT" ? "Herdr is not installed or is not on PATH. Install Herdr 0.7.5+ or set HERDR_BIN." : `Failed to start Herdr: ${cause instanceof Error ? cause.message : String(cause)}`));
41
+ return;
42
+ }
43
+ let stdout = "";
44
+ let stderr = "";
45
+ let settled = false;
46
+ const finish = (result) => {
47
+ if (settled)
48
+ return;
49
+ settled = true;
50
+ clearTimeout(timer);
51
+ runOptions.signal?.removeEventListener("abort", abort);
52
+ resolve(result);
53
+ };
54
+ const abort = () => {
55
+ try {
56
+ child.kill();
57
+ } catch {}
58
+ finish(error("TIMEOUT", `Herdr command '${args.join(" ")}' was aborted.`));
59
+ };
60
+ const timer = setTimeout(() => {
61
+ try {
62
+ child.kill();
63
+ } catch {}
64
+ finish(error("TIMEOUT", `Herdr command '${args.join(" ")}' timed out after ${runOptions.timeoutMs ?? 15000}ms.`));
65
+ }, runOptions.timeoutMs ?? 15000);
66
+ timer.unref?.();
67
+ if (runOptions.signal?.aborted)
68
+ abort();
69
+ else
70
+ runOptions.signal?.addEventListener("abort", abort, { once: true });
71
+ child.stdout?.on("data", (chunk) => {
72
+ stdout += chunk.toString();
73
+ });
74
+ child.stderr?.on("data", (chunk) => {
75
+ stderr += chunk.toString();
76
+ });
77
+ child.on("error", (cause) => {
78
+ const code = cause.code;
79
+ finish(error("HERDR_UNAVAILABLE", code === "ENOENT" ? "Herdr is not installed or is not on PATH. Install Herdr 0.7.5+ or set HERDR_BIN." : `Failed to run Herdr: ${cause.message}`));
80
+ });
81
+ child.on("close", (exitCode) => {
82
+ const parsed = parseLastJson(stdout) ?? (exitCode === 0 ? undefined : parseLastJson(stderr));
83
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && "error" in parsed) {
84
+ const raw = parsed.error;
85
+ finish(error(normalizeCode(raw?.code), String(raw?.message ?? "Herdr command failed."), raw));
86
+ return;
87
+ }
88
+ if (exitCode === 0) {
89
+ if (parsed !== undefined) {
90
+ const envelope = parsed;
91
+ finish({ ok: true, data: envelope.result ?? parsed });
92
+ } else if (runOptions.textOk)
93
+ finish({ ok: true, data: stdout.trim() });
94
+ else
95
+ finish({ ok: true, data: {} });
96
+ return;
97
+ }
98
+ const message = stderr.split(/\r?\n/).find((line) => line.trim())?.trim() ?? `Herdr exited with code ${exitCode}.`;
99
+ finish(error("VALIDATION_ERROR", message, { exitCode }));
100
+ });
101
+ });
102
+ }
103
+ };
104
+ }
105
+ export function parseHerdrVersion(value) {
106
+ const match = /(\d+)\.(\d+)\.(\d+)/.exec(value);
107
+ return match ? { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) } : undefined;
108
+ }
109
+ export function supportsRawPanes(version) {
110
+ return version.major > 0 || version.minor > 7 || version.minor === 7 && version.patch >= 5;
111
+ }
112
+ export async function detectHerdr(client, signal) {
113
+ const result = await client.run(["--version"], { timeoutMs: 3000, signal, textOk: true });
114
+ if (result.ok === false)
115
+ return result;
116
+ const versionText = typeof result.data === "string" ? result.data : JSON.stringify(result.data);
117
+ const version = parseHerdrVersion(versionText);
118
+ if (!version)
119
+ return error("VALIDATION_ERROR", `Could not parse the Herdr version from '${versionText}'.`);
120
+ if (!supportsRawPanes(version))
121
+ return error("HERDR_UNSUPPORTED_VERSION", `Herdr ${versionText} does not support raw inspector panes. Upgrade to Herdr 0.7.5 or newer.`);
122
+ return { ok: true, data: { version, versionText } };
123
+ }