@aiwg/cli 2026.10.1 → 2026.10.4

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 (361) hide show
  1. package/README.md +2 -2
  2. package/agentic/code/providers/capability-matrix.yaml +270 -0
  3. package/agentic/code/providers/model-capabilities.v1.json +3183 -24
  4. package/bin/aiwg.mjs +135 -47
  5. package/dist/src/a2a/codecs.js +9 -0
  6. package/dist/src/agents/grounding/knowledge-base.js +54 -6
  7. package/dist/src/artifacts/browser-export.js +6 -0
  8. package/dist/src/artifacts/checksum-manifest.js +1 -0
  9. package/dist/src/artifacts/citation-parser.js +173 -92
  10. package/dist/src/artifacts/citation-table-schema.js +59 -0
  11. package/dist/src/artifacts/cli.js +57 -18
  12. package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
  13. package/dist/src/artifacts/corpus-tools/vision-extract.js +107 -15
  14. package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
  15. package/dist/src/artifacts/corpus-views/renderers.js +3 -3
  16. package/dist/src/artifacts/discovery-eval.js +6 -4
  17. package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
  18. package/dist/src/artifacts/fortemi-core-sync.js +166 -40
  19. package/dist/src/artifacts/framework-capabilities.js +171 -0
  20. package/dist/src/artifacts/framework-index-paths.js +73 -0
  21. package/dist/src/artifacts/framework-source-digest.js +75 -0
  22. package/dist/src/artifacts/index-builder.js +285 -131
  23. package/dist/src/artifacts/index-files.js +132 -18
  24. package/dist/src/artifacts/index-preparation.js +65 -0
  25. package/dist/src/artifacts/index-refresh.js +576 -0
  26. package/dist/src/artifacts/index-worker.mjs +9 -0
  27. package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
  28. package/dist/src/artifacts/prebuilt-deployment.js +46 -0
  29. package/dist/src/artifacts/prebuilt-relations.js +80 -0
  30. package/dist/src/artifacts/query-engine.js +410 -88
  31. package/dist/src/artifacts/relations-builder.js +168 -0
  32. package/dist/src/artifacts/relations.js +148 -0
  33. package/dist/src/artifacts/repair.js +9 -4
  34. package/dist/src/artifacts/stats.js +5 -2
  35. package/dist/src/artifacts/types.js +30 -10
  36. package/dist/src/artifacts/watcher.js +1 -1
  37. package/dist/src/auth/credential-store.js +2 -1
  38. package/dist/src/catalog/cli.d.mts +5 -0
  39. package/dist/src/channel/manager.d.mts +20 -0
  40. package/dist/src/channel/manager.mjs +78 -12
  41. package/dist/src/cli/child-process-result.js +40 -0
  42. package/dist/src/cli/command-log.js +2 -3
  43. package/dist/src/cli/env.js +38 -16
  44. package/dist/src/cli/flag-parsing.js +236 -0
  45. package/dist/src/cli/handlers/artifacts.js +3 -0
  46. package/dist/src/cli/handlers/auth.js +3 -0
  47. package/dist/src/cli/handlers/decision.js +218 -5
  48. package/dist/src/cli/handlers/diagnose.js +13 -5
  49. package/dist/src/cli/handlers/effect.js +4 -2
  50. package/dist/src/cli/handlers/evidence.js +3 -0
  51. package/dist/src/cli/handlers/feedback.js +14 -5
  52. package/dist/src/cli/handlers/help.js +1 -0
  53. package/dist/src/cli/handlers/index.js +3 -1
  54. package/dist/src/cli/handlers/init.js +248 -30
  55. package/dist/src/cli/handlers/lint.js +5 -0
  56. package/dist/src/cli/handlers/mc.js +23 -0
  57. package/dist/src/cli/handlers/models.js +169 -10
  58. package/dist/src/cli/handlers/ralph-launcher.js +2 -0
  59. package/dist/src/cli/handlers/ralph.js +3 -0
  60. package/dist/src/cli/handlers/refresh.js +28 -0
  61. package/dist/src/cli/handlers/regenerate.js +14 -0
  62. package/dist/src/cli/handlers/resource-versions.js +3 -0
  63. package/dist/src/cli/handlers/rules.js +195 -0
  64. package/dist/src/cli/handlers/run.js +4 -0
  65. package/dist/src/cli/handlers/runtime-info.js +25 -11
  66. package/dist/src/cli/handlers/script-runner.js +19 -8
  67. package/dist/src/cli/handlers/session.js +406 -62
  68. package/dist/src/cli/handlers/sessions.js +243 -76
  69. package/dist/src/cli/handlers/setup-manifest.js +474 -79
  70. package/dist/src/cli/handlers/setup.js +180 -39
  71. package/dist/src/cli/handlers/steward.js +11 -0
  72. package/dist/src/cli/handlers/subcommands.js +60 -3
  73. package/dist/src/cli/handlers/team.js +18 -8
  74. package/dist/src/cli/handlers/uhp.js +3 -0
  75. package/dist/src/cli/handlers/use.js +307 -55
  76. package/dist/src/cli/handlers/utilities.js +125 -26
  77. package/dist/src/cli/handlers/version.js +8 -0
  78. package/dist/src/cli/prompt-utils.js +72 -0
  79. package/dist/src/cli/provider-resolution.js +11 -0
  80. package/dist/src/cli/router.js +15 -1
  81. package/dist/src/cli/services/deployment-verification.js +19 -9
  82. package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
  83. package/dist/src/cli/skill-usage.js +2 -3
  84. package/dist/src/config/aiwg-config.js +349 -35
  85. package/dist/src/config/cli.js +256 -23
  86. package/dist/src/config/decision-config.js +106 -0
  87. package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
  88. package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
  89. package/dist/src/config/gitignore.js +50 -0
  90. package/dist/src/config/index-graph-overrides.js +36 -0
  91. package/dist/src/config/project-artifacts-health.d.mts +37 -0
  92. package/dist/src/config/project-artifacts-health.mjs +14 -3
  93. package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
  94. package/dist/src/config/user-config-dir.d.mts +9 -0
  95. package/dist/src/config/user-config.js +38 -11
  96. package/dist/src/config/user-registry.js +23 -15
  97. package/dist/src/config/user-state.js +7 -0
  98. package/dist/src/decision/adapters/jev.js +75 -27
  99. package/dist/src/decision/ask.js +203 -43
  100. package/dist/src/decision/context-live-qualification.js +2 -2
  101. package/dist/src/decision/driver.js +14 -7
  102. package/dist/src/decision/ensemble/aggregate.js +23 -10
  103. package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
  104. package/dist/src/decision/entry.js +25 -6
  105. package/dist/src/decision/graph-live-qualification.js +1 -1
  106. package/dist/src/decision/graph-run.js +9 -0
  107. package/dist/src/decision/heldout/collector.js +15 -14
  108. package/dist/src/decision/heldout/contract.js +30 -7
  109. package/dist/src/decision/index.js +1 -0
  110. package/dist/src/decision/interop.js +60 -8
  111. package/dist/src/decision/jev-credentials.js +15 -1
  112. package/dist/src/decision/ledger.js +942 -0
  113. package/dist/src/decision/offload-activation.js +137 -0
  114. package/dist/src/decision/offload.js +550 -0
  115. package/dist/src/decision/qualification/load.js +4 -6
  116. package/dist/src/decision/savings.js +28 -0
  117. package/dist/src/decision/validate.js +6 -3
  118. package/dist/src/effects/dispatch-verifier.js +252 -0
  119. package/dist/src/effects/index.js +1 -0
  120. package/dist/src/effects/types.js +5 -1
  121. package/dist/src/effects/verifiers/git.js +2 -1
  122. package/dist/src/effects/verifiers/tracker.js +26 -14
  123. package/dist/src/extensions/commands/definitions.js +19 -0
  124. package/dist/src/extensions/project-local-remove.js +36 -1
  125. package/dist/src/features/installer.js +2 -2
  126. package/dist/src/flow/graph-metadata.js +5 -0
  127. package/dist/src/gates/providers/loader.js +64 -18
  128. package/dist/src/installation/manager-command.d.mts +18 -0
  129. package/dist/src/installation/manager-command.mjs +15 -3
  130. package/dist/src/installation/manager.d.mts +49 -0
  131. package/dist/src/installation/manager.mjs +95 -5
  132. package/dist/src/issues/cli.js +4 -4
  133. package/dist/src/issues/local.js +24 -5
  134. package/dist/src/jobs/runner.js +1 -1
  135. package/dist/src/lint/cli.js +27 -1
  136. package/dist/src/lint/loader.js +2 -1
  137. package/dist/src/lint/reporters.js +25 -1
  138. package/dist/src/lint/rule-activation.js +43 -0
  139. package/dist/src/lint/runner.js +137 -62
  140. package/dist/src/mcp/adapters/codex-runtime.js +366 -56
  141. package/dist/src/mcp/claude-install.d.mts +4 -0
  142. package/dist/src/mcp/claude-install.mjs +41 -0
  143. package/dist/src/mcp/cli.d.mts +1 -0
  144. package/dist/src/mcp/cli.mjs +620 -85
  145. package/dist/src/mcp/config-file.d.mts +28 -0
  146. package/dist/src/mcp/config-file.mjs +279 -0
  147. package/dist/src/mcp/config-layers.d.mts +36 -0
  148. package/dist/src/mcp/config-layers.mjs +348 -0
  149. package/dist/src/mcp/credentials.d.mts +51 -0
  150. package/dist/src/mcp/credentials.mjs +484 -0
  151. package/dist/src/mcp/grok-build-config.d.mts +6 -0
  152. package/dist/src/mcp/grok-build-config.mjs +17 -27
  153. package/dist/src/mcp/helpers.mjs +109 -4
  154. package/dist/src/mcp/muse-native-config.d.mts +13 -0
  155. package/dist/src/mcp/muse-native-config.mjs +1 -0
  156. package/dist/src/mcp/omp-config.d.mts +4 -0
  157. package/dist/src/mcp/omp-config.mjs +50 -29
  158. package/dist/src/mcp/profiles.js +97 -23
  159. package/dist/src/mcp/profiles.mjs +99 -27
  160. package/dist/src/mcp/registry.js +248 -131
  161. package/dist/src/mcp/registry.mjs +169 -100
  162. package/dist/src/mcp/server-config.d.mts +3 -0
  163. package/dist/src/mcp/server-config.mjs +89 -0
  164. package/dist/src/mcp/server.mjs +127 -82
  165. package/dist/src/mcp/test-simple.mjs +2 -1
  166. package/dist/src/mcp/toml-editor.d.mts +4 -0
  167. package/dist/src/mcp/toml-string.d.mts +1 -0
  168. package/dist/src/mcp/toml-string.mjs +9 -0
  169. package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
  170. package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
  171. package/dist/src/mcp/tool-filters.d.mts +46 -0
  172. package/dist/src/mcp/tool-filters.mjs +357 -0
  173. package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
  174. package/dist/src/mcp/tools/decision.mjs +22 -3
  175. package/dist/src/mcp/tools/discovery.mjs +62 -55
  176. package/dist/src/mcp/tools/orchestration.mjs +50 -2
  177. package/dist/src/mcp/tools/subsystems.mjs +39 -8
  178. package/dist/src/mcp/tools/worker-invoke.mjs +2856 -0
  179. package/dist/src/mcp/tools/worker-shell-control.mjs +289 -0
  180. package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
  181. package/dist/src/memory/project-registry.js +2 -2
  182. package/dist/src/mission-protocol/codecs.js +647 -1
  183. package/dist/src/mission-protocol/types.js +110 -0
  184. package/dist/src/mission-protocol/worker-status.js +2 -0
  185. package/dist/src/models/config-loader.js +76 -14
  186. package/dist/src/models/grok-build-models.js +93 -41
  187. package/dist/src/models/model-capabilities.v1.json +3183 -24
  188. package/dist/src/models/model-discovery.js +931 -67
  189. package/dist/src/models/provider-policy.js +719 -11
  190. package/dist/src/models/qualification-digest.d.mts +2 -0
  191. package/dist/src/models/qualification-digest.mjs +17 -0
  192. package/dist/src/models/resolver.js +261 -0
  193. package/dist/src/models/worker-direct-readiness.js +550 -0
  194. package/dist/src/models/worker-dispatch-offer.js +169 -0
  195. package/dist/src/models/worker-health-readiness.js +144 -0
  196. package/dist/src/models/worker-installation.d.mts +39 -0
  197. package/dist/src/models/worker-installation.mjs +986 -0
  198. package/dist/src/models/wrapper-route.js +18 -0
  199. package/dist/src/ops/registry.js +9 -14
  200. package/dist/src/plugins/standalone-packager.js +4 -3
  201. package/dist/src/process/bounded-child-process.d.mts +84 -0
  202. package/dist/src/process/bounded-child-process.mjs +430 -0
  203. package/dist/src/process/cli-command.d.mts +16 -0
  204. package/dist/src/process/cli-command.mjs +75 -0
  205. package/dist/src/process/signal-child.d.mts +6 -0
  206. package/dist/src/process/signal-child.mjs +7 -0
  207. package/dist/src/providers/capability-matrix.js +8 -0
  208. package/dist/src/providers/capability-matrix.yaml +270 -0
  209. package/dist/src/providers/deployed-skill-roots.js +20 -0
  210. package/dist/src/providers/grok-build-acp.js +3 -2
  211. package/dist/src/providers/grok-build-headless.js +53 -23
  212. package/dist/src/providers/grok-build-inspect.js +1 -0
  213. package/dist/src/providers/omp-agent.d.mts +8 -0
  214. package/dist/src/providers/omp-diagnostics.d.mts +1 -0
  215. package/dist/src/providers/omp-paths.d.mts +13 -0
  216. package/dist/src/providers/provider-definitions.js +9 -1
  217. package/dist/src/providers/provider-definitions.mjs +9 -2
  218. package/dist/src/providers/skill-ownership.d.mts +9 -0
  219. package/dist/src/providers/skill-ownership.mjs +88 -0
  220. package/dist/src/rules/activation.d.mts +21 -0
  221. package/dist/src/rules/activation.mjs +62 -0
  222. package/dist/src/rules/inline-budget.d.mts +26 -0
  223. package/dist/src/rules/inline-budget.mjs +66 -0
  224. package/dist/src/rules/inventory.js +129 -0
  225. package/dist/src/rules/pin-state.js +73 -0
  226. package/dist/src/rules/pins.d.mts +14 -0
  227. package/dist/src/rules/pins.mjs +112 -0
  228. package/dist/src/rules/rule-frontmatter.schema.json +197 -0
  229. package/dist/src/serve/executor-registry.js +16 -24
  230. package/dist/src/serve/fleet-mission-conductor.js +9 -0
  231. package/dist/src/serve/mission-conductor.js +47 -12
  232. package/dist/src/serve/shared-host-scheduler.js +2 -0
  233. package/dist/src/serve/worker-invocation.js +558 -0
  234. package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
  235. package/dist/src/serve/worker-stdin-frame.mjs +107 -0
  236. package/dist/src/sessions/adapter-registry.js +49 -0
  237. package/dist/src/sessions/adapters/claude.js +39 -54
  238. package/dist/src/sessions/adapters/codex.js +82 -67
  239. package/dist/src/sessions/adapters/copilot.js +4 -4
  240. package/dist/src/sessions/adapters/cursor.js +40 -57
  241. package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
  242. package/dist/src/sessions/adapters/factory.js +31 -27
  243. package/dist/src/sessions/adapters/generic.js +43 -9
  244. package/dist/src/sessions/adapters/grok-build.js +11 -11
  245. package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
  246. package/dist/src/sessions/adapters/grokbot.js +434 -24
  247. package/dist/src/sessions/adapters/hermes.js +27 -29
  248. package/dist/src/sessions/adapters/muse-workspace-scan.js +128 -0
  249. package/dist/src/sessions/adapters/muse.js +200 -104
  250. package/dist/src/sessions/adapters/omp.js +28 -14
  251. package/dist/src/sessions/adapters/openclaw.js +89 -79
  252. package/dist/src/sessions/adapters/opencode.js +27 -24
  253. package/dist/src/sessions/adapters/openhuman.js +18 -60
  254. package/dist/src/sessions/adapters/pi.js +30 -14
  255. package/dist/src/sessions/adapters/warp.js +3 -3
  256. package/dist/src/sessions/adapters/windsurf.js +19 -48
  257. package/dist/src/sessions/batch-contracts.js +25 -5
  258. package/dist/src/sessions/batch-import.js +72 -51
  259. package/dist/src/sessions/candidates.js +47 -11
  260. package/dist/src/sessions/contracts.js +75 -2
  261. package/dist/src/sessions/coverage-preflight.js +134 -0
  262. package/dist/src/sessions/discovery.js +3 -0
  263. package/dist/src/sessions/export-plan.js +4 -3
  264. package/dist/src/sessions/grok-build-cli.js +67 -5
  265. package/dist/src/sessions/import-exclusions.js +72 -0
  266. package/dist/src/sessions/import-lease.js +34 -18
  267. package/dist/src/sessions/import-limits.js +37 -0
  268. package/dist/src/sessions/importer.js +84 -46
  269. package/dist/src/sessions/index.js +2 -0
  270. package/dist/src/sessions/lifecycle.js +45 -0
  271. package/dist/src/sessions/policy.js +133 -25
  272. package/dist/src/sessions/readers.js +106 -53
  273. package/dist/src/sessions/refresh.js +106 -0
  274. package/dist/src/sessions/repository.js +199 -63
  275. package/dist/src/sessions/workspace-discovery.js +315 -88
  276. package/dist/src/sessions/workspace-matching.js +107 -0
  277. package/dist/src/skills/adapters/clawhub.js +10 -8
  278. package/dist/src/skills/adapters/openclaw.js +10 -7
  279. package/dist/src/skills/importer.js +1 -0
  280. package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
  281. package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
  282. package/dist/src/smiths/context-pipeline/finalization.js +6 -5
  283. package/dist/src/smiths/context-pipeline/generator.js +21 -4
  284. package/dist/src/smiths/context-pipeline/parallelism-section.js +195 -14
  285. package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
  286. package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
  287. package/dist/src/smiths/mcpsmith/example.js +1 -1
  288. package/dist/src/smiths/mcpsmith/generator.js +1 -1
  289. package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
  290. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +85 -31
  291. package/dist/src/storage/backends/fs.js +18 -76
  292. package/dist/src/storage/backends/logseq.js +68 -7
  293. package/dist/src/storage/backends/obsidian.js +1 -0
  294. package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
  295. package/dist/src/testing/generators/test-code-generator.js +57 -30
  296. package/dist/src/tracker/forge-http.js +2 -1
  297. package/dist/src/uhp/client.js +11 -1
  298. package/dist/src/uhp/mission.js +5 -0
  299. package/dist/src/update/checker.d.mts +2 -0
  300. package/dist/src/update/checker.mjs +5 -5
  301. package/dist/src/update/notifier.mjs +54 -2
  302. package/dist/src/update/service.d.mts +22 -0
  303. package/dist/src/utils/contained-filesystem.d.mts +37 -0
  304. package/dist/src/utils/contained-filesystem.mjs +683 -0
  305. package/dist/src/utils/temporary-directory.js +36 -0
  306. package/dist/src/writing/example-generator.js +1 -1
  307. package/dist/src/writing/fidelity.js +18 -1
  308. package/package.json +32 -2
  309. package/schemas/mission-v1.schema.json +2429 -0
  310. package/schemas/models/model-catalog.v1.schema.json +301 -0
  311. package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
  312. package/schemas/models/model-policy.v1.schema.json +14 -0
  313. package/schemas/models/provider-model-capabilities.v1.schema.json +1072 -0
  314. package/tools/_resolve-impl.mjs +39 -2
  315. package/tools/agents/deploy-agents.mjs +64 -23
  316. package/tools/agents/providers/base.mjs +153 -166
  317. package/tools/agents/providers/claude.mjs +8 -24
  318. package/tools/agents/providers/codex.mjs +18 -11
  319. package/tools/agents/providers/cursor.mjs +19 -18
  320. package/tools/agents/providers/grok-build.mjs +3 -1
  321. package/tools/agents/providers/grokbot.mjs +11 -12
  322. package/tools/agents/providers/hermes.mjs +62 -49
  323. package/tools/agents/providers/omp.mjs +5 -2
  324. package/tools/agents/providers/openclaw-translator.mjs +19 -5
  325. package/tools/agents/providers/openclaw.mjs +9 -4
  326. package/tools/agents/providers/pi.mjs +5 -0
  327. package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
  328. package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
  329. package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
  330. package/tools/agents/providers/rule-delivery.mjs +1270 -0
  331. package/tools/agents/providers/warp.mjs +20 -26
  332. package/tools/cli/decision-offload-report.mjs +40 -0
  333. package/tools/cli/workspace-status.mjs +862 -0
  334. package/tools/plugin/package-plugins.mjs +186 -8
  335. package/tools/plugin/plugin-links.mjs +114 -0
  336. package/tools/providers/antigravity-transport.mjs +3 -1
  337. package/tools/providers/deepseek-harness-transport.mjs +360 -0
  338. package/tools/providers/omp-transport.mjs +194 -0
  339. package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
  340. package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
  341. package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
  342. package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
  343. package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
  344. package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
  345. package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
  346. package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
  347. package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
  348. package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
  349. package/tools/ralph-external/lib/pi-adapter.mjs +329 -0
  350. package/tools/ralph-external/lib/provider-adapter.mjs +748 -0
  351. package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
  352. package/tools/ralph-external/lib/session-environment.mjs +28 -0
  353. package/tools/ralph-external/lib/systemd-client.mjs +49 -0
  354. package/tools/ralph-external/lib/worker-health.mjs +439 -0
  355. package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
  356. package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
  357. package/tools/ralph-external/process-monitor.mjs +1017 -0
  358. package/tools/ralph-external/session-launcher.mjs +5057 -0
  359. package/tools/scripts/resource-preflight.mjs +541 -0
  360. package/tools/skills/deploy-skills-codex.mjs +2 -1
  361. package/vscode-extension/schemas/aiwg.config.v1.json +2916 -0
