@duckmind/dm-linux-x64 0.65.5 → 0.65.6

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 (1208) hide show
  1. package/README.md +0 -8
  2. package/dm +2 -2
  3. package/extensions/.dm-extensions.json +677 -44
  4. package/extensions/dm-lens/clients/actionable-warnings-logger.js +0 -6
  5. package/extensions/dm-lens/clients/actionable-warnings.js +42 -13
  6. package/extensions/dm-lens/clients/advisory-provenance.js +129 -41
  7. package/extensions/dm-lens/clients/agent-behavior-client.js +1 -0
  8. package/extensions/dm-lens/clients/analysed-root.js +0 -0
  9. package/extensions/dm-lens/clients/ast-grep-client.js +38 -3
  10. package/extensions/dm-lens/clients/ast-grep-rule-manager.js +37 -5
  11. package/extensions/dm-lens/clients/ast-grep-tool-logger.js +1 -7
  12. package/extensions/dm-lens/clients/bash-file-access.js +138 -1
  13. package/extensions/dm-lens/clients/biome-client.js +9 -2
  14. package/extensions/dm-lens/clients/blocker-freshness.js +171 -21
  15. package/extensions/dm-lens/clients/bootstrap.js +9 -5
  16. package/extensions/dm-lens/clients/bounded-pid-file-lock.js +1 -1
  17. package/extensions/dm-lens/clients/bounded-telemetry.js +1 -4
  18. package/extensions/dm-lens/clients/bundled-resource-health.js +43 -0
  19. package/extensions/dm-lens/clients/bus-events-logger.js +0 -6
  20. package/extensions/dm-lens/clients/cache/rule-cache.js +11 -3
  21. package/extensions/dm-lens/clients/cache-manager.js +29 -5
  22. package/extensions/dm-lens/clients/cache-observability.js +104 -4
  23. package/extensions/dm-lens/clients/cargo-manifest.js +6 -3
  24. package/extensions/dm-lens/clients/cascade-format.js +87 -5
  25. package/extensions/dm-lens/clients/cascade-logger.js +0 -6
  26. package/extensions/dm-lens/clients/child-unref.js +5 -9
  27. package/extensions/dm-lens/clients/code-quality-warnings.js +4 -2
  28. package/extensions/dm-lens/clients/complexity-client.js +5 -1
  29. package/extensions/dm-lens/clients/config-core/index.js +2 -68
  30. package/extensions/dm-lens/clients/config-core/process-spec.js +1 -1
  31. package/extensions/dm-lens/clients/config-core/provenance.js +1 -2
  32. package/extensions/dm-lens/clients/config-core/records.js +1 -1
  33. package/extensions/dm-lens/clients/config-core/schema.js +3 -6
  34. package/extensions/dm-lens/clients/config-diagnostic-codes.js +5 -3
  35. package/extensions/dm-lens/clients/config-locations.js +125 -5
  36. package/extensions/dm-lens/clients/config-resolve.js +12 -6
  37. package/extensions/dm-lens/clients/config-schema.js +56 -3
  38. package/extensions/dm-lens/clients/config-warn.js +3 -2
  39. package/extensions/dm-lens/clients/dead-code-client.js +4 -1
  40. package/extensions/dm-lens/clients/dead-code-logger.js +0 -3
  41. package/extensions/dm-lens/clients/degradation-ledger.js +29 -4
  42. package/extensions/dm-lens/clients/dependency-checker.js +29 -50
  43. package/extensions/dm-lens/clients/diagnostic-dispositions.js +23 -4
  44. package/extensions/dm-lens/clients/diagnostic-logger.js +1 -1
  45. package/extensions/dm-lens/clients/dispatch/ast-grep-catalog.js +19 -0
  46. package/extensions/dm-lens/clients/dispatch/auxiliary-lsp.js +9 -0
  47. package/extensions/dm-lens/clients/dispatch/collect-later-tier.js +0 -3
  48. package/extensions/dm-lens/clients/dispatch/dispatcher.js +30 -27
  49. package/extensions/dm-lens/clients/dispatch/facts/function-facts.js +1 -1
  50. package/extensions/dm-lens/clients/dispatch/facts/import-facts.js +4 -1
  51. package/extensions/dm-lens/clients/dispatch/finding-policy.js +163 -0
  52. package/extensions/dm-lens/clients/dispatch/indent-detect.js +213 -13
  53. package/extensions/dm-lens/clients/dispatch/inline-suppressions.js +20 -1
  54. package/extensions/dm-lens/clients/dispatch/integration.js +77 -13
  55. package/extensions/dm-lens/clients/dispatch/lazy.js +0 -3
  56. package/extensions/dm-lens/clients/dispatch/pending-runner-findings.js +1 -1
  57. package/extensions/dm-lens/clients/dispatch/plan.js +0 -3
  58. package/extensions/dm-lens/clients/dispatch/rule-ignores.js +21 -0
  59. package/extensions/dm-lens/clients/dispatch/rules/high-complexity.js +2 -2
  60. package/extensions/dm-lens/clients/dispatch/rules/high-fan-out.js +1 -1
  61. package/extensions/dm-lens/clients/dispatch/runners/actionlint.js +25 -29
  62. package/extensions/dm-lens/clients/dispatch/runners/ast-grep-napi.js +8 -32
  63. package/extensions/dm-lens/clients/dispatch/runners/biome-check.js +39 -23
  64. package/extensions/dm-lens/clients/dispatch/runners/cpp-check.js +29 -48
  65. package/extensions/dm-lens/clients/dispatch/runners/credo.js +17 -14
  66. package/extensions/dm-lens/clients/dispatch/runners/cue-vet.js +9 -7
  67. package/extensions/dm-lens/clients/dispatch/runners/dart-analyze.js +21 -43
  68. package/extensions/dm-lens/clients/dispatch/runners/detekt.js +11 -5
  69. package/extensions/dm-lens/clients/dispatch/runners/dotnet-build.js +27 -23
  70. package/extensions/dm-lens/clients/dispatch/runners/elixir-check.js +23 -38
  71. package/extensions/dm-lens/clients/dispatch/runners/eslint.js +22 -35
  72. package/extensions/dm-lens/clients/dispatch/runners/fish-indent.js +2 -1
  73. package/extensions/dm-lens/clients/dispatch/runners/gleam-check.js +35 -12
  74. package/extensions/dm-lens/clients/dispatch/runners/go-vet.js +5 -3
  75. package/extensions/dm-lens/clients/dispatch/runners/golangci-lint.js +21 -22
  76. package/extensions/dm-lens/clients/dispatch/runners/hadolint.js +26 -16
  77. package/extensions/dm-lens/clients/dispatch/runners/helm-lint.js +3 -1
  78. package/extensions/dm-lens/clients/dispatch/runners/helm-render.js +3 -2
  79. package/extensions/dm-lens/clients/dispatch/runners/htmlhint.js +18 -9
  80. package/extensions/dm-lens/clients/dispatch/runners/javac.js +24 -23
  81. package/extensions/dm-lens/clients/dispatch/runners/ktlint.js +23 -54
  82. package/extensions/dm-lens/clients/dispatch/runners/lsp.js +17 -7
  83. package/extensions/dm-lens/clients/dispatch/runners/markdownlint.js +12 -6
  84. package/extensions/dm-lens/clients/dispatch/runners/mypy.js +2 -1
  85. package/extensions/dm-lens/clients/dispatch/runners/oxlint.js +24 -7
  86. package/extensions/dm-lens/clients/dispatch/runners/php-lint.js +26 -17
  87. package/extensions/dm-lens/clients/dispatch/runners/phpstan.js +2 -1
  88. package/extensions/dm-lens/clients/dispatch/runners/prisma-validate.js +2 -1
  89. package/extensions/dm-lens/clients/dispatch/runners/psscriptanalyzer.js +10 -11
  90. package/extensions/dm-lens/clients/dispatch/runners/pyright.js +2 -1
  91. package/extensions/dm-lens/clients/dispatch/runners/rubocop.js +22 -18
  92. package/extensions/dm-lens/clients/dispatch/runners/ruff.js +17 -22
  93. package/extensions/dm-lens/clients/dispatch/runners/rust-clippy.js +8 -11
  94. package/extensions/dm-lens/clients/dispatch/runners/shellcheck.js +9 -4
  95. package/extensions/dm-lens/clients/dispatch/runners/shfmt.js +4 -13
  96. package/extensions/dm-lens/clients/dispatch/runners/spellcheck.js +15 -5
  97. package/extensions/dm-lens/clients/dispatch/runners/spotbugs.js +2 -1
  98. package/extensions/dm-lens/clients/dispatch/runners/sqlfluff.js +10 -4
  99. package/extensions/dm-lens/clients/dispatch/runners/stylelint.js +9 -4
  100. package/extensions/dm-lens/clients/dispatch/runners/swiftlint.js +11 -3
  101. package/extensions/dm-lens/clients/dispatch/runners/taplo.js +13 -7
  102. package/extensions/dm-lens/clients/dispatch/runners/terragrunt.js +2 -1
  103. package/extensions/dm-lens/clients/dispatch/runners/tflint.js +26 -16
  104. package/extensions/dm-lens/clients/dispatch/runners/tree-sitter.js +12 -13
  105. package/extensions/dm-lens/clients/dispatch/runners/trivy-config.js +9 -3
  106. package/extensions/dm-lens/clients/dispatch/runners/utils/availability-policy.js +5 -0
  107. package/extensions/dm-lens/clients/dispatch/runners/utils/candidate-probe.js +2 -2
  108. package/extensions/dm-lens/clients/dispatch/runners/utils/diagnostic-parsers.js +8 -52
  109. package/extensions/dm-lens/clients/dispatch/runners/utils/runner-helpers.js +35 -3
  110. package/extensions/dm-lens/clients/dispatch/runners/utils.js +0 -17
  111. package/extensions/dm-lens/clients/dispatch/runners/vale.js +12 -4
  112. package/extensions/dm-lens/clients/dispatch/runners/yaml-rule-parser.js +2 -20
  113. package/extensions/dm-lens/clients/dispatch/runners/yamllint.js +16 -4
  114. package/extensions/dm-lens/clients/dispatch/runners/zig-check.js +26 -38
  115. package/extensions/dm-lens/clients/dispatch/suppress-writer.js +13 -3
  116. package/extensions/dm-lens/clients/dispatch/types.js +4 -1
  117. package/extensions/dm-lens/clients/dispatch/utils/format-utils.js +2 -2
  118. package/extensions/dm-lens/clients/disposition-logger.js +0 -6
  119. package/extensions/dm-lens/clients/disposition-publish.js +2 -1
  120. package/extensions/dm-lens/clients/effective-config.js +14 -4
  121. package/extensions/dm-lens/clients/event-loop-hold.js +123 -0
  122. package/extensions/dm-lens/clients/event-loop-monitor.js +2 -2
  123. package/extensions/dm-lens/clients/extension-log.js +6 -1
  124. package/extensions/dm-lens/clients/feature-hints.js +2 -1
  125. package/extensions/dm-lens/clients/file-kinds.js +17 -21
  126. package/extensions/dm-lens/clients/file-role.js +11 -2
  127. package/extensions/dm-lens/clients/file-time.js +1 -1
  128. package/extensions/dm-lens/clients/file-utils.js +93 -6
  129. package/extensions/dm-lens/clients/finding-delivery-gate.js +22 -26
  130. package/extensions/dm-lens/clients/format-service.js +33 -16
  131. package/extensions/dm-lens/clients/formatters.js +129 -92
  132. package/extensions/dm-lens/clients/generated-artifacts.js +2 -2
  133. package/extensions/dm-lens/clients/generation-guard.js +4 -0
  134. package/extensions/dm-lens/clients/git-guard.js +80 -26
  135. package/extensions/dm-lens/clients/gitleaks-client.js +26 -0
  136. package/extensions/dm-lens/clients/govulncheck-client.js +34 -6
  137. package/extensions/dm-lens/clients/gradle-ktfmt-style.js +96 -13
  138. package/extensions/dm-lens/clients/grammar-source.js +3 -3
  139. package/extensions/dm-lens/clients/host-edit-normalize.js +1 -1
  140. package/extensions/dm-lens/clients/indent-retarget.js +35 -5
  141. package/extensions/dm-lens/clients/inline-blocker-dispositions.js +107 -0
  142. package/extensions/dm-lens/clients/install-diagnostics.js +8 -6
  143. package/extensions/dm-lens/clients/installer/index.js +695 -183
  144. package/extensions/dm-lens/clients/installer/managed-tool-refresh.js +85 -25
  145. package/extensions/dm-lens/clients/instance-reaper-state.js +3 -0
  146. package/extensions/dm-lens/clients/instance-reaper.js +23 -16
  147. package/extensions/dm-lens/clients/instance-registry.js +34 -2
  148. package/extensions/dm-lens/clients/jscpd-client.js +11 -1
  149. package/extensions/dm-lens/clients/knip-client.js +2 -1
  150. package/extensions/dm-lens/clients/language-profile.js +18 -12
  151. package/extensions/dm-lens/clients/language-registry.js +3 -1
  152. package/extensions/dm-lens/clients/latency-logger.js +14 -4
  153. package/extensions/dm-lens/clients/ledger-bounds.js +13 -1
  154. package/extensions/dm-lens/clients/lens-config.js +74 -7
  155. package/extensions/dm-lens/clients/lens-engine.js +9 -10
  156. package/extensions/dm-lens/clients/lens-events.js +1 -1
  157. package/extensions/dm-lens/clients/lens-flag-registry.js +47 -2
  158. package/extensions/dm-lens/clients/lens-map.js +1 -1
  159. package/extensions/dm-lens/clients/log-cleanup.js +0 -28
  160. package/extensions/dm-lens/clients/lsp/cascade-tier.js +2 -1
  161. package/extensions/dm-lens/clients/lsp/client.js +70 -30
  162. package/extensions/dm-lens/clients/lsp/config.js +41 -15
  163. package/extensions/dm-lens/clients/lsp/content-limits.js +21 -0
  164. package/extensions/dm-lens/clients/lsp/diagnostic-binding.js +8 -0
  165. package/extensions/dm-lens/clients/lsp/document-drift.js +72 -1
  166. package/extensions/dm-lens/clients/lsp/edits.js +3 -3
  167. package/extensions/dm-lens/clients/lsp/index.js +435 -62
  168. package/extensions/dm-lens/clients/lsp/inferred-project.js +1 -1
  169. package/extensions/dm-lens/clients/lsp/language.js +0 -3
  170. package/extensions/dm-lens/clients/lsp/launch.js +12 -5
  171. package/extensions/dm-lens/clients/lsp/path-utils.js +0 -2
  172. package/extensions/dm-lens/clients/lsp/pending-aux-coverage.js +0 -1
  173. package/extensions/dm-lens/clients/lsp/server.js +125 -60
  174. package/extensions/dm-lens/clients/lsp/session-roots.js +26 -5
  175. package/extensions/dm-lens/clients/lsp/sync-kind.js +14 -1
  176. package/extensions/dm-lens/clients/lsp/tsserver-sync.js +5 -7
  177. package/extensions/dm-lens/clients/lsp/wait-policy/classification.js +3 -0
  178. package/extensions/dm-lens/clients/lsp/wait-policy/strategies.js +31 -2
  179. package/extensions/dm-lens/clients/lsp/workspace-diagnostics-cache.js +26 -4
  180. package/extensions/dm-lens/clients/lsp-document-symbols.js +1 -1
  181. package/extensions/dm-lens/clients/map-with-concurrency.js +7 -3
  182. package/extensions/dm-lens/clients/mcp/analyze.js +1 -1
  183. package/extensions/dm-lens/clients/mcp/ipc.js +104 -40
  184. package/extensions/dm-lens/clients/mcp/review.js +39 -7
  185. package/extensions/dm-lens/clients/mcp/session.js +38 -4
  186. package/extensions/dm-lens/clients/metrics-history.js +19 -84
  187. package/extensions/dm-lens/clients/middle-man-analysis.js +2 -4
  188. package/extensions/dm-lens/clients/module-report.js +1 -1
  189. package/extensions/dm-lens/clients/mutating-tool.js +3 -3
  190. package/extensions/dm-lens/clients/mutation-attribution.js +3 -3
  191. package/extensions/dm-lens/clients/ndjson-logger.js +17 -9
  192. package/extensions/dm-lens/clients/observed-mutation.js +42 -11
  193. package/extensions/dm-lens/clients/opaque-mutation-scan.js +17 -7
  194. package/extensions/dm-lens/clients/opengrep-client.js +92 -10
  195. package/extensions/dm-lens/clients/opengrep-config.js +1 -1
  196. package/extensions/dm-lens/clients/package-manager.js +2 -1
  197. package/extensions/dm-lens/clients/path-utils.js +199 -3
  198. package/extensions/dm-lens/clients/performance-report.js +3 -3
  199. package/extensions/dm-lens/clients/persistent-reverify.js +167 -0
  200. package/extensions/dm-lens/clients/php-cs-fixer-config.js +9 -4
  201. package/extensions/dm-lens/clients/pipeline.js +124 -68
  202. package/extensions/dm-lens/clients/project-changes.js +1 -1
  203. package/extensions/dm-lens/clients/project-diagnostics/cache.js +19 -5
  204. package/extensions/dm-lens/clients/project-diagnostics/extractors.js +1 -1
  205. package/extensions/dm-lens/clients/project-diagnostics/fresh-fetch.js +150 -18
  206. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
  207. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -3
  208. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
  209. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/knip.js +1 -1
  210. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/madge.js +1 -1
  211. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
  212. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/runner-findings.js +19 -2
  213. package/extensions/dm-lens/clients/project-diagnostics/scanner.js +35 -4
  214. package/extensions/dm-lens/clients/project-lens-config.js +58 -4
  215. package/extensions/dm-lens/clients/project-scan-policy.js +0 -46
  216. package/extensions/dm-lens/clients/python-environment.js +80 -4
  217. package/extensions/dm-lens/clients/python-provenance.js +551 -0
  218. package/extensions/dm-lens/clients/read-guard-logger.js +3 -1
  219. package/extensions/dm-lens/clients/read-guard.js +29 -6
  220. package/extensions/dm-lens/clients/recent-touches.js +2 -2
  221. package/extensions/dm-lens/clients/resource-sampler.js +59 -9
  222. package/extensions/dm-lens/clients/review-graph/builder.js +39 -34
  223. package/extensions/dm-lens/clients/review-graph/git-identity.js +11 -7
  224. package/extensions/dm-lens/clients/review-graph/import-resolvers.js +1 -1
  225. package/extensions/dm-lens/clients/review-graph-logger.js +3 -1
  226. package/extensions/dm-lens/clients/ruff-client.js +11 -10
  227. package/extensions/dm-lens/clients/runtime-agent-end.js +41 -5
  228. package/extensions/dm-lens/clients/runtime-context.js +5 -2
  229. package/extensions/dm-lens/clients/runtime-coordinator.js +60 -6
  230. package/extensions/dm-lens/clients/runtime-session.js +52 -8
  231. package/extensions/dm-lens/clients/runtime-tool-call.js +27 -15
  232. package/extensions/dm-lens/clients/runtime-tool-result.js +279 -63
  233. package/extensions/dm-lens/clients/runtime-turn.js +453 -185
  234. package/extensions/dm-lens/clients/safe-spawn.js +248 -62
  235. package/extensions/dm-lens/clients/sanitize.js +0 -4
  236. package/extensions/dm-lens/clients/scan-utils.js +1 -39
  237. package/extensions/dm-lens/clients/scratch-tree-policy.js +2 -3
  238. package/extensions/dm-lens/clients/security-scan-client.js +2 -2
  239. package/extensions/dm-lens/clients/session-event-guard.js +59 -2
  240. package/extensions/dm-lens/clients/session-summary.js +0 -25
  241. package/extensions/dm-lens/clients/sg-runner.js +24 -12
  242. package/extensions/dm-lens/clients/sgconfig.js +58 -6
  243. package/extensions/dm-lens/clients/shared-checkout-guard.js +1 -1
  244. package/extensions/dm-lens/clients/situational-tool-telemetry.js +85 -0
  245. package/extensions/dm-lens/clients/skills-resolver.js +42 -0
  246. package/extensions/dm-lens/clients/smells-rollup.js +2 -2
  247. package/extensions/dm-lens/clients/spawn-output-cap.js +29 -0
  248. package/extensions/dm-lens/clients/startup-scan.js +1 -2
  249. package/extensions/dm-lens/clients/string-utils.js +3 -0
  250. package/extensions/dm-lens/clients/test-runner-client.js +118 -57
  251. package/extensions/dm-lens/clients/test-runner-delivery.js +118 -66
  252. package/extensions/dm-lens/clients/tool-agreement.js +403 -0
  253. package/extensions/dm-lens/clients/tool-config.js +218 -0
  254. package/extensions/dm-lens/clients/tool-cwd.js +248 -0
  255. package/extensions/dm-lens/clients/tool-definition.js +18 -1
  256. package/extensions/dm-lens/clients/tool-policy.js +138 -10
  257. package/extensions/dm-lens/clients/tool-probe.js +5 -0
  258. package/extensions/dm-lens/clients/tool-set-policy.js +35 -0
  259. package/extensions/dm-lens/clients/tree-sitter-client.js +201 -80
  260. package/extensions/dm-lens/clients/tree-sitter-query-loader.js +78 -130
  261. package/extensions/dm-lens/clients/trivy-client.js +8 -1
  262. package/extensions/dm-lens/clients/tui-fit.js +0 -3
  263. package/extensions/dm-lens/clients/turn-context.js +48 -0
  264. package/extensions/dm-lens/clients/turn-end/lane.js +0 -0
  265. package/extensions/dm-lens/clients/turn-end/lanes/govulncheck.js +54 -0
  266. package/extensions/dm-lens/clients/turn-end/lanes/secrets.js +140 -0
  267. package/extensions/dm-lens/clients/user-notify.js +0 -3
  268. package/extensions/dm-lens/clients/warm-attach.js +25 -0
  269. package/extensions/dm-lens/clients/widget-state.js +203 -13
  270. package/extensions/dm-lens/clients/word-index-logger.js +0 -6
  271. package/extensions/dm-lens/clients/word-index-store.js +1 -4
  272. package/extensions/dm-lens/clients/word-index.js +9 -5
  273. package/extensions/dm-lens/clients/workspace-topology.js +20 -3
  274. package/extensions/dm-lens/clients/write-ordering-guard.js +6 -0
  275. package/extensions/dm-lens/clients/zizmor-config.js +15 -11
  276. package/extensions/dm-lens/config/dependency-cruiser-eager-allowlist.json +8 -2
  277. package/extensions/dm-lens/dist/clients/actionable-warnings-logger.js +24 -0
  278. package/extensions/dm-lens/dist/clients/actionable-warnings.js +1014 -0
  279. package/extensions/dm-lens/dist/clients/advisory-provenance.js +385 -0
  280. package/extensions/dm-lens/dist/clients/agent-behavior-client.js +94 -0
  281. package/extensions/dm-lens/dist/clients/agent-nudge.js +151 -0
  282. package/extensions/dm-lens/dist/clients/analysed-root.js +1 -0
  283. package/extensions/dm-lens/dist/clients/ast-grep-client.js +576 -0
  284. package/extensions/dm-lens/dist/clients/ast-grep-rule-manager.js +114 -0
  285. package/extensions/dm-lens/dist/clients/ast-grep-tool-logger.js +85 -0
  286. package/extensions/dm-lens/dist/clients/ast-grep-types.js +1 -0
  287. package/extensions/dm-lens/dist/clients/ast-grep-yaml-synth.js +109 -0
  288. package/extensions/dm-lens/dist/clients/atomic-write-staging.js +66 -0
  289. package/extensions/dm-lens/dist/clients/atomic-write.js +37 -0
  290. package/extensions/dm-lens/dist/clients/availability-probe-flight.js +11 -0
  291. package/extensions/dm-lens/dist/clients/bash-file-access.js +830 -0
  292. package/extensions/dm-lens/dist/clients/biome-client.js +221 -0
  293. package/extensions/dm-lens/dist/clients/blocker-freshness.js +385 -0
  294. package/extensions/dm-lens/dist/clients/blocker-past-eof.js +49 -0
  295. package/extensions/dm-lens/dist/clients/bootstrap.js +246 -0
  296. package/extensions/dm-lens/dist/clients/bounded-cache.js +105 -0
  297. package/extensions/dm-lens/dist/clients/bounded-pid-file-lock.js +173 -0
  298. package/extensions/dm-lens/dist/clients/bounded-telemetry.js +104 -0
  299. package/extensions/dm-lens/dist/clients/build-identity.js +45 -0
  300. package/extensions/dm-lens/dist/clients/bundled-resource-health.js +41 -0
  301. package/extensions/dm-lens/dist/clients/bus-events-logger.js +48 -0
  302. package/extensions/dm-lens/dist/clients/bus-publish.js +117 -0
  303. package/extensions/dm-lens/dist/clients/cache/rule-cache.js +103 -0
  304. package/extensions/dm-lens/dist/clients/cache-manager.js +340 -0
  305. package/extensions/dm-lens/dist/clients/cache-observability.js +847 -0
  306. package/extensions/dm-lens/dist/clients/call-graph.js +628 -0
  307. package/extensions/dm-lens/dist/clients/cargo-manifest.js +151 -0
  308. package/extensions/dm-lens/dist/clients/cascade-budget.js +52 -0
  309. package/extensions/dm-lens/dist/clients/cascade-format.js +160 -0
  310. package/extensions/dm-lens/dist/clients/cascade-logger.js +22 -0
  311. package/extensions/dm-lens/dist/clients/cascade-types.js +1 -0
  312. package/extensions/dm-lens/dist/clients/child-unref.js +59 -0
  313. package/extensions/dm-lens/dist/clients/code-quality-warnings.js +192 -0
  314. package/extensions/dm-lens/dist/clients/codebase-model.js +110 -0
  315. package/extensions/dm-lens/dist/clients/collateral-test-role.js +8 -0
  316. package/extensions/dm-lens/dist/clients/complexity-client.js +398 -0
  317. package/extensions/dm-lens/dist/clients/config-core/deny.js +117 -0
  318. package/extensions/dm-lens/dist/clients/config-core/index.js +2 -0
  319. package/extensions/dm-lens/dist/clients/config-core/merge.js +228 -0
  320. package/extensions/dm-lens/dist/clients/config-core/normalize.js +217 -0
  321. package/extensions/dm-lens/dist/clients/config-core/process-spec.js +147 -0
  322. package/extensions/dm-lens/dist/clients/config-core/provenance.js +54 -0
  323. package/extensions/dm-lens/dist/clients/config-core/records.js +79 -0
  324. package/extensions/dm-lens/dist/clients/config-core/resolve.js +48 -0
  325. package/extensions/dm-lens/dist/clients/config-core/safe-object.js +22 -0
  326. package/extensions/dm-lens/dist/clients/config-core/schema.js +90 -0
  327. package/extensions/dm-lens/dist/clients/config-diagnostic-codes.js +90 -0
  328. package/extensions/dm-lens/dist/clients/config-locations.js +175 -0
  329. package/extensions/dm-lens/dist/clients/config-resolve.js +359 -0
  330. package/extensions/dm-lens/dist/clients/config-schema.js +128 -0
  331. package/extensions/dm-lens/dist/clients/config-warn.js +146 -0
  332. package/extensions/dm-lens/dist/clients/console-guard-install.js +4 -0
  333. package/extensions/dm-lens/dist/clients/cooperative-budget.js +36 -0
  334. package/extensions/dm-lens/dist/clients/dead-code-client.js +342 -0
  335. package/extensions/dm-lens/dist/clients/dead-code-logger.js +18 -0
  336. package/extensions/dm-lens/dist/clients/deadline-utils.js +117 -0
  337. package/extensions/dm-lens/dist/clients/debug-handles.js +121 -0
  338. package/extensions/dm-lens/dist/clients/debug-heap.js +80 -0
  339. package/extensions/dm-lens/dist/clients/deferred-lsp-work.js +33 -0
  340. package/extensions/dm-lens/dist/clients/degradation-ledger.js +272 -0
  341. package/extensions/dm-lens/dist/clients/demoted-finding-render.js +61 -0
  342. package/extensions/dm-lens/dist/clients/dependency-checker.js +525 -0
  343. package/extensions/dm-lens/dist/clients/deps/ast-grep-napi.js +17 -0
  344. package/extensions/dm-lens/dist/clients/deps/dm-host-deps.js +10 -0
  345. package/extensions/dm-lens/dist/clients/deps/dm-tui-compat.js +58 -0
  346. package/extensions/dm-lens/dist/clients/deps/js-yaml.js +7 -0
  347. package/extensions/dm-lens/dist/clients/deps/minimatch.js +6 -0
  348. package/extensions/dm-lens/dist/clients/deps/pidusage.js +5 -0
  349. package/extensions/dm-lens/dist/clients/deps/typebox.js +5 -0
  350. package/extensions/dm-lens/dist/clients/deps/vscode-jsonrpc.js +8 -0
  351. package/extensions/dm-lens/dist/clients/deps/web-tree-sitter.js +11 -0
  352. package/extensions/dm-lens/dist/clients/diagnostic-dispositions.js +318 -0
  353. package/extensions/dm-lens/dist/clients/diagnostic-line-freshness.js +144 -0
  354. package/extensions/dm-lens/dist/clients/diagnostic-logger.js +60 -0
  355. package/extensions/dm-lens/dist/clients/diagnostic-tracker.js +89 -0
  356. package/extensions/dm-lens/dist/clients/diagnostics-publish.js +134 -0
  357. package/extensions/dm-lens/dist/clients/dispatch/ast-grep-catalog.js +16 -0
  358. package/extensions/dm-lens/dist/clients/dispatch/auxiliary-lsp.js +158 -0
  359. package/extensions/dm-lens/dist/clients/dispatch/collect-later-tier.js +25 -0
  360. package/extensions/dm-lens/dist/clients/dispatch/diagnostic-taxonomy.js +58 -0
  361. package/extensions/dm-lens/dist/clients/dispatch/dispatcher.js +953 -0
  362. package/extensions/dm-lens/dist/clients/dispatch/fact-provider-types.js +1 -0
  363. package/extensions/dm-lens/dist/clients/dispatch/fact-rule-runner.js +17 -0
  364. package/extensions/dm-lens/dist/clients/dispatch/fact-runner.js +18 -0
  365. package/extensions/dm-lens/dist/clients/dispatch/fact-scheduler.js +52 -0
  366. package/extensions/dm-lens/dist/clients/dispatch/fact-store.js +199 -0
  367. package/extensions/dm-lens/dist/clients/dispatch/facts/comment-facts.js +20 -0
  368. package/extensions/dm-lens/dist/clients/dispatch/facts/file-content.js +18 -0
  369. package/extensions/dm-lens/dist/clients/dispatch/facts/function-facts.js +281 -0
  370. package/extensions/dm-lens/dist/clients/dispatch/facts/import-facts.js +169 -0
  371. package/extensions/dm-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +19 -0
  372. package/extensions/dm-lens/dist/clients/dispatch/facts/try-catch-facts.js +95 -0
  373. package/extensions/dm-lens/dist/clients/dispatch/finding-policy.js +159 -0
  374. package/extensions/dm-lens/dist/clients/dispatch/indent-detect.js +227 -0
  375. package/extensions/dm-lens/dist/clients/dispatch/inline-suppressions.js +52 -0
  376. package/extensions/dm-lens/dist/clients/dispatch/integration.js +1463 -0
  377. package/extensions/dm-lens/dist/clients/dispatch/lazy.js +8 -0
  378. package/extensions/dm-lens/dist/clients/dispatch/pending-runner-findings.js +75 -0
  379. package/extensions/dm-lens/dist/clients/dispatch/plan.js +278 -0
  380. package/extensions/dm-lens/dist/clients/dispatch/priorities.js +14 -0
  381. package/extensions/dm-lens/dist/clients/dispatch/rule-id-normalize.js +42 -0
  382. package/extensions/dm-lens/dist/clients/dispatch/rule-ignores.js +21 -0
  383. package/extensions/dm-lens/dist/clients/dispatch/rule-policy.js +73 -0
  384. package/extensions/dm-lens/dist/clients/dispatch/rules/async-noise.js +31 -0
  385. package/extensions/dm-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +27 -0
  386. package/extensions/dm-lens/dist/clients/dispatch/rules/cors-wildcard.js +35 -0
  387. package/extensions/dm-lens/dist/clients/dispatch/rules/error-obscuring.js +29 -0
  388. package/extensions/dm-lens/dist/clients/dispatch/rules/error-swallowing.js +29 -0
  389. package/extensions/dm-lens/dist/clients/dispatch/rules/framework-call-noise.js +31 -0
  390. package/extensions/dm-lens/dist/clients/dispatch/rules/high-complexity.js +56 -0
  391. package/extensions/dm-lens/dist/clients/dispatch/rules/high-fan-out.js +45 -0
  392. package/extensions/dm-lens/dist/clients/dispatch/rules/high-import-coupling.js +31 -0
  393. package/extensions/dm-lens/dist/clients/dispatch/rules/missing-error-propagation.js +45 -0
  394. package/extensions/dm-lens/dist/clients/dispatch/rules/no-commented-credentials.js +46 -0
  395. package/extensions/dm-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +38 -0
  396. package/extensions/dm-lens/dist/clients/dispatch/rules/placeholder-comments.js +40 -0
  397. package/extensions/dm-lens/dist/clients/dispatch/rules/unsafe-boundary.js +101 -0
  398. package/extensions/dm-lens/dist/clients/dispatch/runner-context.js +46 -0
  399. package/extensions/dm-lens/dist/clients/dispatch/runners/actionlint.js +98 -0
  400. package/extensions/dm-lens/dist/clients/dispatch/runners/ast-grep-napi.js +690 -0
  401. package/extensions/dm-lens/dist/clients/dispatch/runners/biome-check.js +202 -0
  402. package/extensions/dm-lens/dist/clients/dispatch/runners/cpp-check.js +190 -0
  403. package/extensions/dm-lens/dist/clients/dispatch/runners/credo.js +66 -0
  404. package/extensions/dm-lens/dist/clients/dispatch/runners/cue-vet.js +167 -0
  405. package/extensions/dm-lens/dist/clients/dispatch/runners/dart-analyze.js +151 -0
  406. package/extensions/dm-lens/dist/clients/dispatch/runners/detekt.js +157 -0
  407. package/extensions/dm-lens/dist/clients/dispatch/runners/dotnet-build.js +157 -0
  408. package/extensions/dm-lens/dist/clients/dispatch/runners/elixir-check.js +153 -0
  409. package/extensions/dm-lens/dist/clients/dispatch/runners/eslint.js +99 -0
  410. package/extensions/dm-lens/dist/clients/dispatch/runners/fact-rules.js +20 -0
  411. package/extensions/dm-lens/dist/clients/dispatch/runners/fish-indent.js +65 -0
  412. package/extensions/dm-lens/dist/clients/dispatch/runners/gleam-check.js +107 -0
  413. package/extensions/dm-lens/dist/clients/dispatch/runners/go-vet.js +51 -0
  414. package/extensions/dm-lens/dist/clients/dispatch/runners/golangci-lint.js +89 -0
  415. package/extensions/dm-lens/dist/clients/dispatch/runners/hadolint.js +83 -0
  416. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-lint.js +144 -0
  417. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-render.js +593 -0
  418. package/extensions/dm-lens/dist/clients/dispatch/runners/htmlhint.js +103 -0
  419. package/extensions/dm-lens/dist/clients/dispatch/runners/index.js +100 -0
  420. package/extensions/dm-lens/dist/clients/dispatch/runners/javac.js +82 -0
  421. package/extensions/dm-lens/dist/clients/dispatch/runners/ktlint.js +93 -0
  422. package/extensions/dm-lens/dist/clients/dispatch/runners/lsp.js +206 -0
  423. package/extensions/dm-lens/dist/clients/dispatch/runners/markdownlint.js +129 -0
  424. package/extensions/dm-lens/dist/clients/dispatch/runners/mypy.js +70 -0
  425. package/extensions/dm-lens/dist/clients/dispatch/runners/oxlint.js +305 -0
  426. package/extensions/dm-lens/dist/clients/dispatch/runners/php-lint.js +70 -0
  427. package/extensions/dm-lens/dist/clients/dispatch/runners/phpstan.js +90 -0
  428. package/extensions/dm-lens/dist/clients/dispatch/runners/prisma-validate.js +56 -0
  429. package/extensions/dm-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +307 -0
  430. package/extensions/dm-lens/dist/clients/dispatch/runners/pyright.js +118 -0
  431. package/extensions/dm-lens/dist/clients/dispatch/runners/rubocop.js +79 -0
  432. package/extensions/dm-lens/dist/clients/dispatch/runners/ruff.js +69 -0
  433. package/extensions/dm-lens/dist/clients/dispatch/runners/rust-clippy.js +147 -0
  434. package/extensions/dm-lens/dist/clients/dispatch/runners/shellcheck.js +111 -0
  435. package/extensions/dm-lens/dist/clients/dispatch/runners/shfmt.js +81 -0
  436. package/extensions/dm-lens/dist/clients/dispatch/runners/spellcheck.js +74 -0
  437. package/extensions/dm-lens/dist/clients/dispatch/runners/spotbugs.js +208 -0
  438. package/extensions/dm-lens/dist/clients/dispatch/runners/sqlfluff.js +136 -0
  439. package/extensions/dm-lens/dist/clients/dispatch/runners/stylelint.js +118 -0
  440. package/extensions/dm-lens/dist/clients/dispatch/runners/swiftlint.js +143 -0
  441. package/extensions/dm-lens/dist/clients/dispatch/runners/taplo.js +97 -0
  442. package/extensions/dm-lens/dist/clients/dispatch/runners/terragrunt.js +110 -0
  443. package/extensions/dm-lens/dist/clients/dispatch/runners/tflint.js +104 -0
  444. package/extensions/dm-lens/dist/clients/dispatch/runners/tree-sitter.js +516 -0
  445. package/extensions/dm-lens/dist/clients/dispatch/runners/trivy-config.js +155 -0
  446. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/availability-policy.js +285 -0
  447. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +61 -0
  448. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +61 -0
  449. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +130 -0
  450. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1067 -0
  451. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +40 -0
  452. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/tool-failure.js +117 -0
  453. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +88 -0
  454. package/extensions/dm-lens/dist/clients/dispatch/runners/utils.js +8 -0
  455. package/extensions/dm-lens/dist/clients/dispatch/runners/vale.js +106 -0
  456. package/extensions/dm-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +163 -0
  457. package/extensions/dm-lens/dist/clients/dispatch/runners/yamllint.js +83 -0
  458. package/extensions/dm-lens/dist/clients/dispatch/runners/zig-check.js +72 -0
  459. package/extensions/dm-lens/dist/clients/dispatch/suppress-writer.js +57 -0
  460. package/extensions/dm-lens/dist/clients/dispatch/tool-profile.js +30 -0
  461. package/extensions/dm-lens/dist/clients/dispatch/types.js +7 -0
  462. package/extensions/dm-lens/dist/clients/dispatch/utils/format-utils.js +45 -0
  463. package/extensions/dm-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +31 -0
  464. package/extensions/dm-lens/dist/clients/disposition-logger.js +19 -0
  465. package/extensions/dm-lens/dist/clients/disposition-publish.js +88 -0
  466. package/extensions/dm-lens/dist/clients/durable-store.js +77 -0
  467. package/extensions/dm-lens/dist/clients/effective-config.js +160 -0
  468. package/extensions/dm-lens/dist/clients/env-utils.js +26 -0
  469. package/extensions/dm-lens/dist/clients/error-class.js +3 -0
  470. package/extensions/dm-lens/dist/clients/eval-timestamp.js +2 -0
  471. package/extensions/dm-lens/dist/clients/event-loop-hold.js +119 -0
  472. package/extensions/dm-lens/dist/clients/event-loop-monitor.js +84 -0
  473. package/extensions/dm-lens/dist/clients/extension-log.js +230 -0
  474. package/extensions/dm-lens/dist/clients/extension-mode.js +20 -0
  475. package/extensions/dm-lens/dist/clients/feature-hints.js +88 -0
  476. package/extensions/dm-lens/dist/clients/file-kinds.js +304 -0
  477. package/extensions/dm-lens/dist/clients/file-role.js +50 -0
  478. package/extensions/dm-lens/dist/clients/file-time.js +112 -0
  479. package/extensions/dm-lens/dist/clients/file-utils.js +630 -0
  480. package/extensions/dm-lens/dist/clients/finding-delivery-gate.js +129 -0
  481. package/extensions/dm-lens/dist/clients/finding-identity.js +23 -0
  482. package/extensions/dm-lens/dist/clients/fix-worklog.js +75 -0
  483. package/extensions/dm-lens/dist/clients/format-events-publish.js +230 -0
  484. package/extensions/dm-lens/dist/clients/format-service.js +154 -0
  485. package/extensions/dm-lens/dist/clients/formatters-lazy.js +8 -0
  486. package/extensions/dm-lens/dist/clients/formatters.js +1351 -0
  487. package/extensions/dm-lens/dist/clients/freshness-cadence.js +1 -0
  488. package/extensions/dm-lens/dist/clients/freshness.js +8 -0
  489. package/extensions/dm-lens/dist/clients/generated-artifacts.js +209 -0
  490. package/extensions/dm-lens/dist/clients/generation-guard.js +105 -0
  491. package/extensions/dm-lens/dist/clients/git-guard.js +770 -0
  492. package/extensions/dm-lens/dist/clients/git-tracked-ignore.js +120 -0
  493. package/extensions/dm-lens/dist/clients/gitleaks-client.js +282 -0
  494. package/extensions/dm-lens/dist/clients/go-client.js +47 -0
  495. package/extensions/dm-lens/dist/clients/govulncheck-client.js +411 -0
  496. package/extensions/dm-lens/dist/clients/gradle-ktfmt-style.js +177 -0
  497. package/extensions/dm-lens/dist/clients/grammar-source.js +224 -0
  498. package/extensions/dm-lens/dist/clients/gzip-stage-write.js +85 -0
  499. package/extensions/dm-lens/dist/clients/hashline-anchor.js +222 -0
  500. package/extensions/dm-lens/dist/clients/hook-budgets.js +16 -0
  501. package/extensions/dm-lens/dist/clients/host-edit-normalize.js +87 -0
  502. package/extensions/dm-lens/dist/clients/host-ports.js +35 -0
  503. package/extensions/dm-lens/dist/clients/indent-retarget.js +102 -0
  504. package/extensions/dm-lens/dist/clients/inline-blocker-dispositions.js +103 -0
  505. package/extensions/dm-lens/dist/clients/install-diagnostics.js +123 -0
  506. package/extensions/dm-lens/dist/clients/installer/index.js +3770 -0
  507. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh-session.js +17 -0
  508. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh.js +522 -0
  509. package/extensions/dm-lens/dist/clients/instance-reaper-state.js +3 -0
  510. package/extensions/dm-lens/dist/clients/instance-reaper.js +577 -0
  511. package/extensions/dm-lens/dist/clients/instance-registry-lock.js +131 -0
  512. package/extensions/dm-lens/dist/clients/instance-registry.js +452 -0
  513. package/extensions/dm-lens/dist/clients/jscpd-client.js +252 -0
  514. package/extensions/dm-lens/dist/clients/json-cache-read.js +25 -0
  515. package/extensions/dm-lens/dist/clients/knip-client.js +472 -0
  516. package/extensions/dm-lens/dist/clients/language-policy.js +242 -0
  517. package/extensions/dm-lens/dist/clients/language-profile.js +261 -0
  518. package/extensions/dm-lens/dist/clients/language-registry.js +424 -0
  519. package/extensions/dm-lens/dist/clients/latency-logger.js +192 -0
  520. package/extensions/dm-lens/dist/clients/lazy-import.js +14 -0
  521. package/extensions/dm-lens/dist/clients/ledger-bounds.js +21 -0
  522. package/extensions/dm-lens/dist/clients/lens-config.js +237 -0
  523. package/extensions/dm-lens/dist/clients/lens-engine.js +181 -0
  524. package/extensions/dm-lens/dist/clients/lens-events.js +105 -0
  525. package/extensions/dm-lens/dist/clients/lens-flag-registry.js +302 -0
  526. package/extensions/dm-lens/dist/clients/lens-map.js +980 -0
  527. package/extensions/dm-lens/dist/clients/live-bus-emitter.js +53 -0
  528. package/extensions/dm-lens/dist/clients/log-cleanup.js +138 -0
  529. package/extensions/dm-lens/dist/clients/lsp/aggregation.js +88 -0
  530. package/extensions/dm-lens/dist/clients/lsp/cascade-tier.js +203 -0
  531. package/extensions/dm-lens/dist/clients/lsp/client.js +2709 -0
  532. package/extensions/dm-lens/dist/clients/lsp/config.js +252 -0
  533. package/extensions/dm-lens/dist/clients/lsp/content-limits.js +21 -0
  534. package/extensions/dm-lens/dist/clients/lsp/diagnostic-binding.js +79 -0
  535. package/extensions/dm-lens/dist/clients/lsp/document-drift.js +312 -0
  536. package/extensions/dm-lens/dist/clients/lsp/edits.js +930 -0
  537. package/extensions/dm-lens/dist/clients/lsp/index.js +4448 -0
  538. package/extensions/dm-lens/dist/clients/lsp/inferred-project.js +121 -0
  539. package/extensions/dm-lens/dist/clients/lsp/jvm-runtime.js +194 -0
  540. package/extensions/dm-lens/dist/clients/lsp/language.js +23 -0
  541. package/extensions/dm-lens/dist/clients/lsp/launch.js +468 -0
  542. package/extensions/dm-lens/dist/clients/lsp/lombok.js +146 -0
  543. package/extensions/dm-lens/dist/clients/lsp/path-utils.js +1 -0
  544. package/extensions/dm-lens/dist/clients/lsp/pending-aux-coverage.js +90 -0
  545. package/extensions/dm-lens/dist/clients/lsp/position-encoding.js +28 -0
  546. package/extensions/dm-lens/dist/clients/lsp/ruby-drive-dirs.js +42 -0
  547. package/extensions/dm-lens/dist/clients/lsp/server.js +2422 -0
  548. package/extensions/dm-lens/dist/clients/lsp/session-roots.js +52 -0
  549. package/extensions/dm-lens/dist/clients/lsp/spawn-history.js +15 -0
  550. package/extensions/dm-lens/dist/clients/lsp/sync-kind.js +30 -0
  551. package/extensions/dm-lens/dist/clients/lsp/tsserver-sync.js +156 -0
  552. package/extensions/dm-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +1 -0
  553. package/extensions/dm-lens/dist/clients/lsp/wait-policy/classification.js +36 -0
  554. package/extensions/dm-lens/dist/clients/lsp/wait-policy/index.js +3 -0
  555. package/extensions/dm-lens/dist/clients/lsp/wait-policy/strategies.js +175 -0
  556. package/extensions/dm-lens/dist/clients/lsp/watch-queue.js +40 -0
  557. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-cache.js +267 -0
  558. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-session.js +7 -0
  559. package/extensions/dm-lens/dist/clients/lsp/workspace-sweep-hold.js +93 -0
  560. package/extensions/dm-lens/dist/clients/lsp-budget.js +83 -0
  561. package/extensions/dm-lens/dist/clients/lsp-document-symbols.js +93 -0
  562. package/extensions/dm-lens/dist/clients/lsp-lazy.js +8 -0
  563. package/extensions/dm-lens/dist/clients/lsp-mutation.js +273 -0
  564. package/extensions/dm-lens/dist/clients/lsp-status.js +37 -0
  565. package/extensions/dm-lens/dist/clients/map-with-concurrency.js +20 -0
  566. package/extensions/dm-lens/dist/clients/mcp/analyze.js +251 -0
  567. package/extensions/dm-lens/dist/clients/mcp/host-shim.js +14 -0
  568. package/extensions/dm-lens/dist/clients/mcp/ipc.js +302 -0
  569. package/extensions/dm-lens/dist/clients/mcp/review.js +137 -0
  570. package/extensions/dm-lens/dist/clients/mcp/session.js +305 -0
  571. package/extensions/dm-lens/dist/clients/memory-sampler.js +107 -0
  572. package/extensions/dm-lens/dist/clients/message-end-attribution.js +18 -0
  573. package/extensions/dm-lens/dist/clients/metrics-client.js +80 -0
  574. package/extensions/dm-lens/dist/clients/metrics-history.js +255 -0
  575. package/extensions/dm-lens/dist/clients/middle-man-analysis.js +161 -0
  576. package/extensions/dm-lens/dist/clients/model-provider.js +31 -0
  577. package/extensions/dm-lens/dist/clients/module-report-lsp.js +140 -0
  578. package/extensions/dm-lens/dist/clients/module-report.js +1642 -0
  579. package/extensions/dm-lens/dist/clients/mutating-tool.js +377 -0
  580. package/extensions/dm-lens/dist/clients/mutation-attribution.js +168 -0
  581. package/extensions/dm-lens/dist/clients/mutation-bridge.js +102 -0
  582. package/extensions/dm-lens/dist/clients/ndjson-logger.js +471 -0
  583. package/extensions/dm-lens/dist/clients/observed-mutation-sources.js +43 -0
  584. package/extensions/dm-lens/dist/clients/observed-mutation.js +709 -0
  585. package/extensions/dm-lens/dist/clients/oldtext-autopatch.js +100 -0
  586. package/extensions/dm-lens/dist/clients/opaque-mutation-scan.js +313 -0
  587. package/extensions/dm-lens/dist/clients/opengrep-client.js +216 -0
  588. package/extensions/dm-lens/dist/clients/opengrep-config.js +52 -0
  589. package/extensions/dm-lens/dist/clients/package-manager.js +303 -0
  590. package/extensions/dm-lens/dist/clients/package-root.js +25 -0
  591. package/extensions/dm-lens/dist/clients/partial-edit-apply.js +337 -0
  592. package/extensions/dm-lens/dist/clients/path-attribution-telemetry.js +31 -0
  593. package/extensions/dm-lens/dist/clients/path-keyed-map.js +57 -0
  594. package/extensions/dm-lens/dist/clients/path-utils.js +476 -0
  595. package/extensions/dm-lens/dist/clients/performance-report.js +291 -0
  596. package/extensions/dm-lens/dist/clients/persist-debounce.js +37 -0
  597. package/extensions/dm-lens/dist/clients/persistent-reverify.js +165 -0
  598. package/extensions/dm-lens/dist/clients/php-cs-fixer-config.js +15 -0
  599. package/extensions/dm-lens/dist/clients/pipeline.js +1091 -0
  600. package/extensions/dm-lens/dist/clients/post-autofix-notice.js +19 -0
  601. package/extensions/dm-lens/dist/clients/print-mode.js +3 -0
  602. package/extensions/dm-lens/dist/clients/probe-home-state.js +62 -0
  603. package/extensions/dm-lens/dist/clients/process-bridge.js +20 -0
  604. package/extensions/dm-lens/dist/clients/process-singletons.js +69 -0
  605. package/extensions/dm-lens/dist/clients/process-snapshot.js +22 -0
  606. package/extensions/dm-lens/dist/clients/project-changes.js +112 -0
  607. package/extensions/dm-lens/dist/clients/project-conventions.js +152 -0
  608. package/extensions/dm-lens/dist/clients/project-diagnostics/cache.js +91 -0
  609. package/extensions/dm-lens/dist/clients/project-diagnostics/extractors.js +53 -0
  610. package/extensions/dm-lens/dist/clients/project-diagnostics/fresh-fetch.js +408 -0
  611. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +64 -0
  612. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +38 -0
  613. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +21 -0
  614. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +23 -0
  615. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +28 -0
  616. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +45 -0
  617. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +34 -0
  618. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +32 -0
  619. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +79 -0
  620. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +41 -0
  621. package/extensions/dm-lens/dist/clients/project-diagnostics/scanner.js +349 -0
  622. package/extensions/dm-lens/dist/clients/project-diagnostics/types.js +1 -0
  623. package/extensions/dm-lens/dist/clients/project-lens-config.js +437 -0
  624. package/extensions/dm-lens/dist/clients/project-report.js +527 -0
  625. package/extensions/dm-lens/dist/clients/project-scale.js +60 -0
  626. package/extensions/dm-lens/dist/clients/project-scan-policy.js +4 -0
  627. package/extensions/dm-lens/dist/clients/project-snapshot-fingerprint.js +39 -0
  628. package/extensions/dm-lens/dist/clients/project-snapshot-persist-worker.js +14 -0
  629. package/extensions/dm-lens/dist/clients/project-snapshot.js +1178 -0
  630. package/extensions/dm-lens/dist/clients/project-trust.js +104 -0
  631. package/extensions/dm-lens/dist/clients/python-environment.js +120 -0
  632. package/extensions/dm-lens/dist/clients/python-provenance.js +551 -0
  633. package/extensions/dm-lens/dist/clients/quiet-window-config.js +16 -0
  634. package/extensions/dm-lens/dist/clients/quiet-window.js +126 -0
  635. package/extensions/dm-lens/dist/clients/read-bridge.js +46 -0
  636. package/extensions/dm-lens/dist/clients/read-expansion.js +218 -0
  637. package/extensions/dm-lens/dist/clients/read-guard-logger.js +178 -0
  638. package/extensions/dm-lens/dist/clients/read-guard-tool-lines.js +1042 -0
  639. package/extensions/dm-lens/dist/clients/read-guard.js +1096 -0
  640. package/extensions/dm-lens/dist/clients/recent-touches.js +126 -0
  641. package/extensions/dm-lens/dist/clients/redact/secrets.js +386 -0
  642. package/extensions/dm-lens/dist/clients/resource-sampler.js +344 -0
  643. package/extensions/dm-lens/dist/clients/reverse-deps.js +227 -0
  644. package/extensions/dm-lens/dist/clients/review-graph/builder.js +3635 -0
  645. package/extensions/dm-lens/dist/clients/review-graph/format.js +30 -0
  646. package/extensions/dm-lens/dist/clients/review-graph/git-identity.js +115 -0
  647. package/extensions/dm-lens/dist/clients/review-graph/import-resolvers.js +325 -0
  648. package/extensions/dm-lens/dist/clients/review-graph/persist-worker.js +8 -0
  649. package/extensions/dm-lens/dist/clients/review-graph/query.js +195 -0
  650. package/extensions/dm-lens/dist/clients/review-graph/revision-drift.js +3 -0
  651. package/extensions/dm-lens/dist/clients/review-graph/service.js +60 -0
  652. package/extensions/dm-lens/dist/clients/review-graph/shared-extraction-ir.js +54 -0
  653. package/extensions/dm-lens/dist/clients/review-graph/symbol-id.js +29 -0
  654. package/extensions/dm-lens/dist/clients/review-graph/tsconfig-paths.js +253 -0
  655. package/extensions/dm-lens/dist/clients/review-graph/types.js +1 -0
  656. package/extensions/dm-lens/dist/clients/review-graph/workspace-modules.js +374 -0
  657. package/extensions/dm-lens/dist/clients/review-graph-logger.js +51 -0
  658. package/extensions/dm-lens/dist/clients/ruff-client.js +109 -0
  659. package/extensions/dm-lens/dist/clients/rules-scanner.js +113 -0
  660. package/extensions/dm-lens/dist/clients/run-duration.js +9 -0
  661. package/extensions/dm-lens/dist/clients/runtime-agent-end.js +608 -0
  662. package/extensions/dm-lens/dist/clients/runtime-config.js +39 -0
  663. package/extensions/dm-lens/dist/clients/runtime-context.js +155 -0
  664. package/extensions/dm-lens/dist/clients/runtime-coordinator.js +817 -0
  665. package/extensions/dm-lens/dist/clients/runtime-session.js +1625 -0
  666. package/extensions/dm-lens/dist/clients/runtime-tool-call.js +868 -0
  667. package/extensions/dm-lens/dist/clients/runtime-tool-result.js +1317 -0
  668. package/extensions/dm-lens/dist/clients/runtime-turn.js +2333 -0
  669. package/extensions/dm-lens/dist/clients/rust-client.js +48 -0
  670. package/extensions/dm-lens/dist/clients/safe-spawn.js +1267 -0
  671. package/extensions/dm-lens/dist/clients/sanitize.js +174 -0
  672. package/extensions/dm-lens/dist/clients/scan-utils.js +7 -0
  673. package/extensions/dm-lens/dist/clients/scratch-tree-policy.js +57 -0
  674. package/extensions/dm-lens/dist/clients/search-read-registration.js +59 -0
  675. package/extensions/dm-lens/dist/clients/secret-findings.js +69 -0
  676. package/extensions/dm-lens/dist/clients/security-scan-client.js +208 -0
  677. package/extensions/dm-lens/dist/clients/session-event-guard.js +111 -0
  678. package/extensions/dm-lens/dist/clients/session-lifecycle.js +173 -0
  679. package/extensions/dm-lens/dist/clients/session-start-observability.js +47 -0
  680. package/extensions/dm-lens/dist/clients/session-state-store.js +63 -0
  681. package/extensions/dm-lens/dist/clients/session-summary.js +8 -0
  682. package/extensions/dm-lens/dist/clients/sessionstart-logger.js +22 -0
  683. package/extensions/dm-lens/dist/clients/sg-runner.js +627 -0
  684. package/extensions/dm-lens/dist/clients/sgconfig.js +280 -0
  685. package/extensions/dm-lens/dist/clients/shared-checkout-guard.js +177 -0
  686. package/extensions/dm-lens/dist/clients/single-flight.js +52 -0
  687. package/extensions/dm-lens/dist/clients/situational-tool-telemetry.js +85 -0
  688. package/extensions/dm-lens/dist/clients/skills-resolver.js +38 -0
  689. package/extensions/dm-lens/dist/clients/slow-fs.js +77 -0
  690. package/extensions/dm-lens/dist/clients/smells-rollup.js +118 -0
  691. package/extensions/dm-lens/dist/clients/source-filter.js +320 -0
  692. package/extensions/dm-lens/dist/clients/source-walker.js +96 -0
  693. package/extensions/dm-lens/dist/clients/spawn-output-cap.js +35 -0
  694. package/extensions/dm-lens/dist/clients/spawn-timeout-cooldown.js +51 -0
  695. package/extensions/dm-lens/dist/clients/stale-marker.js +1 -0
  696. package/extensions/dm-lens/dist/clients/startup-scan.js +222 -0
  697. package/extensions/dm-lens/dist/clients/startup-timing.js +67 -0
  698. package/extensions/dm-lens/dist/clients/string-utils.js +6 -0
  699. package/extensions/dm-lens/dist/clients/subagent-mode.js +40 -0
  700. package/extensions/dm-lens/dist/clients/symbol-containment.js +16 -0
  701. package/extensions/dm-lens/dist/clients/symbol-types.js +1 -0
  702. package/extensions/dm-lens/dist/clients/test-runner-client.js +1504 -0
  703. package/extensions/dm-lens/dist/clients/test-runner-delivery.js +260 -0
  704. package/extensions/dm-lens/dist/clients/todo-scanner.js +164 -0
  705. package/extensions/dm-lens/dist/clients/tool-agreement.js +377 -0
  706. package/extensions/dm-lens/dist/clients/tool-config.js +218 -0
  707. package/extensions/dm-lens/dist/clients/tool-cwd.js +235 -0
  708. package/extensions/dm-lens/dist/clients/tool-definition.js +22 -0
  709. package/extensions/dm-lens/dist/clients/tool-event.js +18 -0
  710. package/extensions/dm-lens/dist/clients/tool-policy.js +2393 -0
  711. package/extensions/dm-lens/dist/clients/tool-probe.js +5 -0
  712. package/extensions/dm-lens/dist/clients/tool-render.js +79 -0
  713. package/extensions/dm-lens/dist/clients/tool-set-policy.js +70 -0
  714. package/extensions/dm-lens/dist/clients/tree-sitter-cache.js +206 -0
  715. package/extensions/dm-lens/dist/clients/tree-sitter-client.js +2787 -0
  716. package/extensions/dm-lens/dist/clients/tree-sitter-logger.js +77 -0
  717. package/extensions/dm-lens/dist/clients/tree-sitter-navigator.js +198 -0
  718. package/extensions/dm-lens/dist/clients/tree-sitter-query-loader.js +318 -0
  719. package/extensions/dm-lens/dist/clients/tree-sitter-shared.js +87 -0
  720. package/extensions/dm-lens/dist/clients/tree-sitter-symbol-extractor.js +957 -0
  721. package/extensions/dm-lens/dist/clients/trivy-client.js +305 -0
  722. package/extensions/dm-lens/dist/clients/tui-fit.js +26 -0
  723. package/extensions/dm-lens/dist/clients/turn-context.js +48 -0
  724. package/extensions/dm-lens/dist/clients/turn-end/lane.js +1 -0
  725. package/extensions/dm-lens/dist/clients/turn-end/lanes/govulncheck.js +54 -0
  726. package/extensions/dm-lens/dist/clients/turn-end/lanes/secrets.js +131 -0
  727. package/extensions/dm-lens/dist/clients/turn-summary-render.js +56 -0
  728. package/extensions/dm-lens/dist/clients/turn-summary.js +84 -0
  729. package/extensions/dm-lens/dist/clients/typos-config.js +9 -0
  730. package/extensions/dm-lens/dist/clients/user-notify.js +15 -0
  731. package/extensions/dm-lens/dist/clients/vanished-instance-marker.js +18 -0
  732. package/extensions/dm-lens/dist/clients/warm-attach.js +210 -0
  733. package/extensions/dm-lens/dist/clients/widget-state.js +963 -0
  734. package/extensions/dm-lens/dist/clients/word-index-logger.js +21 -0
  735. package/extensions/dm-lens/dist/clients/word-index-store.js +222 -0
  736. package/extensions/dm-lens/dist/clients/word-index.js +1426 -0
  737. package/extensions/dm-lens/dist/clients/workspace-topology.js +261 -0
  738. package/extensions/dm-lens/dist/clients/write-ordering-guard.js +24 -0
  739. package/extensions/dm-lens/dist/clients/zizmor-config.js +160 -0
  740. package/extensions/dm-lens/dist/i18n.js +67 -0
  741. package/extensions/dm-lens/dist/index.js +1782 -0
  742. package/extensions/dm-lens/dist/mcp/analyze-cli.js +178 -0
  743. package/extensions/dm-lens/dist/mcp/build-staleness.js +55 -0
  744. package/extensions/dm-lens/dist/mcp/cli.js +78 -0
  745. package/extensions/dm-lens/dist/mcp/server.js +1208 -0
  746. package/extensions/dm-lens/dist/mcp/worker.js +33 -0
  747. package/extensions/dm-lens/dist/scripts/lib/process-scan.mjs +256 -0
  748. package/extensions/dm-lens/dist/scripts/lib/skills-predicate.mjs +53 -0
  749. package/extensions/dm-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +45 -0
  750. package/extensions/dm-lens/dist/tools/activate-tools.js +61 -0
  751. package/extensions/dm-lens/dist/tools/ast-grep-outline.js +127 -0
  752. package/extensions/dm-lens/dist/tools/ast-grep-replace.js +226 -0
  753. package/extensions/dm-lens/dist/tools/ast-grep-search.js +687 -0
  754. package/extensions/dm-lens/dist/tools/effective-config.js +59 -0
  755. package/extensions/dm-lens/dist/tools/lens-diagnostic-mark.js +240 -0
  756. package/extensions/dm-lens/dist/tools/lens-diagnostics.js +1484 -0
  757. package/extensions/dm-lens/dist/tools/lsp-diagnostics.js +1088 -0
  758. package/extensions/dm-lens/dist/tools/lsp-navigation.js +1194 -0
  759. package/extensions/dm-lens/dist/tools/lsp-structured-output.js +277 -0
  760. package/extensions/dm-lens/dist/tools/module-report.js +332 -0
  761. package/extensions/dm-lens/dist/tools/project-report.js +72 -0
  762. package/extensions/dm-lens/dist/tools/render-compact.js +272 -0
  763. package/extensions/dm-lens/dist/tools/scan-progress.js +31 -0
  764. package/extensions/dm-lens/dist/tools/shared.js +26 -0
  765. package/extensions/dm-lens/dist/tools/symbol-search.js +133 -0
  766. package/extensions/dm-lens/index.js +278 -101
  767. package/extensions/dm-lens/mcp/analyze-cli.js +3 -2
  768. package/extensions/dm-lens/mcp/build-staleness.js +1 -1
  769. package/extensions/dm-lens/mcp/server.js +144 -73
  770. package/extensions/dm-lens/package.json +4 -4
  771. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
  772. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +26 -0
  773. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +10 -0
  774. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unchecked-numeric-parse-python-test.yml +18 -0
  775. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +4 -3
  776. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +2 -2
  777. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-assert-tuple.yml +23 -13
  778. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-boolean-in-except.yml +7 -3
  779. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-console-except-error-js.yml +2 -2
  780. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-console-except-error.yml +2 -2
  781. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +12 -7
  782. package/extensions/dm-lens/rules/ast-grep-rules/rules/unchecked-numeric-parse-python.yml +44 -0
  783. package/extensions/dm-lens/rules/ast-grep-rules/rules/unchecked-throwing-call-python.yml +5 -3
  784. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
  785. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
  786. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
  787. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/console-statement.yml +2 -2
  788. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +23 -7
  789. package/extensions/dm-lens/rules/typos/_typos.toml +4 -2
  790. package/extensions/dm-lens/scripts/lib/process-scan.mjs +1 -1
  791. package/extensions/dm-lens/scripts/lib/skills-predicate.mjs +53 -0
  792. package/extensions/dm-lens/scripts/lib/web-tree-sitter-dir.mjs +45 -0
  793. package/extensions/dm-lens/skills/pi-lens-ast-grep/SKILL.md +23 -6
  794. package/extensions/dm-lens/skills/pi-lens-lsp-navigation/SKILL.md +26 -9
  795. package/extensions/dm-lens/tools/activate-tools.js +10 -7
  796. package/extensions/dm-lens/tools/ast-grep-outline.js +2 -6
  797. package/extensions/dm-lens/tools/ast-grep-replace.js +5 -16
  798. package/extensions/dm-lens/tools/ast-grep-search.js +83 -38
  799. package/extensions/dm-lens/tools/effective-config.js +5 -4
  800. package/extensions/dm-lens/tools/lens-diagnostic-mark.js +5 -3
  801. package/extensions/dm-lens/tools/lens-diagnostics.js +478 -106
  802. package/extensions/dm-lens/tools/lsp-diagnostics.js +317 -172
  803. package/extensions/dm-lens/tools/lsp-navigation.js +26 -56
  804. package/extensions/dm-lens/tools/lsp-structured-output.js +3 -3
  805. package/extensions/dm-lens/tools/module-report.js +5 -5
  806. package/extensions/dm-lens/tools/project-report.js +9 -15
  807. package/extensions/dm-lens/tools/render-compact.js +220 -1
  808. package/extensions/dm-lens/tools/symbol-search.js +3 -5
  809. package/extensions/dm-mcp-adapter/OAUTH.md +368 -2
  810. package/extensions/dm-mcp-adapter/THIRD_PARTY_NOTICES.md +1 -1
  811. package/extensions/dm-mcp-adapter/agent-plugin-loader.js +73 -30
  812. package/extensions/dm-mcp-adapter/agent-plugin-provenance.js +26 -0
  813. package/extensions/dm-mcp-adapter/bearer-command-resolver.js +182 -0
  814. package/extensions/dm-mcp-adapter/claude-plugin-loader.js +350 -0
  815. package/extensions/dm-mcp-adapter/cli.js +82 -5
  816. package/extensions/dm-mcp-adapter/commands.js +89 -15
  817. package/extensions/dm-mcp-adapter/config.js +283 -33
  818. package/extensions/dm-mcp-adapter/consent-manager.js +32 -8
  819. package/extensions/dm-mcp-adapter/direct-tool-surface.js +223 -0
  820. package/extensions/dm-mcp-adapter/direct-tools.js +21 -216
  821. package/extensions/dm-mcp-adapter/dist/abort.js +35 -0
  822. package/extensions/dm-mcp-adapter/dist/agent-plugin-loader.js +73 -30
  823. package/extensions/dm-mcp-adapter/dist/agent-plugin-provenance.js +26 -0
  824. package/extensions/dm-mcp-adapter/dist/bearer-command-resolver.js +182 -0
  825. package/extensions/dm-mcp-adapter/dist/claude-plugin-loader.js +350 -0
  826. package/extensions/dm-mcp-adapter/dist/config.js +283 -33
  827. package/extensions/dm-mcp-adapter/dist/consent-manager.js +84 -0
  828. package/extensions/dm-mcp-adapter/dist/elicitation-handler.js +308 -0
  829. package/extensions/dm-mcp-adapter/dist/errors.js +225 -0
  830. package/extensions/dm-mcp-adapter/dist/http-ca.js +71 -0
  831. package/extensions/dm-mcp-adapter/dist/jev-client.js +359 -0
  832. package/extensions/dm-mcp-adapter/dist/jev-contracts.js +1 -0
  833. package/extensions/dm-mcp-adapter/dist/jev-key-store.js +176 -0
  834. package/extensions/dm-mcp-adapter/dist/json-schema-validator.js +70 -0
  835. package/extensions/dm-mcp-adapter/dist/lifecycle.js +387 -0
  836. package/extensions/dm-mcp-adapter/dist/logger.js +115 -0
  837. package/extensions/dm-mcp-adapter/dist/mcp-auth-fetch.js +86 -0
  838. package/extensions/dm-mcp-adapter/dist/mcp-auth-flow.js +949 -0
  839. package/extensions/dm-mcp-adapter/dist/mcp-auth.js +997 -0
  840. package/extensions/dm-mcp-adapter/dist/mcp-bearer-store.js +7 -136
  841. package/extensions/dm-mcp-adapter/dist/mcp-callback-server.js +381 -0
  842. package/extensions/dm-mcp-adapter/dist/mcp-oauth-provider.js +524 -0
  843. package/extensions/dm-mcp-adapter/dist/mcp-probe.js +151 -0
  844. package/extensions/dm-mcp-adapter/dist/mcp-tasks.js +300 -0
  845. package/extensions/dm-mcp-adapter/dist/mcp-trace.js +215 -0
  846. package/extensions/dm-mcp-adapter/dist/metadata-cache.js +10 -28
  847. package/extensions/dm-mcp-adapter/dist/npx-resolver.js +465 -0
  848. package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +5 -16
  849. package/extensions/dm-mcp-adapter/dist/request-headers-command.js +294 -0
  850. package/extensions/dm-mcp-adapter/dist/runtime-owner.js +94 -0
  851. package/extensions/dm-mcp-adapter/dist/sampling-handler.js +213 -0
  852. package/extensions/dm-mcp-adapter/dist/secure-keyring.js +191 -0
  853. package/extensions/dm-mcp-adapter/dist/server-manager.js +1514 -0
  854. package/extensions/dm-mcp-adapter/dist/session-approvals.js +127 -0
  855. package/extensions/dm-mcp-adapter/dist/session-recovery.js +82 -0
  856. package/extensions/dm-mcp-adapter/dist/state.js +1 -0
  857. package/extensions/dm-mcp-adapter/dist/types.js +39 -0
  858. package/extensions/dm-mcp-adapter/dist/ui-resource-handler.js +204 -0
  859. package/extensions/dm-mcp-adapter/dist/unix-socket-transport.js +83 -0
  860. package/extensions/dm-mcp-adapter/dist/utils.js +84 -9
  861. package/extensions/dm-mcp-adapter/elicitation-handler.js +27 -22
  862. package/extensions/dm-mcp-adapter/host-html-template.js +17 -18
  863. package/extensions/dm-mcp-adapter/http-ca.js +71 -0
  864. package/extensions/dm-mcp-adapter/index.js +904 -167
  865. package/extensions/dm-mcp-adapter/init.js +53 -42
  866. package/extensions/dm-mcp-adapter/jev-client.js +359 -0
  867. package/extensions/dm-mcp-adapter/jev-contracts.js +0 -0
  868. package/extensions/dm-mcp-adapter/jev-key-store.js +176 -0
  869. package/extensions/dm-mcp-adapter/json-schema-validator.js +19 -2
  870. package/extensions/dm-mcp-adapter/lazy-loader.js +7 -0
  871. package/extensions/dm-mcp-adapter/lifecycle.js +8 -3
  872. package/extensions/dm-mcp-adapter/mcp-auth-fetch.js +86 -0
  873. package/extensions/dm-mcp-adapter/mcp-auth-flow.js +228 -75
  874. package/extensions/dm-mcp-adapter/mcp-auth.js +312 -47
  875. package/extensions/dm-mcp-adapter/mcp-bearer-store.js +7 -136
  876. package/extensions/dm-mcp-adapter/mcp-code.js +151 -20
  877. package/extensions/dm-mcp-adapter/mcp-install.js +40 -0
  878. package/extensions/dm-mcp-adapter/mcp-oauth-provider.js +52 -8
  879. package/extensions/dm-mcp-adapter/mcp-output-guard.js +42 -43
  880. package/extensions/dm-mcp-adapter/mcp-panel-theme.js +79 -0
  881. package/extensions/dm-mcp-adapter/mcp-panel.js +294 -286
  882. package/extensions/dm-mcp-adapter/mcp-references.js +13 -18
  883. package/extensions/dm-mcp-adapter/mcp-script-worker.mjs +5 -1
  884. package/extensions/dm-mcp-adapter/mcp-setup-panel.js +317 -282
  885. package/extensions/dm-mcp-adapter/mcp-status.js +2 -0
  886. package/extensions/dm-mcp-adapter/mcp-tasks.js +309 -0
  887. package/extensions/dm-mcp-adapter/metadata-cache.js +11 -28
  888. package/extensions/dm-mcp-adapter/namespace-tools.js +43 -7
  889. package/extensions/dm-mcp-adapter/oauth.js +1 -1
  890. package/extensions/dm-mcp-adapter/package-mcp-loader.js +5 -16
  891. package/extensions/dm-mcp-adapter/package.json +4 -1
  892. package/extensions/dm-mcp-adapter/prompts.js +31 -4
  893. package/extensions/dm-mcp-adapter/proxy-modes.js +394 -199
  894. package/extensions/dm-mcp-adapter/request-headers-command.js +3 -2
  895. package/extensions/dm-mcp-adapter/runtime-owner.js +16 -1
  896. package/extensions/dm-mcp-adapter/sampling-handler.js +16 -25
  897. package/extensions/dm-mcp-adapter/sandbox-proxy-template.js +14 -90
  898. package/extensions/dm-mcp-adapter/search-ranking.js +31 -6
  899. package/extensions/dm-mcp-adapter/secure-keyring.js +191 -0
  900. package/extensions/dm-mcp-adapter/semantic-search.js +160 -0
  901. package/extensions/dm-mcp-adapter/server-manager.js +406 -117
  902. package/extensions/dm-mcp-adapter/session-approvals.js +127 -0
  903. package/extensions/dm-mcp-adapter/skills/mcp-scripting/SKILL.md +11 -1
  904. package/extensions/dm-mcp-adapter/test-runner.mjs +3 -4
  905. package/extensions/dm-mcp-adapter/tool-approval.js +32 -22
  906. package/extensions/dm-mcp-adapter/tool-metadata.js +18 -11
  907. package/extensions/dm-mcp-adapter/tool-registrar.js +7 -4
  908. package/extensions/dm-mcp-adapter/tool-result-renderer.js +4 -2
  909. package/extensions/dm-mcp-adapter/types.js +39 -0
  910. package/extensions/dm-mcp-adapter/ui-server.js +51 -36
  911. package/extensions/dm-mcp-adapter/ui-session.js +57 -25
  912. package/extensions/dm-mcp-adapter/utils.js +84 -9
  913. package/extensions/dm-ponytail/hooks/cursor-hooks.json +17 -0
  914. package/extensions/dm-ponytail/hooks/ponytail-activate.js +14 -2
  915. package/extensions/dm-ponytail/hooks/ponytail-mode-tracker.js +21 -2
  916. package/extensions/dm-ponytail/hooks/ponytail-runtime.js +23 -0
  917. package/extensions/dm-ponytail/package.json +1 -1
  918. package/extensions/dm-subagents/agents/claude-code-writer.md +1 -0
  919. package/extensions/dm-subagents/agents/codex-exec-writer.md +1 -0
  920. package/extensions/dm-subagents/agents/cursor-agent-writer.md +1 -0
  921. package/extensions/dm-subagents/agents/evidence-auditor.md +34 -0
  922. package/extensions/dm-subagents/agents/researcher.md +23 -13
  923. package/extensions/dm-subagents/agents/reviewer.md +6 -4
  924. package/extensions/dm-subagents/agents/scout.md +1 -1
  925. package/extensions/dm-subagents/agents/worker.md +3 -2
  926. package/extensions/dm-subagents/index.js +3 -2
  927. package/extensions/dm-subagents/inspector-runner.mjs +2 -2
  928. package/extensions/dm-subagents/install.mjs +1 -2
  929. package/extensions/dm-subagents/package.json +35 -1
  930. package/extensions/dm-subagents/prompts/council.md +6 -3
  931. package/extensions/dm-subagents/prompts/parallel-review.md +1 -1
  932. package/extensions/dm-subagents/runner-peer-loader.mjs +18 -0
  933. package/extensions/dm-subagents/runner-peer-preload.mjs +29 -0
  934. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +35 -22
  935. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +9 -5
  936. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +40 -19
  937. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +6 -6
  938. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +11 -1
  939. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +35 -30
  940. package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +3 -3
  941. package/extensions/dm-subagents/src/agents/advertised-agent-prompt.js +70 -0
  942. package/extensions/dm-subagents/src/agents/agent-management.js +276 -172
  943. package/extensions/dm-subagents/src/agents/agent-memory.js +92 -3
  944. package/extensions/dm-subagents/src/agents/agent-serializer.js +17 -8
  945. package/extensions/dm-subagents/src/agents/agents.js +389 -207
  946. package/extensions/dm-subagents/src/agents/builtin-names.js +1 -0
  947. package/extensions/dm-subagents/src/agents/chain-serializer.js +7 -0
  948. package/extensions/dm-subagents/src/agents/global-npm-root.js +47 -0
  949. package/extensions/dm-subagents/src/agents/proactive-skills.js +1 -1
  950. package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +17 -13
  951. package/extensions/dm-subagents/src/agents/skills.js +36 -10
  952. package/extensions/dm-subagents/src/api/capability-ceiling.js +0 -1
  953. package/extensions/dm-subagents/src/api/child-tool-plan.js +3 -0
  954. package/extensions/dm-subagents/src/api/preflight.js +75 -64
  955. package/extensions/dm-subagents/src/api/required-child-extensions.js +3 -0
  956. package/extensions/dm-subagents/src/api/workflow-resources.js +1 -0
  957. package/extensions/dm-subagents/src/extension/config.js +27 -18
  958. package/extensions/dm-subagents/src/extension/doctor.js +10 -13
  959. package/extensions/dm-subagents/src/extension/fanout-child.js +91 -14
  960. package/extensions/dm-subagents/src/extension/herdr-dm-bridge.js +258 -0
  961. package/extensions/dm-subagents/src/extension/index.js +202 -66
  962. package/extensions/dm-subagents/src/extension/public-execution.js +55 -4
  963. package/extensions/dm-subagents/src/extension/rpc.js +18 -27
  964. package/extensions/dm-subagents/src/extension/schemas.js +99 -84
  965. package/extensions/dm-subagents/src/extension/subagent-guide.js +14 -3
  966. package/extensions/dm-subagents/src/extension/tool-activation.js +157 -0
  967. package/extensions/dm-subagents/src/extension/tool-description.js +30 -78
  968. package/extensions/dm-subagents/src/inspectors/actions.js +145 -0
  969. package/extensions/dm-subagents/src/inspectors/ghostty/actions.js +60 -0
  970. package/extensions/dm-subagents/src/inspectors/ghostty/plugin.js +17 -0
  971. package/extensions/dm-subagents/src/inspectors/herdr/actions.js +94 -179
  972. package/extensions/dm-subagents/src/inspectors/herdr/plugin.js +13 -0
  973. package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +1 -1
  974. package/extensions/dm-subagents/src/inspectors/{herdr/inspector-runner.js → inspector-runner.js} +31 -25
  975. package/extensions/dm-subagents/src/inspectors/plugins.js +5 -0
  976. package/extensions/dm-subagents/src/inspectors/{herdr/session-roots-codec.js → session-roots-codec.js} +1 -6
  977. package/extensions/dm-subagents/src/inspectors/types.js +1 -0
  978. package/extensions/dm-subagents/src/integrations/dm-web-session-liveness.js +50 -0
  979. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +39 -5
  980. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +256 -151
  981. package/extensions/dm-subagents/src/intercom/result-intercom.js +6 -0
  982. package/extensions/dm-subagents/src/intercom/supervisor-ui.js +199 -0
  983. package/extensions/dm-subagents/src/missions/workflow-state.js +30 -17
  984. package/extensions/dm-subagents/src/policy/authority.js +6 -2
  985. package/extensions/dm-subagents/src/profiles/profiles.js +10 -5
  986. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +28 -35
  987. package/extensions/dm-subagents/src/runs/background/active-run-index.js +17 -0
  988. package/extensions/dm-subagents/src/runs/background/async-execution.js +580 -389
  989. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +71 -47
  990. package/extensions/dm-subagents/src/runs/background/async-resume.js +61 -26
  991. package/extensions/dm-subagents/src/runs/background/async-retention.js +8 -0
  992. package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +3 -4
  993. package/extensions/dm-subagents/src/runs/background/async-status.js +90 -13
  994. package/extensions/dm-subagents/src/runs/background/auto-drain.js +57 -33
  995. package/extensions/dm-subagents/src/runs/background/binary-bootstrap.js +54 -0
  996. package/extensions/dm-subagents/src/runs/background/chain-append.js +1 -1
  997. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +11 -27
  998. package/extensions/dm-subagents/src/runs/background/control-channel.js +105 -256
  999. package/extensions/dm-subagents/src/runs/background/fleet-view.js +67 -10
  1000. package/extensions/dm-subagents/src/runs/background/notify.js +252 -17
  1001. package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +33 -2
  1002. package/extensions/dm-subagents/src/runs/background/process-terminal-candidate.js +88 -0
  1003. package/extensions/dm-subagents/src/runs/background/process-terminal.js +29 -87
  1004. package/extensions/dm-subagents/src/runs/background/result-files.js +8 -4
  1005. package/extensions/dm-subagents/src/runs/background/result-watcher.js +15 -3
  1006. package/extensions/dm-subagents/src/runs/background/retained-children.js +3 -2
  1007. package/extensions/dm-subagents/src/runs/background/retained-nested-route-tracker.js +86 -0
  1008. package/extensions/dm-subagents/src/runs/background/run-child-session.js +574 -0
  1009. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +9 -5
  1010. package/extensions/dm-subagents/src/runs/background/run-status.js +114 -11
  1011. package/extensions/dm-subagents/src/runs/background/runner-aliases.js +129 -0
  1012. package/extensions/dm-subagents/src/runs/background/runner-child-launch.js +62 -0
  1013. package/extensions/dm-subagents/src/runs/background/runner-child-sessions.js +16 -0
  1014. package/extensions/dm-subagents/src/runs/background/runner-http-dispatcher.js +84 -0
  1015. package/extensions/dm-subagents/src/runs/background/runner-startup-failure.js +43 -0
  1016. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +119 -20
  1017. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +33 -10
  1018. package/extensions/dm-subagents/src/runs/background/steering.js +24 -3
  1019. package/extensions/dm-subagents/src/runs/background/subagent-runner-bootstrap.js +238 -0
  1020. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +1008 -1344
  1021. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +156 -26
  1022. package/extensions/dm-subagents/src/runs/background/wait-completions.js +91 -23
  1023. package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +10 -3
  1024. package/extensions/dm-subagents/src/runs/background/wait-tool.js +8 -12
  1025. package/extensions/dm-subagents/src/runs/background/workflow-terminal-proof.js +60 -0
  1026. package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +29 -26
  1027. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +94 -2
  1028. package/extensions/dm-subagents/src/runs/foreground/execution.js +446 -648
  1029. package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +4 -0
  1030. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +5 -2
  1031. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +8 -4
  1032. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +1337 -445
  1033. package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +10 -5
  1034. package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +65 -90
  1035. package/extensions/dm-subagents/src/runs/shared/acceptance.js +265 -68
  1036. package/extensions/dm-subagents/src/runs/shared/agent-contract.js +1 -1
  1037. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +133 -76
  1038. package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +4 -2
  1039. package/extensions/dm-subagents/src/runs/shared/child-hooks.js +166 -0
  1040. package/extensions/dm-subagents/src/runs/shared/child-identity.js +10 -2
  1041. package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +19 -2
  1042. package/extensions/dm-subagents/src/runs/shared/child-launch.js +212 -0
  1043. package/extensions/dm-subagents/src/runs/shared/child-lifecycle.js +22 -0
  1044. package/extensions/dm-subagents/src/runs/shared/child-runtime-config.js +31 -0
  1045. package/extensions/dm-subagents/src/runs/shared/child-session.js +378 -0
  1046. package/extensions/dm-subagents/src/runs/shared/child-tool-plan.js +299 -0
  1047. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +1 -1
  1048. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +148 -32
  1049. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +6 -4
  1050. package/extensions/dm-subagents/src/runs/shared/effective-system-prompt.js +19 -0
  1051. package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +6 -1
  1052. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +14 -2
  1053. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +6 -7
  1054. package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +60 -0
  1055. package/extensions/dm-subagents/src/runs/shared/git-environment.js +25 -0
  1056. package/extensions/dm-subagents/src/runs/shared/herdr-connection.js +341 -0
  1057. package/extensions/dm-subagents/src/runs/shared/herdr-dm-protocol.js +60 -0
  1058. package/extensions/dm-subagents/src/runs/shared/herdr-external-adapters.js +555 -0
  1059. package/extensions/dm-subagents/src/runs/shared/herdr-machine.js +239 -0
  1060. package/extensions/dm-subagents/src/runs/shared/herdr-placed-run.js +987 -0
  1061. package/extensions/dm-subagents/src/runs/shared/host-step-status.js +2 -0
  1062. package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +23 -3
  1063. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +4 -3
  1064. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +15 -5
  1065. package/extensions/dm-subagents/src/runs/shared/model-resolution-diagnostic.js +43 -0
  1066. package/extensions/dm-subagents/src/runs/shared/{model-fallback.js → model-resolution.js} +44 -128
  1067. package/extensions/dm-subagents/src/runs/shared/nested-events.js +39 -49
  1068. package/extensions/dm-subagents/src/runs/shared/nested-path.js +0 -13
  1069. package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +22 -12
  1070. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +78 -2
  1071. package/extensions/dm-subagents/src/runs/shared/permissions.js +1 -16
  1072. package/extensions/dm-subagents/src/runs/shared/process-signal.js +3 -0
  1073. package/extensions/dm-subagents/src/runs/shared/readonly-drain-observation.js +51 -0
  1074. package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +0 -13
  1075. package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +0 -26
  1076. package/extensions/dm-subagents/src/runs/shared/single-output.js +20 -2
  1077. package/extensions/dm-subagents/src/runs/shared/structured-output.js +263 -10
  1078. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +6 -14
  1079. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +117 -370
  1080. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +12 -50
  1081. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +10 -13
  1082. package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +1 -1
  1083. package/extensions/dm-subagents/src/runs/shared/usage-reconciliation.js +69 -0
  1084. package/extensions/dm-subagents/src/runs/shared/workflow-async-child-guidance.js +11 -0
  1085. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +30 -10
  1086. package/extensions/dm-subagents/src/runs/shared/worktree-setup-command.js +195 -0
  1087. package/extensions/dm-subagents/src/runs/shared/worktree.js +814 -141
  1088. package/extensions/dm-subagents/src/shared/atomic-json.js +2 -1
  1089. package/extensions/dm-subagents/src/shared/child-cache-retention.js +19 -0
  1090. package/extensions/dm-subagents/src/shared/fork-context.js +40 -77
  1091. package/extensions/dm-subagents/src/shared/fork-session-cwd.js +24 -0
  1092. package/extensions/dm-subagents/src/shared/jsonl-writer.js +8 -0
  1093. package/extensions/dm-subagents/src/shared/launch-contract.js +37 -6
  1094. package/extensions/dm-subagents/src/shared/model-response-aliases.js +15 -0
  1095. package/extensions/dm-subagents/src/shared/opencode-session-headers.js +15 -0
  1096. package/extensions/dm-subagents/src/shared/pruned-fork.js +83 -76
  1097. package/extensions/dm-subagents/src/shared/required-child-extensions.js +72 -0
  1098. package/extensions/dm-subagents/src/shared/shortcuts.js +0 -2
  1099. package/extensions/dm-subagents/src/shared/thinking-ceiling.js +0 -6
  1100. package/extensions/dm-subagents/src/shared/types.js +16 -12
  1101. package/extensions/dm-subagents/src/shared/utils.js +22 -7
  1102. package/extensions/dm-subagents/src/shared/watch-strategy.js +2 -0
  1103. package/extensions/dm-subagents/src/shared/workflow-child-permit.js +70 -0
  1104. package/extensions/dm-subagents/src/slash/delegation-adapters.js +15 -1
  1105. package/extensions/dm-subagents/src/slash/delegation-request.js +13 -0
  1106. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +28 -1
  1107. package/extensions/dm-subagents/src/slash/prompt-workflows.js +15 -2
  1108. package/extensions/dm-subagents/src/slash/slash-commands.js +12 -269
  1109. package/extensions/dm-subagents/src/slash/subagent-cost.js +255 -0
  1110. package/extensions/dm-subagents/src/slash/subagents-admin.js +49 -25
  1111. package/extensions/dm-subagents/src/tui/fleet-status.js +224 -23
  1112. package/extensions/dm-subagents/src/tui/fleet.js +38 -25
  1113. package/extensions/dm-subagents/src/tui/render.js +636 -63
  1114. package/extensions/dm-subagents/src/watchdog/child-status.js +42 -23
  1115. package/extensions/dm-subagents/src/watchdog/diff-tool.js +86 -0
  1116. package/extensions/dm-subagents/src/watchdog/emission-guard.js +4 -3
  1117. package/extensions/dm-subagents/src/watchdog/guidance.js +19 -0
  1118. package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +1 -1
  1119. package/extensions/dm-subagents/src/watchdog/model-selection.js +18 -1
  1120. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +16 -10
  1121. package/extensions/dm-subagents/src/watchdog/register-child.js +39 -26
  1122. package/extensions/dm-subagents/src/watchdog/register-main.js +51 -43
  1123. package/extensions/dm-subagents/src/watchdog/render.js +5 -7
  1124. package/extensions/dm-subagents/src/watchdog/review.js +142 -67
  1125. package/extensions/dm-subagents/src/watchdog/rules.js +55 -0
  1126. package/extensions/dm-subagents/src/watchdog/runtime.js +167 -109
  1127. package/extensions/dm-subagents/src/watchdog/scope.js +1 -9
  1128. package/extensions/dm-subagents/src/watchdog/settings.js +55 -99
  1129. package/extensions/dm-subagents/src/watchdog/tool-actions.js +11 -12
  1130. package/extensions/dm-subagents/src/watchdog/turn-delta.js +30 -5
  1131. package/extensions/dm-subagents/src/watchdog/types.js +2 -4
  1132. package/extensions/dm-subagents/src/watchdog/warning-format.js +2 -3
  1133. package/extensions/dm-subagents/src/workflows/chat-progress.js +4 -4
  1134. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +482 -36
  1135. package/extensions/dm-subagents/src/workflows/workflow-checklist.js +303 -0
  1136. package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +57 -5
  1137. package/extensions/dm-subagents/src/workflows/workflow-preflight.js +27 -1
  1138. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +51 -3
  1139. package/extensions/dm-subagents/src/workflows/workflow-resources.js +226 -0
  1140. package/extensions/dm-subagents/src/workflows/workflow-settlement.js +5 -0
  1141. package/extensions/dm-web-access/abortable.js +19 -0
  1142. package/extensions/dm-web-access/anysearch.js +4 -13
  1143. package/extensions/dm-web-access/baizhi.js +123 -0
  1144. package/extensions/dm-web-access/bocha.js +3 -24
  1145. package/extensions/dm-web-access/brave.js +3 -23
  1146. package/extensions/dm-web-access/brightdata.js +5 -30
  1147. package/extensions/dm-web-access/content-find.js +181 -47
  1148. package/extensions/dm-web-access/crawl4ai.js +166 -0
  1149. package/extensions/dm-web-access/credential-source.js +1 -0
  1150. package/extensions/dm-web-access/curator-page.js +27 -2
  1151. package/extensions/dm-web-access/curator-run.js +36 -0
  1152. package/extensions/dm-web-access/curator-server.js +11 -2
  1153. package/extensions/dm-web-access/domain-filter-normalization.js +17 -0
  1154. package/extensions/dm-web-access/duckduckgo.js +4 -24
  1155. package/extensions/dm-web-access/extract.js +54 -12
  1156. package/extensions/dm-web-access/fetch-params.js +1 -1
  1157. package/extensions/dm-web-access/firecrawl.js +7 -45
  1158. package/extensions/dm-web-access/gemini-search.js +101 -46
  1159. package/extensions/dm-web-access/github-extract.js +2 -11
  1160. package/extensions/dm-web-access/index.js +382 -247
  1161. package/extensions/dm-web-access/jina-search.js +4 -13
  1162. package/extensions/dm-web-access/kagi.js +4 -13
  1163. package/extensions/dm-web-access/kimi-search.js +5 -30
  1164. package/extensions/dm-web-access/mistral-search.js +251 -0
  1165. package/extensions/dm-web-access/ollama.js +2 -7
  1166. package/extensions/dm-web-access/openai-search.js +204 -46
  1167. package/extensions/dm-web-access/opencode-session-headers.js +15 -0
  1168. package/extensions/dm-web-access/package.json +1 -1
  1169. package/extensions/dm-web-access/page-query.js +14 -4
  1170. package/extensions/dm-web-access/parallel.js +1 -17
  1171. package/extensions/dm-web-access/pdf-extract.js +1 -0
  1172. package/extensions/dm-web-access/perplexity.js +10 -1
  1173. package/extensions/dm-web-access/querit.js +5 -34
  1174. package/extensions/dm-web-access/query-rewrite.js +6 -2
  1175. package/extensions/dm-web-access/search-answer-formatting.js +6 -0
  1176. package/extensions/dm-web-access/search-result-count-normalization.js +5 -0
  1177. package/extensions/dm-web-access/search1api.js +5 -34
  1178. package/extensions/dm-web-access/searchinfinity.js +5 -34
  1179. package/extensions/dm-web-access/searxng.js +3 -23
  1180. package/extensions/dm-web-access/serpapi.js +183 -0
  1181. package/extensions/dm-web-access/serpbase.js +3 -24
  1182. package/extensions/dm-web-access/serpdive.js +3 -23
  1183. package/extensions/dm-web-access/serper.js +5 -30
  1184. package/extensions/dm-web-access/serply.js +184 -0
  1185. package/extensions/dm-web-access/source-check.js +10 -46
  1186. package/extensions/dm-web-access/ssrf-protection.js +3 -1
  1187. package/extensions/dm-web-access/storage.js +9 -0
  1188. package/extensions/dm-web-access/summary-review.js +36 -25
  1189. package/extensions/dm-web-access/tavily.js +3 -23
  1190. package/extensions/dm-web-access/tinyfish.js +5 -34
  1191. package/extensions/dm-web-access/tool-activation.js +112 -0
  1192. package/extensions/dm-web-access/utils.js +27 -10
  1193. package/extensions/dm-web-access/valyu.js +5 -30
  1194. package/extensions/dm-web-access/xai-search.js +78 -42
  1195. package/extensions/dm-web-access/xcrawl.js +5 -30
  1196. package/package.json +7 -4
  1197. package/extensions/dm-lens/tools/ast-dump.js +0 -101
  1198. package/extensions/dm-subagents/src/api/dm-args.js +0 -3
  1199. package/extensions/dm-subagents/src/runs/shared/child-protocol.js +0 -447
  1200. package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +0 -40
  1201. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +0 -173
  1202. package/extensions/dm-subagents/src/runs/shared/dm-args.js +0 -581
  1203. package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +0 -190
  1204. package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +0 -207
  1205. package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +0 -50
  1206. package/extensions/dm-subagents/src/runs/shared/task-intent.js +0 -130
  1207. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +0 -68
  1208. /package/extensions/dm-subagents/src/inspectors/{herdr/shell-command.js → shell-command.js} +0 -0
