@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
@@ -1,11 +1,11 @@
1
- import { askDecision, DecisionAskUsageError, decisionCapabilities, evaluateRequestPath, listPatterns, livePlan, materializeSyntheticClassificationSetup, readDecisionContextFile, runOfflinePattern, setupJev, showPattern, syntheticClassificationSetup, validateDecisionInput, } from '../../decision/driver.js';
1
+ import { ATTRIBUTION_FIELD_PATTERN, DecisionAskUsageError, decisionCapabilities, DecisionLedgerSinceError, decisionLedgerHistory, decisionLedgerStats, evaluateRequestPath, listPatterns, livePlan, MAX_ATTRIBUTION_FIELD_LENGTH, materializeSyntheticClassificationSetup, parseDecisionLedgerSince, readDecisionContextFile, runDecisionOffloadCheckpoint, runOfflinePattern, setupJev, showPattern, syntheticClassificationSetup, validateDecisionInput, } from '../../decision/driver.js';
2
2
  function jsonResult(value, exitCode = 0) {
3
3
  return { exitCode, message: JSON.stringify(value, null, 2), rawOutput: true };
4
4
  }
5
5
  function usage() {
6
6
  return [
7
- 'Usage: aiwg decision <capabilities|status|patterns|validate|evaluate|setup> [options]',
8
- ' aiwg decision ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5) [--context <text> | --context-file <path> | --context-stdin] [--threshold 0.8] [--timeout-ms 15000] [--json]',
7
+ 'Usage: aiwg decision <capabilities|status|patterns|validate|evaluate|setup|history|stats> [options]',
8
+ ' aiwg decision ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5) [--context <text> | --context-file <path> | --context-stdin] [--threshold 0.8] [--timeout-ms 15000] [--passes N] [--escalation-passes N] [--provider <id>] [--session <id>] [--caller <tag>] [--record-text] [--json]',
9
9
  '',
10
10
  'Commands:',
11
11
  ' capabilities|status Show offline readiness, primitives, config and feature availability',
@@ -17,7 +17,33 @@ function usage() {
17
17
  ' evaluate --request <path> [--host-policy-module <path>]',
18
18
  ' setup synthetic-classification [--output-dir <dir>]',
19
19
  ' setup jev [--token-stdin] [--region <r>] [--endpoint <url>] [--verify] [--remove]',
20
- ' ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5)',
20
+ ' ask --question "<q>" (--yes-no | --choices a,b,c | --scale 1-5) [--provider <id>] [--session <id>] [--caller <tag>] [--record-text]',
21
+ ' history [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--json]',
22
+ ' stats [--since <date>] [--provider <id>] [--session <id>] [--kind yes-no|choices|scale] [--status answered|fallback] [--caller <tag>|<prefix>* | --no-caller] [--group-by provider|session|kind|caller|passes|escalation] [--json]',
23
+ '',
24
+ 'Notes:',
25
+ ' Every COMPLETED `ask` call (CLI and MCP) appends one record to the decision',
26
+ ' ledger (.aiwg/decision/ledger.jsonl, resolved like `aiwg artifacts path`).',
27
+ ' Usage errors (bad flags, oversized context) are never recorded. Question',
28
+ ' and context text are never written unless --record-text is passed, and even',
29
+ ' then only after redaction and truncation to a documented size cap. Every',
30
+ ' other persisted field (session, caller, choice ids, answer, model, provider,',
31
+ ' project root) is also redacted before being written. `questionDigest` and',
32
+ ' `contextDigest` are plain SHA-256 over the raw text: a short, predictable',
33
+ ' question can still be matched by hashing candidate guesses, so a digest is',
34
+ ' not a confidentiality guarantee on its own.',
35
+ ' `history` and `stats` read that ledger offline — no network, no Jev call.',
36
+ ' `--since` is strict ISO-8601: a bare date or an offsetless timestamp is',
37
+ ' interpreted as UTC; invalid calendar dates (e.g. 2026-02-30) are rejected,',
38
+ ' including when an explicit offset is present.',
39
+ ` --session and --caller must match ${ATTRIBUTION_FIELD_PATTERN.source} (<= ${MAX_ATTRIBUTION_FIELD_LENGTH} characters).`,
40
+ ' `history`/`stats` accept `--caller <tag>` (exact), `--caller \'<prefix>*\'` (prefix; the only wildcard), or `--no-caller` (records with no tag; not combinable with `--caller`).',
41
+ ' `history`/`stats` reject unknown flags and positional arguments with exit 2.',
42
+ ' The ledger has no built-in retention: it grows without bound and the',
43
+ ' operator may truncate or delete it at any time; readers tolerate a missing',
44
+ ' file. The ledger trusts only the local filesystem under the project',
45
+ ' artifact root, owned by the same user running aiwg — it is not a defense',
46
+ ' against a hostile process already running as that user.',
21
47
  ].join('\n');
22
48
  }
23
49
  function takeOption(args, name) {
@@ -62,6 +88,16 @@ function parseScale(value) {
62
88
  throw new DecisionAskUsageError('invalid-scale', '--scale requires a range like 1-5');
63
89
  return { low: Number(match[1]), high: Number(match[2]) };
64
90
  }
91
+ /** Shared by --session and --caller (review r1 finding 1): a conservative identifier shape, rejected with exit 2. */
92
+ function takeAttributionOption(args, name, reason) {
93
+ const value = takeOption(args, name);
94
+ if (value === undefined)
95
+ return undefined;
96
+ if (!ATTRIBUTION_FIELD_PATTERN.test(value)) {
97
+ throw new DecisionAskUsageError(reason, `${name} must match ${ATTRIBUTION_FIELD_PATTERN.source} (<= ${MAX_ATTRIBUTION_FIELD_LENGTH} characters)`);
98
+ }
99
+ return value;
100
+ }
65
101
  async function decisionSetupJev(rest) {
66
102
  const token = rest.includes('--token-stdin') ? (await readStdin()).trim() : undefined;
67
103
  const result = await setupJev({
@@ -81,6 +117,9 @@ async function decisionAsk(ctx) {
81
117
  const contextModes = flagCount(args, ['--context', '--context-file', '--context-stdin']);
82
118
  if (contextModes > 1)
83
119
  throw new DecisionAskUsageError('invalid-context', 'Select at most one context source');
120
+ // Validated before any Jev call, so a malformed attribution flag never wastes one.
121
+ const explicitSessionId = takeAttributionOption(args, '--session', 'invalid-session');
122
+ const caller = takeAttributionOption(args, '--caller', 'invalid-caller');
84
123
  const question = args.includes('--question') ? takeRequiredOption(args, '--question') : '';
85
124
  let context = takeOption(args, '--context');
86
125
  if (args.includes('--context') && (context === undefined || context.startsWith('--'))) {
@@ -100,16 +139,186 @@ async function decisionAsk(ctx) {
100
139
  : choices !== undefined ? { kind: 'choices', choices: choices.split(',').map(value => value.trim()).filter(Boolean) }
101
140
  : { kind: 'scale', ...scale },
102
141
  ...(context === undefined ? {} : { context }),
142
+ ...(args.includes('--passes') ? { passes: parseNumber(takeRequiredOption(args, '--passes'), '--passes') } : {}),
143
+ ...(args.includes('--escalation-passes') ? { escalationPasses: parseNumber(takeRequiredOption(args, '--escalation-passes'), '--escalation-passes') } : {}),
103
144
  ...(args.includes('--threshold') ? { threshold: parseNumber(takeOption(args, '--threshold'), '--threshold') } : {}),
104
145
  ...(args.includes('--timeout-ms') ? { timeoutMs: parseNumber(takeOption(args, '--timeout-ms'), '--timeout-ms') } : {}),
105
146
  };
106
- const result = await askDecision(input, { env: process.env });
147
+ const invocation = await runDecisionOffloadCheckpoint(input, {
148
+ transport: 'cli',
149
+ projectRoot: ctx.cwd,
150
+ env: process.env,
151
+ explicitProvider: takeOption(args, '--provider'),
152
+ explicitSessionId,
153
+ caller: caller ?? 'decision-cli:ask',
154
+ ledgerCaller: caller ?? null,
155
+ category: caller ? undefined : 'unattributed',
156
+ recordText: args.includes('--record-text'),
157
+ });
158
+ if (!invocation.result)
159
+ throw invocation.outcome === 'unknown' ? invocation.error : new Error('Decision ask was skipped');
160
+ const result = invocation.result;
107
161
  if (args.includes('--json'))
108
162
  return jsonResult(result);
109
163
  if (result.status === 'fallback')
110
164
  return { exitCode: 0, message: `FALLBACK to LLM: ${result.reason}`, rawOutput: true };
111
165
  return { exitCode: 0, message: `${String(result.answer)} (confidence ${result.confidence?.toFixed(2) ?? 'unknown'}, ${result.model ?? 'unknown-model'})`, rawOutput: true };
112
166
  }
167
+ function parseSince(value) {
168
+ if (value === undefined)
169
+ return undefined;
170
+ try {
171
+ return parseDecisionLedgerSince(value);
172
+ }
173
+ catch (error) {
174
+ if (error instanceof DecisionLedgerSinceError)
175
+ throw new DecisionAskUsageError('invalid-since', error.message);
176
+ throw error;
177
+ }
178
+ }
179
+ const DECISION_LEDGER_KINDS = ['yes-no', 'choices', 'scale'];
180
+ const DECISION_LEDGER_STATUSES = ['answered', 'fallback'];
181
+ const DECISION_LEDGER_GROUP_BYS = ['provider', 'session', 'kind', 'caller', 'passes', 'escalation'];
182
+ function parseKindFilter(value) {
183
+ if (value === undefined)
184
+ return undefined;
185
+ if (!DECISION_LEDGER_KINDS.includes(value)) {
186
+ throw new DecisionAskUsageError('invalid-kind', `--kind must be one of ${DECISION_LEDGER_KINDS.join(', ')}`);
187
+ }
188
+ return value;
189
+ }
190
+ function parseStatusFilter(value) {
191
+ if (value === undefined)
192
+ return undefined;
193
+ if (!DECISION_LEDGER_STATUSES.includes(value)) {
194
+ throw new DecisionAskUsageError('invalid-status', `--status must be one of ${DECISION_LEDGER_STATUSES.join(', ')}`);
195
+ }
196
+ return value;
197
+ }
198
+ function parseGroupBy(value) {
199
+ if (value === undefined)
200
+ return undefined;
201
+ if (!DECISION_LEDGER_GROUP_BYS.includes(value)) {
202
+ throw new DecisionAskUsageError('invalid-group-by', `--group-by must be one of ${DECISION_LEDGER_GROUP_BYS.join(', ')}`);
203
+ }
204
+ return value;
205
+ }
206
+ const HISTORY_VALUE_FLAGS = ['--since', '--provider', '--session', '--kind', '--status', '--caller'];
207
+ const HISTORY_BOOL_FLAGS = ['--json', '--no-caller'];
208
+ const STATS_VALUE_FLAGS = [...HISTORY_VALUE_FLAGS, '--group-by'];
209
+ const STATS_BOOL_FLAGS = HISTORY_BOOL_FLAGS;
210
+ /**
211
+ * Strict allow-list for `history`/`stats`: unknown `--flags` and positional
212
+ * arguments are usage errors (exit 2) naming the offending token, instead of
213
+ * being silently ignored. `ask`/`setup` parsing is intentionally untouched.
214
+ */
215
+ function assertLedgerArgs(args, valueFlags, boolFlags) {
216
+ let index = 0;
217
+ while (index < args.length) {
218
+ const token = args[index];
219
+ if (valueFlags.includes(token)) {
220
+ if (args[index + 1] === undefined)
221
+ throw new DecisionAskUsageError(`missing-${token.slice(2)}`, `${token} requires a value`);
222
+ index += 2;
223
+ continue;
224
+ }
225
+ if (boolFlags.includes(token)) {
226
+ index += 1;
227
+ continue;
228
+ }
229
+ if (token.startsWith('--'))
230
+ throw new DecisionAskUsageError('unknown-flag', `unknown flag ${token}`);
231
+ throw new DecisionAskUsageError('unexpected-argument', `unexpected argument ${token}`);
232
+ }
233
+ }
234
+ /**
235
+ * Parses `--caller <tag>` for `history`/`stats`: an exact match, except a
236
+ * single trailing `*` means prefix match (`--caller 'address-issues:*'`).
237
+ * The tag itself must match the attribution shape; `--no-caller` (records
238
+ * with no caller tag) is parsed separately and cannot be combined with it.
239
+ */
240
+ function parseCallerFilter(args) {
241
+ const raw = takeOption(args, '--caller');
242
+ const noCaller = args.includes('--no-caller');
243
+ if (raw !== undefined && noCaller) {
244
+ throw new DecisionAskUsageError('invalid-caller-filter', '--caller and --no-caller cannot be used together');
245
+ }
246
+ if (noCaller)
247
+ return { noCaller: true };
248
+ if (raw === undefined)
249
+ return {};
250
+ if (raw === '' || raw.startsWith('--')) {
251
+ throw new DecisionAskUsageError('invalid-caller', '--caller requires a non-empty value');
252
+ }
253
+ const prefix = raw.endsWith('*');
254
+ const tag = prefix ? raw.slice(0, -1) : raw;
255
+ if (tag === '' || !ATTRIBUTION_FIELD_PATTERN.test(tag)) {
256
+ throw new DecisionAskUsageError('invalid-caller', `--caller must match ${ATTRIBUTION_FIELD_PATTERN.source} (<= ${MAX_ATTRIBUTION_FIELD_LENGTH} characters), allowing one trailing *`);
257
+ }
258
+ return prefix ? { callerPrefix: tag } : { caller: tag };
259
+ }
260
+ /** Shared by `history` and `stats` (review r1 finding 9): the same filters, parsed the same way. */
261
+ function parseLedgerFilters(args) {
262
+ return {
263
+ since: parseSince(takeOption(args, '--since')),
264
+ provider: takeOption(args, '--provider'),
265
+ sessionId: takeOption(args, '--session'),
266
+ kind: parseKindFilter(takeOption(args, '--kind')),
267
+ status: parseStatusFilter(takeOption(args, '--status')),
268
+ ...parseCallerFilter(args),
269
+ };
270
+ }
271
+ /** One header line stating the caller filter, shown only when one is set. */
272
+ function callerFilterHeader(filters) {
273
+ if (filters.noCaller)
274
+ return 'Caller filter: no caller (records with no caller tag)';
275
+ if (filters.caller !== undefined)
276
+ return `Caller filter: ${filters.caller}`;
277
+ if (filters.callerPrefix !== undefined)
278
+ return `Caller filter: ${filters.callerPrefix}*`;
279
+ return null;
280
+ }
281
+ async function decisionHistory(ctx) {
282
+ const args = ctx.args.slice(1);
283
+ assertLedgerArgs(args, HISTORY_VALUE_FLAGS, HISTORY_BOOL_FLAGS);
284
+ const filters = parseLedgerFilters(args);
285
+ const result = await decisionLedgerHistory(ctx.cwd, filters);
286
+ if (args.includes('--json'))
287
+ return jsonResult(result);
288
+ const header = result.skipped > 0 ? [`(${result.skipped} invalid line(s) skipped)`] : [];
289
+ const callerHeader = callerFilterHeader(filters);
290
+ if (callerHeader)
291
+ header.push(callerHeader);
292
+ if (result.count === 0)
293
+ return { exitCode: 0, message: [...header, 'No decision ledger records match the filters.'].join('\n'), rawOutput: true };
294
+ const lines = result.records.map(record => `${record.timestamp} ${record.status.padEnd(8)} provider=${record.provider} kind=${record.decisionKind} confidence=${record.confidence ?? '-'} caller=${record.caller ?? '-'} id=${record.id}`);
295
+ return { exitCode: 0, message: [...header, ...lines].join('\n'), rawOutput: true };
296
+ }
297
+ async function decisionStats(ctx) {
298
+ const args = ctx.args.slice(1);
299
+ assertLedgerArgs(args, STATS_VALUE_FLAGS, STATS_BOOL_FLAGS);
300
+ const filters = { ...parseLedgerFilters(args), groupBy: parseGroupBy(takeOption(args, '--group-by')) };
301
+ const result = await decisionLedgerStats(ctx.cwd, filters);
302
+ if (args.includes('--json'))
303
+ return jsonResult(result);
304
+ const header = result.skipped > 0 ? [`(${result.skipped} invalid line(s) skipped)`] : [];
305
+ const callerHeader = callerFilterHeader(filters);
306
+ if (callerHeader)
307
+ header.push(callerHeader);
308
+ if (result.groups.length === 0)
309
+ return { exitCode: 0, message: [...header, 'No decision ledger records match the filters.'].join('\n'), rawOutput: true };
310
+ const lines = result.groups.flatMap(group => [
311
+ `${result.groupBy ?? 'all'}=${group.key ?? 'null'}: ${group.totalCalls} calls (${group.answered} answered, ${group.fallback} fallback, hit rate=${group.hitRate.toFixed(2)}, fallback rate=${group.fallbackRate.toFixed(2)})`,
312
+ ` confidence: mean=${group.confidence.mean?.toFixed(2) ?? '-'} min=${group.confidence.min?.toFixed(2) ?? '-'} max=${group.confidence.max?.toFixed(2) ?? '-'} (n=${group.confidence.count})`,
313
+ ` agreement: mean=${group.agreement.mean?.toFixed(2) ?? '-'} escalated=${group.escalatedCalls} passes run=${group.passesRun}`,
314
+ ` jev usage: input=${group.jevUsage.inputTokens} output=${group.jevUsage.outputTokens}`,
315
+ ` tokens per answered decision=${group.tokensPerAnsweredDecision?.toFixed(2) ?? '-'}`,
316
+ ` llm_tokens_avoided=${group.llm_tokens_avoided} jev_tokens=${group.jev_tokens} cost_weighted_net_usd=${group.cost_weighted_net_usd.toFixed(6)}`,
317
+ ` v1 comparison only: estimated LLM tokens avoided=${group.estimatedLlmTokensAvoidedTotal} net savings=${group.netSavingsTokens}`,
318
+ ...(group.legacyReestimatedCalls ? [` v1 records re-estimated=${group.legacyReestimatedCalls} weights=${JSON.stringify(result.legacyEstimationWeights)}`] : []),
319
+ ]);
320
+ return { exitCode: 0, message: [...header, ...lines].join('\n'), rawOutput: true };
321
+ }
113
322
  async function executeDecision(ctx) {
114
323
  const [command, subcommand, ...rest] = ctx.args;
115
324
  const options = { cwd: ctx.cwd, frameworkRoot: ctx.frameworkRoot, env: process.env };
@@ -120,6 +329,10 @@ async function executeDecision(ctx) {
120
329
  return jsonResult(decisionCapabilities(options));
121
330
  if (command === 'ask')
122
331
  return await decisionAsk(ctx);
332
+ if (command === 'history')
333
+ return await decisionHistory(ctx);
334
+ if (command === 'stats')
335
+ return await decisionStats(ctx);
123
336
  if (command === 'patterns') {
124
337
  if (subcommand === 'list')
125
338
  return jsonResult(listPatterns());
@@ -26,6 +26,8 @@ import { getLoggerInfo } from '../log.js';
26
26
  import { readAiwgConfig, getProjectDir } from '../../config/aiwg-config.js';
27
27
  import { getLogger } from '../log.js';
28
28
  import { spawnSync } from 'child_process';
29
+ import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
30
+ import { exitCodeForSpawnResult } from '../child-process-result.js';
29
31
  import { readFileSync, writeFileSync, existsSync, statSync, readdirSync, mkdtempSync, rmSync } from 'fs';
30
32
  import path from 'path';
31
33
  import os from 'os';
@@ -85,9 +87,14 @@ export const diagnoseHandler = {
85
87
  }
86
88
  // tar it up via system tar. We rely on GNU/BSD tar being present;
87
89
  // degrade gracefully if not.
88
- const tar = spawnSync('tar', ['-czf', outPath, '-C', stage, '.'], { stdio: 'pipe' });
90
+ // Packaging a small local diagnostics bundle; quick tier (#3062).
91
+ const tar = boundedSpawnSync('tar', ['-czf', outPath, '-C', stage, '.'], 'quick', { stdio: 'pipe' });
89
92
  if (tar.status !== 0) {
90
- ui.error(`tar failed: ${tar.stderr?.toString() ?? '(no stderr)'}`);
93
+ // #3062 review item 7: already correctly treats a null status
94
+ // (timeout/signal) as failure; surface the bounded helper's
95
+ // diagnostic (e.g. the enriched timeout message) ahead of stderr.
96
+ const detail = exitCodeForSpawnResult(tar).message ?? tar.stderr?.toString() ?? '(no stderr)';
97
+ ui.error(`tar failed: ${detail}`);
91
98
  ui.info(`Bundle contents staged at: ${stage}`);
92
99
  ui.info(`You can tar it manually: tar -czf ${outName} -C ${stage} .`);
93
100
  return { exitCode: 1, error: new Error('tar failed') };
@@ -200,9 +207,9 @@ function redactSecretsInObject(obj) {
200
207
  }
201
208
  function collectGitInfo(cwd) {
202
209
  try {
203
- const branch = spawnSync('git', ['-C', cwd, 'rev-parse', '--abbrev-ref', 'HEAD'], { stdio: 'pipe', timeout: 5000 });
204
- const log = spawnSync('git', ['-C', cwd, 'log', '-10', '--oneline'], { stdio: 'pipe', timeout: 5000 });
205
- const remote = spawnSync('git', ['-C', cwd, 'remote', '-v'], { stdio: 'pipe', timeout: 5000 });
210
+ const branch = spawnSync('git', ['-C', cwd, 'rev-parse', '--abbrev-ref', 'HEAD'], { stdio: 'pipe', timeout: 5000, killSignal: 'SIGKILL' });
211
+ const log = spawnSync('git', ['-C', cwd, 'log', '-10', '--oneline'], { stdio: 'pipe', timeout: 5000, killSignal: 'SIGKILL' });
212
+ const remote = spawnSync('git', ['-C', cwd, 'remote', '-v'], { stdio: 'pipe', timeout: 5000, killSignal: 'SIGKILL' });
206
213
  if (branch.status !== 0)
207
214
  return null;
208
215
  return [
@@ -225,6 +232,7 @@ function collectDoctorOutput() {
225
232
  stdio: 'pipe',
226
233
  timeout: 30_000,
227
234
  env: { ...process.env, AIWG_LOG_DISABLE: '1', NO_COLOR: '1' },
235
+ killSignal: 'SIGKILL',
228
236
  });
229
237
  const out = r.stdout?.toString() ?? '';
230
238
  const err = r.stderr?.toString() ?? '';
@@ -243,7 +243,7 @@ function openLedger(session, registry) {
243
243
  * `kinds`, `record`, `reconcile` and `probe` all use it, so `kinds` lists
244
244
  * exactly what the registry contains. Tracker authority is resolved lazily at
245
245
  * verification time, so a project without tracker configuration still lists
246
- * the tracker kinds and answers `unknown` / `tracker-blocked`.
246
+ * the tracker kinds and answers `unknown` with a tracker precondition reason.
247
247
  */
248
248
  export function buildCliVerifierRegistry(projectRoot, extensions = [], tracker = { config: null, remoteUrls: {} }) {
249
249
  const injected = new Set(extensions.map(verifier => verifier.kind));
@@ -425,7 +425,9 @@ function expectationsFrom(parsed) {
425
425
  return { expected, ...(timeoutMs !== undefined ? { timeoutMs } : {}), ...(verifierVersion ? { verifierVersion } : {}) };
426
426
  }
427
427
  function emit(rendered, format) {
428
- const message = format === 'text' ? rendered.text : effectOutputJson(rendered.output);
428
+ const evidence = rendered.output.evidence;
429
+ const hint = typeof evidence?.hint === 'string' ? `\n${evidence.hint}` : '';
430
+ const message = format === 'text' ? rendered.text + hint : effectOutputJson(rendered.output);
429
431
  return { exitCode: rendered.output.exitCode, message, rawOutput: true };
430
432
  }
431
433
  function errorOutput(error) {
@@ -28,6 +28,9 @@ function usage() {
28
28
  }
29
29
  export const evidenceHandler = {
30
30
  id: 'evidence', name: 'Evidence', description: 'Export and verify portable evaluation evidence bundles', category: 'utility', aliases: [],
31
+ async help() {
32
+ return { exitCode: 0, message: usage(), rawOutput: true };
33
+ },
31
34
  async execute(ctx) {
32
35
  const [subcommand] = ctx.args;
33
36
  if (!subcommand || subcommand === '--help' || subcommand === '-h')
@@ -19,11 +19,12 @@
19
19
  *
20
20
  * @issue #885
21
21
  */
22
- import { spawnSync } from 'child_process';
22
+ import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
23
23
  import os from 'os';
24
24
  import { readAiwgConfig } from '../../config/aiwg-config.js';
25
25
  import { createPromptInterface, askString, askChoice } from '../prompt-utils.js';
26
26
  import { debug } from '../log.js';
27
+ import { exitCodeForSpawnResult } from '../child-process-result.js';
27
28
  // ── GitHub repo ───────────────────────────────────────────────────────────────
28
29
  const GITHUB_REPO = 'jmagly/aiwg';
29
30
  const GITHUB_ISSUES_URL = `https://github.com/${GITHUB_REPO}/issues/new`;
@@ -57,7 +58,7 @@ async function collectSystemContext(cwd) {
57
58
  // aiwg version from package.json if available
58
59
  let aiwgVersion = 'unknown';
59
60
  try {
60
- const r = spawnSync(process.execPath, [process.argv[1], 'version'], {
61
+ const r = boundedSpawnSync(process.execPath, [process.argv[1], 'version'], 'quick', {
61
62
  encoding: 'utf-8',
62
63
  stdio: 'pipe',
63
64
  });
@@ -235,7 +236,7 @@ async function promptSelect(question, options, signal) {
235
236
  // ── Submission ────────────────────────────────────────────────────────────────
236
237
  function hasGhCli() {
237
238
  try {
238
- const r = spawnSync('gh', ['--version'], { stdio: 'pipe' });
239
+ const r = boundedSpawnSync('gh', ['--version'], 'quick', { stdio: 'pipe' });
239
240
  return r.status === 0;
240
241
  }
241
242
  catch {
@@ -244,7 +245,14 @@ function hasGhCli() {
244
245
  }
245
246
  function submitViaGh(title, body, type) {
246
247
  const label = type === 'bug' ? 'bug' : type === 'feature' ? 'enhancement' : type === 'doc' ? 'documentation' : 'feedback';
247
- const result = spawnSync('gh', ['issue', 'create', '--repo', GITHUB_REPO, '--title', title, '--body', body, '--label', label], { stdio: 'inherit' });
248
+ // Creates a GitHub issue via the `gh` CLI (network call); network tier (#3062).
249
+ const result = boundedSpawnSync('gh', ['issue', 'create', '--repo', GITHUB_REPO, '--title', title, '--body', body, '--label', label], 'network', { stdio: 'inherit' });
250
+ // #3062 review item 7: already correctly treats a null status
251
+ // (timeout/signal) as failure; surface the bounded helper's diagnostic
252
+ // under AIWG_DEBUG — the caller falls back to the browser either way.
253
+ const { message } = exitCodeForSpawnResult(result, 'gh issue create');
254
+ if (message)
255
+ debug('cli:feedback:gh', message);
248
256
  return result.status === 0;
249
257
  }
250
258
  function submitViaBrowser(title, body) {
@@ -260,7 +268,8 @@ function submitViaBrowser(title, body) {
260
268
  : process.platform === 'win32'
261
269
  ? 'start'
262
270
  : 'xdg-open';
263
- spawnSync(openCmd, [urlStr], { stdio: 'ignore' });
271
+ // Fire-and-forget local browser launch; quick tier (#3062).
272
+ boundedSpawnSync(openCmd, [urlStr], 'quick', { stdio: 'ignore' });
264
273
  console.log(`\n Opened GitHub in your browser to file the issue.`);
265
274
  console.log(` If the browser did not open, visit:\n ${urlStr}`);
266
275
  }
@@ -92,6 +92,7 @@ function displayHelp() {
92
92
  ['show <type> <name>', 'Stream the body of an indexed artifact'],
93
93
  ['versions <list|resolve|show>', 'Browse and resolve signed AIWG web resource releases'],
94
94
  ['auth <login|status|logout>', 'Authenticate for paid AIWG web resources'],
95
+ ['corpus <subcommand>', 'Research corpus tools (snapshot, radar, profiles, curator)'],
95
96
  ['index <subcommand>', 'Manage the artifact index (build/query/discover/deps/stats)'],
96
97
  ['artifacts move --to <path>', 'Move/rename the project AIWG artifact root and reindex'],
97
98
  ]);
@@ -73,6 +73,7 @@ import { installationHandler } from './installation.js';
73
73
  import { uhpHandler } from './uhp.js';
74
74
  import { schemaHandler } from './schema.js';
75
75
  import { datasetHandler } from './dataset.js';
76
+ import { rulesHandler } from './rules.js';
76
77
  import { decisionHandler } from './decision.js';
77
78
  import { gatesHandler } from './gates.js';
78
79
  // Re-export individual handlers
@@ -80,7 +81,7 @@ export {
80
81
  // Maintenance
81
82
  helpHandler, versionHandler, authHandler, doctorHandler, contextFirewallHandler, updateHandler, refreshHandler, regenerateHandler, workspaceContextHandler,
82
83
  // Framework management
83
- useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, writerProfileHandler, botHandoffHandler, buildVerifyHandler, writingHandler, schemaHandler, datasetHandler, decisionHandler, gatesHandler, installationHandler,
84
+ useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, writerProfileHandler, botHandoffHandler, buildVerifyHandler, writingHandler, schemaHandler, datasetHandler, decisionHandler, rulesHandler, gatesHandler, installationHandler,
84
85
  // Project
85
86
  newBundleHandler, quickrefHandler, newProjectHandler, sessionHandler, sessionsHandler,
86
87
  // Workspace
@@ -172,6 +173,7 @@ export const allHandlers = [
172
173
  schemaHandler,
173
174
  datasetHandler,
174
175
  decisionHandler,
176
+ rulesHandler,
175
177
  gatesHandler,
176
178
  // Workspace management
177
179
  ...workspaceHandlers,