@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
@@ -0,0 +1,245 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import { writePrivateAtomicJson } from "../shared/atomic-json.js";
6
+ import { DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS, isRetryableFileSystemError, waitForFileSystemRetry } from "../shared/file-system-retry.js";
7
+ import { assertWorkflowJsonValue } from "../workflows/scripted-workflow.js";
8
+ import { validateMissionId } from "./store.js";
9
+ const STATE_KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
10
+ const STATE_LOCK_STALE_MS = 60000;
11
+ export const MISSION_STATE_MAX_BYTES = 256 * 1024;
12
+ export function missionStatePath(location, missionId) {
13
+ return path.join(location.missionDir, validateMissionId(missionId), "state.json");
14
+ }
15
+ function isProcessAlive(pid) {
16
+ try {
17
+ process.kill(pid, 0);
18
+ return true;
19
+ } catch (error) {
20
+ return error.code === "EPERM";
21
+ }
22
+ }
23
+ function linuxProcessStartKey(pid) {
24
+ try {
25
+ const raw = fs.readFileSync(`/proc/${pid}/stat`, "utf-8");
26
+ const tail = raw.slice(raw.lastIndexOf(")") + 2).trim().split(/\s+/);
27
+ return tail[19] ? `linux:${tail[19]}` : undefined;
28
+ } catch {
29
+ return;
30
+ }
31
+ }
32
+ function psProcessStartKey(pid) {
33
+ try {
34
+ const raw = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"], timeout: 1000 }).trim();
35
+ return raw ? `ps:${raw}` : undefined;
36
+ } catch {
37
+ return;
38
+ }
39
+ }
40
+ function windowsProcessStartKey(pid) {
41
+ try {
42
+ const raw = execFileSync("powershell.exe", ["-NoProfile", "-Command", `(Get-CimInstance Win32_Process -Filter "ProcessId=${pid}").CreationDate`], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"], timeout: 1000, windowsHide: true }).trim();
43
+ return raw ? `win:${raw}` : undefined;
44
+ } catch {
45
+ return;
46
+ }
47
+ }
48
+ function processStartKey(pid) {
49
+ if (process.platform === "linux")
50
+ return linuxProcessStartKey(pid) ?? psProcessStartKey(pid);
51
+ if (process.platform === "win32")
52
+ return windowsProcessStartKey(pid);
53
+ return;
54
+ }
55
+ const CURRENT_PROCESS_KEY = processStartKey(process.pid);
56
+ function readStateLockOwner(lockPath) {
57
+ try {
58
+ const owner = JSON.parse(fs.readFileSync(path.join(lockPath, "owner.json"), "utf-8"));
59
+ if (Number.isSafeInteger(owner.pid) && owner.pid > 0 && typeof owner.token === "string" && owner.token && Number.isSafeInteger(owner.createdAt)) {
60
+ return {
61
+ pid: owner.pid,
62
+ token: owner.token,
63
+ createdAt: owner.createdAt,
64
+ ...typeof owner.processKey === "string" && owner.processKey ? { processKey: owner.processKey } : {}
65
+ };
66
+ }
67
+ } catch {
68
+ return;
69
+ }
70
+ return;
71
+ }
72
+ function stateLockIsStale(lockPath, now = Date.now()) {
73
+ const owner = readStateLockOwner(lockPath);
74
+ if (owner) {
75
+ if (!isProcessAlive(owner.pid))
76
+ return true;
77
+ if (owner.processKey) {
78
+ const currentProcessKey = owner.pid === process.pid ? CURRENT_PROCESS_KEY : processStartKey(owner.pid);
79
+ if (currentProcessKey)
80
+ return owner.processKey !== currentProcessKey;
81
+ if (owner.pid === process.pid)
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+ try {
87
+ return now - fs.statSync(lockPath).mtimeMs > STATE_LOCK_STALE_MS;
88
+ } catch (error) {
89
+ if (error.code === "ENOENT")
90
+ return false;
91
+ throw error;
92
+ }
93
+ }
94
+ function removeOwnedStateLock(lockPath, owner) {
95
+ const current = readStateLockOwner(lockPath);
96
+ if (current?.token !== owner.token)
97
+ return;
98
+ fs.rmSync(lockPath, { recursive: true, force: true });
99
+ }
100
+ function staleDirectoryExists(dirPath, now = Date.now()) {
101
+ try {
102
+ return now - fs.statSync(dirPath).mtimeMs > STATE_LOCK_STALE_MS;
103
+ } catch (error) {
104
+ if (error.code === "ENOENT")
105
+ return false;
106
+ throw error;
107
+ }
108
+ }
109
+ function tryMakeDirectory(dirPath, mode) {
110
+ try {
111
+ fs.mkdirSync(dirPath, { mode });
112
+ return true;
113
+ } catch (error) {
114
+ if (error.code === "EEXIST")
115
+ return false;
116
+ throw error;
117
+ }
118
+ }
119
+ function waitForStateLock(delayMs, lockPath) {
120
+ if (delayMs === undefined)
121
+ throw new Error(`Timed out acquiring mission state lock '${lockPath}'.`);
122
+ waitForFileSystemRetry(delayMs);
123
+ }
124
+ function reclaimStaleStateLock(lockPath, reclaimPath) {
125
+ if (!stateLockIsStale(lockPath))
126
+ return false;
127
+ if (!tryMakeDirectory(reclaimPath, 448))
128
+ return false;
129
+ try {
130
+ if (!stateLockIsStale(lockPath))
131
+ return false;
132
+ fs.rmSync(lockPath, { recursive: true, force: true });
133
+ return true;
134
+ } finally {
135
+ fs.rmSync(reclaimPath, { recursive: true, force: true });
136
+ }
137
+ }
138
+ function withStateFileLock(filePath, operation) {
139
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
140
+ const lockPath = `${filePath}.lock`;
141
+ const reclaimPath = `${lockPath}.reclaim`;
142
+ let owner;
143
+ for (let attempt = 0;; attempt++) {
144
+ if (fs.existsSync(reclaimPath)) {
145
+ if (staleDirectoryExists(reclaimPath)) {
146
+ fs.rmSync(reclaimPath, { recursive: true, force: true });
147
+ continue;
148
+ }
149
+ waitForStateLock(DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS[attempt], lockPath);
150
+ continue;
151
+ }
152
+ let acquired = false;
153
+ try {
154
+ acquired = tryMakeDirectory(lockPath, 448);
155
+ } catch (error) {
156
+ if (isRetryableFileSystemError(error)) {
157
+ waitForStateLock(DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS[attempt], lockPath);
158
+ continue;
159
+ }
160
+ throw new Error(`Failed to acquire mission state lock '${lockPath}': ${error instanceof Error ? error.message : String(error)}`);
161
+ }
162
+ if (!acquired) {
163
+ if (reclaimStaleStateLock(lockPath, reclaimPath))
164
+ continue;
165
+ waitForStateLock(DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS[attempt], lockPath);
166
+ continue;
167
+ }
168
+ owner = { pid: process.pid, token: randomUUID(), createdAt: Date.now(), ...CURRENT_PROCESS_KEY ? { processKey: CURRENT_PROCESS_KEY } : {} };
169
+ try {
170
+ fs.writeFileSync(path.join(lockPath, "owner.json"), JSON.stringify(owner), { encoding: "utf-8", mode: 384 });
171
+ } catch (error) {
172
+ fs.rmSync(lockPath, { recursive: true, force: true });
173
+ owner = undefined;
174
+ throw error;
175
+ }
176
+ break;
177
+ }
178
+ try {
179
+ return operation();
180
+ } finally {
181
+ if (owner)
182
+ removeOwnedStateLock(lockPath, owner);
183
+ }
184
+ }
185
+ function validateStateKey(value) {
186
+ if (typeof value !== "string" || !STATE_KEY_PATTERN.test(value)) {
187
+ throw new Error("state key must be 1-128 characters using letters, numbers, '.', '_' or '-', and start with a letter or number.");
188
+ }
189
+ return value;
190
+ }
191
+ export function createMissionWorkflowState(location, missionId) {
192
+ const filePath = missionStatePath(location, missionId);
193
+ let loaded = false;
194
+ let values = Object.create(null);
195
+ const readStateFile = () => {
196
+ let raw;
197
+ try {
198
+ raw = fs.readFileSync(filePath, "utf-8");
199
+ } catch (error) {
200
+ if (error.code === "ENOENT")
201
+ return Object.create(null);
202
+ throw new Error(`Failed to read mission state '${filePath}': ${error instanceof Error ? error.message : String(error)}`);
203
+ }
204
+ const bytes = Buffer.byteLength(raw);
205
+ if (bytes > MISSION_STATE_MAX_BYTES)
206
+ throw new Error(`Mission state file '${filePath}' exceeds the 256 KiB limit (${bytes} bytes).`);
207
+ try {
208
+ const parsed = JSON.parse(raw);
209
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
210
+ throw new Error("root must be a JSON object");
211
+ assertWorkflowJsonValue(parsed, "mission state");
212
+ return Object.assign(Object.create(null), parsed);
213
+ } catch (error) {
214
+ throw new Error(`Invalid mission state file '${filePath}': ${error instanceof Error ? error.message : String(error)}`);
215
+ }
216
+ };
217
+ const load = () => {
218
+ if (loaded)
219
+ return values;
220
+ values = readStateFile();
221
+ loaded = true;
222
+ return values;
223
+ };
224
+ return {
225
+ path: filePath,
226
+ get(key) {
227
+ const validKey = validateStateKey(key);
228
+ const current = load();
229
+ return Object.hasOwn(current, validKey) ? current[validKey] : undefined;
230
+ },
231
+ set(key, value) {
232
+ const validKey = validateStateKey(key);
233
+ assertWorkflowJsonValue(value, `state.set('${validKey}') value`);
234
+ withStateFileLock(filePath, () => {
235
+ const next = Object.assign(Object.create(null), readStateFile(), { [validKey]: value });
236
+ const bytes = Buffer.byteLength(JSON.stringify(next, null, 2));
237
+ if (bytes > MISSION_STATE_MAX_BYTES)
238
+ throw new Error(`Mission state exceeds the 256 KiB limit (${bytes} bytes; maximum ${MISSION_STATE_MAX_BYTES} bytes).`);
239
+ writePrivateAtomicJson(filePath, next);
240
+ values = next;
241
+ loaded = true;
242
+ });
243
+ }
244
+ };
245
+ }
@@ -0,0 +1,37 @@
1
+ export const AUTHORITY_ACTIONS = [
2
+ "discardWorktree",
3
+ "destructiveCleanup",
4
+ "spawnBudgetGrant",
5
+ "scheduleCreate",
6
+ "stopRun",
7
+ "steerRun"
8
+ ];
9
+ const DEFAULT_AUTHORITY_POLICY = {
10
+ discardWorktree: "confirm",
11
+ destructiveCleanup: "confirm",
12
+ spawnBudgetGrant: "confirm",
13
+ scheduleCreate: "auto",
14
+ stopRun: "auto",
15
+ steerRun: "auto"
16
+ };
17
+ export function resolveAuthorityDecision(input) {
18
+ return input.policy?.[input.action] ?? DEFAULT_AUTHORITY_POLICY[input.action];
19
+ }
20
+ export function validateAuthorityPolicy(value, label = "config.authorityPolicy") {
21
+ if (value === undefined)
22
+ return;
23
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
24
+ throw new Error(`${label} must be a JSON object`);
25
+ }
26
+ const policy = value;
27
+ const allowedActions = new Set(AUTHORITY_ACTIONS);
28
+ for (const [action, decision] of Object.entries(policy)) {
29
+ if (!allowedActions.has(action)) {
30
+ throw new Error(`${label}.${action} is unknown; expected one of ${AUTHORITY_ACTIONS.join(", ")}`);
31
+ }
32
+ if (decision !== "auto" && decision !== "confirm" && decision !== "forbid") {
33
+ throw new Error(`${label}.${action} must be "auto", "confirm", or "forbid"`);
34
+ }
35
+ }
36
+ return policy;
37
+ }
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
+ import { getPiSpawnCommand } from "../runs/shared/dm-spawn.js";
4
5
  import { findModelInfo, getSupportedThinkingLevels, splitKnownThinkingSuffix, toModelInfo } from "../shared/model-info.js";
5
6
  import { getAgentDir } from "../shared/utils.js";
6
7
  export const DEFAULT_PROVIDER_MODELS_MAX_AGE_DAYS = 7;
@@ -48,10 +49,23 @@ function validateSubagentProfile(filePath, parsed) {
48
49
  if (!value || typeof value !== "object" || Array.isArray(value)) {
49
50
  throw new Error(`Profile '${filePath}' has invalid override '${name}'; expected an object.`);
50
51
  }
51
- const model = value.model;
52
+ const override = value;
53
+ const model = override.model;
52
54
  if (model !== undefined && typeof model !== "string") {
53
55
  throw new Error(`Profile '${filePath}' has invalid model for '${name}'; expected a string.`);
54
56
  }
57
+ const thinking = override.thinking;
58
+ if (thinking !== undefined && thinking !== false && typeof thinking !== "string") {
59
+ throw new Error(`Profile '${filePath}' has invalid thinking for '${name}'; expected a string or false.`);
60
+ }
61
+ const fallbackModels = override.fallbackModels;
62
+ if (fallbackModels !== undefined && fallbackModels !== false && (!Array.isArray(fallbackModels) || fallbackModels.some((item) => typeof item !== "string"))) {
63
+ throw new Error(`Profile '${filePath}' has invalid fallbackModels for '${name}'; expected an array of strings or false.`);
64
+ }
65
+ }
66
+ const disableBuiltins = subagents.disableBuiltins;
67
+ if (disableBuiltins !== undefined && typeof disableBuiltins !== "boolean") {
68
+ throw new Error(`Profile '${filePath}' has invalid subagents.disableBuiltins; expected a boolean.`);
55
69
  }
56
70
  return parsed;
57
71
  }
@@ -137,7 +151,7 @@ function agentsForRoleTier(roleTier) {
137
151
  if (roleTier === "cheap")
138
152
  return ["scout", "delegate"];
139
153
  if (roleTier === "medium")
140
- return ["planner", "context-builder", "researcher"];
154
+ return ["researcher", "reviewer"];
141
155
  return ["worker", "reviewer", "oracle"];
142
156
  }
143
157
  function classifyModel(input, context) {
@@ -192,11 +206,12 @@ function resolveProbeStatus(text, timedOut) {
192
206
  return "unavailable";
193
207
  return "error";
194
208
  }
195
- async function probeModel(pi, ctx, fullId) {
196
- if (typeof pi.exec !== "function") {
197
- return { status: "skipped", message: "DM exec is unavailable in this runtime." };
209
+ async function probeModel(dm, fullId) {
210
+ if (typeof dm.exec !== "function") {
211
+ return { status: "skipped", message: "dm.exec is unavailable in this runtime." };
198
212
  }
199
- const result = await pi.exec("dm", ["-p", "--model", fullId, "--no-tools", 'Reply with exactly "OK".'], {
213
+ const spawnSpec = getPiSpawnCommand(["-p", "--model", fullId, "--no-tools", 'Reply with exactly "OK".']);
214
+ const result = await dm.exec(spawnSpec.command, spawnSpec.args, {
200
215
  cwd: os.tmpdir(),
201
216
  timeout: 45000
202
217
  });
@@ -250,14 +265,12 @@ function dominatesModel(a, b) {
250
265
  function filterDominatedModels(models) {
251
266
  return models.filter((candidate, index) => !models.some((other, otherIndex) => otherIndex !== index && dominatesModel(other, candidate)));
252
267
  }
253
- function buildProfileFile(kind, models) {
268
+ function buildProfileFile(models) {
254
269
  return {
255
270
  subagents: {
256
271
  agentOverrides: {
257
272
  scout: { model: models.cheap },
258
273
  delegate: { model: models.cheap },
259
- planner: { model: models.medium },
260
- "context-builder": { model: models.medium },
261
274
  researcher: { model: models.medium },
262
275
  worker: { model: models.strong },
263
276
  reviewer: { model: models.strong },
@@ -319,7 +332,12 @@ export function applySubagentProfile(name) {
319
332
  const { filePath, profile } = readSubagentProfile(name);
320
333
  const settingsPath = getUserSettingsPath();
321
334
  const settings = readSettingsFile(settingsPath);
322
- settings.subagents = profile.subagents;
335
+ const existing = settings.subagents && typeof settings.subagents === "object" && !Array.isArray(settings.subagents) ? settings.subagents : {};
336
+ settings.subagents = {
337
+ ...existing,
338
+ ...profile.subagents,
339
+ agentOverrides: profile.subagents.agentOverrides
340
+ };
323
341
  writeJsonFile(settingsPath, settings);
324
342
  return { filePath, settingsPath };
325
343
  }
@@ -336,7 +354,7 @@ export function isProviderModelCatalogStale(catalog, maxAgeDays = DEFAULT_PROVID
336
354
  const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
337
355
  return Date.now() - refreshedAt > maxAgeMs;
338
356
  }
339
- export async function refreshProviderModelCatalog(pi, ctx, provider, options = {}) {
357
+ export async function refreshProviderModelCatalog(dm, ctx, provider, options = {}) {
340
358
  const normalizedProvider = normalizeProviderName(provider);
341
359
  const maxAgeDays = options.maxAgeDays ?? DEFAULT_PROVIDER_MODELS_MAX_AGE_DAYS;
342
360
  const filePath = getProviderModelsPath(normalizedProvider);
@@ -354,7 +372,7 @@ export async function refreshProviderModelCatalog(pi, ctx, provider, options = {
354
372
  for (const rawModel of availableModels) {
355
373
  const modelRecord = rawModel;
356
374
  const fullId = `${modelRecord.provider}/${modelRecord.id}`;
357
- const probe = options.probe === false ? { status: "skipped", message: "Live probing disabled." } : await probeModel(pi, ctx, fullId);
375
+ const probe = options.probe === false ? { status: "skipped", message: "Live probing disabled." } : await probeModel(dm, fullId);
358
376
  observedModels.push({ rawModel, modelRecord, fullId, probe });
359
377
  }
360
378
  const classificationContext = buildClassificationContext(observedModels.map(({ modelRecord }) => ({
@@ -409,9 +427,9 @@ export async function refreshProviderModelCatalog(pi, ctx, provider, options = {
409
427
  writeJsonFile(filePath, catalog);
410
428
  return { filePath, catalog, reused: false, heuristicFallbackCount: countHeuristicFallbackModels(catalog) };
411
429
  }
412
- export async function generateProfilesForProvider(pi, ctx, provider, options = {}) {
430
+ export async function generateProfilesForProvider(dm, ctx, provider, options = {}) {
413
431
  const normalizedProvider = normalizeProviderName(provider);
414
- const { filePath: catalogPath, catalog, heuristicFallbackCount } = await refreshProviderModelCatalog(pi, ctx, normalizedProvider, {
432
+ const { filePath: catalogPath, catalog, heuristicFallbackCount } = await refreshProviderModelCatalog(dm, ctx, normalizedProvider, {
415
433
  maxAgeDays: options.maxAgeDays,
416
434
  force: options.forceRefresh,
417
435
  probe: options.probe
@@ -426,13 +444,13 @@ export async function generateProfilesForProvider(pi, ctx, provider, options = {
426
444
  const dir = ensureSubagentProfilesDir();
427
445
  const quotaPath = path.join(dir, `${normalizedProvider}.quota.json`);
428
446
  const qualityPath = path.join(dir, `${normalizedProvider}.quality.json`);
429
- writeJsonFile(quotaPath, buildProfileFile("quota", quotaModels));
430
- writeJsonFile(qualityPath, buildProfileFile("quality", qualityModels));
447
+ writeJsonFile(quotaPath, buildProfileFile(quotaModels));
448
+ writeJsonFile(qualityPath, buildProfileFile(qualityModels));
431
449
  const selectedModels = new Set([...Object.values(quotaModels), ...Object.values(qualityModels)]);
432
450
  const selectedHeuristicFallbackCount = profileModels.filter((model) => selectedModels.has(model.fullId) && modelUsesHeuristicClassification(model)).length;
433
451
  return { quotaPath, qualityPath, catalogPath, quotaModels, qualityModels, heuristicFallbackCount, selectedHeuristicFallbackCount };
434
452
  }
435
- export async function checkSubagentProfile(pi, ctx, name) {
453
+ export async function checkSubagentProfile(dm, ctx, name) {
436
454
  const { filePath, profile } = readSubagentProfile(name);
437
455
  const availableModels = ctx.modelRegistry.getAvailable().map(toModelInfo);
438
456
  const entries = Object.entries(profile.subagents.agentOverrides).filter(([, value]) => typeof value?.model === "string" && value.model.trim()).map(([agent, value]) => ({ agent, model: value.model.trim() }));
@@ -444,7 +462,7 @@ export async function checkSubagentProfile(pi, ctx, name) {
444
462
  const probeModelId = modelInfo ? `${modelInfo.fullId}${thinkingSuffix}` : entry.model;
445
463
  let probe = probeCache.get(probeModelId);
446
464
  if (!probe) {
447
- probe = await probeModel(pi, ctx, probeModelId);
465
+ probe = await probeModel(dm, probeModelId);
448
466
  probeCache.set(probeModelId, probe);
449
467
  }
450
468
  results.push({