@@ -1,8 +1,9 @@
1
- import { spawn, spawnSync } from "node:child_process";
2
- import { randomUUID } from "node:crypto";
1
+ import { spawnSync } from "node:child_process";
3
2
  import * as fs from "node:fs";
4
3
  import * as path from "node:path";
4
+ import { performance } from "node:perf_hooks";
5
5
  import { pathToFileURL } from "node:url";
6
+ import { installRunnerHttpDispatcher } from "./runner-http-dispatcher.js";
6
7
  import { writeAtomicJson } from "../../shared/atomic-json.js";
7
8
  import { writeAsyncResultFile, writePendingAsyncResultFile } from "./result-files.js";
8
9
  import { createFileCoalescer } from "../../shared/file-coalescer.js";
@@ -10,16 +11,16 @@ import { createCapacityResilientJsonWriter } from "../../shared/capacity-resilie
10
11
  import { isStorageCapacityError } from "../../shared/file-system-retry.js";
11
12
  import { updateActiveRunIndex } from "./active-run-index.js";
12
13
  import { createChildTranscriptWriter } from "../../shared/child-transcript.js";
13
- import { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, enqueueStepSteer, steerAcksDir, steerCapabilityPath, stepSteerInboxDir, watchAsyncControlInbox } from "./control-channel.js";
14
+ import { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, consumeStopRequestPayloads, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, watchAsyncControlInbox } from "./control-channel.js";
14
15
  import { appendJsonl as appendRawJsonl, formatOutputArtifactContent, getArtifactPaths, writeArtifact, writeMetadata } from "../../shared/artifacts.js";