@@ -24,6 +24,7 @@ import { refreshAllPackages } from '../../packages/registry.js';
24
24
  import { resolveActiveProvider } from '../provider-resolution.js';
25
25
  import { readAiwgConfig, writeAiwgConfig, hashManifest, getProviderParallelismDefaults, } from '../../config/aiwg-config.js';
26
26
  import { discoverProjectLocalBundles } from '../../extensions/project-local-discovery.js';
27
+ import { detectInstalledWorkerClis, evaluateWorkerDispatchOffer, workerDispatchOfferHint } from '../../models/worker-dispatch-offer.js';
27
28
  import { getProviderArtifactPathStrings } from '../../providers/provider-definitions.js';
28
29
  import { collectPackagedAgentInventory, normalizeAgentArtifactName, parseManagedArtifactMarker, } from '../../agents/packaged-agent-inventory.js';
29
30
  import * as ui from '../ui.js';
@@ -571,6 +572,7 @@ export const refreshHandler = {
571
572
  // #2507: give operators a reclaim path for artifacts an older
572
573
  // AIWG left behind without a managed marker.
573
574
  ...(forceDeploy ? ['--force'] : []),
575
+ ...(hasFlag(ctx.args, '--allow-over-budget') ? ['--allow-over-budget'] : []),
574
576
  ...modelDeployArgs,
575
577
  ],