15
- import { DM_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from "../shared/dm-spawn.js";
16
+ import { DM_CODING_AGENT_PACKAGE, resolveInstalledPiPackageRoot } from "../shared/dm-spawn.js";
16
17
  import { preflightLaunchCwd } from "../shared/launch-cwd.js";
17
18
  import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, injectSingleOutputInstruction, resolveSingleOutput } from "../shared/single-output.js";
19
+ import { runSetupCommand } from "../shared/worktree-setup-command.js";
18
20
  import {
19
21
  DEFAULT_MAX_OUTPUT,
20
22
  SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
21
- truncateOutput,
22
- getSubagentDepthEnv
23
+ truncateOutput
23
24
  } from "../../shared/types.js";
24
25
  import {
25
26
  DEFAULT_CONTROL_CONFIG,
@@ -40,33 +41,27 @@ import {
40
41
  DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
41
42
  Semaphore
42
43
  } from "../shared/parallel-utils.js";
43
- import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, deriveForkPromptCacheKey, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/dm-args.js";
44
+ import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/child-tool-plan.js";
45
+ import { buildRunnerChildLaunch } from "./runner-child-launch.js";
46
+ import { normalizeExtensionBindings } from "../shared/extension-bindings.js";
47
+ import { runChildSession } from "./run-child-session.js";
48
+ import { loadRunnerChildSessionFactory } from "./runner-child-sessions.js";
49
+ import { SUBAGENT_CHILD_ENV } from "../shared/child-runtime-config.js";
44
50
  import { deriveChildSessionName } from "../../shared/child-session-name.js";
45
- import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.js";
51
+ import { alignForkedSessionCwd } from "../../shared/fork-session-cwd.js";
46
52
  import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.js";
47
- import { createStructuredOutputRuntime, MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.js";
48
- import { formatMidToolExitError, formatProcessSignalError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.js";
49
- import { readChildToolDiagnosticError } from "../shared/tool-availability.js";
53
+ import { clearStructuredOutputCaptures, createStructuredOutputFileCapture, createStructuredOutputRuntime, formatStructuredOutputRejectionError, MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.js";
54
+ import { formatMidToolExitError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.js";
55
+ import { formatChildToolDiagnostic } from "../shared/tool-availability.js";
50
56
  import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTrackedMutations } from "../shared/mutation-evidence.js";
51
57
  import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.js";
52
58
  import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.js";
53
59
  import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.js";
54
- import { formatModelAttemptNote, formatSubagentModelVerificationError, isContextOverflow, isRetryableModelFailureAttempt, recordRetryableModelFailure } from "../shared/model-fallback.js";
55
- import {
56
- SUBAGENT_STARTUP_RETRY_DELAYS_MS,
57
- formatSubagentExtensionConflictError,
58
- formatSubagentStartupRetryExhaustedError,
59
- formatSubagentStartupRetryNote,
60
- isRetryableSubagentStartupFailure,
61
- waitForSubagentStartupRetry
62
- } from "../shared/subagent-startup-retry.js";
63
- import { markProcessTerminalCandidateLeaseRelease, writeProcessTerminalCandidate } from "./process-terminal.js";
64
- import { createOwnedProcessTreeController } from "./owned-process-tree.js";
65
- import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.js";
66
- import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.js";
67
- import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.js";
68
- import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.js";
69
- import { planCompletionEvidence, projectSettlementDiagnostic } from "../shared/completion-evidence.js";
60
+ import { isContextOverflow } from "../shared/model-resolution.js";
61
+ import { processTerminalPath, writeProcessTerminalCandidate } from "./process-terminal.js";
62
+ import { persistRunnerStartupFailure } from "./runner-startup-failure.js";
63
+ import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, unconsumedSteerReason, updateSteeringTarget } from "./steering.js";
64
+ import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getAgentDir, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.js";
70
65
  import { planAbortRecovery } from "../shared/abort-recovery.js";
71
66
  import {
72
67
  createMutatingFailureState,
@@ -83,46 +78,46 @@ import { parseSessionTokens } from "../../shared/session-tokens.js";
83
78
  import {
84
79
  cleanupWorktrees,
85
80
  createWorktrees,
81
+ withWorktreeTransaction,
82
+ WorktreeSetupError,
86
83
  diffWorktrees,
87
84
  findWorktreeTaskCwdConflict,
88
85
  formatWorktreeDiffSummary,
89
- formatWorktreeTaskCwdConflict
86
+ formatWorktreeTaskCwdConflict,
87
+ WORKTREE_AGENT_CWD_PLACEHOLDER
90
88
  } from "../shared/worktree.js";
91
89
  import { findModelInfo, resolveEffectiveThinking } from "../../shared/model-info.js";
92
- import { assertThinkingWithinCeiling, decodeThinkingCeiling, SUBAGENT_THINKING_CEILING_ENV } from "../../shared/thinking-ceiling.js";
93
- import { launchBindingDigest } from "../../shared/launch-contract.js";
90
+ import { assertThinkingWithinCeiling } from "../../shared/thinking-ceiling.js";
91
+ import { resolveLaunchBinding } from "../../shared/launch-contract.js";
94
92
  import { writeInitialProgressFile } from "../../shared/settings.js";
95
93
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.js";
96
- import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.js";
97
- import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.js";
94
+ import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, captureStagedIndexBaseline, evaluateAcceptance, formatAcceptancePrompt, resolveAcceptanceReportMode, resolveEffectiveAcceptance, stripAcceptanceReport, typedVerifyOutput } from "../shared/acceptance.js";
95
+ import { attachContractProjections, isAgentContract } from "../shared/agent-contract.js";
98
96
  import { waitForImportedAsyncRoot } from "./chain-root-attachment.js";
99
- import { normalizeExtensionBindings } from "../shared/extension-bindings.js";
100
97
  import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.js";
101
98
  import { asyncStatusChildIdentity } from "../shared/child-identity.js";
102
99
  import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.js";
103
- import { effectiveToolTimeoutMs, formatToolTimeoutMessage, toolTimeoutCallKey } from "../shared/tool-timeout.js";
100
+ import { toolTimeoutCallKey } from "../shared/tool-timeout.js";
104
101
  import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.js";
105
- import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writePendingParallelHandoff } from "../shared/parallel-handoff.js";
102
+ import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.js";
106
103
  import { resolveWatchdogConfig } from "../../watchdog/settings.js";
107
- import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, PI_AGGREGATE_EVENT_PROJECTOR, projectChildLifecycle } from "../shared/child-protocol.js";
108
- import { acquireSessionLease } from "../shared/session-lease.js";
109
104
  import { buildExternalCliPrompt, runExternalCli } from "../shared/external-cli-runner.js";
110
105
  import { resolveClaudeCodeLaunch } from "../shared/claude-code-adapter.js";
111
106
  import { resolveCodexExecLaunch } from "../shared/codex-exec-adapter.js";
112
107
  import { resolveCursorAgentLaunch } from "../shared/cursor-agent-adapter.js";
113
108
  import { resolveExternalCliRunnerStatus } from "../shared/external-cli-contract.js";
109
+ import { formatHerdrMachineHint, prepareHerdrMachineExternalCliRun } from "../shared/herdr-machine.js";
110
+ import { HerdrExternalNeedsAttentionError, createHerdrExternalAdapter, prepareInternalHerdrExternalAdapter } from "../shared/herdr-external-adapters.js";
114
111
  import { runExternalJob } from "../shared/external-job-runner.js";
115
112
  import { createOrcaProgressTab } from "../shared/orca-progress-tabs.js";
116
- import { decodeSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.js";
117
113
  import {
118
- CHILD_WATCHDOG_CONFIG_ENV,
119
114
  acceptChildWatchdogEvent,
120
- childWatchdogIsActive,
121
- decodeChildWatchdogConfig,
115
+ applyChildWatchdogMessage,
122
116
  isChildWatchdogStatusEvent,
123
117
  resolveChildWatchdogConfig
124
118
  } from "../../watchdog/child-status.js";
125
119
  const INTERCOM_DETACH_RECEIPT = "Detached for intercom coordination before task completion.";
120
+ process.env[SUBAGENT_CHILD_ENV] = "1";
126
121
  function persistStepArtifacts(input) {
127
122
  const errors = {};
128
123
  if (input.artifactConfig?.includeOutput !== false) {
@@ -205,9 +200,6 @@ function appendDiagnosticJsonl(filePath, line, droppedEventType) {
205
200
  }
206
201
  state.diagnosticsTruncated = true;
207
202
  }
208
- function shouldPersistChildEvent(event) {
209
- return event.type !== "message_update";
210
- }
211
203
  function isBlockingSupervisorTool(toolName, args) {
212
204
  if (!args || typeof args !== "object" || Array.isArray(args))
213
205
  return false;
@@ -231,47 +223,18 @@ function findLatestSessionFile(sessionDir) {
231
223
  function emptyUsage() {
232
224
  return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
233
225
  }
234
- function tokenUsageFromAttempts(attempts) {
235
- if (!attempts || attempts.length === 0)
236
- return null;
237
- let input = 0;
238
- let output = 0;
239
- for (const attempt of attempts) {
240
- input += attempt.usage?.input ?? 0;
241
- output += attempt.usage?.output ?? 0;
242
- }
226
+ function tokenUsageFromUsage(usage) {
227
+ const input = usage?.input ?? 0;
228
+ const output = usage?.output ?? 0;
243
229
  const total = input + output;
244
230
  return total > 0 ? { input, output, total } : null;
245
231
  }
246
- function costSummaryFromAttempts(attempts) {
247
- if (!attempts || attempts.length === 0)
248
- return;
249
- let inputTokens = 0;
250
- let outputTokens = 0;
251
- let costUsd = 0;
252
- for (const attempt of attempts) {
253
- inputTokens += attempt.usage?.input ?? 0;
254
- outputTokens += attempt.usage?.output ?? 0;
255
- costUsd += attempt.usage?.cost ?? 0;
256
- }
232
+ function costSummaryFromUsage(usage) {
233
+ const inputTokens = usage?.input ?? 0;
234
+ const outputTokens = usage?.output ?? 0;
235
+ const costUsd = usage?.cost ?? 0;
257
236
  return inputTokens > 0 || outputTokens > 0 || costUsd > 0 ? { inputTokens, outputTokens, costUsd } : undefined;
258
237
  }
259
- function usageFromAttempts(attempts) {
260
- if (!attempts || attempts.length === 0)
261
- return;
262
- const usage = emptyUsage();
263
- for (const attempt of attempts) {
264
- if (!attempt.usage)
265
- continue;
266
- usage.input += attempt.usage.input;
267
- usage.output += attempt.usage.output;
268
- usage.cacheRead += attempt.usage.cacheRead;
269
- usage.cacheWrite += attempt.usage.cacheWrite;
270
- usage.cost += attempt.usage.cost;
271
- usage.turns += attempt.usage.turns;
272
- }
273
- return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0 ? usage : undefined;
274
- }
275
238
  function appendRecentStepOutput(step, lines) {
276
239
  const nonEmpty = lines.filter((line) => line.trim());
277
240
  if (nonEmpty.length === 0)
@@ -282,12 +245,6 @@ function appendRecentStepOutput(step, lines) {
282
245
  step.recentOutput.splice(0, step.recentOutput.length - 50);
283
246
  }
284
247
  }
285
- function assistantStartsToolCall(message) {
286
- return Array.isArray(message.content) && message.content.some((part) => part.type === "toolCall");
287
- }
288
- function isTerminalAssistantStop(message) {
289
- return message.stopReason === "stop" && !assistantStartsToolCall(message);
290
- }
291
248
  function omitUndefinedProperties(value) {
292
249
  for (const key in value) {
293
250
  if (value[key] === undefined)
@@ -338,549 +295,6 @@ function formatChildFailureDiagnostic(input) {
338
295
  return `${baseError.slice(0, Math.max(0, errorLimit))}${context ? `
339
296
  ${context}` : ""}`;
340
297
  }
341
- function runPiStreaming(args, cwd, outputFile, env, piPackageRoot, piArgv1, maxSubagentDepth, childEventContext, registerInterrupt, onChildEvent, transcriptWriter, registerTimeout, timeoutMessage, registerStop, stopMessage, onWriterProcess, toolTimeoutMs, runDeadlineAt, orcaProgressTab, expectedModelForVerification, modelVerificationRegistry, mutationTools) {
342
- return new Promise((resolve) => {
343
- const startedAt = Date.now();
344
- const processInstanceId = randomUUID();
345
- onWriterProcess?.({ state: "spawning" });
346
- const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
347
- const spawnEnv = { ...process.env, ...env ?? {}, ...getSubagentDepthEnv(maxSubagentDepth) };
348
- const spawnSpec = getPiSpawnCommand(args, {
349
- ...piPackageRoot ? { piPackageRoot } : {},
350
- ...piArgv1 ? { argv1: piArgv1 } : {}
351
- });
352
- const child = spawn(spawnSpec.command, spawnSpec.args, {
353
- cwd,
354
- stdio: ["ignore", "pipe", "pipe"],
355
- env: spawnEnv,
356
- windowsHide: true,
357
- detached: process.platform !== "win32"
358
- });
359
- let processTreeController;
360
- const stderrTail = createBoundedByteTail();
361
- const rawStdoutTail = createBoundedByteTail();
362
- const messages = [];
363
- const usage = emptyUsage();
364
- let model;
365
- let writerRegistrationError;
366
- if (typeof child.pid === "number") {
367
- processTreeController = createOwnedProcessTreeController(child.pid);
368
- try {
369
- onWriterProcess?.({ state: "running", pid: child.pid });
370
- } catch (writerError) {
371
- writerRegistrationError = `Failed to record revived DM writer ownership: ${writerError instanceof Error ? writerError.message : String(writerError)}`;
372
- trySignalChild(child, "SIGKILL");
373
- }
374
- }
375
- let error = writerRegistrationError;
376
- let assistantError;
377
- let interrupted = false;
378
- let timedOut = false;
379
- let stopped = false;
380
- let observedMutationAttempt = false;
381
- let structuredOutputToolInvoked = false;
382
- let structuredOutputMessageStartIndex;
383
- let currentTool;
384
- let currentToolArgs;
385
- let currentPath;
386
- let toolCount = 0;
387
- let activeToolSequence = 0;
388
- const activeToolCalls = new Map;
389
- const activeToolKeysByName = new Map;
390
- const refreshCurrentTool = () => {
391
- const active = [...activeToolCalls.values()].at(-1);
392
- currentTool = active?.tool;
393
- currentToolArgs = active?.args;
394
- currentPath = active?.path;
395
- };
396
- const recordActiveToolCall = (event) => {
397
- const key = toolTimeoutCallKey(event, ++activeToolSequence);
398
- const active = omitUndefinedProperties({
399
- key,
400
- tool: event.toolName,
401
- args: extractToolArgsPreview(event.args ?? {}),
402
- path: resolveCurrentPath(event.toolName, event.args)
403
- });
404
- activeToolCalls.set(key, active);
405
- const keys = activeToolKeysByName.get(active.tool) ?? [];
406
- keys.push(key);
407
- activeToolKeysByName.set(active.tool, keys);
408
- refreshCurrentTool();
409
- };
410
- const removeActiveToolCall = (event) => {
411
- const key = typeof event.toolCallId === "string" && event.toolCallId.length > 0 ? `id:${event.toolCallId}` : typeof event.toolName === "string" ? activeToolKeysByName.get(event.toolName)?.[0] : activeToolCalls.size === 1 ? [...activeToolCalls.keys()][0] : undefined;
412
- if (!key)
413
- return;
414
- const active = activeToolCalls.get(key);
415
- if (!active)
416
- return;
417
- activeToolCalls.delete(key);
418
- const keys = activeToolKeysByName.get(active.tool)?.filter((candidate) => candidate !== key) ?? [];
419
- if (keys.length > 0)
420
- activeToolKeysByName.set(active.tool, keys);
421
- else
422
- activeToolKeysByName.delete(active.tool);
423
- refreshCurrentTool();
424
- };
425
- const childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);
426
- let childWatchdogState;
427
- const childLifecycleState = { compactionRetryActive: false };
428
- let applyChildLifecycle = (_action) => {};
429
- const updateChildWatchdogState = (snapshot) => {
430
- childWatchdogState = snapshot;
431
- };
432
- const writeOutputLine = (line) => {
433
- if (!line.trim())
434
- return;
435
- outputStream.write(`${line}
436
- `);
437
- orcaProgressTab?.append(`${line}
438
- `);
439
- };
440
- const writeOutputText = (text) => {
441
- for (const line of text.split(`
442
- `)) {
443
- writeOutputLine(line);
444
- }
445
- };
446
- const appendChildEvent = (event) => {
447
- if (!childEventContext)
448
- return;
449
- if (!shouldPersistChildEvent(event))
450
- return;
451
- appendDiagnosticJsonl(childEventContext.eventsPath, JSON.stringify({
452
- ...event,
453
- subagentSource: "child",
454
- subagentRunId: childEventContext.runId,
455
- subagentStepIndex: childEventContext.stepIndex,
456
- subagentAgent: childEventContext.agent,
457
- observedAt: Date.now()
458
- }), typeof event.type === "string" ? event.type : undefined);
459
- };
460
- const appendChildLine = (type, line) => {
461
- appendChildEvent({ type, line });
462
- if (type === "subagent.child.stdout")
463
- transcriptWriter?.writeStdoutLine(line);
464
- else
465
- transcriptWriter?.writeStderrLine(line);
466
- };
467
- const processStdoutLine = (line) => {
468
- if (!line.trim())
469
- return;
470
- let event;
471
- try {
472
- event = JSON.parse(line);
473
- } catch {
474
- rawStdoutTail.push(`${line}
475
- `);
476
- writeOutputLine(line);
477
- appendChildLine("subagent.child.stdout", line);
478
- return;
479
- }
480
- appendChildEvent(event);
481
- transcriptWriter?.writeChildEvent(event);
482
- if (event.type === "compaction_start")
483
- compactionStartedReceived = true;
484
- if (event.type === "compaction_end" && event.willRetry === true) {
485
- compactionStartedReceived = false;
486
- afterCompactionSettlement = false;
487
- }
488
- if (event.type === "agent_start" || event.type === "auto_retry_start") {
489
- compactionStartedReceived = false;
490
- afterCompactionSettlement = false;
491
- }
492
- const lifecycleAction = projectChildLifecycle(event, false, childLifecycleState);
493
- if (event.type === "agent_settled" && lifecycleAction === "start-drain") {
494
- agentSettledReceived = true;
495
- afterCompactionSettlement = compactionStartedReceived;
496
- }
497
- applyChildLifecycle(lifecycleAction);
498
- if (isChildWatchdogStatusEvent(event)) {
499
- if (!childWatchdogConfig)
500
- return;
501
- const next = acceptChildWatchdogEvent({
502
- current: childWatchdogState,
503
- event,
504
- ...childEventContext ? {
505
- runId: childEventContext.runId,
506
- agent: childEventContext.agent,
507
- childIndex: childEventContext.stepIndex
508
- } : {}
509
- });
510
- if (!next)
511
- return;
512
- updateChildWatchdogState(next);
513
- onChildEvent?.(event);
514
- if (childWatchdogIsActive(next)) {
515
- if (finalDrainTimer) {
516
- clearTimeout(finalDrainTimer);
517
- finalDrainTimer = undefined;
518
- }
519
- if (finalHardKillTimer) {
520
- clearTimeout(finalHardKillTimer);
521
- finalHardKillTimer = undefined;
522
- }
523
- armWatchdogTail();
524
- } else {
525
- clearWatchdogTailTimer();
526
- if (cleanTerminalAssistantStopReceived || agentSettledReceived)
527
- startFinalDrain();
528
- }
529
- return;
530
- }
531
- onChildEvent?.(event);
532
- if (event.type === "tool_execution_end") {
533
- clearActiveToolTimeout(event);
534
- removeActiveToolCall(event);
535
- return;
536
- }
537
- if (event.type === "tool_execution_start" && event.toolName) {
538
- toolCount += 1;
539
- armToolTimeout({ toolCallId: event.toolCallId, toolName: event.toolName });
540
- recordActiveToolCall({ toolCallId: event.toolCallId, toolName: event.toolName, args: event.args });
541
- if (event.toolName === "structured_output") {
542
- structuredOutputToolInvoked = true;
543
- structuredOutputMessageStartIndex = messages.length;
544
- }
545
- observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args, mutationTools);
546
- const toolArgs = extractToolArgsPreview(event.args ?? {});
547
- writeOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);
548
- return;
549
- }
550
- if ((event.type === "message_end" || event.type === "tool_result_end") && event.message) {
551
- if (event.type === "tool_result_end") {
552
- clearActiveToolTimeout(event);
553
- removeActiveToolCall({
554
- toolCallId: event.message.toolCallId ?? event.toolCallId,
555
- toolName: event.message.toolName ?? event.toolName
556
- });
557
- }
558
- messages.push(event.message);
559
- const text = extractTextFromContent(event.message.content);
560
- if (text)
561
- writeOutputText(text);
562
- if (event.type !== "message_end" || event.message.role !== "assistant")
563
- return;
564
- const hasToolCall = assistantStartsToolCall(event.message);
565
- if (event.message.model) {
566
- model = event.message.model;
567
- if (expectedModelForVerification && !hasToolCall) {
568
- const modelVerificationError = formatSubagentModelVerificationError(expectedModelForVerification, event.message.model, modelVerificationRegistry);
569
- if (modelVerificationError && !error)
570
- error = modelVerificationError;
571
- }
572
- }
573
- if (event.message.errorMessage)
574
- assistantError = event.message.errorMessage;
575
- const eventUsage = event.message.usage;
576
- if (eventUsage) {
577
- usage.turns++;
578
- usage.input += eventUsage.input ?? eventUsage.inputTokens ?? 0;
579
- usage.output += eventUsage.output ?? eventUsage.outputTokens ?? 0;
580
- usage.cacheRead += eventUsage.cacheRead ?? 0;
581
- usage.cacheWrite += eventUsage.cacheWrite ?? 0;
582
- usage.cost += eventUsage.cost?.total ?? 0;
583
- }
584
- if (isTerminalAssistantStop(event.message)) {
585
- if (!event.message.errorMessage && extractTextFromContent(event.message.content).trim())
586
- assistantError = undefined;
587
- cleanTerminalAssistantStopReceived ||= !event.message.errorMessage;
588
- clearAllToolTimeouts();
589
- activeToolCalls.clear();
590
- activeToolKeysByName.clear();
591
- refreshCurrentTool();
592
- applyChildLifecycle(projectChildLifecycle(event, true, childLifecycleState));
593
- }
594
- }
595
- };
596
- const FINAL_STOP_GRACE_MS = 1000;
597
- const HARD_KILL_MS = 3000;
598
- let childExited = false;
599
- let forcedTerminationSignal = false;
600
- let cleanTerminalAssistantStopReceived = false;
601
- let agentSettledReceived = false;
602
- let compactionStartedReceived = false;
603
- let afterCompactionSettlement = false;
604
- let finalDrainTimer;
605
- let finalHardKillTimer;
606
- let watchdogTailTimer;
607
- let protocolHardKillTimer;
608
- let protocolError;
609
- let settled = false;
610
- applyChildLifecycle = (action) => {
611
- if (action === "cancel-drain") {
612
- if (finalDrainTimer) {
613
- clearTimeout(finalDrainTimer);
614
- finalDrainTimer = undefined;
615
- }
616
- if (finalHardKillTimer) {
617
- clearTimeout(finalHardKillTimer);
618
- finalHardKillTimer = undefined;
619
- }
620
- clearWatchdogTailTimer();
621
- return;
622
- }
623
- if (action === "start-drain")
624
- startFinalDrain();
625
- };
626
- const failProtocol = (limit) => {
627
- if (protocolError)
628
- return;
629
- protocolError = limit;
630
- error = formatProtocolOutputLimit(limit);
631
- if (!childExited) {
632
- trySignalChild(child, "SIGTERM");
633
- protocolHardKillTimer = setTimeout(() => {
634
- if (!settled)
635
- trySignalChild(child, "SIGKILL");
636
- }, 3000);
637
- protocolHardKillTimer.unref?.();
638
- }
639
- };
640
- const stdoutReader = createBoundedLineReader({
641
- oversizedLineProjector: PI_AGGREGATE_EVENT_PROJECTOR,
642
- onLine: processStdoutLine,
643
- onLimit: failProtocol
644
- });
645
- const stderrReader = createBoundedLineReader({
646
- stream: "stderr",
647
- maxPendingLineBytes: MAX_CHILD_STDERR_BYTES,
648
- onLine: (line) => appendChildLine("subagent.child.stderr", line),
649
- onLimit: (limit) => appendChildLine("subagent.child.stderr", formatProtocolOutputLimit(limit))
650
- });
651
- const clearStdioGuard = attachPostExitStdioGuard(child, { idleMs: 2000, hardMs: 8000 });
652
- child.stdout.on("data", (chunk) => stdoutReader.push(chunk));
653
- child.stderr.on("data", (chunk) => {
654
- stderrTail.push(chunk);
655
- stderrReader.push(chunk);
656
- outputStream.write(chunk);
657
- orcaProgressTab?.append(chunk.toString("utf-8"));
658
- });
659
- registerInterrupt?.(() => {
660
- if (settled || timedOut || stopped)
661
- return;
662
- interrupted = true;
663
- if (!error)
664
- error = "Interrupted. Waiting for explicit next action.";
665
- trySignalChild(child, "SIGINT");
666
- setTimeout(() => {
667
- if (!settled && !timedOut && !stopped)
668
- trySignalChild(child, "SIGTERM");
669
- }, 1000).unref?.();
670
- });
671
- const terminateForTimeout = (message) => {
672
- if (settled || timedOut || stopped)
673
- return;
674
- timedOut = true;
675
- timeoutMessage = message;
676
- interrupted = false;
677
- error = message;
678
- if (processTreeController)
679
- processTreeController.terminate();
680
- else
681
- trySignalChild(child, "SIGTERM");
682
- };
683
- let toolTimeoutSequence = 0;
684
- const activeToolTimeouts = new Map;
685
- const activeToolTimeoutKeysByName = new Map;
686
- const removeToolTimeoutKey = (key) => {
687
- const active = activeToolTimeouts.get(key);
688
- if (!active)
689
- return;
690
- clearTimeout(active.timer);
691
- activeToolTimeouts.delete(key);
692
- const keys = activeToolTimeoutKeysByName.get(active.toolName)?.filter((candidate) => candidate !== key) ?? [];
693
- if (keys.length > 0)
694
- activeToolTimeoutKeysByName.set(active.toolName, keys);
695
- else
696
- activeToolTimeoutKeysByName.delete(active.toolName);
697
- };
698
- const clearActiveToolTimeout = (event) => {
699
- const key = typeof event.toolCallId === "string" && event.toolCallId.length > 0 ? `id:${event.toolCallId}` : typeof event.toolName === "string" ? activeToolTimeoutKeysByName.get(event.toolName)?.[0] : activeToolTimeouts.size === 1 ? [...activeToolTimeouts.keys()][0] : undefined;
700
- if (key)
701
- removeToolTimeoutKey(key);
702
- };
703
- const clearAllToolTimeouts = () => {
704
- for (const key of [...activeToolTimeouts.keys()])
705
- removeToolTimeoutKey(key);
706
- };
707
- const armToolTimeout = (event) => {
708
- const timeoutForTool = effectiveToolTimeoutMs(event.toolName, toolTimeoutMs);
709
- if (timeoutForTool === undefined)
710
- return;
711
- const runRemaining = runDeadlineAt === undefined ? undefined : Math.max(0, runDeadlineAt - Date.now());
712
- if (runRemaining !== undefined && timeoutForTool >= runRemaining)
713
- return;
714
- const key = toolTimeoutCallKey(event, ++toolTimeoutSequence);
715
- const toolName = event.toolName;
716
- const timer = setTimeout(() => {
717
- removeToolTimeoutKey(key);
718
- terminateForTimeout(formatToolTimeoutMessage(toolName, timeoutForTool));
719
- }, timeoutForTool);
720
- timer.unref?.();
721
- activeToolTimeouts.set(key, { toolName, timer });
722
- const keys = activeToolTimeoutKeysByName.get(toolName) ?? [];
723
- keys.push(key);
724
- activeToolTimeoutKeysByName.set(toolName, keys);
725
- };
726
- registerTimeout?.(() => terminateForTimeout(timeoutMessage ?? "Subagent timed out."));
727
- registerStop?.(() => {
728
- if (settled || timedOut || stopped)
729
- return;
730
- stopped = true;
731
- interrupted = false;
732
- error = stopMessage ?? "Subagent stopped by user.";
733
- if (processTreeController)
734
- processTreeController.terminate();
735
- else
736
- trySignalChild(child, "SIGTERM");
737
- });
738
- const clearDrainTimers = () => {
739
- clearAllToolTimeouts();
740
- if (finalDrainTimer) {
741
- clearTimeout(finalDrainTimer);
742
- finalDrainTimer = undefined;
743
- }
744
- if (finalHardKillTimer) {
745
- clearTimeout(finalHardKillTimer);
746
- finalHardKillTimer = undefined;
747
- }
748
- clearWatchdogTailTimer();
749
- if (protocolHardKillTimer) {
750
- clearTimeout(protocolHardKillTimer);
751
- protocolHardKillTimer = undefined;
752
- }
753
- };
754
- function startFinalDrain() {
755
- if (childWatchdogIsActive(childWatchdogState)) {
756
- armWatchdogTail();
757
- return;
758
- }
759
- if (childExited || finalDrainTimer || settled)
760
- return;
761
- finalDrainTimer = setTimeout(() => {
762
- if (settled)
763
- return;
764
- const termSent = trySignalChild(child, "SIGTERM");
765
- if (!termSent)
766
- return;
767
- forcedTerminationSignal = true;
768
- if (!cleanTerminalAssistantStopReceived && !agentSettledReceived && !error && !assistantError) {
769
- error = `Subagent process did not exit within ${FINAL_STOP_GRACE_MS}ms after its terminal event. Forcing termination.`;
770
- }
771
- finalHardKillTimer = setTimeout(() => {
772
- if (settled)
773
- return;
774
- forcedTerminationSignal = trySignalChild(child, "SIGKILL") || forcedTerminationSignal;
775
- }, HARD_KILL_MS);
776
- finalHardKillTimer.unref?.();
777
- }, FINAL_STOP_GRACE_MS);
778
- finalDrainTimer.unref?.();
779
- }
780
- function clearWatchdogTailTimer() {
781
- if (watchdogTailTimer) {
782
- clearTimeout(watchdogTailTimer);
783
- watchdogTailTimer = undefined;
784
- }
785
- }
786
- function armWatchdogTail() {
787
- if (!cleanTerminalAssistantStopReceived && !agentSettledReceived || watchdogTailTimer || settled)
788
- return;
789
- watchdogTailTimer = setTimeout(() => {
790
- watchdogTailTimer = undefined;
791
- updateChildWatchdogState({
792
- phase: "stale",
793
- seq: (childWatchdogState?.seq ?? 0) + 1,
794
- lastUpdate: Date.now(),
795
- followUpPending: false,
796
- reason: "child watchdog tail timeout",
797
- timedOut: true
798
- });
799
- startFinalDrain();
800
- }, childWatchdogConfig?.watchdogTailTimeoutMs ?? 120000);
801
- watchdogTailTimer.unref?.();
802
- }
803
- child.on("exit", () => {
804
- childExited = true;
805
- clearDrainTimers();
806
- });
807
- child.on("close", async (exitCode, signal) => {
808
- settled = true;
809
- const processCloseObservedAt = Date.now();
810
- const processTree = processTreeController ? await processTreeController.finishAfterWriterClose() : { state: "unknown", reason: "verification-failed", diagnostic: "Writer PID was unavailable." };
811
- try {
812
- onWriterProcess?.({ state: "none" });
813
- } catch {}
814
- registerInterrupt?.(undefined);
815
- registerTimeout?.(undefined);
816
- registerStop?.(undefined);
817
- clearDrainTimers();
818
- clearStdioGuard();
819
- stdoutReader.end();
820
- stderrReader.end();
821
- outputStream.end();
822
- const stderr = stderrTail.text();
823
- const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
824
- const finalError = error ?? assistantError;
825
- const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
826
- const forcedDrainAfterEmptyTerminal = forcedDrainAfterFinalSuccess && hasEmptyTerminalAssistantResponse(messages);
827
- const forcedDrainError = forcedDrainAfterEmptyTerminal && stderr.trim() ? stderr.trim() : undefined;
828
- const signalError = isUnexplainedProcessSignal({
829
- processSignal: signal,
830
- interrupted,
831
- timedOut,
832
- stopped,
833
- forcedDrainAfterFinalSuccess: forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal
834
- }) ? formatProcessSignalError(signal) : undefined;
835
- resolve(omitUndefinedProperties({
836
- stderr,
837
- exitCode: timedOut || stopped ? 1 : interrupted || forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal ? 0 : forcedTerminationSignal || signal ? exitCode ?? 1 : exitCode,
838
- messages,
839
- usage,
840
- toolCount,
841
- durationMs: Date.now() - startedAt,
842
- model,
843
- error: stopped ? stopMessage ?? "Subagent stopped by user." : timedOut ? timeoutMessage ?? "Subagent timed out." : interrupted || forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal ? undefined : finalError ?? forcedDrainError ?? signalError,
844
- protocolError,
845
- finalOutput: (timedOut || stopped) && !finalOutput.trim() ? stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out." : finalOutput,
846
- outputState: finalOutput.trim() ? "present" : "absent",
847
- interrupted,
848
- timedOut,
849
- stopped,
850
- observedMutationAttempt,
851
- structuredOutputToolInvoked,
852
- structuredOutputMessageStartIndex,
853
- watchdog: childWatchdogState,
854
- processInstanceId,
855
- processCloseObservedAt,
856
- processSignal: signal,
857
- processTree,
858
- currentTool,
859
- currentToolArgs,
860
- currentPath,
861
- afterCompactionSettlement: afterCompactionSettlement || undefined
862
- }));
863
- });
864
- child.on("error", (spawnError) => {
865
- settled = true;
866
- try {
867
- onWriterProcess?.({ state: "none" });
868
- } catch {}
869
- registerInterrupt?.(undefined);
870
- registerTimeout?.(undefined);
871
- registerStop?.(undefined);
872
- clearDrainTimers();
873
- clearStdioGuard();
874
- stdoutReader.end();
875
- stderrReader.end();
876
- outputStream.end();
877
- const stderr = stderrTail.text();
878
- const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
879
- const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
880
- resolve(omitUndefinedProperties({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? stopMessage ?? "Subagent stopped by user." : timedOut ? timeoutMessage ?? "Subagent timed out." : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out." : finalOutput, outputState: finalOutput.trim() ? "present" : "absent", timedOut, stopped, observedMutationAttempt, structuredOutputToolInvoked, structuredOutputMessageStartIndex, watchdog: childWatchdogState, processInstanceId, processTree: { state: "unknown", reason: "verification-failed", diagnostic: spawnErrorMessage } }));
881
- });
882
- });
883
- }
884
298
  function resolvePiPackageRootFallback() {
885
299
  const root = resolveInstalledPiPackageRoot();
886
300
  if (root)
@@ -969,7 +383,68 @@ function writeRunLog(logPath, input, write = (filePath, content) => fs.writeFile
969
383
  write(logPath, lines.join(`
970
384
  `));
971
385
  }
972
- async function runSingleStepInner(step, ctx) {
386
+ function expectedMissingGitEvidence(error) {
387
+ if (typeof error?.code !== "number")
388
+ return false;
389
+ const stderr = error.stderr;
390
+ const detail = Buffer.isBuffer(stderr) ? stderr.toString("utf-8") : String(stderr ?? "");
391
+ return /not a git repository|Needed a single revision/i.test(detail);
392
+ }
393
+ async function readGitFingerprint(cwd, signal, onError) {
394
+ try {
395
+ const runGit = async (args) => {
396
+ const result = await runSetupCommand("git", args, {
397
+ cwd,
398
+ signal,
399
+ maxBuffer: 16777216,
400
+ deadlineAt: Date.now() + 30000,
401
+ acceptedExitCodes: Array.from({ length: 256 }, (_, code) => code)
402
+ });
403
+ if (result.error)
404
+ throw result.error;
405
+ if (result.status !== 0) {
406
+ throw Object.assign(new Error(result.stderr || `git exited with ${result.status}`), { code: result.status, stderr: result.stderr });
407
+ }
408
+ return result.stdoutBuffer;
409
+ };
410
+ const headOutput = await runGit(["rev-parse", "--verify", "HEAD"]);
411
+ const head = headOutput.toString("utf-8").trim();
412
+ if (!head)
413
+ return;
414
+ const status = await runGit(["status", "--porcelain=v1", "-z", "--untracked-files=normal"]);
415
+ return `${head}\x00${status.toString("base64")}`;
416
+ } catch (error) {
417
+ if (error?.code === "PROCESS_TREE_UNVERIFIED")
418
+ throw error;
419
+ if (!signal.aborted && !expectedMissingGitEvidence(error))
420
+ onError(error);
421
+ return;
422
+ }
423
+ }
424
+ function decorateHerdrMachineResult(result, machine, adapter) {
425
+ let stderrTail = "";
426
+ try {
427
+ const stderr = fs.readFileSync(result.externalProcess.stderrPath, "utf-8");
428
+ stderrTail = stderr.slice(-4096);
429
+ } catch {}
430
+ const hint = result.exitCode === 0 ? undefined : formatHerdrMachineHint(machine, `${result.error ?? ""}
431
+ ${stderrTail}
432
+ exit code ${result.exitCode}`);
433
+ const error = hint ? `${result.error ?? `Remote command exited with code ${result.exitCode}.`}
434
+ ${hint}` : result.error;
435
+ const note = result.exitCode === 0 && adapter?.endsWith("-writer") ? `Changes made by this run live on ${machine.label ?? machine.id} at ${machine.cwd}; the local checkout is unchanged.` : undefined;
436
+ const output = note ? result.output.trim() ? `${result.output.trimEnd()}
437
+
438
+ ${note}` : note : result.output;
439
+ return { ...result, output, ...error !== undefined ? { error } : {} };
440
+ }
441
+ export async function settleHerdrExternalRunnerError(error, adapter, evidence, retain) {
442
+ await retain();
443
+ if (!(error instanceof HerdrExternalNeedsAttentionError))
444
+ throw error;
445
+ return createHerdrExternalAdapter(adapter).normalize(evidence, error.message);
446
+ }
447
+ export async function runSingleStepInner(step, ctx) {
973
448
  if (step.importAsyncRoot) {
974
449
  let importTimedOut = false;
975
450
  let importStopped = false;
@@ -1018,8 +493,7 @@ async function runSingleStepInner(step, ctx) {
1018
493
  sessionFile: imported.sessionFile,
1019
494
  intercomTarget: imported.intercomTarget,
1020
495
  model: imported.model,
1021
- attemptedModels: imported.attemptedModels,
1022
- modelAttempts: imported.modelAttempts,
496
+ requestedModel: imported.requestedModel,
1023
497
  contextOverflow: imported.contextOverflow,
1024
498
  totalCost: imported.totalCost,
1025
499
  usage: imported.usage,
@@ -1035,58 +509,34 @@ async function runSingleStepInner(step, ctx) {
1035
509
  ctx.registerStop?.(undefined);
1036
510
  }
1037
511
  }
1038
- const effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema ? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), "structured-output")) : undefined);
512
+ const effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema ? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), "structured-output"), { acceptanceReport: resolveAcceptanceReportMode(step.acceptanceInput) }) : undefined);
1039
513
  const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
1040
514
  let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
1041
515
  if (ctx.outputs)
1042
516
  task = resolveOutputReferences(task, ctx.outputs);
1043
- const taskForCompletionGuard = task;
1044
517
  let resolvedTaskToolPlan;
1045
518
  if (!step.runner) {
1046
519
  resolvedTaskToolPlan = resolvePiLaunchToolPlan(omitUndefinedProperties({
1047
520
  tools: step.tools,
521
+ excludeTools: step.excludeTools,
1048
522
  allowNestedSubagents: step.allowNestedSubagents,
1049
523
  extensions: step.extensions,
1050
524
  subagentOnlyExtensions: step.subagentOnlyExtensions,
1051
525
  fast: step.fast,
1052
526
  model: step.model,
1053
- modelCandidates: step.modelCandidates,
1054
527
  mcpDirectTools: step.mcpDirectTools,
1055
- mcpConfig: step.mcpConfig,
1056
- runtimeServerNames: step.runtimeServerNames,
1057
528
  cwd: step.cwd ?? ctx.cwd,
1058
529
  requireReadTool: Boolean(step.skills?.length),
1059
530
  structuredOutput: Boolean(effectiveStructuredOutput),
1060
531
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1061
- inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
532
+ inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
533
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
1062
534
  permissionRules: step.permissionRules
1063
535
  }));
1064
- const contractTools = resolvedTaskToolPlan.explicitToolAllowlist ? resolvedTaskToolPlan.effectiveToolAllowlist : undefined;
1065
- const contractError = validateImplementationToolContract({
1066
- agent: step.agent,
1067
- task: taskForCompletionGuard,
1068
- tools: contractTools,
1069
- mcpDirectTools: resolvedTaskToolPlan.effectiveMcpTools,
1070
- configuredExtensions: resolvedTaskToolPlan.configuredExtensions,
1071
- requestedTools: resolvedTaskToolPlan.requestedBuiltinTools,
1072
- acceptanceRole: step.acceptanceRole,
1073
- completionGuard: step.completionGuard
1074
- });
1075
- if (contractError) {
1076
- return omitUndefinedProperties({
1077
- agent: step.agent,
1078
- context: step.context,
1079
- output: contractError,
1080
- error: contractError,
1081
- exitCode: 1,
1082
- capabilityCeiling: resolvedTaskToolPlan.capabilityCeiling,
1083
- capabilityAudit: resolvedTaskToolPlan.capabilityAudit
1084
- });
1085
- }
1086
536
  }
1087
537
  const childSessionName = step.sessionName ?? deriveChildSessionName({ agent: step.agent, task, label: step.label });
1088
- if (step.effectiveAcceptance) {
1089
- const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance, { reportOptional: isAgentContractV1(step.agentContract), structuredOutput: Boolean(step.structuredOutput?.acceptanceReportPath) });
538
+ if (step.effectiveAcceptance && (step.runner?.type === "external-cli" || step.runner?.type === "external-job")) {
539
+ const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance, { reportOptional: isAgentContract(step.agentContract), structuredOutput: Boolean(step.structuredOutput?.acceptanceReportPath) });
1090
540
  if (acceptancePrompt)
1091
541
  task = `${task}
1092
542
  ${acceptancePrompt}`;
@@ -1118,11 +568,81 @@ ${PROMPT_REDACTED}; live Prompt Audit only.
1118
568
  }
1119
569
  transcriptWriter?.writeInitialUserMessage(`${PROMPT_REDACTED}; live Prompt Audit only.`);
1120
570
  if (step.runner?.type === "external-cli") {
1121
- const externalCwd = step.cwd ?? ctx.cwd;
571
+ const externalCwd = step.machine?.cwd ?? step.cwd ?? ctx.cwd;
572
+ const externalAbortSignal = combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]);
573
+ if (!step.machine && externalAbortSignal)
574
+ await ctx.prepareExternalActivity?.(externalCwd, externalAbortSignal);
575
+ if (externalAbortSignal?.aborted) {
576
+ const stopped = ctx.stopSignal?.aborted === true;
577
+ const message = stopped ? ctx.stopMessage ?? "Subagent stopped by user." : ctx.timeoutMessage ?? "Subagent timed out.";
578
+ return omitUndefinedProperties({ agent: step.agent, context: step.context, output: message, error: message, exitCode: 1, stopped: stopped || undefined, timedOut: stopped ? undefined : true });
579
+ }
580
+ if (step.machine) {
581
+ const runner = resolveExternalCliRunnerStatus({ ...step.runner, machine: step.machine });
582
+ const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
583
+ const placedRunId = `${ctx.id}-${ctx.flatIndex}`;
584
+ const session = await prepareInternalHerdrExternalAdapter({ adapter: step.runner.adapter, machine: step.machine, runId: placedRunId }, {});
585
+ let timedOut = false, stopped = false, retain = false;
586
+ const evidenceInput = { runId: placedRunId, requestId: `prompt-${ctx.flatIndex}`, task: buildExternalCliPrompt(step.systemPrompt ?? "", task), cwd: externalCwd, nativeSessionId: session.launch.nativeSessionId };
587
+ let resolveInterruption, rejectInterruption;
588
+ const interruption = new Promise((resolve, reject) => {
589
+ resolveInterruption = resolve;
590
+ rejectInterruption = reject;
591
+ });
592
+ ctx.registerTimeout?.(() => {
593
+ timedOut = true;
594
+ retain = true;
595
+ resolveInterruption("timeout");
596
+ });
597
+ ctx.registerStop?.(() => {
598
+ stopped = true;
599
+ session.abort().then(() => resolveInterruption("stop"), rejectInterruption);
600
+ });
601
+ try {
602
+ let settled;
603
+ try {
604
+ const raced = await Promise.race([session.promptAndSettle(evidenceInput).then((value) => ({ kind: "settled", value })), interruption.then((kind) => ({ kind }))]);
605
+ if (raced.kind === "settled")
606
+ settled = raced.value;
607
+ else if (raced.kind === "timeout")
608
+ settled = createHerdrExternalAdapter(step.runner.adapter).normalize(evidenceInput, "Placed external run timed out; truthful pane retained for inspection.");
609
+ else
610
+ return { agent: step.agent, context: step.context, output: "Placed external run stopped by user.", outputState: "present", exitCode: 1, stopped: true, runner, execution: { status: "stopped", success: false, exitCode: 1, stopped: true } };
611
+ } catch (error) {
612
+ retain = true;
613
+ settled = await settleHerdrExternalRunnerError(error, step.runner.adapter, evidenceInput, () => session.retain());
614
+ }
615
+ const output = settled.output;
616
+ try {
617
+ fs.writeFileSync(ctx.outputFile, output, "utf-8");
618
+ } catch {}
619
+ const resolvedOutput = step.outputPath ? resolveSingleOutput(step.outputPath, output, outputSnapshot, step.outputClaimPath) : { fullOutput: output };
620
+ const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, resolvedOutput.fullOutput) : undefined;
621
+ const finalizedOutput = finalizeSingleOutput(omitUndefinedProperties({ fullOutput: resolvedOutput.fullOutput, outputPath: step.outputPath, outputMode: step.outputMode, exitCode: 1, preserveSavedOutput: true, savedPath: resolvedOutput.savedPath, outputReference, saveError: resolvedOutput.saveError }));
622
+ const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false ? persistStepArtifacts({ artifactPaths, artifactConfig: ctx.artifactConfig, output: formatOutputArtifactContent(omitUndefinedProperties({ output: resolvedOutput.fullOutput, metadataPath: ctx.artifactConfig?.includeMetadata === false ? undefined : artifactPaths.metadataPath })), metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, placement: session.owner.identity, settlement: settled.settlement, outcome: settled.outcome, timestamp: Date.now() } }) : {};
623
+ return omitUndefinedProperties({ agent: step.agent, ...childSessionName ? { sessionName: childSessionName } : {}, context: step.context, output: finalizedOutput.displayOutput, outputState: output.trim() ? "present" : "absent", exitCode: 1, error: resolvedOutput.fatalError ? resolvedOutput.saveError : undefined, timedOut, stopped, artifactPaths, outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join(`
624
+ `) || undefined, metadataSaveError: artifactErrors.metadataSaveError, runner, execution: { status: "partial", success: false, exitCode: 1 } });
625
+ } catch (error) {
626
+ retain = true;
627
+ throw error;
628
+ } finally {
629
+ ctx.registerTimeout?.(undefined);
630
+ ctx.registerStop?.(undefined);
631
+ if (retain)
632
+ await session.retain();
633
+ else
634
+ await session.dispose();
635
+ }
636
+ }
1122
637
  const adapterLaunch = step.runner.adapter === "codex-exec" || step.runner.adapter === "codex-exec-writer" ? resolveCodexExecLaunch({ adapter: step.runner.adapter, command: step.runner.command, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex }) : step.runner.adapter === "claude-code" || step.runner.adapter === "claude-code-writer" ? resolveClaudeCodeLaunch({ adapter: step.runner.adapter, command: step.runner.command }) : step.runner.adapter === "cursor-agent" || step.runner.adapter === "cursor-agent-writer" ? resolveCursorAgentLaunch({ adapter: step.runner.adapter, command: step.runner.command, cwd: externalCwd, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex }) : undefined;
1123
- const runner = resolveExternalCliRunnerStatus({ ...step.runner, ...adapterLaunch ? { args: adapterLaunch.args } : {} });
638
+ const runner = resolveExternalCliRunnerStatus({ ...step.runner, ...adapterLaunch ? { args: adapterLaunch.args } : {}, ...step.machine ? { machine: step.machine } : {} });
1124
639
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
1125
- const external = await runExternalCli(omitUndefinedProperties({
640
+ const onExternalOutput = (chunk) => {
641
+ if (chunk.length > 0)
642
+ ctx.onExternalStreamActivity?.();
643
+ ctx.orcaProgressTab?.append(chunk.toString("utf-8"));
644
+ };
645
+ const externalInput = omitUndefinedProperties({
1126
646
  command: adapterLaunch?.command ?? runner.command,
1127
647
  args: adapterLaunch?.args ?? runner.args,
1128
648
  cwd: externalCwd,
@@ -1140,9 +660,13 @@ ${PROMPT_REDACTED}; live Prompt Audit only.
1140
660
  timeoutMessage: ctx.timeoutMessage,
1141
661
  stopMessage: ctx.stopMessage,
1142
662
  onProcess: ctx.onExternalProcess,
1143
- onStdout: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8")),
1144
- onStderr: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8"))
1145
- }));
663
+ onStdout: onExternalOutput,
664
+ onStderr: onExternalOutput
665
+ });
666
+ const preparedExternal = prepareHerdrMachineExternalCliRun(externalInput, step.machine ? { machine: step.machine, ...step.machineEnv ? { env: step.machineEnv } : {} } : undefined, { localCwd: ctx.cwd });
667
+ const ran = await runExternalCli(preparedExternal.input);
668
+ const externalProcess = preparedExternal.decorateProcess(ran.externalProcess);
669
+ const external = step.machine ? decorateHerdrMachineResult(ran, step.machine, step.runner.adapter) : ran;
1146
670
  try {
1147
671
  fs.writeFileSync(ctx.outputFile, external.output, "utf-8");
1148
672
  } catch {}
@@ -1164,7 +688,7 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1164
688
  artifactPaths,
1165
689
  artifactConfig: ctx.artifactConfig,
1166
690
  output: formatOutputArtifactContent(omitUndefinedProperties({ output: resolvedOutput.fullOutput, error: external.error, metadataPath: ctx.artifactConfig?.includeMetadata === false ? undefined : artifactPaths.metadataPath })),
1167
- metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, externalProcess: external.externalProcess, exitCode: external.exitCode, error: external.error, timestamp: Date.now() }
691
+ metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, externalProcess, exitCode: external.exitCode, error: external.error, timestamp: Date.now() }
1168
692
  }) : {};
1169
693
  return omitUndefinedProperties({
1170
694
  agent: step.agent,
@@ -1180,9 +704,10 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1180
704
  artifactPaths,
1181
705
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join(`
1182
706
  `) || undefined,
707
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
1183
708
  metadataSaveError: artifactErrors.metadataSaveError,
1184
709
  runner,
1185
- externalProcess: external.externalProcess
710
+ externalProcess
1186
711
  });
1187
712
  }
1188
713
  if (step.runner?.type === "external-job") {
@@ -1246,6 +771,7 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1246
771
  artifactPaths,
1247
772
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join(`
1248
773
  `) || undefined,
774
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
1249
775
  metadataSaveError: artifactErrors.metadataSaveError,
1250
776
  runner,
1251
777
  externalJob: external.externalJob
@@ -1255,58 +781,51 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1255
781
  const cwdError = preflightLaunchCwd(step.requestedCwd ?? effectiveCwd, effectiveCwd);
1256
782
  if (cwdError)
1257
783
  return { agent: step.agent, output: cwdError, error: cwdError, exitCode: 1, context: step.context };
1258
- const candidates = step.modelCandidates !== undefined ? step.modelCandidates.length > 0 ? step.modelCandidates : [undefined] : step.model ? [step.model] : [undefined];
1259
- const attemptedModels = [];
784
+ if (step.context === "fork" && step.sessionFile && fs.existsSync(step.sessionFile)) {
785
+ alignForkedSessionCwd(step.sessionFile, effectiveCwd);
786
+ }
787
+ const candidate = step.model;
1260
788
  let capabilityAudit;
1261
789
  let launchResolvedExtensions = step.launchResolvedExtensions;
1262
- const modelAttempts = [];
1263
- const writerProcesses = [];
1264
- let writerAttemptCount = 0;
1265
- const attemptNotes = [];
1266
790
  let finalRequiredOutputMissing;
1267
791
  const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
1268
792
  let finalResult;
1269
793
  let finalOutputSnapshot;
1270
794
  let structuredAcceptanceReport;
1271
795
  let structuredAcceptanceReportError;
1272
- let completionGuardTriggeredFinal = false;
1273
796
  let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
1274
797
  let toolBudgetBlocked = false;
1275
798
  let actualLaunchContractDigest = step.launchContractDigest;
1276
- const mutationSnapshot = snapshotTrackedMutations(step.cwd ?? ctx.cwd);
799
+ const mutationSnapshot = step.machine ? { source: "tracked-files", trackedOnly: true, cwd: step.cwd ?? ctx.cwd, dirtyFiles: [], fingerprints: {}, unavailable: "Local Git evidence is not authoritative for a pane-native remote run." } : snapshotTrackedMutations(step.cwd ?? ctx.cwd);
1277
800
  let finalMutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1278
- let modelIndex = 0;
1279
- let startupAttemptIndex = 0;
1280
- let taskDeliveryOverride;
1281
801
  let contextOverflow = false;
1282
802
  let launchWarningsEmitted = false;
1283
- let abortRecoveryAttempted = false;
1284
- let nextAttemptTask = task;
1285
- modelAttemptsLoop:
1286
- while (modelIndex < candidates.length) {
803
+ const aggregateUsage = emptyUsage();
804
+ let launched = false;
805
+ let recoveryTask = task;
806
+ let stagedIndexBaseline;
807
+ singleLaunch:
808
+ for (let attemptIndex = 0;attemptIndex < 2; attemptIndex++) {
1287
809
  if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.())
1288
- break;
1289
- const recoveringAbort = abortRecoveryAttempted;
1290
- const attemptTask = nextAttemptTask;
1291
- const candidate = candidates[modelIndex];
1292
- const expectedModelForVerification = candidate && !(step.skipPrimaryModelVerification && modelIndex === 0) ? candidate : undefined;
810
+ break singleLaunch;
811
+ const expectedModelForVerification = candidate && !step.skipPrimaryModelVerification ? candidate : undefined;
1293
812
  try {
1294
- assertThinkingWithinCeiling({ model: candidate, configThinking: step.thinking, ceiling: step.thinkingCeiling ?? decodeThinkingCeiling(process.env[SUBAGENT_THINKING_CEILING_ENV]), agent: step.agent, runId: ctx.id });
813
+ assertThinkingWithinCeiling({ model: candidate, configThinking: step.thinking, ceiling: step.thinkingCeiling, agent: step.agent, runId: ctx.id });
1295
814
  } catch (error) {
1296
815
  const message = error instanceof Error ? error.message : String(error);
1297
816
  return omitUndefinedProperties({ agent: step.agent, output: message, error: message, exitCode: 1, context: step.context, thinkingCeiling: step.thinkingCeiling });
1298
817
  }
818
+ const attemptModel = omitUndefinedProperties({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
1299
819
  ctx.onAttemptStart?.(omitUndefinedProperties({
1300
- model: candidate,
1301
- thinking: resolveEffectiveThinking(candidate, step.thinking),
820
+ ...attemptModel,
1302
821
  contextLimit: findModelInfo(candidate, step.modelVerificationRegistry)?.contextWindow
1303
822
  }));
1304
823
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
1305
824
  if (effectiveStructuredOutput) {
1306
- try {
1307
- if (fs.existsSync(effectiveStructuredOutput.outputPath))
1308
- fs.unlinkSync(effectiveStructuredOutput.outputPath);
1309
- } catch {}
825
+ const cleanupError = clearStructuredOutputCaptures(effectiveStructuredOutput);
826
+ if (cleanupError) {
827
+ return omitUndefinedProperties({ agent: step.agent, output: cleanupError, error: cleanupError, exitCode: 1, context: step.context });
828
+ }
1310
829
  }
1311
830
  const watchdogConfig = resolveWatchdogConfig(step.cwd ?? ctx.cwd);
1312
831
  const extensionBindings = normalizeExtensionBindings(step.extensionBindings)?.value;
@@ -1316,61 +835,25 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1316
835
  runId: ctx.id,
1317
836
  childIndex: ctx.flatIndex
1318
837
  }) : undefined;
1319
- const { args, env, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit: attemptCapabilityAudit, warnings } = buildPiArgs(omitUndefinedProperties({
1320
- parentSessionId: step.parentSessionId,
1321
- forkCacheKey: step.context === "fork" ? deriveForkPromptCacheKey(step.parentSessionId) : undefined,
1322
- baseArgs: ["--mode", "json", "-p"],
1323
- task: attemptTask,
1324
- taskDelivery: taskDeliveryOverride,
1325
- sessionEnabled,
1326
- sessionDir,
1327
- sessionFile: step.sessionFile,
1328
- model: candidate,
1329
- inheritProjectContext: step.inheritProjectContext,
1330
- inheritGlobalContext: step.inheritGlobalContext,
1331
- inheritSkills: step.inheritSkills,
1332
- requireReadTool: Boolean(step.skills?.length),
1333
- tools: step.tools,
1334
- allowNestedSubagents: step.allowNestedSubagents,
1335
- extensions: step.extensions,
1336
- subagentOnlyExtensions: step.subagentOnlyExtensions,
1337
- fast: step.fast,
1338
- modelCandidates: step.modelCandidates,
1339
- systemPrompt: step.systemPrompt ?? "",
1340
- systemPromptMode: step.systemPromptMode,
1341
- mcpDirectTools: step.mcpDirectTools,
1342
- mcpConfig: step.mcpConfig,
1343
- runtimeServerNames: step.runtimeServerNames,
1344
- capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1345
- cwd: step.cwd ?? ctx.cwd,
1346
- promptFileStem: step.agent,
1347
- intercomSessionName: ctx.childIntercomTarget,
1348
- sessionName: childSessionName,
1349
- orchestratorIntercomTarget: ctx.orchestratorIntercomTarget,
1350
- runId: ctx.id,
1351
- childAgentName: step.agent,
1352
- childIndex: ctx.flatIndex,
1353
- parentEventSink: ctx.nestedRoute?.eventSink,
1354
- parentControlInbox: ctx.nestedRoute?.controlInbox,
1355
- parentRootRunId: ctx.nestedRoute?.rootRunId,
1356
- parentCapabilityToken: ctx.nestedRoute?.capabilityToken,
1357
- runFanoutBudget: ctx.runFanoutBudget ? {
1358
- ...ctx.runFanoutBudget,
1359
- ...step.runFanoutPath ? { parentPath: `${ctx.runFanoutBudget.parentPath ? `${ctx.runFanoutBudget.parentPath}/` : ""}${step.runFanoutPath}` } : {}
1360
- } : undefined,
1361
- steerInboxDir: ctx.steerInboxDir,
1362
- steerCapabilityPath: ctx.steerCapabilityPath,
1363
- steerAckDir: ctx.steerAckDir,
1364
- structuredOutput: effectiveStructuredOutput,
1365
- toolBudget: step.toolBudget,
1366
- permissionRules: step.permissionRules,
1367
- permissionAuditPath: step.permissionRules && ctx.artifactsDir ? path.join(ctx.artifactsDir, "permission-audit", `${ctx.id}-${ctx.flatIndex}.jsonl`) : undefined,
1368
- childWatchdog,
1369
- waitToolEnabled: step.waitToolEnabled,
1370
- waitToolDefaultTimeoutMs: step.waitToolDefaultTimeoutMs,
1371
- thinkingCeiling: step.thinkingCeiling,
1372
- extensionBindings
1373
- }));
838
+ let watchdogSink;
839
+ let launch;
840
+ try {
841
+ launch = buildRunnerChildLaunch(step, ctx, {
842
+ sessionEnabled,
843
+ sessionDir,
844
+ model: candidate,
845
+ sessionName: childSessionName,
846
+ structuredOutput: effectiveStructuredOutput,
847
+ childWatchdog,
848
+ watchdogStatus: (event) => watchdogSink?.(event)
849
+ });
850
+ } catch (error) {
851
+ throw error;
852
+ }
853
+ if (effectiveStructuredOutput && launch.config.structuredOutput) {
854
+ launch.config.structuredOutput.capture = createStructuredOutputFileCapture(effectiveStructuredOutput);
855
+ }
856
+ const { warnings, capabilityAudit: attemptCapabilityAudit } = launch;
1374
857
  if (!launchWarningsEmitted && warnings.length > 0) {
1375
858
  for (const warning of warnings)
1376
859
  console.warn(`[dm-subagents] ${warning}`);
@@ -1379,83 +862,116 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1379
862
  if (step.definitionDigest) {
1380
863
  const toolPlan = resolvedTaskToolPlan ?? resolvePiLaunchToolPlan(omitUndefinedProperties({
1381
864
  tools: step.tools,
865
+ excludeTools: step.excludeTools,
1382
866
  allowNestedSubagents: step.allowNestedSubagents,
1383
867
  extensions: step.extensions,
1384
868
  subagentOnlyExtensions: step.subagentOnlyExtensions,
1385
869
  fast: step.fast,
1386
870
  model: step.model,
1387
- modelCandidates: step.modelCandidates,
1388
871
  mcpDirectTools: step.mcpDirectTools,
1389
- mcpConfig: step.mcpConfig,
1390
- runtimeServerNames: step.runtimeServerNames,
1391
872
  cwd: step.cwd ?? ctx.cwd,
1392
873
  requireReadTool: Boolean(step.skills?.length),
1393
874
  structuredOutput: Boolean(effectiveStructuredOutput),
1394
875
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1395
- inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
876
+ inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
877
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
1396
878
  permissionRules: step.permissionRules
1397
879
  }));
1398
880
  launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1399
- actualLaunchContractDigest = launchBindingDigest(omitUndefinedProperties({
881
+ actualLaunchContractDigest = resolveLaunchBinding({
1400
882
  definitionDigest: step.definitionDigest,
1401
- task: step.launchBindingTask ?? task,
1402
- ...candidate ? { model: candidate } : {},
1403
- modelCandidates: candidates,
1404
- ...step.fast !== undefined ? { fast: step.fast } : {},
1405
- ...resolveEffectiveThinking(candidate, step.thinking) ? { thinking: resolveEffectiveThinking(candidate, step.thinking) } : {},
1406
- ...step.thinkingCeiling ? { thinkingCeiling: step.thinkingCeiling } : {},
1407
- systemPrompt: step.systemPrompt ?? "",
1408
883
  systemPromptMode: step.systemPromptMode,
1409
884
  inheritProjectContext: step.inheritProjectContext,
1410
885
  inheritGlobalContext: step.inheritGlobalContext,
1411
886
  inheritSkills: step.inheritSkills,
887
+ task: step.launchBindingTask ?? task,
888
+ model: candidate,
889
+ fast: step.fast,
890
+ thinking: resolveEffectiveThinking(candidate, step.thinking),
891
+ systemPrompt: step.systemPrompt ?? "",
1412
892
  skills: step.skills,
1413
- tools: toolPlan.effectiveToolAllowlist,
1414
- extensions: toolPlan.extensionArgs,
1415
- mcpDirectTools: toolPlan.effectiveMcpTools,
1416
- ...step.outputPath ? { outputPath: step.outputPath } : {},
1417
- ...step.outputMode ? { outputMode: step.outputMode } : {},
1418
- ...step.structuredOutputSchema ? { structuredOutputSchema: step.structuredOutputSchema } : {},
1419
- ...extensionBindings ? { extensionBindings } : {}
1420
- }));
893
+ toolPlan,
894
+ outputPath: step.outputPath,
895
+ outputMode: step.outputMode,
896
+ structuredOutputSchema: step.structuredOutputSchema,
897
+ extensionBindings
898
+ }).launchContractDigest;
1421
899
  }
1422
900
  capabilityAudit = attemptCapabilityAudit;
1423
- writerAttemptCount += 1;
1424
- const run = await runPiStreaming(args, step.cwd ?? ctx.cwd, ctx.outputFile, env, ctx.piPackageRoot, ctx.piArgv1, step.maxSubagentDepth, { eventsPath, runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent }, ctx.registerInterrupt, ctx.onChildEvent, transcriptWriter, ctx.registerTimeout, ctx.timeoutMessage, ctx.registerStop, ctx.stopMessage, ctx.onWriterProcess, ctx.toolTimeoutMs, ctx.deadlineAt, ctx.orcaProgressTab, expectedModelForVerification, step.modelVerificationRegistry, step.mutationTools);
1425
- if (run.processCloseObservedAt !== undefined) {
1426
- writerProcesses.push({
1427
- processInstanceId: run.processInstanceId,
1428
- kind: "dm-writer",
1429
- attempt: writerAttemptCount - 1,
1430
- closeObservedAt: run.processCloseObservedAt,
1431
- exitCode: run.exitCode,
1432
- signal: run.processSignal ?? null,
1433
- processTree: run.processTree
1434
- });
901
+ fs.writeFileSync(ctx.outputFile, "", "utf-8");
902
+ if (step.effectiveAcceptance?.preserveStagedIndex && stagedIndexBaseline === undefined) {
903
+ try {
904
+ stagedIndexBaseline = captureStagedIndexBaseline(step.cwd ?? ctx.cwd);
905
+ } catch (error) {
906
+ const message = error instanceof Error ? error.message : String(error);
907
+ return { agent: step.agent, output: message, error: message, exitCode: 1, context: step.context };
908
+ }
1435
909
  }
1436
- const toolAvailabilityError = run.exitCode === 0 && !run.error ? readChildToolDiagnosticError(toolDiagnosticPath) : undefined;
1437
- const runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
1438
- cleanupTempDir(tempDir);
1439
- const midToolExitError = run.currentTool && isOrdinaryToolForMidToolExit(run.currentTool) && !run.interrupted && !run.timedOut && !run.stopped && !run.protocolError && !toolAvailabilityError ? formatMidToolExitError({
1440
- toolName: run.currentTool,
1441
- exitCode: run.exitCode,
1442
- processSignal: run.processSignal
1443
- }) : undefined;
910
+ const run = await runChildSession(omitUndefinedProperties({
911
+ factory: ctx.childSessions,
912
+ launch,
913
+ prompt: `Task: ${recoveryTask}`,
914
+ childWatchdog,
915
+ childEventContext: { runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },
916
+ appendChildEvent: (event) => appendDiagnosticJsonl(eventsPath, JSON.stringify(event), typeof event.type === "string" ? event.type : undefined),
917
+ writeOutputLine: (line) => {
918
+ try {
919
+ fs.appendFileSync(ctx.outputFile, `${line}
920
+ `, "utf-8");
921
+ } catch {}
922
+ ctx.orcaProgressTab?.append(`${line}
923
+ `);
924
+ },
925
+ registerInterrupt: ctx.registerInterrupt,
926
+ registerTimeout: ctx.registerTimeout,
927
+ registerStop: ctx.registerStop,
928
+ registerSteer: ctx.registerSteer,
929
+ onSteerOutcome: ctx.onSteerOutcome,
930
+ registerWatchdogStatus: (sink) => {
931
+ watchdogSink = sink;
932
+ },
933
+ timeoutMessage: ctx.timeoutMessage,
934
+ stopMessage: ctx.stopMessage,
935
+ onChildEvent: ctx.onChildEvent,
936
+ onContextWindow: (contextLimit) => ctx.onAttemptStart?.({ ...attemptModel, contextLimit }),
937
+ transcriptWriter,
938
+ toolTimeoutMs: ctx.toolTimeoutMs,
939
+ runDeadlineAt: ctx.deadlineAt,
940
+ expectedModelForVerification,
941
+ modelVerificationRegistry: step.modelVerificationRegistry,
942
+ modelResponseAliases: step.modelResponseAliases,
943
+ mutationTools: step.mutationTools
944
+ }));
945
+ launched = true;
946
+ aggregateUsage.input += run.usage.input;
947
+ aggregateUsage.output += run.usage.output;
948
+ aggregateUsage.cacheRead += run.usage.cacheRead;
949
+ aggregateUsage.cacheWrite += run.usage.cacheWrite;
950
+ aggregateUsage.cost += run.usage.cost;
951
+ aggregateUsage.turns += run.usage.turns;
952
+ const terminalDiagnosticsEligible = !run.interrupted && !run.stopped && !run.timedOut;
953
+ const toolDiagnostic = run.exitCode === 0 && !run.error ? launch.capture.toolDiagnostic() : undefined;
954
+ const toolAvailabilityError = toolDiagnostic ? formatChildToolDiagnostic(toolDiagnostic) : undefined;
955
+ const runtimeAcknowledgedExtensions = launch.capture.runtimeAcknowledgedExtensions();
956
+ const midToolExitError = run.currentTool && isOrdinaryToolForMidToolExit(run.currentTool) && !run.interrupted && !run.timedOut && !run.stopped && !toolAvailabilityError ? formatMidToolExitError({ toolName: run.currentTool }) : undefined;
1444
957
  let structuredOutput;
1445
958
  let structuredError;
1446
959
  let validatedStructuredOutput = false;
1447
- if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError) {
1448
- if (!run.structuredOutputToolInvoked) {
960
+ if (effectiveStructuredOutput) {
961
+ const otherwiseSuccessful = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError;
962
+ if (!run.structuredOutputToolInvoked && otherwiseSuccessful) {
1449
963
  structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
1450
- } else {
964
+ } else if (run.structuredOutputToolInvoked) {
1451
965
  const structured = await readStructuredOutput({
1452
966
  schema: effectiveStructuredOutput.schema,
1453
967
  schemaPath: effectiveStructuredOutput.schemaPath,
1454
968
  outputPath: effectiveStructuredOutput.outputPath
1455
969
  });
1456
- if (structured.error)
1457
- structuredError = structured.error;
1458
- else {
970
+ if (structured.error) {
971
+ if (otherwiseSuccessful) {
972
+ structuredError = structured.error === MISSING_STRUCTURED_OUTPUT_CALL_ERROR ? formatStructuredOutputRejectionError(run.messages) : structured.error;
973
+ }
974
+ } else {
1459
975
  structuredOutput = structured.value;
1460
976
  const acceptanceReport = readStructuredOutputAcceptanceReport(effectiveStructuredOutput);
1461
977
  structuredAcceptanceReport = acceptanceReport.value;
@@ -1465,63 +981,21 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1465
981
  }
1466
982
  }
1467
983
  const errorMessages = validatedStructuredOutput ? run.messages.slice(run.structuredOutputMessageStartIndex ?? run.messages.length) : run.messages;
1468
- const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError ? detectSubagentError(errorMessages) : null;
984
+ const hiddenError = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError ? detectSubagentError(errorMessages) : null;
1469
985
  const terminalEmptyAfterUsefulWork = !validatedStructuredOutput && hasEmptyTerminalAssistantResponse(run.messages) && (run.toolCount > 0 || Boolean(run.finalOutput.trim()));
1470
- const emptyOutputError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !validatedStructuredOutput && (!run.finalOutput.trim() || terminalEmptyAfterUsefulWork) && (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages)) ? formatEmptyTerminalAssistantResponseError(run.messages) : undefined;
1471
- const completionGuardEnabled = isAgentContractV1(step.agentContract) ? step.completionGuard === true : step.completionGuard !== false;
1472
- const completionToolPlan = resolvedTaskToolPlan;
1473
- const completionTools = completionToolPlan ? completionToolPlan.explicitToolAllowlist ? completionToolPlan.effectiveToolAllowlist : undefined : step.tools;
1474
- const mutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
986
+ const emptyOutputError = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !validatedStructuredOutput && (!run.finalOutput.trim() || terminalEmptyAfterUsefulWork) && (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages)) ? formatEmptyTerminalAssistantResponseError(run.messages) : undefined;
987
+ const remoteGitChanged = run.nativeMachine?.initialGit && run.nativeMachine.finalGit ? run.nativeMachine.initialGit.head !== run.nativeMachine.finalGit.head || run.nativeMachine.initialGit.dirty !== run.nativeMachine.finalGit.dirty : undefined;
988
+ const mutationEvidence = run.nativeMachine ? { source: "tracked-files", trackedOnly: true, changedFiles: [], attemptedMutation: remoteGitChanged === true, ...remoteGitChanged === undefined ? { unavailable: "Remote Git before/after evidence was incomplete." } : {} } : collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1475
989
  finalMutationEvidence = mutationEvidence;
1476
- const completionMutationEvidence = ctx.trackedMutationEvidenceForCompletionGuard === false ? undefined : mutationEvidence;
1477
- const completionGuard = run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !midToolExitError && !emptyOutputError && completionGuardEnabled ? evaluateCompletionMutationGuard(omitUndefinedProperties({
1478
- agent: step.agent,
1479
- task: taskForCompletionGuard,
1480
- messages: run.messages,
1481
- tools: completionTools,
1482
- mcpDirectTools: completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools,
1483
- mutationTools: step.mutationTools,
1484
- toolAvailabilityError,
1485
- mutationEvidence: completionMutationEvidence
1486
- })) : undefined;
1487
- const mutationAttemptObserved = run.observedMutationAttempt === true || completionMutationEvidence?.attemptedMutation === true;
1488
- const completionEvidence = planCompletionEvidence({
1489
- guard: completionGuard,
1490
- completionGuardEnabled,
1491
- mutationCapable: hasMutationToolCapability(completionTools, completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools),
1492
- implementationMutationExpected: expectsImplementationMutation(step.agent, taskForCompletionGuard),
1493
- mutationAttemptObserved,
1494
- mutationEvidence: completionMutationEvidence,
1495
- agentContractV1: isAgentContractV1(step.agentContract)
1496
- });
990
+ const mutationAttemptObserved = run.observedMutationAttempt === true || mutationEvidence.attemptedMutation === true;
1497
991
  const finalOutputHasPersistableFileContent = run.exitCode === 0 && !run.error && !emptyOutputError && Boolean(stripAcceptanceReport(run.finalOutput).trim());
1498
992
  const requiredOutput = step.outputMode === "file-only" && step.outputPath ? { kind: "file-only", path: step.outputPath, missing: !fs.existsSync(step.outputPath) && !finalOutputHasPersistableFileContent } : effectiveStructuredOutput ? { kind: "structured", path: effectiveStructuredOutput.outputPath, missing: !fs.existsSync(effectiveStructuredOutput.outputPath) } : undefined;
1499
993
  finalRequiredOutputMissing = requiredOutput?.missing;
1500
- const missingRequiredOutputError = formatRequiredOutputError(requiredOutput);
994
+ const missingRequiredOutputError = terminalDiagnosticsEligible ? formatRequiredOutputError(requiredOutput) : undefined;
1501
995
  const missingRequiredOutputAfterMutation = Boolean(missingRequiredOutputError) && (mutationAttemptObserved || Boolean(mutationEvidence.changedFiles.length));
1502
- const effectiveExitCode = toolAvailabilityError || completionEvidence.legacyFailureError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError ? 1 : hiddenError?.hasError ? hiddenError.exitCode ?? 1 : run.error && run.exitCode === 0 ? 1 : run.exitCode;
1503
- const signalError = run.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
1504
- processSignal: run.processSignal,
1505
- interrupted: run.interrupted,
1506
- timedOut: run.timedOut,
1507
- stopped: run.stopped
1508
- })) ? formatProcessSignalError(run.processSignal) : undefined;
1509
- const underlyingError = toolAvailabilityError ?? midToolExitError ?? structuredError ?? run.error ?? signalError ?? (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined) ?? ((emptyOutputError || missingRequiredOutputError) && run.stderr.trim() ? run.stderr.trim() : undefined) ?? emptyOutputError ?? (missingRequiredOutputAfterMutation ? missingRequiredOutputError : undefined) ?? (hiddenError?.hasError ? hiddenError.details ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}` : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}` : undefined);
1510
- const error = formatSubagentExtensionConflictError(underlyingError ?? missingRequiredOutputError ?? completionEvidence.legacyFailureError, {
1511
- agent: step.agent,
1512
- ambientExtensionsEnabled: launchResolvedExtensions?.disableAmbientExtensions === false
1513
- });
1514
- const attempt = omitUndefinedProperties({
1515
- model: candidate ?? run.model ?? step.model ?? "default",
1516
- success: effectiveExitCode === 0 && !error,
1517
- exitCode: effectiveExitCode,
1518
- error,
1519
- usage: run.usage
1520
- });
1521
- modelAttempts.push(attempt);
1522
- if (!recoveringAbort && candidate && startupAttemptIndex === 0)
1523
- attemptedModels.push(candidate);
1524
- completionGuardTriggeredFinal = completionEvidence.guardTriggered && !underlyingError && !missingRequiredOutputError;
996
+ const effectiveExitCode = toolAvailabilityError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError ? 1 : hiddenError?.hasError ? hiddenError.exitCode ?? 1 : run.error && run.exitCode === 0 ? 1 : run.exitCode;
997
+ const underlyingError = toolAvailabilityError ?? midToolExitError ?? structuredError ?? run.error ?? emptyOutputError ?? (missingRequiredOutputAfterMutation ? missingRequiredOutputError : undefined) ?? (hiddenError?.hasError ? hiddenError.details ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}` : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}` : undefined);
998
+ const error = underlyingError ?? missingRequiredOutputError;
1525
999
  finalOutputSnapshot = outputSnapshot;