576
578
  rawArgs: ['use', fw],
@@ -595,6 +597,17 @@ export const refreshHandler = {
595
597
  }
596
598
  }
597
599
  }
600
+ // Runtime updates can change the corpus even when there are no recorded
601
+ // deployments. Refresh both discovery representations, independently of use.
602
+ if (!dryRun) {
603
+ try {
604
+ const { refreshFrameworkCapabilities } = await import('../../artifacts/framework-capabilities.js');
605
+ await refreshFrameworkCapabilities(frameworkRoot, true, { force: true });
606
+ }
607
+ catch (error) {
608
+ ui.warn(`Capability index refresh failed: ${error instanceof Error ? error.message : String(error)}`);
609
+ }
610
+ }
598
611
  // Step 4.25: Report planned project-local deploys (#1035).
599
612
  // The active use handler performs the actual project-local deploy during
600
613
  // framework refresh; this block surfaces dry-run and completion details.
@@ -786,6 +799,21 @@ export const refreshHandler = {
786
799
  // Non-fatal — refresh continues even if migration fails
787
800
  }
788
801
  }
802
+ // Step 4.65: Direct worker dispatch opt-in hint (#3050). Refresh never
803
+ // prompts; this only names the enable command when dispatch is off and
804
+ // two or more worker CLIs are detected (presence-only PATH scan, no
805
+ // spawn). Silent otherwise, including after a previous decline.
806
+ if (!quiet) {
807
+ try {
808
+ const config = await readAiwgConfig(process.cwd());
809
+ const offer = evaluateWorkerDispatchOffer(config?.parallelism, config?.setup, detectInstalledWorkerClis());
810
+ if (offer.shouldOffer)
811
+ ui.info(workerDispatchOfferHint(offer.detected));
812
+ }
813
+ catch {
814
+ // Non-fatal — refresh continues even if the hint check fails
815
+ }
816
+ }
789
817
  // Step 5: Health check