1526
1000
  if (step.toolBudget) {
1527
1001
  const toolMessages = run.messages.filter((message) => message.role === "toolResult");
@@ -1529,21 +1003,23 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1529
1003
  toolBudgetBlocked = Boolean(blockedMessage);
1530
1004
  toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? blockedMessage.toolName : undefined);
1531
1005
  }
1532
- const settlementDiagnostic = projectSettlementDiagnostic(completionEvidence, {
1533
- terminalFailed: effectiveExitCode !== 0,
1006
+ const settlementDiagnostic = effectiveExitCode !== 0 ? {
1534
1007
  finalTextPresent: Boolean(stripAcceptanceReport(run.finalOutput).trim()),
1535
- mutationObserved: mutationEvidence.attemptedMutation,
1536
- requiredOutput,
1008
+ mutation: { attempted: mutationAttemptObserved, observed: mutationEvidence.attemptedMutation },
1009
+ ...requiredOutput ? { requiredOutput } : {},
1537
1010
  afterCompactionSettlement: run.afterCompactionSettlement === true
1538
- });
1539
- const fileMutationEffect = completionEvidence.fileMutation ?? (missingRequiredOutputAfterMutation ? { status: "observed", expected: completionEvidence.mutationExpected, attempted: true, evidence: mutationEvidence } : undefined);
1540
- finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...step.agentContract ? { agentContract: step.agentContract } : {}, ...fileMutationEffect || settlementDiagnostic ? { effects: { ...fileMutationEffect ? { fileMutation: fileMutationEffect } : {}, ...settlementDiagnostic ? { settlementDiagnostic } : {} } } : {} };
1541
- const abortRecovery = !attempt.success ? planAbortRecovery({
1011
+ } : undefined;
1012
+ const fileMutationEffect = missingRequiredOutputAfterMutation ? { status: "observed", attempted: true, evidence: mutationEvidence } : undefined;
1013
+ finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, structuredOutputFailed: structuredError ? true : undefined, runtimeAcknowledgedExtensions, ...step.agentContract ? { agentContract: step.agentContract } : {}, ...fileMutationEffect || settlementDiagnostic ? { effects: { ...fileMutationEffect ? { fileMutation: fileMutationEffect } : {}, ...settlementDiagnostic ? { settlementDiagnostic } : {} } } : {} };
1014
+ if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.())
1015
+ break singleLaunch;
1016
+ if (effectiveExitCode === 0 && !error)
1017
+ break singleLaunch;
1018
+ const recovery = planAbortRecovery({
1542
1019
  messages: run.messages,
1543
1020
  error,
1544
- processSignal: run.processSignal,
1545
1021
  sessionAvailable: Boolean(step.sessionFile && fs.existsSync(step.sessionFile)),
1546
- alreadyResumed: abortRecoveryAttempted,
1022
+ alreadyResumed: attemptIndex > 0,
1547
1023
  stopped: run.stopped || ctx.stopSignal?.aborted || ctx.skipAcceptance?.(),
1548
1024
  interrupted: run.interrupted,
1549
1025
  timedOut: run.timedOut || ctx.timeoutSignal?.aborted,
@@ -1553,90 +1029,24 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError : external.error;
1553
1029
  acceptanceFailed: false,
1554
1030
  currentTool: run.currentTool,
1555
1031
  afterCompactionSettlement: run.afterCompactionSettlement
1556
- }) : undefined;
1557
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) {
1558
- attempt.error = attempt.error ? `${abortRecovery.diagnostic}
1559
- ${attempt.error.slice(0, 8000)}` : abortRecovery.diagnostic;
1560
- if (finalResult)
1561
- finalResult.abortRecoveryDiagnostic = abortRecovery.diagnostic;
1562
- }
1563
- if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.())
1564
- break modelAttemptsLoop;
1565
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic)
1566
- break modelAttemptsLoop;
1567
- if (attempt.success)
1568
- break modelAttemptsLoop;
1569
- if (recoveringAbort)
1570
- break modelAttemptsLoop;
1571
- if (abortRecovery?.action === "resume") {
1572
- abortRecoveryAttempted = true;
1573
- nextAttemptTask = abortRecovery.prompt;
1574
- attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
1575
- continue;
1576
- }
1577
- if (completionEvidence.guardTriggered)
1578
- break modelAttemptsLoop;
1579
- const startupFailure = isRetryableSubagentStartupFailure(omitUndefinedProperties({
1580
- exitCode: effectiveExitCode,
1581
- error,
1582
- finalOutput: run.finalOutput,
1583
- messageCount: run.messages.length,
1584
- toolCount: run.toolCount,
1585
- usage: run.usage,
1586
- durationMs: run.durationMs,
1587
- protocolError: run.protocolError,
1588
- processSignal: run.processSignal,
1589
- observedMutationAttempt: run.observedMutationAttempt,
1590
- interrupted: run.interrupted,
1591
- timedOut: run.timedOut,
1592
- stopped: run.stopped
1593
- }));
1594
- const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
1595
- if (startupFailure && retryDelayMs !== undefined) {
1596
- const retryNote = formatSubagentStartupRetryNote({
1597
- model: attempt.model,
1598
- attempt: startupAttemptIndex + 1,
1599
- maxAttempts: SUBAGENT_STARTUP_RETRY_DELAYS_MS.length + 1,
1600
- delayMs: retryDelayMs
1601
- });
1602
- const shouldRetry = await waitForSubagentStartupRetry(retryDelayMs, [ctx.timeoutSignal, ctx.stopSignal]);
1603
- if (!shouldRetry || ctx.skipAcceptance?.())
1604
- break modelAttemptsLoop;
1605
- if (!taskDeliveryOverride && run.processSignal === "SIGKILL") {
1606
- taskDeliveryOverride = "file";
1607
- attemptNotes.push("[startup-retry] retrying with file task delivery to keep the task text out of the child process argv.");
1608
- }
1609
- attempt.error = retryNote;
1610
- attemptNotes.push(retryNote);
1611
- startupAttemptIndex += 1;
1612
- continue;
1032
+ });
1033
+ if (recovery.action === "resume") {
1034
+ recoveryTask = recovery.prompt;
1035
+ continue singleLaunch;
1613
1036
  }
1614
- if (startupFailure) {
1615
- const startupError = formatSubagentStartupRetryExhaustedError({
1616
- model: attempt.model,
1617
- attempts: startupAttemptIndex + 1
1618
- });
1619
- attempt.error = startupError;
1620
- finalResult.error = startupError;
1621
- finalResult.finalOutput = startupError;
1622
- break modelAttemptsLoop;
1037
+ if (recovery.diagnostic) {
1038
+ finalResult.abortRecoveryDiagnostic = recovery.diagnostic;
1623
1039
  }
1624
- const retryableModelFailure = isRetryableModelFailureAttempt({ error, messages: run.messages, toolCount: run.toolCount });
1625
- if (retryableModelFailure)
1626
- recordRetryableModelFailure(candidate ?? run.model ?? step.model, error);
1627
1040
  if (isContextOverflow(error)) {
1628
1041
  contextOverflow = true;
1629
- attemptNotes.push(`[fallback] ${attempt.model} failed: context overflow — the input exceeds this model's context window. Reduce the task input or use a model with a larger context window.`);
1630
- break modelAttemptsLoop;
1042
+ break singleLaunch;
1631
1043
  }
1632
- if (!retryableModelFailure || modelIndex === candidates.length - 1)
1633
- break modelAttemptsLoop;
1634
- attemptNotes.push(formatModelAttemptNote(attempt, candidates[modelIndex + 1]));
1635
- modelIndex += 1;
1636
- startupAttemptIndex = 0;
1044
+ break singleLaunch;
1637
1045
  }
1638
1046
  const rawOutput = finalResult?.finalOutput ?? "";
1639
- const outputForPersistence = stripAcceptanceReport(rawOutput);
1047
+ let outputForPersistence = stripAcceptanceReport(rawOutput);
1048
+ if (!outputForPersistence.trim() && finalResult?.structuredOutput !== undefined)
1049
+ outputForPersistence = JSON.stringify(finalResult.structuredOutput, null, 2);
1640
1050
  const resolvedOutput = step.outputPath && finalResult?.exitCode === 0 ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot, step.outputClaimPath) : { fullOutput: outputForPersistence };
1641
1051
  if (resolvedOutput.fatalError) {
1642
1052
  if (finalResult) {
@@ -1648,12 +1058,6 @@ ${resolvedOutput.saveError}` : resolvedOutput.saveError;
1648
1058
  const output = stripAcceptanceReport(resolvedOutput.fullOutput);
1649
1059
  const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;
1650
1060
  let outputForSummary = output;
1651
- if (attemptNotes.length > 0) {
1652
- outputForSummary = `${attemptNotes.join(`
1653
- `)}
1654
-
1655
- ${outputForSummary}`.trim();
1656
- }
1657
1061
  if (finalResult?.stopped && !outputForSummary.trim()) {
1658
1062
  outputForSummary = ctx.stopMessage ?? "Subagent stopped by user.";
1659
1063
  }
@@ -1692,18 +1096,24 @@ ${timeoutRecovery.message}` : timeoutRecovery.message;
1692
1096
  reportError: structuredAcceptanceReportError,
1693
1097
  fileOutput: childWrittenOutput !== undefined && step.outputPath ? { content: childWrittenOutput, path: step.outputPath, authoritative: step.outputMode === "file-only", durable: resolvedOutput.savedPath !== undefined } : undefined,
1694
1098
  cwd: step.cwd ?? ctx.cwd,
1099
+ stagedIndexBaseline,
1695
1100
  signal: combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]),