790
818
  if (!quiet)
791
819
  ui.info(dryRun ? 'Would run health check...' : 'Running health check...');
@@ -150,6 +150,20 @@ async function handleRegenerate(args, cwd) {
150
150
  console.log(` Selected: ${selection.explicit ? 'explicit' : 'inferred'} — ${selection.reason}`);
151
151
  if (selection.evidence.length > 0)
152
152
  console.log(` Evidence: ${selection.evidence.join(', ')}`);
153
+ // #3050: regenerate never prompts. Point at direct worker dispatch when
154
+ // it is off and two or more worker CLIs are detected (presence-only PATH
155
+ // scan, no spawn); silent otherwise, including after a decline.
156
+ try {
157
+ const { readAiwgConfig } = await import('../../config/aiwg-config.js');
158
+ const { detectInstalledWorkerClis, evaluateWorkerDispatchOffer, workerDispatchOfferHint } = await import('../../models/worker-dispatch-offer.js');
159
+ const dispatchConfig = await readAiwgConfig(target);
160
+ const offer = evaluateWorkerDispatchOffer(dispatchConfig?.parallelism, dispatchConfig?.setup, detectInstalledWorkerClis());
161
+ if (offer.shouldOffer)
162
+ console.log(` ${workerDispatchOfferHint(offer.detected)}`);
163
+ }
164
+ catch {
165
+ // Non-fatal — this is an informational nudge, never a regenerate gate.
166
+ }
153
167
  if (existingProject) {
154
168
  const preflight = await migrateWorkspaceContext(target, {
155
169
  dryRun: true,
@@ -159,6 +159,9 @@ export const versionsHandler = {
159
159
  description: "Browse and resolve signed AIWG web resource releases",
160
160
  category: "index",
161
161
  aliases: [],
162
+ async help() {
163
+ return { exitCode: 0, message: usage(), rawOutput: true };
164
+ },
162
165
  async execute(ctx) {
163
166
  if (ctx.args[0] === "help" || ctx.args[0] === "--help" || ctx.args[0] === "-h") {
164
167
  console.log(usage());
@@ -0,0 +1,195 @@
1
+ import path from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { loadRulePinConfigs, selectorKey, validateRulePinCapabilities } from '../../rules/pins.mjs';
4
+ const usage = `Usage: aiwg rules pin|unpin [rule...] [--tier critical,high] [--capability id,... | --group name] [--all-tiers] [--all]
5
+ aiwg rules pinned [--capability id] [--json]
6
+ aiwg rules inventory|list [--scope workspace|user|installation|catalog] [--capability id,...] [--activation mode,...] [--tier level,...] [--provider name] [--bodies] [--json]
7
+ aiwg rules group set <name> <capability>... | group list
8
+ Flags: --project (default), --user, --dry-run, --no-deploy, --json, --allow-over-budget
9
+ Pins and group changes validate every input without prompting. --dry-run prints effective rules and per-provider startup bytes.`;
10
+ const valueFlags = new Set(['--tier', '--capability', '--group', '--scope', '--activation', '--provider']);
11
+ const boolFlags = new Set(['--all-tiers', '--all', '--dry-run', '--no-deploy', '--json', '--allow-over-budget', '--user', '--project', '--help', '-h', '--bodies']);
12
+ function parse(args) {
13
+ const values = new Map();
14
+ const flags = new Set();
15
+ const positional = [];
16
+ for (let i = 0; i < args.length; i++) {
17
+ const arg = args[i];
18
+ if (valueFlags.has(arg)) {
19
+ if (!args[i + 1] || args[i + 1].startsWith('-') || values.has(arg))
20
+ throw new Error(`${arg} requires one value`);
21
+ values.set(arg, args[++i]);
22
+ }
23
+ else if (boolFlags.has(arg))
24
+ flags.add(arg);
25
+ else if (arg.startsWith('-'))
26
+ throw new Error(`Unknown flag: ${arg}`);
27
+ else
28
+ positional.push(arg);
29
+ }
30
+ if (flags.has('--user') && flags.has('--project'))
31
+ throw new Error('Choose --project or --user');
32
+ const list = (flag) => values.get(flag)?.split(',').map(id => id.trim());
33
+ return { values, flags, positional, list };
34
+ }
35
+ // Provider helpers log progress while assembling staged output. Keep the command's
36
+ // stdout a single JSON document (and keep temporary staging paths out of text output).
37
+ async function quietDeployment(deploy, options) {
38
+ const log = console.log;
39
+ const warn = console.warn;
40
+ try {
41
+ console.log = () => { };
42
+ console.warn = () => { };
43
+ return await deploy(options);
44
+ }
45
+ finally {
46
+ console.log = log;
47
+ console.warn = warn;
48
+ }
49
+ }
50
+ export const rulesHandler = {
51
+ id: 'rules', name: 'Rule pins', category: 'config', aliases: [],
52
+ description: 'Pin rules to every request, inspect pins, and manage capability groups',
53
+ async help() { return { exitCode: 0, message: usage, rawOutput: true }; },
54
+ async execute(ctx) {
55
+ const json = ctx.args.includes('--json');
56
+ try {
57
+ const { values, flags, positional, list } = parse(ctx.args);
58
+ if (flags.has('--help') || flags.has('-h') || !positional.length)
59
+ return { exitCode: 0, message: usage, rawOutput: true };
60
+ const { rulePinState } = await import('../../rules/pin-state.js');
61
+ const { setRuleConfigKey } = await import('../../config/cli.js');
62
+ const [command, ...ids] = positional;
63
+ if (command === 'inventory' || command === 'list') {
64
+ if (ids.length || values.has('--group') || [...flags].some(flag => !['--json', '--bodies'].includes(flag)))
65
+ throw new Error('inventory accepts only inventory filters and output flags');
66
+ const scope = values.get('--scope') ?? 'workspace';
67
+ if (!['workspace', 'user', 'installation', 'catalog'].includes(scope))
68
+ throw new Error('Invalid inventory scope');
69
+ const activation = list('--activation');
70
+ const tier = list('--tier');
71
+ if (activation?.some(value => !['kernel', 'summary', 'bound', 'paths', 'on-demand'].includes(value)))
72
+ throw new Error('Invalid activation filter');
73
+ if (tier?.some(value => !['critical', 'high', 'medium', 'low'].includes(value)))
74
+ throw new Error('Invalid tier filter');
75
+ if (list('--capability')?.some(value => !value))
76
+ throw new Error('Invalid capability filter');
77
+ const { ruleInventory } = await import('../../rules/inventory.js');
78
+ const report = await ruleInventory(ctx.cwd, ctx.frameworkRoot, { scope: scope, capability: list('--capability'), activation, enforcement: tier, provider: values.get('--provider'), bodies: flags.has('--bodies') });
79
+ return { exitCode: 0, rawOutput: true, message: json ? JSON.stringify(report, null, 2) :
80
+ [`Scope: ${report.scope} (${report.scope_description})`, 'Per-rule delivery and session loading: unknown.', ...report.rules.map(rule => `${rule.capability}/${rule.name} [${rule.effective_activation ?? 'unconfigured'}, ${rule.enforcement ?? 'unknown'}]: ${rule.summary ?? '(no summary)'}; ${rule.fetch_command ?? 'fetch ID unknown'}${rule.content ? `\n${rule.content}` : ''}`), ...report.warnings, ...(!report.rules.length ? ['No matching rules.'] : [])].join('\n') };
81
+ }
82
+ if (values.has('--scope') || values.has('--activation') || values.has('--provider') || flags.has('--bodies'))
83
+ throw new Error('Inventory filters are only valid for rules inventory');
84
+ const source = flags.has('--user') ? 'user' : 'project';
85
+ const configs = loadRulePinConfigs(ctx.cwd);
86
+ const before = rulePinState(ctx.cwd, ctx.frameworkRoot, configs, true);
87
+ if (command === 'pinned') {
88
+ if (ids.length || [...values.keys()].some(key => key !== '--capability'))
89
+ throw new Error('pinned accepts only --capability and output/scope flags');
90
+ const filter = list('--capability');
91
+ if (filter?.some(id => !before.installed.includes(id)))
92
+ throw new Error(`Unknown capability. Installed ids: ${before.installed.join(', ')}`);
93
+ const rules = before.rules.filter(rule => !filter || filter.includes(rule.capability?.replace(/^(framework|addon|extension|plugin):/, '') || ''));
94
+ return { exitCode: 0, message: json ? JSON.stringify({ rules, warnings: before.warnings }, null, 2)
95
+ : [...rules.map(rule => `${rule.name}: pinned kernel (canonical ${rule.canonical_activation}) ${rule.matches.map(match => `${match.source}: ${JSON.stringify(match.selector)}`).join('; ')}`), ...before.warnings, ...(!rules.length ? ['No effective rule pins.'] : [])].join('\n'), rawOutput: true };
96
+ }
97
+ if (command === 'group' && ids[0] === 'list') {
98
+ if (ids.length !== 1 || values.size)
99
+ throw new Error('Usage: aiwg rules group list');
100
+ const groups = { user: configs.user.rules?.pin_groups || {}, project: configs.project.rules?.pin_groups || {} };
101
+ return { exitCode: 0, message: JSON.stringify(groups, null, 2), rawOutput: true };
102
+ }
103
+ const selected = configs[source];
104
+ selected.rules = { ...selected.rules };
105
+ if (command === 'group') {
106
+ const [action, name, ...capabilities] = ids;
107
+ if (action !== 'set' || !name || !capabilities.length || values.size)
108
+ throw new Error('Usage: aiwg rules group set <name> <capability>...');
109
+ selected.rules.pin_groups = { ...selected.rules.pin_groups, [name]: [...new Set(capabilities.flatMap(id => id.split(',')))].sort() };
110
+ }
111
+ else if (command === 'pin' || command === 'unpin') {
112
+ if (flags.has('--all-tiers') && values.has('--tier'))
113
+ throw new Error('--all-tiers and --tier are mutually exclusive');
114
+ const selector = {};
115
+ if (ids.length)
116
+ selector.rules = [...new Set(ids)].sort();
117
+ if (values.has('--tier'))
118
+ selector.enforcement = list('--tier');
119
+ if (values.has('--capability'))
120
+ selector.capabilities = list('--capability');
121
+ if (values.has('--group'))
122
+ selector.group = values.get('--group');
123
+ if (flags.has('--all'))
124
+ selector.all = true;
125
+ if (!Object.keys(selector).length)
126
+ throw new Error('Supply rule ids, --tier, --capability, --group, or --all');
127
+ if (flags.has('--all-tiers') && !selector.capabilities && !selector.group && !selector.all)
128
+ throw new Error('--all-tiers requires --capability, --group or --all');
129
+ const existing = selected.rules.always_load || [];
130
+ const key = selectorKey(selector);
131
+ if (command === 'pin') {
132
+ const unknown = ids.filter(id => !before.inventory.some(rule => [rule.name, rule.id, rule.path].includes(id)));
133
+ if (unknown.length)
134
+ throw new Error(`Unknown installed rule ids: ${unknown.join(', ')}`);
135
+ selected.rules.always_load = existing.some(item => selectorKey(item) === key) ? existing : [...existing, selector];
136
+ }
137
+ else
138
+ selected.rules.always_load = existing.filter(item => selectorKey(item) !== key);
139
+ }
140
+ else
141
+ throw new Error(usage);
142
+ // Only the edited scope is strict: stale pins in another scope remain visible warnings.
143
+ const errors = validateRulePinCapabilities(selected.rules, before.installed, { ...configs.user.rules?.pin_groups, ...configs.project.rules?.pin_groups });
144
+ if (errors.length)
145
+ throw new Error(errors.join('\n'));
146
+ const after = rulePinState(ctx.cwd, ctx.frameworkRoot, configs, true);
147
+ const providers = [...new Set([...(configs.project.providers || []), ...Object.values(configs.project.installed || {}).flatMap(entry => Object.keys(entry.deployedTo || {}))])];
148
+ const reports = [];
149
+ const failures = [];
150
+ const plans = [];
151
+ // Use precisely the installed rule inventory, including local bundles; do not select new capabilities.
152
+ for (const provider of providers) {
153
+ if (!['claude', 'codex', 'cursor', 'hermes', 'warp', 'openclaw'].includes(provider)) {
154
+ failures.push(`Rule pin projection is unavailable for provider '${provider}'`);
155
+ continue;
156
+ }
157
+ const module = await import(pathToFileURL(path.join(ctx.frameworkRoot, 'tools/agents/providers', `${provider}.mjs`)).href);
158
+ const options = { srcRoot: path.join(ctx.frameworkRoot, 'agentic/code'), target: ctx.cwd, mode: 'all',
159
+ ruleSources: after.inventory.map(rule => rule.path), config: configs.project, pinConfigs: configs,
160
+ rulesOnly: true, deployRules: true, deploySkills: false, deployCommands: false,
161
+ force: true, quiet: true, allowOverBudget: flags.has('--allow-over-budget') };
162
+ try {
163
+ const report = await quietDeployment(module.deploy, { ...options, dryRun: true, previewReport: true });
164
+ reports.push(report);
165
+ plans.push({ deploy: module.deploy, options });
166
+ }
167
+ catch (error) {
168
+ failures.push(`${provider}: ${error instanceof Error ? error.message : String(error)}`);
169
+ }
170
+ }
171
+ if (failures.length)
172
+ throw new Error(failures.join('\n'));
173
+ const dryRun = flags.has('--dry-run') || ctx.dryRun;
174
+ if (!dryRun) {
175
+ await setRuleConfigKey(ctx.cwd, source, 'rules', JSON.stringify(selected.rules));
176
+ if (!flags.has('--no-deploy'))
177
+ for (const plan of plans)
178
+ await quietDeployment(plan.deploy, plan.options);
179
+ }
180
+ const redeploy = 'aiwg refresh --skip-update --force' + (flags.has('--allow-over-budget') ? ' --allow-over-budget' : '');
181
+ const needsRedeploy = flags.has('--no-deploy') || plans.length === 0;
182
+ const output = { dry_run: !!dryRun, source, rules: after.rules, warnings: after.warnings, providers: reports,
183
+ deployed: !dryRun && !needsRedeploy, ...(needsRedeploy ? { redeploy } : {}) };
184
+ return { exitCode: 0, message: json ? JSON.stringify(output, null, 2)
185
+ : [dryRun ? 'Rule pin preview (config unchanged)' : 'Rule pins updated', ...after.rules.map(rule => `${rule.name}: kernel (canonical ${rule.canonical_activation})`),
186
+ ...reports.map(report => { const r = report; return `${r.provider}: ${r.selected_bytes} startup bytes${report.exceeded ? ' (over budget; explicitly allowed)' : ''}`; }),
187
+ ...after.warnings, ...(needsRedeploy ? [`Redeploy: ${redeploy}`] : [])].join('\n'), rawOutput: true };
188
+ }
189
+ catch (error) {
190
+ const message = error instanceof Error ? error.message : String(error);
191
+ return { exitCode: 1, message: json ? JSON.stringify({ error: message }) : message, rawOutput: json };
192
+ }
193
+ },
194
+ };
195
+ //# sourceMappingURL=rules.js.map
@@ -62,6 +62,10 @@ export const runHandler = {
62
62
  description: 'Run a user-defined script from aiwg.config',
63
63
  category: 'utility',
64
64
  aliases: [],
65
+ async help() {
66
+ printRunUsage();
67
+ return { exitCode: 0 };
68
+ },
65
69
  async execute(ctx) {
66
70
  let parsed;
67
71
  try {
@@ -12,6 +12,7 @@ import path from 'path';
12
12
  import { AiwgError, EXIT_CODES, handlerResultFromError } from '../errors.js';
13
13
  import { getPackageRoot } from '../../channel/manager.mjs';
14
14
  import { inspectInstallation } from '../../installation/manager.mjs';
15
+ import { isSessionProviderResolution, resolveActiveProvider } from '../provider-resolution.js';
15
16
  function isMissingRuntimeCatalogError(error) {
16
17
  return error instanceof Error && error.message.includes('No catalog found');
17
18
  }
@@ -201,8 +202,7 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
201
202
  const { RuntimeDiscovery } = await import('../../smiths/toolsmith/runtime-discovery.mjs');
202
203
  const discovery = new RuntimeDiscovery();
203
204
  if (hasDiscover) {
204
- // Full discovery
205
- const catalog = await discovery.discover();
205
+ const catalog = await discovery.discover({ force: args.includes('--force') });
206
206
  if (hasJson) {
207
207
  console.log(JSON.stringify(catalog, null, 2));
208
208
  }
@@ -304,21 +304,35 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
304
304
  console.log(` Run mode: ${installation.identity?.runMode ?? '(unrecorded)'}`);
305
305
  console.log(` State: ${installation.state}`);
306
306
  // Scheduler backend detection
307
- const { execSync } = await import('child_process');
307
+ const { boundedExecFileSync } = await import('../../process/bounded-child-process.mjs');
308
308
  let schedulerBackend = 'external trigger required (system cron/systemd/CI)';
309
309
  let chronyInstalled = false;
310
- try {
311
- execSync('which chronyc 2>/dev/null || which chronyd 2>/dev/null', { stdio: 'pipe' });
312
- chronyInstalled = true;
313
- }
314
- catch {
315
- // chrony not found
310
+ for (const tool of ['chronyc', 'chronyd']) {
311
+ try {
312
+ boundedExecFileSync('which', [tool], 'quick', { stdio: ['pipe', 'pipe', 'ignore'] });
313
+ chronyInstalled = true;
314
+ break;
315
+ }
316
+ catch {
317
+ // Try the next chrony binary.
318
+ }
316
319
  }
317
320
  // Native CronCreate is only available when running inside a Claude Code agent context.
318
321
  // The CLI itself cannot call agent tools, so we report based on platform heuristics.
319
322
  // When invoked from within an agent, the schedule skill performs live detection.
320
- const isClaudeCodeContext = process.env.CLAUDE_CODE_VERSION !== undefined ||
321
- process.env.ANTHROPIC_API_KEY !== undefined;
323
+ //
324
+ // Resolved through the same shared provider-resolution path `steward
325
+ // capabilities` uses (`resolveActiveProvider` -> the `claude` provider's
326
+ // `detection.env` markers in provider-definitions.ts) so the two never
327
+ // disagree about which provider the current session is running under
328
+ // (#2623, #2627). The ad-hoc `CLAUDE_CODE_VERSION`/`ANTHROPIC_API_KEY`
329
+ // check this replaced was stale (neither is set by current Claude Code)
330
+ // and `ANTHROPIC_API_KEY` was a false positive for any non-Claude
331
+ // session with that key set.
332
+ const activeProviderResolution = await resolveActiveProvider({ cwd });
333
+ // Only a session signal counts: a project merely configured or deployed
334
+ // for Claude is not a Claude Code agent context.
335
+ const isClaudeCodeContext = activeProviderResolution.provider === 'claude' && isSessionProviderResolution(activeProviderResolution);
322
336
  if (isClaudeCodeContext) {
323
337
  schedulerBackend = 'native-cron (CronCreate); external trigger outside agent sessions';
324
338
  }
@@ -8,6 +8,7 @@
8
8
  * @source @src/cli/router.ts
9
9
  * @issue #33
10
10
  */
11
+ import { signalChild } from '../../process/signal-child.mjs';
11
12
  import { spawn } from 'child_process';
12
13
  import path from 'path';
13
14
  /**
@@ -30,8 +31,8 @@ export class DefaultScriptRunner {
30
31
  async run(scriptPath, args = [], options = {}) {
31
32
  const fullPath = path.join(this.frameworkRoot, scriptPath);
32
33
  return new Promise((resolve) => {
33
- // When capture mode is enabled, stdout/stderr are piped back to the
34
- // caller so that quiet-mode callers can suppress output. When not
34
+ // When capture mode is enabled, stdout/stderr are piped so that
35
+ // quiet-mode callers can suppress output. When not
35
36
  // capturing, stdio: 'inherit' lets subprocess output flow directly to
36
37
  // the terminal (verbose mode).
37
38
  const stdio = options.capture ? 'pipe' : 'inherit';
@@ -40,10 +41,20 @@ export class DefaultScriptRunner {
40
41
  cwd: options.cwd || process.cwd(),
41
42
  env: { ...process.env, ...options.env },
42
43
  });
43
- let capturedStderr = '';
44
+ // Always drain captured pipes, even after the diagnostic cap is reached.
45
+ // stdout is not part of HandlerResult; discard it. Retain only the first
46
+ // 1 MiB of stderr for failure messages, discarding any excess.
47
+ child.stdout?.resume();
48
+ const stderrLimit = 1024 * 1024;
49
+ const capturedStderr = [];
50
+ let capturedStderrBytes = 0;
44
51
  if (options.capture && child.stderr) {
45
52
  child.stderr.on('data', (data) => {
46
- capturedStderr += data.toString();
53
+ const retained = data.subarray(0, stderrLimit - capturedStderrBytes);
54
+ if (retained.length > 0) {
55
+ capturedStderr.push(Buffer.from(retained));
56
+ capturedStderrBytes += retained.length;
57
+ }
47
58
  });
48
59
  }
49
60
  const timeout = options.timeout;
@@ -63,12 +74,12 @@ export class DefaultScriptRunner {
63
74
  // does not exit within the deadline. Both kill() calls are wrapped
64
75
  // because they can throw ESRCH on an already-exited child.
65
76
  try {
66
- child.kill('SIGTERM');
77
+ signalChild(child, 'SIGTERM');
67
78
  }
68
79
  catch { /* already exited */ }
69
80
  killEscalationId = setTimeout(() => {
70
81
  try {
71
- child.kill('SIGKILL');
82
+ signalChild(child, 'SIGKILL');
72
83
  }
73
84
  catch { /* already exited */ }
74
85
  }, killDeadlineMs);
@@ -86,10 +97,10 @@ export class DefaultScriptRunner {
86
97
  if (killEscalationId)
87
98
  clearTimeout(killEscalationId);
88
99
  // On failure in capture mode, surface the captured stderr
89
- if (options.capture && code !== 0 && capturedStderr) {
100
+ if (options.capture && code !== 0 && capturedStderrBytes > 0) {
90
101
  resolve({
91
102
  exitCode: code ?? 1,
92
- message: capturedStderr.trim(),
103
+ message: Buffer.concat(capturedStderr).toString().trim(),
93
104
  });
94
105
  }
95
106
  else {