1696
1101
  abortMessage: ctx.stopSignal?.aborted ? ctx.stopMessage ?? "Subagent stopped by user." : ctx.timeoutMessage ?? "Subagent timed out.",
1697
- reportOptional: isAgentContractV1(step.agentContract),
1102
+ reportOptional: isAgentContract(step.agentContract),
1698
1103
  artifactsDir: ctx.artifactsDir,
1699
- runId: ctx.id
1104
+ runId: ctx.id,
1105
+ watchdog: finalResult?.watchdog
1700
1106
  })) : undefined;
1701
1107
  const stoppedAfterAcceptance = finalResult?.stopped === true || ctx.stopSignal?.aborted === true;
1702
1108
  const timedOutAfterAcceptance = !stoppedAfterAcceptance && (finalResult?.timedOut === true || ctx.timeoutSignal?.aborted === true);
1703
1109
  const effectiveAcceptance = step.effectiveAcceptance ? stoppedAfterAcceptance ? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: "stopped", message: "Acceptance was not evaluated because the subagent was stopped." }) : timedOutAfterAcceptance ? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: "timeout", message: "Acceptance was not evaluated because the subagent timed out." }) : acceptance : undefined;
1704
1110
  const acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;
1705
- const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !isAgentContractV1(step.agentContract);
1111
+ const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !isAgentContract(step.agentContract);
1706
1112
  const effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;
1113
+ const typedGate = typedVerifyOutput(effectiveAcceptance);
1114
+ if (typedGate && finalResult && finalResult.structuredOutput === undefined && effectiveFinalExitCode === 0) {
1115
+ finalResult = { ...finalResult, structuredOutput: typedGate.value };
1116
+ }
1707
1117
  const intercomDetachReceipt = finalResult?.finalOutput === INTERCOM_DETACH_RECEIPT;
1708
1118
  const baseFinalError = stoppedAfterAcceptance ? ctx.stopMessage ?? "Subagent stopped by user." : timedOutAfterAcceptance ? finalResult?.error ?? ctx.timeoutMessage ?? "Subagent timed out." : acceptanceCanFailRun ? finalResult?.error ? `${finalResult.error}
1709
1119
  ${acceptanceFailure}` : acceptanceFailure : finalResult?.error ?? (intercomDetachReceipt ? INTERCOM_DETACH_RECEIPT : undefined);
@@ -1713,7 +1123,7 @@ ${acceptanceFailure}` : acceptanceFailure : finalResult?.error ?? (intercomDetac
1713
1123
  abortRecoveryDiagnostic: effectiveFinalExitCode !== 0 ? finalResult?.abortRecoveryDiagnostic : undefined,
1714
1124
  requiredOutput: effectiveFinalExitCode !== 0 ? finalResult?.effects?.settlementDiagnostic?.requiredOutput : undefined
1715
1125
  });
1716
- const usage = usageFromAttempts(modelAttempts);
1126
+ const usage = launched ? aggregateUsage : undefined;
1717
1127
  const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false ? persistStepArtifacts({
1718
1128
  artifactPaths,
1719
1129
  artifactConfig: ctx.artifactConfig,
@@ -1729,8 +1139,8 @@ ${acceptanceFailure}` : acceptanceFailure : finalResult?.error ?? (intercomDetac
1729
1139
  task: PROMPT_REDACTED,
1730
1140
  exitCode: effectiveFinalExitCode,
1731
1141
  model: finalResult?.model,
1732
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1733
- modelAttempts,
1142
+ nativeMachine: finalResult?.nativeMachine,
1143
+ requestedModel: step.requestedModel,
1734
1144
  usage,
1735
1145
  error: effectiveFinalError,
1736
1146
  acceptance: effectiveAcceptance,
@@ -1754,42 +1164,41 @@ ${acceptanceFailure}` : acceptanceFailure : finalResult?.error ?? (intercomDetac
1754
1164
  outputState,
1755
1165
  exitCode: effectiveFinalExitCode,
1756
1166
  error: effectiveFinalError,
1757
- protocolError: finalResult?.protocolError,
1758
1167
  sessionFile: step.sessionFile,
1759
1168
  intercomTarget: ctx.childIntercomTarget,
1760
1169
  model: finalResult?.model,
1761
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1762
- modelAttempts,
1170
+ nativeMachine: finalResult?.nativeMachine,
1171
+ thinking: resolveEffectiveThinking(finalResult?.model, step.thinking),
1172
+ requestedModel: step.requestedModel,
1763
1173
  contextOverflow: contextOverflow || undefined,
1764
- totalCost: costSummaryFromAttempts(modelAttempts),
1174
+ totalCost: costSummaryFromUsage(usage),
1765
1175
  usage,
1766
1176
  artifactPaths,
1177
+ savedOutputPath: finalizedOutput.savedPath,
1767
1178
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join(`
1768
1179
  `) || undefined,
1180
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
1769
1181
  metadataSaveError: artifactErrors.metadataSaveError,
1770
1182
  transcriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,
1771
1183
  transcriptError: transcriptWriter?.getError(),
1772
1184
  interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance ? false : finalResult?.interrupted,
1773
1185
  timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
1774
1186
  stopped: stoppedAfterAcceptance ? true : finalResult?.stopped,
1775
- processSignal: finalResult?.processSignal,
1776
1187
  timeoutRecovery,
1777
1188
  toolBudget,
1778
1189
  toolBudgetBlocked: toolBudgetBlocked || undefined,
1779
- completionGuardTriggered: completionGuardTriggeredFinal,
1780
1190
  ...finalResult?.effects ? { effects: finalResult.effects } : {},
1781
- structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : finalResult?.structuredOutput,
1782
- structuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.outputPath,
1783
- structuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : effectiveStructuredOutput?.schemaPath,
1191
+ structuredOutput: finalResult?.structuredOutput,
1192
+ structuredOutputFailed: finalResult?.structuredOutputFailed,
1193
+ structuredOutputPath: effectiveStructuredOutput?.outputPath,
1194
+ structuredOutputSchemaPath: effectiveStructuredOutput?.schemaPath,
1784
1195
  acceptance: effectiveAcceptance,
1785
1196
  watchdog: finalResult?.watchdog,
1786
1197
  ...capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {},
1787
1198
  launchResolvedExtensions,
1788
- ...finalResult?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: finalResult.runtimeAcknowledgedExtensions } : {},
1789
- writerProcesses,
1790
- writerAttemptCount
1199
+ ...finalResult?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: finalResult.runtimeAcknowledgedExtensions } : {}
1791
1200
  });
1792
- return isAgentContractV1(step.agentContract) ? attachContractProjections(result) : result;
1201
+ return isAgentContract(step.agentContract) ? attachContractProjections(result) : result;
1793
1202
  }
1794
1203
  async function runSingleStep(step, ctx) {
1795
1204
  if (!step.importAsyncRoot)
@@ -1832,6 +1241,10 @@ function requiredStatusStep(statusPayload, index) {
1832
1241
  function setStatusWorktreeReference(statusStep, worktree) {
1833
1242
  statusStep.worktreePath = worktree.path;
1834
1243
  statusStep.branch = worktree.branch;
1244
+ if (worktree.provider)
1245
+ statusStep.provider = worktree.provider;
1246
+ if (worktree.naming)
1247
+ statusStep.naming = worktree.naming;
1835
1248
  }
1836
1249
  function markParallelGroupSetupFailure(input) {
1837
1250
  for (let taskIndex = 0;taskIndex < input.group.parallel.length; taskIndex++) {
@@ -1840,12 +1253,15 @@ function markParallelGroupSetupFailure(input) {
1840
1253
  const task = input.group.parallel[taskIndex];
1841
1254
  if (!task)
1842
1255
  throw new Error(`Missing parallel task at index ${taskIndex}`);
1843
- statusStep.status = "failed";
1256
+ const stopped = statusStep.stopped || statusStep.stopRequested || input.statusPayload.stopped;
1257
+ const paused = !stopped && input.statusPayload.state === "paused";
1258
+ statusStep.status = stopped ? "stopped" : paused ? "paused" : "failed";
1844
1259
  statusStep.startedAt = input.failedAt;
1845
1260
  statusStep.endedAt = input.failedAt;
1846
1261
  statusStep.durationMs = 0;
1847
- statusStep.exitCode = 1;
1848
- input.results.push(omitUndefinedProperties({ agent: task.agent, context: task.context, output: input.setupError, success: false, exitCode: 1, sessionFile: task.sessionFile }));
1262
+ statusStep.exitCode = paused ? 0 : 1;
1263
+ statusStep.error ??= input.setupError;
1264
+ input.results.push(omitUndefinedProperties({ agent: task.agent, context: task.context, output: input.setupError, error: input.setupError, success: false, exitCode: paused ? 0 : 1, sessionFile: task.sessionFile, stopped: stopped || undefined, interrupted: paused || undefined, timedOut: input.statusPayload.timedOut || undefined }));
1849
1265
  }
1850
1266
  input.statusPayload.currentStep = input.groupStartFlatIndex;
1851
1267
  input.statusPayload.lastUpdate = input.failedAt;
@@ -1886,12 +1302,24 @@ function markParallelGroupRunning(input) {
1886
1302
  count: input.group.parallel.length
1887
1303
  }));
1888
1304
  }
1305
+ function bindWorktreeCwd(step, worktreeCwd) {
1306
+ const bind = (value) => value === null || value === undefined ? value : value.replaceAll(WORKTREE_AGENT_CWD_PLACEHOLDER, worktreeCwd);
1307
+ return {
1308
+ ...step,
1309
+ task: bind(step.task) ?? step.task,
1310
+ ...step.systemPrompt !== undefined ? { systemPrompt: bind(step.systemPrompt) } : {},
1311
+ ...step.outputPath !== undefined ? { outputPath: bind(step.outputPath) } : {},
1312
+ ...step.launchBindingTask !== undefined ? { launchBindingTask: bind(step.launchBindingTask) } : {},
1313
+ ...step.requestedCwd !== undefined ? { requestedCwd: bind(step.requestedCwd) } : {}
1314
+ };
1315
+ }
1889
1316
  function prepareParallelTaskRun(task, cwd, worktreeSetup, taskIndex) {
1890
1317
  if (!worktreeSetup)
1891
1318
  return { taskForRun: task, taskCwd: cwd };
1892
1319
  const { cwd: _taskCwd, ...taskForRun } = task;
1320
+ const boundTask = bindWorktreeCwd(taskForRun, worktreeSetup.worktrees[taskIndex].agentCwd);
1893
1321
  return {
1894
- taskForRun,
1322
+ taskForRun: boundTask,
1895
1323
  taskCwd: worktreeSetup.worktrees[taskIndex].agentCwd
1896
1324
  };
1897
1325
  }
@@ -1916,8 +1344,12 @@ function missingRequiredOutputAfterUsefulMutation(result) {
1916
1344
  return effects?.settlementDiagnostic?.requiredOutput?.missing === true && (effects.settlementDiagnostic.mutation.attempted || effects.fileMutation?.attempted === true || Boolean(effects.fileMutation?.evidence?.changedFiles.length));
1917
1345
  }
1918
1346
  function partialExecutionWithUsefulMutation(result) {
1347
+ if (result.execution?.status !== "partial")
1348
+ return false;
1349
+ if (result.runner?.type === "external-cli" && result.runner.machine)
1350
+ return true;
1919
1351
  const fileMutation = result.effects?.fileMutation;
1920
- return result.execution?.status === "partial" && (fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length));
1352
+ return fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length);
1921
1353
  }
1922
1354
  function partialEvidenceResult(result) {
1923
1355
  return missingRequiredOutputAfterUsefulMutation(result) || partialExecutionWithUsefulMutation(result);
@@ -1944,7 +1376,10 @@ function combinedAbortSignal(signals) {
1944
1376
  }
1945
1377
  async function runSingleStepWithTimeout(step, ctx, parentDeadlineAt) {
1946
1378
  if (step.timeoutMs === undefined)
1947
- return runSingleStep(step, ctx);
1379
+ return runSingleStep(step, parentDeadlineAt === undefined ? ctx : {
1380
+ ...ctx,
1381
+ deadlineAt: ctx.deadlineAt === undefined ? parentDeadlineAt : Math.min(ctx.deadlineAt, parentDeadlineAt)
1382
+ });
1948
1383
  const parentRemainingMs = parentDeadlineAt === undefined ? undefined : Math.max(0, parentDeadlineAt - Date.now());
1949
1384
  const timeoutMs = parentRemainingMs === undefined ? step.timeoutMs : Math.min(step.timeoutMs, parentRemainingMs);
1950
1385
  const timeoutMessage = parentRemainingMs !== undefined && parentRemainingMs <= step.timeoutMs ? ctx.timeoutMessage : `Subagent timed out after ${step.timeoutMs}ms.`;
@@ -1979,7 +1414,7 @@ async function runSingleStepWithTimeout(step, ctx, parentDeadlineAt) {
1979
1414
  ctx.registerTimeout?.(undefined);
1980
1415
  }
1981
1416
  }
1982
- async function runSubagent(config, onWriterProcess) {
1417
+ export async function runSubagent(config, childSessions) {
1983
1418
  const { id, steps, resultPath, cwd, placeholder, taskIndex, totalTasks, maxOutput, artifactsDir, artifactConfig } = config;
1984
1419
  const globalSemaphore = new Semaphore(config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);
1985
1420
  let previousOutput = "";
@@ -1997,13 +1432,15 @@ async function runSubagent(config, onWriterProcess) {
1997
1432
  const activeChildInterrupts = new Map;
1998
1433
  const activeChildTimeouts = new Map;
1999
1434
  const activeChildStops = new Map;
1435
+ const activeChildSteers = new Map;
1436
+ const queuedStepSteers = new Map;
2000
1437
  const childStopRequests = new Map;
2001
1438
  const pendingStepSteers = [];
2002
- const steeringCapabilities = new Map;
2003
1439
  let interrupted = false;
2004
1440
  let currentActivityState;
2005
1441
  let activityTimer;
2006
1442
  let timeoutTimer;
1443
+ let checkpointTimer;
2007
1444
  let timedOut = false;
2008
1445
  let stopped = false;
2009
1446
  let usageBudgetExceeded = false;
@@ -2011,6 +1448,9 @@ async function runSubagent(config, onWriterProcess) {
2011
1448
  const stopMessage = "Subagent stopped by user.";
2012
1449
  const timeoutAbortController = new AbortController;
2013
1450
  const stopAbortController = new AbortController;
1451
+ const setupInterruptController = new AbortController;
1452
+ const runStopSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal]);
1453
+ const setupSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal, setupInterruptController.signal]);
2014
1454
  let previousCumulativeTokens = { input: 0, output: 0, total: 0 };
2015
1455
  let latestSessionFile;
2016
1456
  const flatSteps = flattenSteps(steps);
@@ -2050,7 +1490,7 @@ async function runSubagent(config, onWriterProcess) {
2050
1490
  model: task.model,
2051
1491
  ...task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {},
2052
1492
  thinking: task.thinking,
2053
- attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
1493
+ requestedModel: task.requestedModel,
2054
1494
  recentTools: [],
2055
1495
  recentOutput: []
2056
1496
  }));
@@ -2104,7 +1544,7 @@ async function runSubagent(config, onWriterProcess) {
2104
1544
  model: step.model,
2105
1545
  ...step.contextLimit !== undefined ? { contextLimit: step.contextLimit } : {},
2106
1546
  thinking: step.thinking,
2107
- attemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,
1547
+ requestedModel: step.requestedModel,
2108
1548
  recentTools: [],
2109
1549
  recentOutput: []
2110
1550
  }));
@@ -2168,22 +1608,32 @@ async function runSubagent(config, onWriterProcess) {
2168
1608
  },
2169
1609
  onError: (error, filePath) => console.error(`Failed to update async run index '${filePath}':`, error)
2170
1610
  });
2171
- const queueActiveRunIndex = () => {
2172
- const state = statusPayload.state;
1611
+ const queueActiveRunIndex = (status) => {
1612
+ const state = status.state;
2173
1613
  if (state === lastIndexedStatusState && indexPersistence.pendingCount() === 0)
2174
1614
  return;
2175
- indexPersistence.write(asyncDir, { state, toolCallId: statusPayload.toolCallId }, (_filePath, payload) => {
1615
+ indexPersistence.write(asyncDir, { state, toolCallId: status.toolCallId }, (_filePath, payload) => {
2176
1616
  const indexPayload = payload;
2177
1617
  updateActiveRunIndex(asyncDir, indexPayload.state, indexPayload.toolCallId, { retryCapacityErrors: true });
2178
1618
  });
2179
1619
  };
1620
+ let finalResultCommitted = false;
1621
+ let finalResultPublication;
2180
1622
  const runPersistence = createCapacityResilientJsonWriter({
2181
1623
  keepAlive: true,
2182
- onSuccess: (filePath) => {
1624
+ onSuccess: (filePath, payload) => {
2183
1625
  if (filePath === statusPath)
2184
- queueActiveRunIndex();
1626
+ queueActiveRunIndex(payload);
1627
+ if (filePath === resultPath && finalResultPublication) {
1628
+ finalResultCommitted = true;
1629
+ finalResultPublication.resolve();
1630
+ }
2185
1631
  },
2186
- onError: (error, filePath) => console.error(`Failed to persist async run state '${filePath}':`, error)
1632
+ onError: (error, filePath) => {
1633
+ console.error(`Failed to persist async run state '${filePath}':`, error);
1634
+ if (filePath === resultPath)
1635
+ finalResultPublication?.reject(error);
1636
+ }
2187
1637
  });
2188
1638
  try {
2189
1639
  fs.mkdirSync(asyncDir, { recursive: true });
@@ -2192,7 +1642,7 @@ async function runSubagent(config, onWriterProcess) {
2192
1642
  throw error;
2193
1643
  console.error(`Failed to prepare async run storage '${asyncDir}' while storage is full:`, error);
2194
1644
  }
2195
- runPersistence.write(statusPath, statusPayload);
1645
+ runPersistence.write(statusPath, { ...statusPayload });
2196
1646
  let pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
2197
1647
  const currentUsageTotals = () => {
2198
1648
  const cost = results.reduce((sum, result) => ({
@@ -2210,6 +1660,11 @@ async function runSubagent(config, onWriterProcess) {
2210
1660
  setOptionalProperty(statusPayload, "usageBudget", usageBudgetState(config.usageBudget, currentUsageTotals()));
2211
1661
  return statusPayload.usageBudget;
2212
1662
  };
1663
+ let continuationUsageUncertain = config.steps.some(isDynamicRunnerGroup) || flatSteps.some((step) => Boolean(step.runner || step.importAsyncRoot));
1664
+ const continuationUsageBudgetExhausted = () => {
1665
+ const exhausted = refreshUsageBudget()?.exhausted === true;
1666
+ return exhausted ? true : config.usageBudget && continuationUsageUncertain ? undefined : false;
1667
+ };
2213
1668
  const emitNestedSelfEvent = (type) => {
2214
1669
  if (!config.nestedRoute || !config.nestedSelf)
2215
1670
  return;
@@ -2278,7 +1733,6 @@ async function runSubagent(config, onWriterProcess) {
2278
1733
  updateNode(node);
2279
1734
  statusPayload.workflowGraph = graph;
2280
1735
  };
2281
- let finalResultCommitted = false;
2282
1736
  const statusResultState = () => {
2283
1737
  if (statusPayload.state === "running" || statusPayload.state === "queued")
2284
1738
  return;
@@ -2335,9 +1789,8 @@ async function runSubagent(config, onWriterProcess) {
2335
1789
  success: statusResultSuccess(state, step),
2336
1790
  sessionFile: step.sessionFile,
2337
1791
  model: step.model,
2338
- attemptedModels: step.attemptedModels,
2339
- modelAttempts: step.modelAttempts,
2340
- usage: usageFromAttempts(step.modelAttempts),
1792
+ thinking: step.thinking,
1793
+ requestedModel: step.requestedModel,
2341
1794
  contextOverflow: step.contextOverflow
2342
1795
  })),
2343
1796
  exitCode: state === "complete" || state === "paused" ? 0 : 1,
@@ -2351,14 +1804,16 @@ async function runSubagent(config, onWriterProcess) {
2351
1804
  }), (filePath, payload) => writePendingAsyncResultFile(filePath, payload));
2352
1805
  };
2353
1806
  const writeStatusPayloadNow = () => {
1807
+ if (finalResultPublication)
1808
+ return;
2354
1809
  refreshWorkflowGraph();
2355
1810
  writeRecoverableStatusResult();
2356
- runPersistence.write(statusPath, statusPayload);
1811
+ runPersistence.write(statusPath, { ...statusPayload });
2357
1812
  emitNestedSelfEvent(statusPayload.state === "running" || statusPayload.state === "queued" ? "subagent.nested.updated" : "subagent.nested.completed");
2358
1813
  };
2359
1814
  const statusWriteCoalescer = createFileCoalescer(writeStatusPayloadNow, 100);
2360
1815
  const writeStatusPayload = (immediate = true) => {
2361
- if (immediate || statusPayload.state !== "running" || statusPayload.activityState !== undefined) {
1816
+ if (immediate || statusPayload.state !== "running") {
2362
1817
  if (!statusWriteCoalescer.flush(statusPath))
2363
1818
  writeStatusPayloadNow();
2364
1819
  return;
@@ -2483,6 +1938,17 @@ async function runSubagent(config, onWriterProcess) {
2483
1938
  if (stopped || childStopRequests.has(flatIndex))
2484
1939
  stop();
2485
1940
  };
1941
+ const registerStepSteer = (flatIndex, steer) => {
1942
+ if (!steer) {
1943
+ activeChildSteers.delete(flatIndex);
1944
+ return;
1945
+ }
1946
+ activeChildSteers.set(flatIndex, steer);
1947
+ const queued = queuedStepSteers.get(flatIndex);
1948
+ queuedStepSteers.delete(flatIndex);
1949
+ for (const request of queued ?? [])
1950
+ steerLiveChild(flatIndex, request);
1951
+ };
2486
1952
  const interruptActiveChildren = () => {
2487
1953
  for (const interrupt of [...activeChildInterrupts.values()])
2488
1954
  interrupt();
@@ -2502,6 +1968,7 @@ async function runSubagent(config, onWriterProcess) {
2502
1968
  yield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));
2503
1969
  }
2504
1970
  };
1971
+ const isNestedControlDescendant = (run) => !config.nestedSelf || run.path.some((entry) => entry.runId === id);
2505
1972
  const interruptNestedAsyncDescendants = () => {
2506
1973
  if (!config.nestedRoute)
2507
1974
  return;
@@ -2518,7 +1985,7 @@ async function runSubagent(config, onWriterProcess) {
2518
1985
  return;
2519
1986
  }
2520
1987
  for (const run of nestedRuns(registry.children)) {
2521
- if (run.state !== "running" && run.state !== "queued")
1988
+ if (!isNestedControlDescendant(run) || run.state !== "running" && run.state !== "queued")
2522
1989
  continue;
2523
1990
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2524
1991
  if (!nestedAsyncDir)
@@ -2552,7 +2019,7 @@ async function runSubagent(config, onWriterProcess) {
2552
2019
  return;
2553
2020
  }
2554
2021
  for (const run of nestedRuns(registry.children)) {
2555
- if (run.state !== "running" && run.state !== "queued")
2022
+ if (!isNestedControlDescendant(run) || run.state !== "running" && run.state !== "queued")
2556
2023
  continue;
2557
2024
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2558
2025
  if (!nestedAsyncDir)
@@ -2586,7 +2053,7 @@ async function runSubagent(config, onWriterProcess) {
2586
2053
  return;
2587
2054
  }
2588
2055
  for (const run of nestedRuns(registry.children)) {
2589
- if (run.state !== "running" && run.state !== "queued")
2056
+ if (!isNestedControlDescendant(run) || run.state !== "running" && run.state !== "queued")
2590
2057
  continue;
2591
2058
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2592
2059
  if (!nestedAsyncDir)
@@ -2645,6 +2112,7 @@ async function runSubagent(config, onWriterProcess) {
2645
2112
  }
2646
2113
  const appendedSteps = requests.flatMap((request) => request.steps);
2647
2114
  steps.push(...appendedSteps);
2115
+ flatSteps.push(...flattenSteps(appendedSteps));
2648
2116
  const now = Date.now();
2649
2117
  const pendingAppends = countPendingChainAppendRequests(asyncDir);
2650
2118
  const added = appendRunnerStepsToStatus({
@@ -2680,9 +2148,64 @@ async function runSubagent(config, onWriterProcess) {
2680
2148
  setOptionalProperty(groupNode, "error", error);
2681
2149
  setOptionalProperty(groupNode, "acceptanceStatus", acceptance?.status ?? groupNode.acceptanceStatus);
2682
2150
  };
2151
+ const EXTERNAL_GIT_PROBE_MIN_INTERVAL_MS = 2000;
2152
+ const externalActivityEvidence = new Map;
2153
+ const gitProbesByCwd = new Map;
2154
+ let periodicGitProbeFailure;
2155
+ const reportedGitProbeErrors = new Set;
2156
+ const reportGitProbeError = (externalCwd, error) => {
2157
+ if (reportedGitProbeErrors.has(externalCwd))
2158
+ return;
2159
+ reportedGitProbeErrors.add(externalCwd);
2160
+ const detail = error instanceof Error ? error.message : String(error);
2161
+ console.error(`[dm-subagents] Git activity evidence unavailable for '${externalCwd.slice(-300)}'; check the cwd and Git installation: ${detail.slice(0, 500)}`);
2162
+ };
2163
+ const readSharedGitFingerprint = (externalCwd) => {
2164
+ const inFlight = gitProbesByCwd.get(externalCwd);
2165
+ if (inFlight)
2166
+ return inFlight;
2167
+ const probe = readGitFingerprint(externalCwd, runStopSignal, (error) => reportGitProbeError(externalCwd, error)).finally(() => gitProbesByCwd.delete(externalCwd));
2168
+ gitProbesByCwd.set(externalCwd, probe);
2169
+ return probe;
2170
+ };
2171
+ const recordPeriodicGitProbeFailure = (index, error) => {
2172
+ if (periodicGitProbeFailure)
2173
+ return;
2174
+ const cause = error instanceof Error ? error : new Error(String(error));
2175
+ const message = `PROCESS_TREE_UNVERIFIED: ${cause.message}`;
2176
+ periodicGitProbeFailure = { index, error: cause, message };
2177
+ statusPayload.error = message;
2178
+ const step = statusPayload.steps[index];
2179
+ if (step)
2180
+ step.error = message;
2181
+ statusPayload.lastUpdate = Date.now();
2182
+ writeStatusPayload();
2183
+ appendJsonl(eventsPath, JSON.stringify({
2184
+ type: "subagent.run.process_tree_unverified",
2185
+ ts: statusPayload.lastUpdate,
2186
+ runId: id,
2187
+ index,
2188
+ code: "PROCESS_TREE_UNVERIFIED",
2189
+ message
2190
+ }));
2191
+ };
2192
+ const prepareExternalActivity = async (index, externalCwd, signal) => {
2193
+ if (!controlConfig.enabled)
2194
+ return;
2195
+ const resolvedCwd = path.resolve(externalCwd);
2196
+ const evidence = { cwd: resolvedCwd, lastProbeStartedAt: performance.now() };
2197
+ externalActivityEvidence.set(index, evidence);
2198
+ evidence.fingerprint = await readGitFingerprint(resolvedCwd, signal, (error) => reportGitProbeError(resolvedCwd, error));
2199
+ };
2200
+ const recordExternalStreamActivity = (index) => {
2201
+ const evidence = externalActivityEvidence.get(index) ?? {};
2202
+ externalActivityEvidence.set(index, evidence);
2203
+ evidence.lastStreamActivityAt = Date.now();
2204
+ };
2683
2205
  const stepOutputActivityAt = (index) => {
2684
2206
  const step = statusPayload.steps[index];
2685
2207
  let lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;
2208
+ lastActivityAt = Math.max(lastActivityAt, externalActivityEvidence.get(index)?.lastStreamActivityAt ?? 0);
2686
2209
  const outputPath = path.join(asyncDir, `output-${index}.log`);
2687
2210
  try {
2688
2211
  lastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);
@@ -2934,23 +2457,15 @@ async function runSubagent(config, onWriterProcess) {
2934
2457
  return { index, state: "scheduled" };
2935
2458
  if (step.status !== "running")
2936
2459
  return { index, state: "failed", reason: `child is ${step.status}` };
2937
- if (steeringCapabilities.get(index)?.supported === false)
2938
- return { index, state: "failed", reason: "child DM session does not support steering" };
2939
2460
  return { index, state: "routed" };
2940
2461
  });
2941
2462
  recordSteeringLifecycle(request, targetStates);
2942
2463
  emitSteeringEvent("subagent.steer.requested", request, undefined, { targets: targetStates });
2943
2464
  for (const target of targetStates) {
2944
2465
  if (target.state === "routed") {
2945
- try {
2946
- enqueueStepSteer(asyncDir, target.index, request);
2947
- updateSteeringLifecycleTarget(request.id, target.index, "routed", now);
2948
- emitSteeringEvent("subagent.steer.routed", request, target.index);
2949
- } catch (error) {
2950
- markSteeringAttention(target.index);
2951
- updateSteeringLifecycleTarget(request.id, target.index, "failed", now, { reason: error instanceof Error ? error.message : String(error) });
2952
- emitSteeringEvent("subagent.steer.failed", request, target.index, { reason: error instanceof Error ? error.message : String(error) });
2953
- }
2466
+ updateSteeringLifecycleTarget(request.id, target.index, "routed", now);
2467
+ emitSteeringEvent("subagent.steer.routed", request, target.index);
2468
+ steerLiveChild(target.index, request);
2954
2469
  } else if (target.state === "failed") {
2955
2470
  markSteeringAttention(target.index);
2956
2471
  emitSteeringEvent("subagent.steer.failed", request, target.index, { reason: target.reason });
@@ -2962,28 +2477,43 @@ async function runSubagent(config, onWriterProcess) {
2962
2477
  statusPayload.lastUpdate = now;
2963
2478
  writeStatusPayload();
2964
2479
  };
2965
- const consumeSteerAck = (ack) => {
2480
+ const applySteerDelivery = (requestId, index, delivery) => {
2966
2481
  const lifecycle = steeringStatus(statusPayload);
2967
- const request = lifecycle.recent.find((candidate) => candidate.id === ack.requestId);
2968
- if (!request || !request.targets.some((target) => target.index === ack.index))
2482
+ const request = lifecycle.recent.find((candidate) => candidate.id === requestId);
2483
+ const target = request?.targets.find((candidate) => candidate.index === index);
2484
+ if (!request || !target)
2485
+ return;
2486
+ if (target.state === "delivered" || target.state === "late" || target.state === "failed")
2969
2487
  return;
2970
- const late = fs.existsSync(steeringMarkerPath(ack.requestId));
2488
+ if (target.state === delivery.state)
2489
+ return;
2490
+ const late = fs.existsSync(steeringMarkerPath(requestId));
2971
2491
  const now = Date.now();
2972
- if (ack.state === "delivered") {
2973
- updateSteeringLifecycleTarget(ack.requestId, ack.index, late ? "late" : "delivered", now, omitUndefinedProperties({ reason: late ? "acknowledged after recovery commit" : undefined }));
2974
- emitSteeringEvent("subagent.steer.delivered", { type: "steer", id: ack.requestId, ts: now, message: ack.message }, ack.index, { late, deliveryStatus: "delivered", message: ack.message });
2975
- } else if (ack.state === "queued") {
2976
- updateSteeringLifecycleTarget(ack.requestId, ack.index, "queued", now);
2977
- emitSteeringEvent("subagent.steer.queued", { type: "steer", id: ack.requestId, ts: now, message: ack.message }, ack.index, { deliveryStatus: "queued", message: ack.message });
2492
+ if (delivery.state === "delivered") {
2493
+ updateSteeringLifecycleTarget(requestId, index, late ? "late" : "delivered", now, omitUndefinedProperties({ reason: late ? "acknowledged after recovery commit" : undefined }));
2494
+ emitSteeringEvent("subagent.steer.delivered", { type: "steer", id: requestId, ts: now, message: delivery.message }, index, { late, deliveryStatus: "delivered", message: delivery.message });
2495
+ } else if (delivery.state === "queued") {
2496
+ updateSteeringLifecycleTarget(requestId, index, "queued", now);
2497
+ emitSteeringEvent("subagent.steer.queued", { type: "steer", id: requestId, ts: now, message: delivery.message }, index, { deliveryStatus: "queued", message: delivery.message });
2978
2498
  } else {
2979
- markSteeringAttention(ack.index);
2980
- updateSteeringLifecycleTarget(ack.requestId, ack.index, "failed", now, { reason: ack.message });
2981
- emitSteeringEvent("subagent.steer.failed", { type: "steer", id: ack.requestId, ts: now, message: ack.message }, ack.index, { reason: ack.message });
2499
+ markSteeringAttention(index);
2500
+ updateSteeringLifecycleTarget(requestId, index, "failed", now, { reason: delivery.message });
2501
+ emitSteeringEvent("subagent.steer.failed", { type: "steer", id: requestId, ts: now, message: delivery.message }, index, { reason: delivery.message });
2982
2502
  }
2983
- emitTerminalSteeringNotice(ack.requestId, `Steering failed for run ${id}: ${ack.message}`);
2503
+ emitTerminalSteeringNotice(requestId, `Steering failed for run ${id}: ${delivery.message}`);
2984
2504
  statusPayload.lastUpdate = now;
2985
2505
  writeStatusPayload();
2986
2506
  };
2507
+ const steerLiveChild = (index, request) => {
2508
+ const steer = activeChildSteers.get(index);
2509
+ if (!steer) {
2510
+ const queued = queuedStepSteers.get(index) ?? [];
2511
+ queued.push(request);
2512
+ queuedStepSteers.set(index, queued);
2513
+ return;
2514
+ }
2515
+ steer(request).then((delivery) => applySteerDelivery(request.id, index, delivery), (error) => applySteerDelivery(request.id, index, { state: "failed", message: error instanceof Error ? error.message : String(error) }));
2516
+ };
2987
2517
  const flushPendingStepSteers = (flatIndex) => {
2988
2518
  const remaining = [];
2989
2519
  for (const request of pendingStepSteers.splice(0)) {
@@ -3010,6 +2540,7 @@ async function runSubagent(config, onWriterProcess) {
3010
2540
  const step = statusPayload.steps[flatIndex];
3011
2541
  if (!step)
3012
2542
  return;
2543
+ const previousActivityState = step.activityState;
3013
2544
  const now = Date.now();
3014
2545
  statusPayload.currentStep = flatIndex;
3015
2546
  if (isChildWatchdogStatusEvent(event)) {
@@ -3029,6 +2560,16 @@ async function runSubagent(config, onWriterProcess) {
3029
2560
  writeStatusPayload(false);
3030
2561
  return;
3031
2562
  }
2563
+ if (event.type === "message_end") {
2564
+ const next = applyChildWatchdogMessage(step.watchdog, event.message);
2565
+ if (next)
2566
+ step.watchdog = next;
2567
+ if (next && event.message?.role === "custom") {
2568
+ statusPayload.lastUpdate = now;
2569
+ writeStatusPayload(false);
2570
+ return;
2571
+ }
2572
+ }
3032
2573
  if (event.type === "tool_execution_start" && event.toolName) {
3033
2574
  const mutates = isMutatingTool(event.toolName, event.args, flatSteps[flatIndex]?.mutationTools);
3034
2575
  const currentPath = resolveCurrentPath(event.toolName, event.args);
@@ -3064,6 +2605,7 @@ async function runSubagent(config, onWriterProcess) {
3064
2605
  tokens: step.tokens?.total,
3065
2606
  toolCount: step.toolCount,
3066
2607
  currentTool: step.currentTool,
2608
+ toolCallId: event.toolCallId,
3067
2609
  currentToolDurationMs: 0,
3068
2610
  currentPath: step.currentPath
3069
2611
  })));
@@ -3138,6 +2680,11 @@ async function runSubagent(config, onWriterProcess) {
3138
2680
  `).slice(-10));
3139
2681
  step.turnCount = (step.turnCount ?? 0) + 1;
3140
2682
  const usage = event.message.usage;
2683
+ if (config.usageBudget) {
2684
+ const known = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
2685
+ if (!known(usage?.input ?? usage?.inputTokens) || !known(usage?.output ?? usage?.outputTokens))
2686
+ continuationUsageUncertain = true;
2687
+ }
3141
2688
  if (usage) {
3142
2689
  const input = usage.input ?? usage.inputTokens ?? 0;
3143
2690
  const output = usage.output ?? usage.outputTokens ?? 0;
@@ -3157,9 +2704,9 @@ async function runSubagent(config, onWriterProcess) {
3157
2704
  statusPayload.lastActivityAt = now;
3158
2705
  statusPayload.lastUpdate = now;
3159
2706
  maybeEmitActiveLongRunning(flatIndex, now);
3160
- writeStatusPayload(false);
2707
+ writeStatusPayload(step.activityState !== previousActivityState);
3161
2708
  };
3162
- const updateRunnerActivityState = (now) => {
2709
+ const updateRunnerActivityState = (now, skipExternalProbeIndex) => {
3163
2710
  if (!controlConfig.enabled)
3164
2711
  return false;
3165
2712
  let changed = false;
@@ -3178,11 +2725,37 @@ async function runSubagent(config, onWriterProcess) {
3178
2725
  config: controlConfig,
3179
2726
  startedAt: step.startedAt ?? overallStartTime,
3180
2727
  lastActivityAt,
2728
+ turnCount: flatSteps[index]?.runner?.type === "external-cli" ? 1 : step.turnCount,
3181
2729
  currentTool: step.currentTool,
3182
2730
  thinking: step.thinking,
3183
2731
  now
3184
2732
  }));
3185
2733
  if (idleState === "needs_attention") {
2734
+ const evidence = externalActivityEvidence.get(index);
2735
+ if (index !== skipExternalProbeIndex && evidence?.cwd && evidence.fingerprint) {
2736
+ if (evidence.probeInFlight)
2737
+ continue;
2738
+ if (performance.now() - (evidence.lastProbeStartedAt ?? 0) >= EXTERNAL_GIT_PROBE_MIN_INTERVAL_MS) {
2739
+ evidence.lastProbeStartedAt = performance.now();
2740
+ const baseline = evidence.fingerprint;
2741
+ evidence.probeInFlight = readSharedGitFingerprint(evidence.cwd).then((fingerprint) => {
2742
+ if (requiredStatusStep(statusPayload, index).status !== "running")
2743
+ return;
2744
+ if (fingerprint && fingerprint !== baseline) {
2745
+ evidence.fingerprint = fingerprint;
2746
+ evidence.lastStreamActivityAt = Date.now();
2747
+ updateRunnerActivityState(Date.now());
2748
+ } else {
2749
+ updateRunnerActivityState(Date.now(), index);
2750
+ }
2751
+ }).catch((error) => {
2752
+ recordPeriodicGitProbeFailure(index, error);
2753
+ }).finally(() => {
2754
+ delete evidence.probeInFlight;
2755
+ });
2756
+ continue;
2757
+ }
2758
+ }
3186
2759
  const previous = step.activityState;
3187
2760
  step.activityState = "needs_attention";
3188
2761
  if (previous !== "needs_attention") {
@@ -3227,11 +2800,88 @@ async function runSubagent(config, onWriterProcess) {
3227
2800
  }, 1000);
3228
2801
  activityTimer.unref?.();
3229
2802
  }
2803
+ const publishSetupUnknown = (progress) => {
2804
+ if (!progress.unknown)
2805
+ return;
2806
+ const proof = {
2807
+ version: 1,
2808
+ state: "unknown",
2809
+ runId: id,
2810
+ runnerProcessInstanceId: config.runnerProcessInstanceId ?? "unknown",
2811
+ reason: "process-tree-unverified",
2812
+ diagnostic: `Worktree setup settlement unknown: ${progress.unknown}; manual reconciliation required; ${parallelHandoffPath(asyncDir)}`
2813
+ };
2814
+ statusPayload.processTerminal = proof;
2815
+ writeAtomicJson(processTerminalPath(asyncDir), proof);
2816
+ };
2817
+ const finalizeWorktree = async (setup, stepIndex, flatStartIndex, action, deadlineAt) => {
2818
+ let admitted = false;
2819
+ try {
2820
+ await Promise.all([...externalActivityEvidence.values()].map((evidence) => evidence.probeInFlight).filter((probe) => probe !== undefined));
2821
+ if (periodicGitProbeFailure)
2822
+ throw periodicGitProbeFailure.error;
2823
+ await withWorktreeTransaction(() => {
2824
+ if (deadlineAt !== undefined && Date.now() >= deadlineAt)
2825
+ throw new Error("Run deadline expired before worktree cleanup");
2826
+ admitted = true;
2827
+ action();
2828
+ });
2829
+ } catch (error) {
2830
+ if (admitted)
2831
+ throw error;
2832
+ const reason = `Worktree finalization retained; manual reconciliation required: ${error instanceof Error ? error.message : String(error)}`;
2833
+ statusPayload.parallelHandoff = writeParallelHandoffGroup({
2834
+ manifestPath: parallelHandoffPath(asyncDir),
2835
+ runId: id,
2836
+ mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : (config.resultMode ?? statusPayload.mode) === "single" ? "single" : "chain",
2837
+ source: "async",
2838
+ cwd,
2839
+ stepIndex,
2840
+ flatStartIndex,
2841
+ setup,
2842
+ diffs: [],
2843
+ results: [],
2844
+ cleanup: { state: "partial", pruned: false, errors: [reason], tasks: setup.worktrees.map((worktree) => ({
2845
+ index: worktree.index,
2846
+ path: worktree.path,
2847
+ branch: worktree.branch,
2848
+ provider: worktree.provider,
2849
+ naming: worktree.naming,
2850
+ worktreeRemoved: false,
2851
+ branchRemoved: false,
2852
+ preserved: true,
2853
+ reason
2854
+ })) }
2855
+ });
2856
+ previousOutput = [previousOutput, reason, formatParallelHandoffReference(statusPayload.parallelHandoff)].filter(Boolean).join(`
2857
+
2858
+ `);
2859
+ writeStatusPayload();
2860
+ }
2861
+ };
2862
+ const cleanupRemainingWorktree = (setup, stepIndex, flatStartIndex) => finalizeWorktree(setup, stepIndex, flatStartIndex, () => {
2863
+ const cleanup = cleanupWorktrees(setup);
2864
+ statusPayload.parallelHandoff = writeParallelHandoffGroup({
2865
+ manifestPath: parallelHandoffPath(asyncDir),
2866
+ runId: id,
2867
+ mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : (config.resultMode ?? statusPayload.mode) === "single" ? "single" : "chain",
2868
+ source: "async",
2869
+ cwd,
2870
+ stepIndex,
2871
+ flatStartIndex,
2872
+ setup,
2873
+ diffs: [],
2874
+ results: [],
2875
+ cleanup
2876
+ });
2877
+ writeStatusPayload();
2878
+ }, config.deadlineAt);
3230
2879
  const interruptRunner = () => {
3231
2880
  consumeInterruptRequest(asyncDir);
3232
2881
  if (interrupted || statusPayload.state !== "running")
3233
2882
  return;
3234
2883
  interrupted = true;
2884
+ setupInterruptController.abort();
3235
2885
  const now = Date.now();
3236
2886
  statusPayload.state = "paused";
3237
2887
  currentActivityState = undefined;
@@ -3256,17 +2906,18 @@ async function runSubagent(config, onWriterProcess) {
3256
2906
  interruptActiveChildren();
3257
2907
  };
3258
2908
  const stopRunner = () => {
3259
- if (stopped || timedOut || interrupted || statusPayload.state !== "running")
2909
+ if (stopped || timedOut || statusPayload.state !== "running" && statusPayload.state !== "paused")
3260
2910
  return;
3261
2911
  stopped = true;
2912
+ interrupted = false;
3262
2913
  const now = Date.now();
3263
2914
  statusPayload.stopped = true;
3264
2915
  statusPayload.error = stopMessage;
3265
2916
  currentActivityState = undefined;
3266
2917
  delete statusPayload.activityState;
3267
2918
  statusPayload.lastUpdate = now;
3268
- for (const step of statusPayload.steps) {
3269
- if (step.status !== "running" && step.status !== "pending")
2919
+ for (const [index, step] of statusPayload.steps.entries()) {
2920
+ if (step.status !== "running" && step.status !== "pending" && step.status !== "paused")
3270
2921
  continue;
3271
2922
  step.status = "stopped";
3272
2923
  step.error = stopMessage;
@@ -3276,6 +2927,9 @@ async function runSubagent(config, onWriterProcess) {
3276
2927
  step.endedAt = now;
3277
2928
  step.durationMs = step.startedAt ? now - step.startedAt : 0;
3278
2929
  step.lastActivityAt = now;
2930
+ const result = results[index];
2931
+ if (result?.interrupted)
2932
+ results[index] = { ...result, output: stopMessage, error: stopMessage, exitCode: 1, success: false, interrupted: false, stopped: true };
3279
2933
  }
3280
2934
  writeStatusPayload();
3281
2935
  appendJsonl(eventsPath, JSON.stringify({
@@ -3340,30 +2994,35 @@ async function runSubagent(config, onWriterProcess) {
3340
2994
  deliverSteerRequest(request);
3341
2995
  pendingStepSteers.push(request);
3342
2996
  }
3343
- },
3344
- onSteerCapability: (capability) => {
3345
- steeringCapabilities.set(capability.index, capability);
3346
- if (!capability.supported) {
3347
- const now = Date.now();
3348
- const lifecycle = steeringStatus(statusPayload);
3349
- for (const request of lifecycle.recent) {
3350
- if (!request.targets.some((target) => target.index === capability.index && (target.state === "routed" || target.state === "scheduled")))
3351
- continue;
3352
- markSteeringAttention(capability.index);
3353
- updateSteeringLifecycleTarget(request.id, capability.index, "failed", now, { reason: "child DM session does not support steering" });
3354
- emitSteeringEvent("subagent.steer.failed", { type: "steer", id: request.id, ts: request.requestedAt, message: "child DM session does not support steering" }, capability.index, { reason: "child DM session does not support steering" });
3355
- emitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: child ${capability.index} does not support steering.`);
3356
- }
3357
- statusPayload.lastUpdate = now;
3358
- writeStatusPayload();
3359
- }
3360
- },
3361
- onSteerAck: consumeSteerAck
2997
+ }
3362
2998
  });
3363
2999
  if (config.deadlineAt !== undefined) {
3364
3000
  const remainingMs = Math.max(0, config.deadlineAt - Date.now());
3365
3001
  timeoutTimer = setTimeout(timeoutRunner, remainingMs);
3366
3002
  timeoutTimer.unref?.();
3003
+ const checkpointBeforeDeadlineMs = config.checkpointBeforeDeadlineMs;
3004
+ const checkpointDelayMs = checkpointBeforeDeadlineMs === undefined || !Number.isInteger(checkpointBeforeDeadlineMs) || checkpointBeforeDeadlineMs <= 0 ? undefined : remainingMs - checkpointBeforeDeadlineMs;
3005
+ if (checkpointDelayMs !== undefined && checkpointDelayMs >= 1000) {
3006
+ const deadlineAt = config.deadlineAt;
3007
+ checkpointTimer = setTimeout(() => {
3008
+ checkpointTimer = undefined;
3009
+ if (timedOut || stopped || interrupted)
3010
+ return;
3011
+ if (!statusPayload.steps.some((step) => step.status === "running"))
3012
+ return;
3013
+ const now = Date.now();
3014
+ const seconds = Math.round(Math.max(0, deadlineAt - now) / 1000);
3015
+ deliverSteerRequest({
3016
+ type: "steer",
3017
+ id: `deadline-checkpoint-${now}`,
3018
+ ts: now,
3019
+ mode: "steer",
3020
+ source: "deadline-checkpoint",
3021
+ message: `Deadline checkpoint from the runner: this run is killed in about ${seconds} seconds. Finish the current tool call only, then stop and reply with a handoff: changed files, build/test state, remaining work, and commit/PR state. Do not start new work.`
3022
+ });
3023
+ }, checkpointDelayMs);
3024
+ checkpointTimer.unref?.();
3025
+ }
3367
3026
  }
3368
3027
  appendJsonl(eventsPath, JSON.stringify({
3369
3028
  type: "subagent.run.started",
@@ -3406,10 +3065,7 @@ async function runSubagent(config, onWriterProcess) {
3406
3065
  const thinkingOverride = step.thinkingOverrides?.[itemIndex];
3407
3066
  const model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;
3408
3067
  const configThinking = thinkingOverride ? thinkingOverride : step.parallel.thinking;
3409
- const candidates = step.parallel.modelCandidates !== undefined ? step.parallel.modelCandidates.length > 0 ? step.parallel.modelCandidates.map((candidate) => thinkingOverride ? applyThinkingSuffix(candidate, thinkingOverride, true) ?? candidate : candidate) : [undefined] : model ? [model] : [undefined];
3410
- for (const candidate of candidates) {
3411
- assertThinkingWithinCeiling({ model: candidate, configThinking, ceiling: step.parallel.thinkingCeiling ?? decodeThinkingCeiling(process.env[SUBAGENT_THINKING_CEILING_ENV]), agent: step.parallel.agent, runId: id });
3412
- }
3068
+ assertThinkingWithinCeiling({ model, configThinking, ceiling: step.parallel.thinkingCeiling, agent: step.parallel.agent, runId: id });
3413
3069
  }
3414
3070
  if (materialized.collectedOnEmpty)
3415
3071
  await validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);
@@ -3477,14 +3133,14 @@ async function runSubagent(config, onWriterProcess) {
3477
3133
  cwd,
3478
3134
  signal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),
3479
3135
  abortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? "Subagent timed out.",
3480
- reportOptional: isAgentContractV1(step.agentContract)
3136
+ reportOptional: isAgentContract(step.agentContract)
3481
3137
  })) : undefined;
3482
3138
  const groupStopped = stopped || stopAbortController.signal.aborted;
3483
3139
  const groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);
3484
3140
  const effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;
3485
3141
  if (placeholder && effectiveGroupAcceptance)
3486
3142
  placeholder.acceptance = effectiveGroupAcceptance;
3487
- const groupAcceptanceFailure = effectiveGroupAcceptance && (!isAgentContractV1(step.agentContract) || step.gateOn === "acceptance") ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
3143
+ const groupAcceptanceFailure = effectiveGroupAcceptance && (!isAgentContract(step.agentContract) || step.gateOn === "acceptance") ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
3488
3144
  if (groupTimedOut || groupStopped || groupAcceptanceFailure) {
3489
3145
  const errorMessage = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? "Subagent timed out." : groupAcceptanceFailure;
3490
3146
  statusPayload.state = groupStopped ? "stopped" : "failed";
@@ -3538,11 +3194,7 @@ async function runSubagent(config, onWriterProcess) {
3538
3194
  ...step.sessionFiles?.[itemIndex] ? { sessionFile: step.sessionFiles[itemIndex] } : {},
3539
3195
  ...thinkingOverride ? {
3540
3196
  ...model ? { model } : {},
3541
- ...thinking ? { thinking } : {},
3542
- ...step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.flatMap((candidate) => {
3543
- const resolved = applyThinkingSuffix(candidate, thinkingOverride, true);
3544
- return resolved ? [resolved] : [];
3545
- }) } : {}
3197
+ ...thinking ? { thinking } : {}
3546
3198
  } : {},
3547
3199
  structuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema
3548
3200
  });
@@ -3569,7 +3221,7 @@ async function runSubagent(config, onWriterProcess) {
3569
3221
  ...task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {},
3570
3222
  ...task.thinking ? { thinking: task.thinking } : {},
3571
3223
  ...task.thinkingCeiling ? { thinkingCeiling: task.thinkingCeiling } : {},
3572
- ...task.modelCandidates && task.modelCandidates.length > 0 ? { attemptedModels: task.modelCandidates } : task.model ? { attemptedModels: [task.model] } : {},
3224
+ ...task.requestedModel ? { requestedModel: task.requestedModel } : {},
3573
3225
  recentTools: [],
3574
3226
  recentOutput: []
3575
3227
  });
@@ -3687,11 +3339,9 @@ async function runSubagent(config, onWriterProcess) {
3687
3339
  flatIndex: fi,
3688
3340
  flatStepCount: Math.max(statusPayload.steps.length, 1),
3689
3341
  outputFile: path.join(asyncDir, `output-${fi}.log`),
3690
- steerInboxDir: stepSteerInboxDir(asyncDir, fi),
3691
- steerCapabilityPath: steerCapabilityPath(asyncDir, fi),
3692
- steerAckDir: steerAcksDir(asyncDir, fi),
3693
3342
  piPackageRoot: config.piPackageRoot,
3694
- piArgv1: config.piArgv1,
3343
+ childSessions,
3344
+ inheritedChildRuntime: config.inheritedChildRuntime,
3695
3345
  childIntercomTarget: config.childIntercomTargets?.[fi],
3696
3346
  orchestratorIntercomTarget: config.controlIntercomTarget,
3697
3347
  nestedRoute: config.nestedRoute,
@@ -3700,25 +3350,28 @@ async function runSubagent(config, onWriterProcess) {
3700
3350
  registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
3701
3351
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
3702
3352
  registerStop: (stop) => registerStepStop(fi, stop),
3353
+ registerSteer: (steer) => registerStepSteer(fi, steer),
3354
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
3703
3355
  timeoutSignal: timeoutAbortController.signal,
3704
3356
  stopSignal: stopAbortController.signal,
3705
- trackedMutationEvidenceForCompletionGuard: false,
3706
3357
  timeoutMessage,
3707
3358
  stopMessage,
3708
3359
  toolTimeoutMs: task.toolTimeoutMs ?? config.toolTimeoutMs,
3709
3360
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
3710
3361
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
3711
- onWriterProcess,
3712
3362
  onExternalProcess: (process) => updateExternalProcess(fi, process),
3363
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
3364
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
3713
3365
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
3714
3366
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
3715
- usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
3367
+ usageBudgetExhausted: continuationUsageBudgetExhausted,
3368
+ usageBudget: config.usageBudget,
3716
3369
  orcaProgressTab
3717
3370
  }), config.deadlineAt);
3718
3371
  const taskEndTime = Date.now();
3719
3372
  const childInterrupted = singleResult.interrupted === true;
3720
3373
  const childStopped = singleResult.stopped === true;
3721
- requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
3374
+ requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
3722
3375
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
3723
3376
  requiredStatusStep(statusPayload, fi).durationMs = taskEndTime - taskStartTime;
3724
3377
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -3733,8 +3386,7 @@ async function runSubagent(config, onWriterProcess) {
3733
3386
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
3734
3387
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
3735
3388
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
3736
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
3737
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
3389
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
3738
3390
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
3739
3391
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
3740
3392
  if (singleResult.totalCost) {
@@ -3798,8 +3450,7 @@ async function runSubagent(config, onWriterProcess) {
3798
3450
  output: pr.output,
3799
3451
  outputState: pr.outputState,
3800
3452
  error: pr.error,
3801
- protocolError: pr.protocolError,
3802
- success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
3453
+ success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
3803
3454
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
3804
3455
  skipped: pr.skipped,
3805
3456
  interrupted: pr.interrupted,
@@ -3810,12 +3461,14 @@ async function runSubagent(config, onWriterProcess) {
3810
3461
  sessionFile: pr.sessionFile,
3811
3462
  intercomTarget: pr.intercomTarget,
3812
3463
  model: pr.model,
3813
- attemptedModels: pr.attemptedModels,
3814
- modelAttempts: pr.modelAttempts,
3464
+ thinking: pr.thinking,
3465
+ requestedModel: pr.requestedModel,
3815
3466
  contextOverflow: pr.contextOverflow,
3816
3467
  totalCost: pr.totalCost,
3817
3468
  usage: pr.usage,
3818
3469
  artifactPaths: pr.artifactPaths,
3470
+ outputSaveError: pr.outputSaveError,
3471
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
3819
3472
  transcriptPath: pr.transcriptPath,
3820
3473
  transcriptError: pr.transcriptError,
3821
3474
  effects: pr.effects,
@@ -3823,6 +3476,7 @@ async function runSubagent(config, onWriterProcess) {
3823
3476
  review: pr.review,
3824
3477
  timeoutRecovery: pr.timeoutRecovery,
3825
3478
  structuredOutput: pr.structuredOutput,
3479
+ structuredOutputFailed: pr.structuredOutputFailed,
3826
3480
  structuredOutputPath: pr.structuredOutputPath,
3827
3481
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
3828
3482
  acceptance: pr.acceptance,
@@ -3835,7 +3489,7 @@ async function runSubagent(config, onWriterProcess) {
3835
3489
  refreshUsageBudget();
3836
3490
  const collection = collectDynamicResults(step, materialized.items, parallelResults);
3837
3491
  const failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
3838
- const acceptanceFailures = parallelResults.map((result, originalIndex) => ({ result, originalIndex, task: dynamicSteps[originalIndex] })).filter(({ result, task }) => isAgentContractV1(task?.agentContract ?? step.agentContract) && task?.gateOn === "acceptance" && result.acceptance?.status === "rejected");
3492
+ const acceptanceFailures = parallelResults.map((result, originalIndex) => ({ result, originalIndex, task: dynamicSteps[originalIndex] })).filter(({ result, task }) => isAgentContract(task?.agentContract ?? step.agentContract) && task?.gateOn === "acceptance" && result.acceptance?.status === "rejected");
3839
3493
  if (acceptanceFailures.length > 0) {
3840
3494
  const message = acceptanceFailures.map(({ result, originalIndex }) => `Dynamic item ${originalIndex + 1} (${result.agent}, key ${materialized.items[originalIndex]?.key ?? originalIndex}) acceptance rejected: ${(result.acceptance ? acceptanceFailureMessage(result.acceptance) : undefined) ?? "acceptance rejected"}`).join(`
3841
3495
  `);
@@ -3863,12 +3517,12 @@ async function runSubagent(config, onWriterProcess) {
3863
3517
  cwd,
3864
3518
  signal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),
3865
3519
  abortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? "Subagent timed out.",
3866
- reportOptional: isAgentContractV1(step.agentContract)
3520
+ reportOptional: isAgentContract(step.agentContract)
3867
3521
  })) : undefined;
3868
3522
  const groupStopped = stopped || stopAbortController.signal.aborted;
3869
3523
  const groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);
3870
3524
  const effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;
3871
- const groupAcceptanceFailure = effectiveDynamicGroupAcceptance.explicit && effectiveGroupAcceptance && (!isAgentContractV1(step.agentContract) || step.gateOn === "acceptance") ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
3525
+ const groupAcceptanceFailure = effectiveDynamicGroupAcceptance.explicit && effectiveGroupAcceptance && (!isAgentContract(step.agentContract) || step.gateOn === "acceptance") ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
3872
3526
  const groupError = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? "Subagent timed out." : groupAcceptanceFailure;
3873
3527
  markDynamicGraphGroup(stepIndex, groupError ? groupStopped ? "stopped" : "failed" : "completed", groupError, effectiveGroupAcceptance);
3874
3528
  if (groupError) {
@@ -3945,14 +3599,22 @@ async function runSubagent(config, onWriterProcess) {
3945
3599
  break;
3946
3600
  }
3947
3601
  try {
3948
- worktreeSetup = createWorktrees(cwd, `${id}-s${stepIndex}`, group.parallel.length, omitUndefinedProperties({
3602
+ worktreeSetup = await createWorktrees(cwd, `${id}-s${stepIndex}`, group.parallel.length, omitUndefinedProperties({
3603
+ signal: setupSignal,
3604
+ deadlineAt: config.deadlineAt,
3949
3605
  agents: group.parallel.map((task) => task.agent),
3606
+ labels: group.parallel.map((task) => task.lane?.key ?? config.workflowKey ?? task.outputName ?? task.label),
3607
+ tasks: group.parallel.map((task) => task.task),
3608
+ provider: config.worktreeProvider,
3609
+ baseRef: config.baseRef,
3610
+ branchPrefix: config.worktreeBranchPrefix,
3950
3611
  setupHook: config.worktreeSetupHook ? omitUndefinedProperties({ hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs }) : undefined,
3951
3612
  baseDir: config.worktreeBaseDir,
3952
- beforeCreate: (plannedSetup) => {
3953
- for (const worktree of plannedSetup.worktrees)
3613
+ onProgress: (progress) => {
3614
+ publishSetupUnknown(progress);
3615
+ for (const worktree of progress.setup.worktrees)
3954
3616
  setStatusWorktreeReference(requiredStatusStep(statusPayload, groupStartFlatIndex + worktree.index), worktree);
3955
- const pendingHandoff = writePendingParallelHandoff({
3617
+ const pendingHandoff = writeWorktreeSetupHandoff({
3956
3618
  manifestPath: parallelHandoffPath(asyncDir),
3957
3619
  runId: id,
3958
3620
  mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : "chain",
@@ -3960,16 +3622,32 @@ async function runSubagent(config, onWriterProcess) {
3960
3622
  cwd,
3961
3623
  stepIndex,
3962
3624
  flatStartIndex: groupStartFlatIndex,
3963
- setup: plannedSetup,
3625
+ progress,
3964
3626
  laneBindings: handoffWorkflowKey || config.lane ? [{ index: groupStartFlatIndex, taskIndex: 0, ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}, ...handoffChildRunId ? { runId: handoffChildRunId } : {}, ...config.lane ? { lane: config.lane } : {} }] : undefined
3965
3627
  });
3628
+ if (!pendingHandoff)
3629
+ return;
3966
3630
  statusPayload.parallelHandoff = pendingHandoff;
3967
3631
  statusPayload.lastUpdate = Date.now();
3968
3632
  writeStatusPayload();
3969
3633
  }
3970
3634
  }));
3635
+ if (config.deadlineAt !== undefined && Date.now() >= config.deadlineAt)
3636
+ timeoutRunner();
3637
+ if (setupSignal.aborted)
3638
+ throw new Error(stopped ? stopMessage : timedOut ? timeoutMessage ?? "Subagent timed out." : "Subagent paused during worktree setup.");
3971
3639
  } catch (error) {
3640
+ if (worktreeSetup)
3641
+ await cleanupRemainingWorktree(worktreeSetup, stepIndex, groupStartFlatIndex);
3642
+ if (config.deadlineAt !== undefined && Date.now() >= config.deadlineAt)
3643
+ timeoutRunner();
3972
3644
  const setupError = error instanceof Error ? error.message : String(error);
3645
+ if (error instanceof WorktreeSetupError)
3646
+ publishSetupUnknown(error.snapshot);
3647
+ for (let index = groupStartFlatIndex;index < groupStartFlatIndex + group.parallel.length; index++) {
3648
+ if (childStopRequests.has(index))
3649
+ markChildStopped(index);
3650
+ }
3973
3651
  const failedAt = Date.now();
3974
3652
  markParallelGroupSetupFailure({
3975
3653
  statusPayload,
@@ -4099,11 +3777,9 @@ async function runSubagent(config, onWriterProcess) {
4099
3777
  flatIndex: fi,
4100
3778
  flatStepCount: Math.max(statusPayload.steps.length, 1),
4101
3779
  outputFile: path.join(asyncDir, `output-${fi}.log`),
4102
- steerInboxDir: stepSteerInboxDir(asyncDir, fi),
4103
- steerCapabilityPath: steerCapabilityPath(asyncDir, fi),
4104
- steerAckDir: steerAcksDir(asyncDir, fi),
4105
3780
  piPackageRoot: config.piPackageRoot,
4106
- piArgv1: config.piArgv1,
3781
+ childSessions,
3782
+ inheritedChildRuntime: config.inheritedChildRuntime,
4107
3783
  childIntercomTarget: config.childIntercomTargets?.[fi],
4108
3784
  orchestratorIntercomTarget: config.controlIntercomTarget,
4109
3785
  nestedRoute: config.nestedRoute,
@@ -4112,19 +3788,22 @@ async function runSubagent(config, onWriterProcess) {
4112
3788
  registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
4113
3789
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
4114
3790
  registerStop: (stop) => registerStepStop(fi, stop),
3791
+ registerSteer: (steer) => registerStepSteer(fi, steer),
3792
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
4115
3793
  timeoutSignal: timeoutAbortController.signal,
4116
3794
  stopSignal: stopAbortController.signal,
4117
- trackedMutationEvidenceForCompletionGuard: Boolean(worktreeSetup),
4118
3795
  timeoutMessage,
4119
3796
  stopMessage,
4120
3797
  toolTimeoutMs: taskForRun.toolTimeoutMs ?? config.toolTimeoutMs,
4121
3798
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
4122
3799
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
4123
- onWriterProcess,
4124
3800
  onExternalProcess: (process) => updateExternalProcess(fi, process),
3801
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
3802
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
4125
3803
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
4126
3804
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
4127
- usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
3805
+ usageBudgetExhausted: continuationUsageBudgetExhausted,
3806
+ usageBudget: config.usageBudget,
4128
3807
  orcaProgressTab
4129
3808
  }), config.deadlineAt);
4130
3809
  if (task.sessionFile) {
@@ -4134,7 +3813,7 @@ async function runSubagent(config, onWriterProcess) {
4134
3813
  const taskDuration = taskEndTime - taskStartTime;
4135
3814
  const childInterrupted = singleResult.interrupted === true;
4136
3815
  const childStopped = singleResult.stopped === true;
4137
- requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
3816
+ requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
4138
3817
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
4139
3818
  requiredStatusStep(statusPayload, fi).durationMs = taskDuration;
4140
3819
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4149,8 +3828,7 @@ async function runSubagent(config, onWriterProcess) {
4149
3828
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
4150
3829
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
4151
3830
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
4152
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
4153
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
3831
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
4154
3832
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
4155
3833
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
4156
3834
  if (singleResult.totalCost) {
@@ -4196,19 +3874,6 @@ async function runSubagent(config, onWriterProcess) {
4196
3874
  }));
4197
3875
  if (stopped || childStopped)
4198
3876
  appendTerminalChildStatusEvent(fi, taskEndTime);
4199
- if (singleResult.completionGuardTriggered) {
4200
- const event = buildControlEvent(omitUndefinedProperties({
4201
- from: requiredStatusStep(statusPayload, fi).activityState,
4202
- to: "needs_attention",
4203
- runId: id,
4204
- agent: task.agent,
4205
- index: fi,
4206
- ts: taskEndTime,
4207
- message: `${task.agent} completed without making edits for an implementation task`,
4208
- reason: "completion_guard"
4209
- }));
4210
- appendControlEvent(event);
4211
- }
4212
3877
  if (singleResult.exitCode !== 0 && failFast && !childStopped)
4213
3878
  aborted = true;
4214
3879
  return stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: singleResult.output || (timeoutMessage ?? "Subagent timed out."), error: singleResult.error ?? timeoutMessage ?? "Subagent timed out.", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };
@@ -4217,7 +3882,7 @@ async function runSubagent(config, onWriterProcess) {
4217
3882
  for (let t = 0;t < group.parallel.length; t++) {
4218
3883
  const fi = groupStartFlatIndex + t;
4219
3884
  const sessionTokens = config.sessionDir ? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`)) : null;
4220
- const fallbackTokens = tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);
3885
+ const fallbackTokens = tokenUsageFromUsage(parallelResults[t]?.usage);
4221
3886
  const observedTokens = requiredStatusStep(statusPayload, fi).tokens;
4222
3887
  const taskTokens = sessionTokens ?? (fallbackTokens ? { ...fallbackTokens, ...observedTokens?.window !== undefined ? { window: observedTokens.window } : {}, ...observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {} } : null);
4223
3888
  if (!taskTokens)
@@ -4244,8 +3909,7 @@ async function runSubagent(config, onWriterProcess) {
4244
3909
  output: pr.output,
4245
3910
  outputState: pr.outputState,
4246
3911
  error: pr.error,
4247
- protocolError: pr.protocolError,
4248
- success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
3912
+ success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
4249
3913
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
4250
3914
  skipped: pr.skipped,
4251
3915
  interrupted: pr.interrupted,
@@ -4256,12 +3920,14 @@ async function runSubagent(config, onWriterProcess) {
4256
3920
  sessionFile: pr.sessionFile,
4257
3921
  intercomTarget: pr.intercomTarget,
4258
3922
  model: pr.model,
4259
- attemptedModels: pr.attemptedModels,
4260
- modelAttempts: pr.modelAttempts,
3923
+ thinking: pr.thinking,
3924
+ requestedModel: pr.requestedModel,
4261
3925
  contextOverflow: pr.contextOverflow,
4262
3926
  totalCost: pr.totalCost,
4263
3927
  usage: pr.usage,
4264
3928
  artifactPaths: pr.artifactPaths,
3929
+ outputSaveError: pr.outputSaveError,
3930
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
4265
3931
  transcriptPath: pr.transcriptPath,
4266
3932
  transcriptError: pr.transcriptError,
4267
3933
  effects: pr.effects,
@@ -4269,6 +3935,7 @@ async function runSubagent(config, onWriterProcess) {
4269
3935
  review: pr.review,
4270
3936
  timeoutRecovery: pr.timeoutRecovery,
4271
3937
  structuredOutput: pr.structuredOutput,
3938
+ structuredOutputFailed: pr.structuredOutputFailed,
4272
3939
  structuredOutputPath: pr.structuredOutputPath,
4273
3940
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
4274
3941
  acceptance: pr.acceptance,
@@ -4293,66 +3960,69 @@ async function runSubagent(config, onWriterProcess) {
4293
3960
  exitCode: r.exitCode,
4294
3961
  error: r.error,
4295
3962
  model: r.model,
4296
- attemptedModels: r.attemptedModels
3963
+ requestedModel: r.requestedModel
4297
3964
  })));
4298
3965
  if (worktreeSetup) {
4299
- const captured = captureParallelWorktreeDiffs(worktreeSetup, asyncDir, stepIndex, group);
4300
- if (captured.summary)
4301
- previousOutput = `${previousOutput}
3966
+ const setup = worktreeSetup;
3967
+ worktreeFinalized = true;
3968
+ await finalizeWorktree(setup, stepIndex, groupStartFlatIndex, () => {
3969
+ const captured = captureParallelWorktreeDiffs(setup, asyncDir, stepIndex, group);
3970
+ if (captured.summary)
3971
+ previousOutput = `${previousOutput}
4302
3972
 
4303
3973
  ${captured.summary}`;
4304
- worktreeFinalized = true;
4305
- const manifestPath = parallelHandoffPath(asyncDir);
4306
- const handoff = {
4307
- manifestPath,
4308
- runId: id,
4309
- mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : "chain",
4310
- source: "async",
4311
- cwd,
4312
- stepIndex,
4313
- flatStartIndex: groupStartFlatIndex,
4314
- setup: worktreeSetup,
4315
- diffs: captured.diffs,
4316
- results: parallelResults.map((result) => ({
4317
- agent: result.agent,
4318
- ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {},
4319
- ...handoffChildRunId ? { runId: handoffChildRunId } : {},
4320
- ...config.lane ? { lane: config.lane } : {},
4321
- status: result.stopped || result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
4322
- processSignal: result.processSignal,
4323
- interrupted: result.interrupted,
4324
- timedOut: result.timedOut,
4325
- stopped: result.stopped
4326
- })) ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
4327
- summary: result.output || result.error || "(no output)",
4328
- ...result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {},
4329
- ...result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {},
4330
- ...result.structuredOutputPath ? { structuredOutputPath: result.structuredOutputPath } : {},
4331
- ...result.sessionFile ? { sessionPath: result.sessionFile } : {}
4332
- }))
4333
- };
4334
- try {
4335
- writeParallelHandoffGroup(handoff);
4336
- const cleanup = cleanupWorktrees(worktreeSetup, { kind: "preserve", capturedDiffs: captured.diffs, handoffManifestPath: manifestPath });
4337
- statusPayload.parallelHandoff = writeParallelHandoffGroup({ ...handoff, cleanup });
4338
- previousOutput = `${previousOutput}
3974
+ const manifestPath = parallelHandoffPath(asyncDir);
3975
+ const handoff = {
3976
+ manifestPath,
3977
+ runId: id,
3978
+ mode: (config.resultMode ?? statusPayload.mode) === "parallel" ? "parallel" : "chain",
3979
+ source: "async",
3980
+ cwd,
3981
+ stepIndex,
3982
+ flatStartIndex: groupStartFlatIndex,
3983
+ setup,
3984
+ diffs: captured.diffs,
3985
+ results: parallelResults.map((result) => ({
3986
+ agent: result.agent,
3987
+ ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {},
3988
+ ...handoffChildRunId ? { runId: handoffChildRunId } : {},
3989
+ ...config.lane ? { lane: config.lane } : {},
3990
+ status: result.stopped || result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
3991
+ processSignal: result.processSignal,
3992
+ interrupted: result.interrupted,
3993
+ timedOut: result.timedOut,
3994
+ stopped: result.stopped
3995
+ })) ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
3996
+ summary: result.output || result.error || "(no output)",
3997
+ ...result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {},
3998
+ ...result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {},
3999
+ ...result.structuredOutputPath ? { structuredOutputPath: result.structuredOutputPath } : {},
4000
+ ...result.sessionFile ? { sessionPath: result.sessionFile } : {}
4001
+ }))
4002
+ };
4003
+ try {
4004
+ writeParallelHandoffGroup(handoff);
4005
+ const cleanup = cleanupWorktrees(setup, { kind: "preserve", capturedDiffs: captured.diffs, handoffManifestPath: manifestPath });
4006
+ statusPayload.parallelHandoff = writeParallelHandoffGroup({ ...handoff, cleanup });
4007
+ previousOutput = `${previousOutput}
4339
4008
 
4340
4009
  ${formatParallelHandoffReference(statusPayload.parallelHandoff)}`;
4341
- } catch (error) {
4342
- previousOutput = `${previousOutput}
4010
+ } catch (error) {
4011
+ previousOutput = `${previousOutput}
4343
4012
 
4344
4013
  ${formatParallelHandoffError(error)}`;
4345
- }
4346
- writeStatusPayload();
4014
+ }
4015
+ writeStatusPayload();
4016
+ });
4347
4017
  }
4348
4018
  appendJsonl(eventsPath, JSON.stringify({
4349
4019
  type: "subagent.parallel.completed",
4350
4020
  ts: Date.now(),
4351
4021
  runId: id,
4352
4022
  stepIndex,
4353
- success: parallelResults.every((r) => r.exitCode === 0 || r.exitCode === -1) && parallelResults.every((result, index) => !(isAgentContractV1(group.parallel[index]?.agentContract) && group.parallel[index]?.gateOn === "acceptance" && result.acceptance?.status === "rejected"))
4023
+ success: parallelResults.every((r) => r.exitCode === 0 || r.exitCode === -1) && parallelResults.every((result, index) => !(isAgentContract(group.parallel[index]?.agentContract) && group.parallel[index]?.gateOn === "acceptance" && result.acceptance?.status === "rejected"))
4354
4024
  }));
4355
- const acceptanceGateFailure = parallelResults.map((result, index) => ({ result, index, task: group.parallel[index] })).find(({ result, task }) => isAgentContractV1(task?.agentContract) && task?.gateOn === "acceptance" && result.acceptance?.status === "rejected");
4025
+ const acceptanceGateFailure = parallelResults.map((result, index) => ({ result, index, task: group.parallel[index] })).find(({ result, task }) => isAgentContract(task?.agentContract) && task?.gateOn === "acceptance" && result.acceptance?.status === "rejected");
4356
4026
  if (acceptanceGateFailure) {
4357
4027
  statusPayload.error = (acceptanceGateFailure.result.acceptance ? acceptanceFailureMessage(acceptanceGateFailure.result.acceptance) : undefined) ?? "Parallel acceptance gate rejected the step.";
4358
4028
  writeStatusPayload();
@@ -4363,7 +4033,7 @@ ${formatParallelHandoffError(error)}`;
4363
4033
  }
4364
4034
  } finally {
4365
4035
  if (worktreeSetup && !worktreeFinalized)
4366
- cleanupWorktrees(worktreeSetup);
4036
+ await cleanupRemainingWorktree(worktreeSetup, stepIndex, groupStartFlatIndex);
4367
4037
  }
4368
4038
  } else {
4369
4039
  const seqStep = step;
@@ -4390,16 +4060,24 @@ ${formatParallelHandoffError(error)}`;
4390
4060
  let singleWorktreeSetup;
4391
4061
  if (seqStep.worktree) {
4392
4062
  try {
4393
- singleWorktreeSetup = createWorktrees(cwd, `${id}-s${stepIndex}`, 1, omitUndefinedProperties({
4063
+ singleWorktreeSetup = await createWorktrees(cwd, `${id}-s${stepIndex}`, 1, omitUndefinedProperties({
4064
+ signal: setupSignal,
4065
+ deadlineAt: config.deadlineAt,
4394
4066
  agents: [seqStep.agent],
4067
+ labels: [seqStep.lane?.key ?? config.workflowKey ?? seqStep.outputName ?? seqStep.label],
4068
+ tasks: [seqStep.task],
4069
+ provider: config.worktreeProvider,
4070
+ baseRef: config.baseRef,
4071
+ branchPrefix: config.worktreeBranchPrefix,
4395
4072
  setupHook: config.worktreeSetupHook ? omitUndefinedProperties({ hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs }) : undefined,
4396
4073
  baseDir: config.worktreeBaseDir,
4397
- beforeCreate: (plannedSetup) => {
4398
- const worktree = plannedSetup.worktrees[0];
4074
+ onProgress: (progress) => {
4075
+ publishSetupUnknown(progress);
4076
+ const worktree = progress.setup.worktrees[0];
4399
4077
  if (worktree) {
4400
4078
  setStatusWorktreeReference(requiredStatusStep(statusPayload, flatIndex), worktree);
4401
4079
  }
4402
- const pendingHandoff = writePendingParallelHandoff({
4080
+ const pendingHandoff = writeWorktreeSetupHandoff({
4403
4081
  manifestPath: parallelHandoffPath(asyncDir),
4404
4082
  runId: id,
4405
4083
  mode: "single",
@@ -4407,20 +4085,46 @@ ${formatParallelHandoffError(error)}`;
4407
4085
  cwd,
4408
4086
  stepIndex,
4409
4087
  flatStartIndex: flatIndex,
4410
- setup: plannedSetup,
4088
+ progress,
4411
4089
  laneBindings: handoffWorkflowKey || config.lane ? [{ index: flatIndex, taskIndex: 0, ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {}, ...handoffChildRunId ? { runId: handoffChildRunId } : {}, ...config.lane ? { lane: config.lane } : {} }] : undefined
4412
4090
  });
4091
+ if (!pendingHandoff)
4092
+ return;
4413
4093
  statusPayload.parallelHandoff = pendingHandoff;
4414
4094
  statusPayload.lastUpdate = Date.now();
4415
4095
  writeStatusPayload();
4416
4096
  }
4417
4097
  }));
4418
4098
  } catch (error) {
4419
- if (singleWorktreeSetup)
4420
- cleanupWorktrees(singleWorktreeSetup);
4421
- throw error;
4099
+ if (error instanceof WorktreeSetupError)
4100
+ publishSetupUnknown(error.snapshot);
4101
+ if (config.deadlineAt !== undefined && Date.now() >= config.deadlineAt)
4102
+ timeoutRunner();
4103
+ const message = error instanceof Error ? error.message : String(error);
4104
+ if (childStopRequests.has(flatIndex))
4105
+ markChildStopped(flatIndex);
4106
+ const statusStep = requiredStatusStep(statusPayload, flatIndex);
4107
+ statusStep.status = stopped || childStopRequests.has(flatIndex) ? "stopped" : interrupted ? "paused" : "failed";
4108
+ statusStep.error ??= message;
4109
+ statusStep.exitCode = interrupted ? 0 : 1;
4110
+ statusStep.endedAt = Date.now();
4111
+ results.push(stopped ? stoppedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName) : childStopRequests.has(flatIndex) ? childStopResult(flatIndex, seqStep.agent, seqStep.context) : timedOut ? timedOutStepResult(seqStep.agent, seqStep.context, seqStep.sessionName) : interrupted ? pausedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName) : { agent: seqStep.agent, output: message, error: message, exitCode: 1, success: false });
4112
+ statusPayload.error ??= message;
4113
+ writeStatusPayload();
4114
+ flatIndex++;
4115
+ break;
4422
4116
  }
4423
4117
  }
4118
+ if (singleWorktreeSetup && config.deadlineAt !== undefined && Date.now() >= config.deadlineAt)
4119
+ timeoutRunner();
4120
+ if (singleWorktreeSetup && (timedOut || stopped || interrupted || childStopRequests.has(flatIndex))) {
4121
+ await cleanupRemainingWorktree(singleWorktreeSetup, stepIndex, flatIndex);
4122
+ results.push(stopped ? stoppedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName) : childStopRequests.has(flatIndex) ? childStopResult(flatIndex, seqStep.agent, seqStep.context) : timedOut ? timedOutStepResult(seqStep.agent, seqStep.context, seqStep.sessionName) : pausedStepResult(seqStep.agent, seqStep.context, seqStep.sessionName));
4123
+ if (interrupted)
4124
+ requiredStatusStep(statusPayload, flatIndex).status = "paused";
4125
+ flatIndex++;
4126
+ continue;
4127
+ }
4424
4128
  const singleCwd = singleWorktreeSetup?.worktrees[0]?.agentCwd ?? cwd;
4425
4129
  const stepStartTime = Date.now();
4426
4130
  statusPayload.currentStep = flatIndex;
@@ -4443,7 +4147,7 @@ ${formatParallelHandoffError(error)}`;
4443
4147
  agent: seqStep.agent
4444
4148
  }));
4445
4149
  flushPendingStepSteers(flatIndex);
4446
- const executionStep = singleWorktreeSetup ? { ...seqStep, cwd: singleCwd } : seqStep;
4150
+ const executionStep = singleWorktreeSetup ? bindWorktreeCwd({ ...seqStep, cwd: singleCwd }, singleCwd) : seqStep;
4447
4151
  let singleResult;
4448
4152
  try {
4449
4153
  singleResult = await runSingleStepWithTimeout(executionStep, compactOptional({
@@ -4459,11 +4163,9 @@ ${formatParallelHandoffError(error)}`;
4459
4163
  flatIndex,
4460
4164
  flatStepCount: Math.max(statusPayload.steps.length, 1),
4461
4165
  outputFile: path.join(asyncDir, `output-${flatIndex}.log`),
4462
- steerInboxDir: stepSteerInboxDir(asyncDir, flatIndex),
4463
- steerCapabilityPath: steerCapabilityPath(asyncDir, flatIndex),
4464
- steerAckDir: steerAcksDir(asyncDir, flatIndex),
4465
4166
  piPackageRoot: config.piPackageRoot,
4466
- piArgv1: config.piArgv1,
4167
+ childSessions,
4168
+ inheritedChildRuntime: config.inheritedChildRuntime,
4467
4169
  childIntercomTarget: config.childIntercomTargets?.[flatIndex],
4468
4170
  orchestratorIntercomTarget: config.controlIntercomTarget,
4469
4171
  nestedRoute: config.nestedRoute,
@@ -4472,6 +4174,8 @@ ${formatParallelHandoffError(error)}`;
4472
4174
  registerInterrupt: (interrupt) => registerStepInterrupt(flatIndex, interrupt),
4473
4175
  registerTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),
4474
4176
  registerStop: (stop) => registerStepStop(flatIndex, stop),
4177
+ registerSteer: (steer) => registerStepSteer(flatIndex, steer),
4178
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, flatIndex, delivery),
4475
4179
  timeoutSignal: timeoutAbortController.signal,
4476
4180
  stopSignal: stopAbortController.signal,
4477
4181
  timeoutMessage,
@@ -4479,16 +4183,18 @@ ${formatParallelHandoffError(error)}`;
4479
4183
  toolTimeoutMs: seqStep.toolTimeoutMs ?? config.toolTimeoutMs,
4480
4184
  onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking, attempt.contextLimit),
4481
4185
  onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
4482
- onWriterProcess,
4483
4186
  onExternalProcess: (process) => updateExternalProcess(flatIndex, process),
4187
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(flatIndex, externalCwd, signal),
4188
+ onExternalStreamActivity: () => recordExternalStreamActivity(flatIndex),
4484
4189
  onExternalJob: (externalJob) => updateExternalJob(flatIndex, externalJob),
4485
4190
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(flatIndex),
4486
- usageBudgetExhausted: () => refreshUsageBudget()?.exhausted === true,
4191
+ usageBudgetExhausted: continuationUsageBudgetExhausted,
4192
+ usageBudget: config.usageBudget,
4487
4193
  orcaProgressTab
4488
4194
  }), config.deadlineAt);
4489
4195
  } catch (error) {
4490
4196
  if (singleWorktreeSetup)
4491
- cleanupWorktrees(singleWorktreeSetup);
4197
+ await cleanupRemainingWorktree(singleWorktreeSetup, stepIndex, flatIndex);
4492
4198
  throw error;
4493
4199
  }
4494
4200
  if (seqStep.sessionFile) {
@@ -4507,18 +4213,20 @@ ${formatParallelHandoffError(error)}`;
4507
4213
  output: stopped || childStopped ? stopMessage : timedOut ? singleResult.output || (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
4508
4214
  outputState: singleResult.outputState,
4509
4215
  error: stopped || childStopped ? stopMessage : timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error,
4510
- protocolError: singleResult.protocolError,
4511
- success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
4216
+ success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0 && singleResult.execution?.status !== "partial",
4512
4217
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,
4513
4218
  sessionFile: singleResult.sessionFile,
4514
4219
  intercomTarget: singleResult.intercomTarget,
4515
4220
  model: singleResult.model,
4516
- attemptedModels: singleResult.attemptedModels,
4517
- modelAttempts: singleResult.modelAttempts,
4221
+ thinking: singleResult.thinking,
4222
+ requestedModel: singleResult.requestedModel,
4518
4223
  contextOverflow: singleResult.contextOverflow,
4519
4224
  totalCost: singleResult.totalCost,
4520
4225
  usage: singleResult.usage,
4521
4226
  artifactPaths: singleResult.artifactPaths,
4227
+ savedOutputPath: singleResult.savedOutputPath,
4228
+ outputSaveError: singleResult.outputSaveError,
4229
+ artifactOutputSaveFailed: singleResult.artifactOutputSaveFailed,
4522
4230
  transcriptPath: singleResult.transcriptPath,
4523
4231
  transcriptError: singleResult.transcriptError,
4524
4232
  effects: singleResult.effects,
@@ -4526,6 +4234,7 @@ ${formatParallelHandoffError(error)}`;
4526
4234
  review: singleResult.review,
4527
4235
  timeoutRecovery: singleResult.timeoutRecovery,
4528
4236
  structuredOutput: singleResult.structuredOutput,
4237
+ structuredOutputFailed: singleResult.structuredOutputFailed,
4529
4238
  structuredOutputPath: singleResult.structuredOutputPath,
4530
4239
  structuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,
4531
4240
  acceptance: singleResult.acceptance,
@@ -4560,7 +4269,7 @@ ${formatParallelHandoffError(error)}`;
4560
4269
  if (cumulativeTokens) {
4561
4270
  previousCumulativeTokens = cumulativeTokens;
4562
4271
  } else {
4563
- const fallbackTokens = tokenUsageFromAttempts(singleResult.modelAttempts);
4272
+ const fallbackTokens = tokenUsageFromUsage(singleResult.usage);
4564
4273
  const observedTokens = requiredStatusStep(statusPayload, flatIndex).tokens;
4565
4274
  stepTokens = fallbackTokens ? { ...fallbackTokens, ...observedTokens?.window !== undefined ? { window: observedTokens.window } : {}, ...observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {} } : null;
4566
4275
  if (stepTokens) {
@@ -4575,7 +4284,7 @@ ${formatParallelHandoffError(error)}`;
4575
4284
  }
4576
4285
  const stepEndTime = Date.now();
4577
4286
  const childInterrupted = singleResult.interrupted === true;
4578
- requiredStatusStep(statusPayload, flatIndex).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
4287
+ requiredStatusStep(statusPayload, flatIndex).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
4579
4288
  requiredStatusStep(statusPayload, flatIndex).endedAt = stepEndTime;
4580
4289
  requiredStatusStep(statusPayload, flatIndex).durationMs = stepEndTime - stepStartTime;
4581
4290
  requiredStatusStep(statusPayload, flatIndex).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4590,8 +4299,7 @@ ${formatParallelHandoffError(error)}`;
4590
4299
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "sessionName", singleResult.sessionName);
4591
4300
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "model", singleResult.model);
4592
4301
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, flatIndex).thinking));
4593
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "attemptedModels", singleResult.attemptedModels);
4594
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "modelAttempts", singleResult.modelAttempts);
4302
+ setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "requestedModel", singleResult.requestedModel);
4595
4303
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "contextOverflow", singleResult.contextOverflow);
4596
4304
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "totalCost", singleResult.totalCost);
4597
4305
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "error", stopped || childStopped ? stopMessage : timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error);
@@ -4635,66 +4343,56 @@ ${formatParallelHandoffError(error)}`;
4635
4343
  if (stopped || childStopped)
4636
4344
  appendTerminalChildStatusEvent(flatIndex, stepEndTime);
4637
4345
  if (singleWorktreeSetup && !singleResult.detached) {
4638
- const diffs = diffWorktrees(singleWorktreeSetup, [seqStep.agent], path.join(asyncDir, "worktree-diffs", `step-${stepIndex}`));
4639
- const diffSummary = formatWorktreeDiffSummary(diffs);
4640
- const manifestPath = parallelHandoffPath(asyncDir);
4641
- const handoff = {
4642
- manifestPath,
4643
- runId: id,
4644
- mode: "single",
4645
- source: "async",
4646
- cwd,
4647
- stepIndex,
4648
- flatStartIndex: flatIndex,
4649
- setup: singleWorktreeSetup,
4650
- diffs,
4651
- results: [{
4652
- agent: singleResult.agent,
4653
- ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {},
4654
- ...handoffChildRunId ? { runId: handoffChildRunId } : {},
4655
- ...config.lane ? { lane: config.lane } : {},
4656
- status: singleResult.stopped ? "stopped" : singleResult.interrupted ? "paused" : singleResult.exitCode === 0 ? "completed" : "failed",
4657
- summary: singleResult.output || singleResult.error || "(no output)",
4658
- ...singleResult.artifactPaths?.outputPath ? { outputPath: singleResult.artifactPaths.outputPath } : {},
4659
- ...singleResult.structuredOutput !== undefined ? { structuredOutput: singleResult.structuredOutput } : {},
4660
- ...singleResult.structuredOutputPath ? { structuredOutputPath: singleResult.structuredOutputPath } : {},
4661
- ...singleResult.sessionFile ? { sessionPath: singleResult.sessionFile } : {}
4662
- }]
4663
- };
4664
- try {
4665
- writeParallelHandoffGroup(handoff);
4666
- const cleanup = cleanupWorktrees(singleWorktreeSetup, {
4667
- kind: "preserve",
4668
- capturedDiffs: diffs,
4669
- handoffManifestPath: manifestPath,
4670
- ...config.parentWorkflowRunId && singleResult.sessionFile && fs.existsSync(singleResult.sessionFile) && !singleResult.stopped ? { cleanupBlocker: "retained child resume requires managed worktree cwd" } : {}
4671
- });
4672
- statusPayload.parallelHandoff = writeParallelHandoffGroup({ ...handoff, cleanup });
4673
- previousOutput = [previousOutput, diffSummary, formatParallelHandoffReference(statusPayload.parallelHandoff)].filter(Boolean).join(`
4346
+ const setup = singleWorktreeSetup;
4347
+ await finalizeWorktree(setup, stepIndex, flatIndex, () => {
4348
+ const diffs = diffWorktrees(setup, [seqStep.agent], path.join(asyncDir, "worktree-diffs", `step-${stepIndex}`));
4349
+ const diffSummary = formatWorktreeDiffSummary(diffs);
4350
+ const manifestPath = parallelHandoffPath(asyncDir);
4351
+ const handoff = {
4352
+ manifestPath,
4353
+ runId: id,
4354
+ mode: "single",
4355
+ source: "async",
4356
+ cwd,
4357
+ stepIndex,
4358
+ flatStartIndex: flatIndex,
4359
+ setup,
4360
+ diffs,
4361
+ results: [{
4362
+ agent: singleResult.agent,
4363
+ ...handoffWorkflowKey ? { workflowKey: handoffWorkflowKey } : {},
4364
+ ...handoffChildRunId ? { runId: handoffChildRunId } : {},
4365
+ ...config.lane ? { lane: config.lane } : {},
4366
+ status: singleResult.stopped ? "stopped" : singleResult.interrupted ? "paused" : singleResult.exitCode === 0 ? "completed" : "failed",
4367
+ summary: singleResult.output || singleResult.error || "(no output)",
4368
+ ...singleResult.artifactPaths?.outputPath ? { outputPath: singleResult.artifactPaths.outputPath } : {},
4369
+ ...singleResult.structuredOutput !== undefined ? { structuredOutput: singleResult.structuredOutput } : {},
4370
+ ...singleResult.structuredOutputPath ? { structuredOutputPath: singleResult.structuredOutputPath } : {},
4371
+ ...singleResult.sessionFile ? { sessionPath: singleResult.sessionFile } : {}
4372
+ }]
4373
+ };
4374
+ try {
4375
+ writeParallelHandoffGroup(handoff);
4376
+ const cleanup = cleanupWorktrees(setup, {
4377
+ kind: "preserve",
4378
+ capturedDiffs: diffs,
4379
+ handoffManifestPath: manifestPath,
4380
+ ...config.parentWorkflowRunId && singleResult.sessionFile && fs.existsSync(singleResult.sessionFile) && !singleResult.stopped ? { cleanupBlocker: "retained child resume requires managed worktree cwd" } : {}
4381
+ });
4382
+ statusPayload.parallelHandoff = writeParallelHandoffGroup({ ...handoff, cleanup });
4383
+ previousOutput = [previousOutput, diffSummary, formatParallelHandoffReference(statusPayload.parallelHandoff)].filter(Boolean).join(`
4674
4384
 
4675
4385
  `);
4676
- } catch (error) {
4677
- previousOutput = [previousOutput, diffSummary, formatParallelHandoffError(error)].filter(Boolean).join(`
4386
+ } catch (error) {
4387
+ previousOutput = [previousOutput, diffSummary, formatParallelHandoffError(error)].filter(Boolean).join(`
4678
4388
 
4679
4389
  `);
4680
- }
4681
- writeStatusPayload();
4682
- }
4683
- if (singleResult.completionGuardTriggered) {
4684
- const event = buildControlEvent(omitUndefinedProperties({
4685
- from: requiredStatusStep(statusPayload, flatIndex).activityState,
4686
- to: "needs_attention",
4687
- runId: id,
4688
- agent: seqStep.agent,
4689
- index: flatIndex,
4690
- ts: stepEndTime,
4691
- message: `${seqStep.agent} completed without making edits for an implementation task`,
4692
- reason: "completion_guard"
4693
- }));
4694
- appendControlEvent(event);
4390
+ }
4391
+ writeStatusPayload();
4392
+ });
4695
4393
  }
4696
4394
  flatIndex++;
4697
- if (isAgentContractV1(seqStep.agentContract) && seqStep.gateOn === "acceptance" && singleResult.acceptance?.status === "rejected") {
4395
+ if (isAgentContract(seqStep.agentContract) && seqStep.gateOn === "acceptance" && singleResult.acceptance?.status === "rejected") {
4698
4396
  statusPayload.error = acceptanceFailureMessage(singleResult.acceptance) ?? "Chain acceptance gate rejected the step.";
4699
4397
  writeStatusPayload();
4700
4398
  break;
@@ -4704,6 +4402,33 @@ ${formatParallelHandoffError(error)}`;
4704
4402
  }
4705
4403
  }
4706
4404
  }
4405
+ await Promise.all([...externalActivityEvidence.values()].map((evidence) => evidence.probeInFlight).filter((probe) => probe !== undefined));
4406
+ if (periodicGitProbeFailure) {
4407
+ stopped = false;
4408
+ timedOut = false;
4409
+ interrupted = false;
4410
+ delete statusPayload.stopped;
4411
+ delete statusPayload.timedOut;
4412
+ statusPayload.error = periodicGitProbeFailure.message;
4413
+ const step = statusPayload.steps[periodicGitProbeFailure.index];
4414
+ if (step) {
4415
+ step.status = "failed";
4416
+ step.error = periodicGitProbeFailure.message;
4417
+ step.exitCode = 1;
4418
+ delete step.stopped;
4419
+ delete step.timedOut;
4420
+ }
4421
+ const result = results[periodicGitProbeFailure.index];
4422
+ if (result) {
4423
+ result.success = false;
4424
+ result.exitCode = 1;
4425
+ result.error = periodicGitProbeFailure.message;
4426
+ result.output = periodicGitProbeFailure.message;
4427
+ result.stopped = false;
4428
+ result.timedOut = false;
4429
+ result.interrupted = false;
4430
+ }
4431
+ }
4707
4432
  let summary = results.map((r) => `${r.agent}:
4708
4433
  ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(`
4709
4434
 
@@ -4763,9 +4488,16 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4763
4488
  clearTimeout(timeoutTimer);
4764
4489
  timeoutTimer = undefined;
4765
4490
  }
4766
- if (!timedOut && !stopped && !interrupted && config.timeoutMs !== undefined && results.some((result) => result.timedOut === true && result.error === timeoutMessage)) {
4491
+ if (checkpointTimer) {
4492
+ clearTimeout(checkpointTimer);
4493
+ checkpointTimer = undefined;
4494
+ }
4495
+ if (!timedOut && !stopped && !interrupted && config.timeoutMs !== undefined && timeoutMessage !== undefined && results.some((result) => result.timedOut === true && result.error?.startsWith(timeoutMessage))) {
4767
4496
  timedOut = true;
4768
4497
  }
4498
+ disposeControlInbox();
4499
+ for (const request of consumeStopRequestPayloads(asyncDir))
4500
+ stopChildStep(request);
4769
4501
  const signalTerminated = !stopped && !timedOut && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
4770
4502
  processSignal: result.processSignal,
4771
4503
  interrupted: result.interrupted,
@@ -4773,9 +4505,12 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4773
4505
  stopped: result.stopped
4774
4506
  })));
4775
4507
  const partialWithEvidence = !stopped && !signalTerminated && !timedOut && !usageBudgetExceeded && !interrupted && results.some(partialEvidenceResult) && !results.some(concreteFailureResult);
4508
+ statusWriteCoalescer.flush(statusPath);
4509
+ const publication = new Promise((resolve, reject) => {
4510
+ finalResultPublication = { resolve, reject };
4511
+ });
4776
4512
  statusPayload.state = stopped || signalTerminated ? "stopped" : timedOut || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : partialWithEvidence ? "partial" : "failed";
4777
4513
  closeSteerInbox(asyncDir, statusPayload.state, (filePath, payload) => runPersistence.write(filePath, payload));
4778
- disposeControlInbox();
4779
4514
  for (const request of consumeSteerRequests(asyncDir))
4780
4515
  deliverSteerRequest(request);
4781
4516
  const effectiveSessionFile = sessionFile ?? latestSessionFile;
@@ -4786,7 +4521,7 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4786
4521
  if (target.state !== "scheduled" && target.state !== "routed" && target.state !== "queued")
4787
4522
  continue;
4788
4523
  changed = true;
4789
- const reason = target.state === "queued" ? "run ended before queued follow-up delivery" : "child terminated before steering delivery";
4524
+ const reason = target.state === "queued" ? unconsumedSteerReason() : "child terminated before steering delivery";
4790
4525
  updateSteeringLifecycleTarget(request.id, target.index, "failed", Date.now(), { reason });
4791
4526
  markSteeringAttention(target.index);
4792
4527
  emitSteeringEvent("subagent.steer.failed", { type: "steer", id: request.id, ts: request.requestedAt, message: reason }, target.index, { reason });
@@ -4814,7 +4549,7 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4814
4549
  statusPayload.activityState = "needs_attention";
4815
4550
  statusPayload.error = partialResult?.error ?? statusPayload.error;
4816
4551
  for (const step of statusPayload.steps) {
4817
- if (step.status === "failed")
4552
+ if (step.status === "failed" || step.status === "partial")
4818
4553
  step.activityState = "needs_attention";
4819
4554
  }
4820
4555
  }
@@ -4837,7 +4572,8 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4837
4572
  statusPayload.error = `Step failed: ${failedStep.agent}`;
4838
4573
  }
4839
4574
  }
4840
- writeStatusPayload();
4575
+ let childSessionDisposal;
4576
+ const disposeChildSessions = () => childSessionDisposal ??= childSessions.dispose().catch((error) => console.error("Failed to dispose runner child sessions:", error));
4841
4577
  try {
4842
4578
  runPersistence.write(resultPath, {
4843
4579
  lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
@@ -4860,7 +4596,6 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4860
4596
  output: r.output,
4861
4597
  outputState: r.outputState,
4862
4598
  error: r.error,
4863
- protocolError: r.protocolError,
4864
4599
  success: r.success,
4865
4600
  skipped: r.skipped || undefined,
4866
4601
  interrupted: r.interrupted || undefined,
@@ -4872,13 +4607,15 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4872
4607
  sessionFile: r.sessionFile,
4873
4608
  intercomTarget: r.intercomTarget,
4874
4609
  model: r.model,
4875
- attemptedModels: r.attemptedModels,
4876
- modelAttempts: r.modelAttempts,
4610
+ thinking: r.thinking,
4611
+ requestedModel: r.requestedModel,
4877
4612
  contextOverflow: r.contextOverflow,
4878
4613
  totalCost: r.totalCost,
4879
4614
  usage: r.usage,
4880
4615
  artifactPaths: r.artifactPaths,
4616
+ savedOutputPath: r.savedOutputPath,
4881
4617
  outputSaveError: r.outputSaveError,
4618
+ artifactOutputSaveFailed: r.artifactOutputSaveFailed,
4882
4619
  metadataSaveError: r.metadataSaveError,
4883
4620
  truncated: r.truncated,
4884
4621
  transcriptPath: r.transcriptPath,
@@ -4894,6 +4631,7 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4894
4631
  review: r.review,
4895
4632
  effects: r.effects,
4896
4633
  structuredOutput: r.structuredOutput,
4634
+ structuredOutputFailed: r.structuredOutputFailed,
4897
4635
  structuredOutputPath: r.structuredOutputPath,
4898
4636
  structuredOutputSchemaPath: r.structuredOutputSchemaPath,
4899
4637
  acceptance: r.acceptance,
@@ -4934,16 +4672,19 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4934
4672
  }, (filePath, payload) => {
4935
4673
  writeAsyncResultFile(filePath, payload);
4936
4674
  });
4937
- finalResultCommitted = true;
4675
+ if (!finalResultCommitted)
4676
+ await Promise.all([publication, disposeChildSessions()]);
4938
4677
  } catch (err) {
4939
4678
  const message = `Failed to write result file ${resultPath}: ${err instanceof Error ? err.message : String(err)}`;
4940
4679
  console.error(message, err);
4941
4680
  statusPayload.state = "failed";
4942
4681
  statusPayload.error = message;
4943
4682
  statusPayload.lastUpdate = Date.now();
4683
+ } finally {
4684
+ finalResultPublication = undefined;
4944
4685
  }
4945
4686
  writeStatusPayload();
4946
- orcaProgressTab?.finish(statusPayload.state === "complete" ? "completed" : statusPayload.state === "stopped" ? "stopped" : "failed", effectiveSessionFile);
4687
+ await orcaProgressTab?.finish(statusPayload.state === "complete" ? "completed" : statusPayload.state === "stopped" ? "stopped" : "failed", effectiveSessionFile);
4947
4688
  appendJsonl(eventsPath, JSON.stringify({
4948
4689
  type: "subagent.run.completed",
4949
4690
  lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
@@ -4975,16 +4716,18 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
4975
4716
  }), (filePath, content) => runPersistence.write(filePath, { content }, (_path, payload) => {
4976
4717
  fs.writeFileSync(_path, payload.content, "utf-8");
4977
4718
  }));
4978
- if (runPersistence.pendingCount() === 0)
4979
- runPersistence.dispose();
4980
- if (indexPersistence.pendingCount() === 0)
4981
- indexPersistence.dispose();
4719
+ await disposeChildSessions();
4720
+ while (runPersistence.pendingCount() + indexPersistence.pendingCount() > 0) {
4721
+ await new Promise((resolve) => setTimeout(resolve, 200));
4722
+ }
4723
+ runPersistence.dispose();
4724
+ indexPersistence.dispose();
4982
4725
  if (config.runnerProcessInstanceId) {
4983
4726
  const writers = {};
4984
4727
  const expectedWriters = {};
4985
- for (const [index, result] of results.entries()) {
4986
- writers[String(index)] = result.writerProcesses ?? [];
4987
- expectedWriters[String(index)] = result.writerAttemptCount ?? 0;
4728
+ for (const index of results.keys()) {
4729
+ writers[String(index)] = [];
4730
+ expectedWriters[String(index)] = 0;
4988
4731
  }
4989
4732
  const candidate = {
4990
4733
  version: 1,
@@ -5002,117 +4745,38 @@ ${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join(
5002
4745
  }
5003
4746
  }
5004
4747
  }
5005
- async function waitForStartupControl(controlPath, token, action, timeoutMs = 30000) {
5006
- const deadline = Date.now() + timeoutMs;
5007
- while (Date.now() <= deadline) {
5008
- if (fs.existsSync(controlPath)) {
5009
- let payload;
5010
- try {
5011
- payload = JSON.parse(fs.readFileSync(controlPath, "utf-8"));
5012
- } catch (error) {
5013
- throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
5014
- }
5015
- if (payload.token !== token)
5016
- throw new Error("Runner startup control token does not match.");
5017
- if (payload.action === action)
5018
- return;
5019
- if (payload.action !== "ack" && payload.action !== "proceed")
5020
- throw new Error("Runner startup control action is invalid.");
5021
- }
5022
- await new Promise((resolve) => setTimeout(resolve, 20));
5023
- }
5024
- throw new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);
5025
- }
5026
- async function runConfiguredSubagent(config) {
5027
- let lease;
5028
- let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
5029
- const startupPath = path.join(config.asyncDir, "runner-startup.json");
5030
- const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
5031
- const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
5032
- const releaseOnExit = () => {
5033
- try {
5034
- lease?.release();
5035
- } catch {}
5036
- };
5037
- process.once("exit", releaseOnExit);
4748
+ export async function runConfiguredSubagentExecution(config, options) {
4749
+ let childSessions;
5038
4750
  try {
5039
- if (config.launchBarrierToken) {
5040
- await waitForStartupControl(startupProceedPath, config.launchBarrierToken, "proceed");
5041
- startupCommitted = true;
5042
- try {
5043
- fs.rmSync(startupProceedPath, { force: true });
5044
- } catch {}
5045
- } else if (config.revivalLease) {
5046
- lease = acquireSessionLease(config.revivalLease);
5047
- config.revivalLeaseToken = lease.owner.token;
5048
- writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
5049
- await waitForStartupControl(startupAckPath, lease.owner.token, "ack");
5050
- writeAtomicJson(startupPath, { state: "acknowledged", token: lease.owner.token, pid: process.pid });
5051
- await waitForStartupControl(startupProceedPath, lease.owner.token, "proceed");
5052
- startupCommitted = true;
5053
- for (const controlPath of [startupAckPath, startupProceedPath]) {
5054
- try {
5055
- fs.rmSync(controlPath, { force: true });
5056
- } catch {}
5057
- }
5058
- }
5059
- await runSubagent(config, lease ? (writer) => lease.updateWriter(writer) : undefined);
4751
+ if (!options?.loadPiCodingAgent)
4752
+ installRunnerHttpDispatcher({ agentDir: getAgentDir(), cwd: process.cwd() });
4753
+ childSessions = await loadRunnerChildSessionFactory(config, options);
5060
4754
  } catch (error) {
5061
- if (!startupCommitted) {
5062
- try {
5063
- writeAtomicJson(startupPath, { state: "error", pid: process.pid, error: error instanceof Error ? error.message : String(error) });
5064
- } catch {}
4755
+ try {
4756
+ persistRunnerStartupFailure({
4757
+ asyncDir: config.asyncDir,
4758
+ runId: config.id,
4759
+ runnerProcessInstanceId: config.runnerProcessInstanceId ?? "unknown-runner-instance",
4760
+ message: `Subagent runner startup failed: ${error instanceof Error ? error.message : String(error)}`,
4761
+ ...config.sessionId ? { sessionId: config.sessionId } : {},
4762
+ ...config.completionOwnerId ? { completionOwnerId: config.completionOwnerId } : {},
4763
+ candidate: {
4764
+ ...config.revivalLease?.sessionFile ? { sessionFile: config.revivalLease.sessionFile } : {},
4765
+ ...config.revivalLeaseToken ? { revivalLeaseToken: config.revivalLeaseToken } : {}
4766
+ }
4767
+ });
4768
+ } catch (persistenceError) {
4769
+ console.error("Failed to persist runner setup failure:", persistenceError);
5065
4770
  }
5066
4771
  throw error;
5067
- } finally {
5068
- process.off("exit", releaseOnExit);
5069
- if (lease) {
5070
- let acknowledged = false;
5071
- try {
5072
- acknowledged = lease.release();
5073
- } catch (error) {
5074
- console.error("Failed to release session revival lease:", error);
5075
- }
5076
- try {
5077
- markProcessTerminalCandidateLeaseRelease(config.asyncDir, lease.owner.token, acknowledged);
5078
- } catch (error) {
5079
- console.error("Failed to record session revival lease release:", error);
5080
- }
5081
- }
5082
4772
  }
5083
- }
5084
- function startConfiguredSubagent(config) {
5085
- runConfiguredSubagent(config).catch((runErr) => {
5086
- console.error("Subagent runner error:", runErr);
5087
- process.exit(1);
5088
- });
5089
- }
5090
- const configArg = process.argv[2];
5091
- if (configArg) {
5092
4773
  try {
5093
- const configJson = fs.readFileSync(configArg, "utf-8");
5094
- const config = JSON.parse(configJson);
5095
- try {
5096
- fs.unlinkSync(configArg);
5097
- } catch {}
5098
- startConfiguredSubagent(config);
5099
- } catch (err) {
5100
- console.error("Subagent runner error:", err);
5101
- process.exit(1);
5102
- }
5103
- } else {
5104
- let input = "";
5105
- process.stdin.setEncoding("utf-8");
5106
- process.stdin.on("data", (chunk) => {
5107
- input += chunk;
5108
- });
5109
- process.stdin.on("end", () => {
4774
+ await runSubagent(config, childSessions);
4775
+ } finally {
5110
4776
  try {
5111
- const config = JSON.parse(input);
5112
- startConfiguredSubagent(config);
5113
- } catch (err) {
5114
- console.error("Subagent runner error:", err);
5115
- process.exit(1);
4777
+ await childSessions.dispose();
4778
+ } catch (error) {
4779
+ console.error("Failed to dispose runner child sessions:", error);
5116
4780
  }
5117
- });
4781
+ }
5118
4782
  }