@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
@@ -31,14 +31,33 @@ function formatDiagnostic(d) {
31
31
  /**
32
32
  * Format lint results in full detail
33
33
  */
34
+ function formatBudget(result) {
35
+ const report = result.inlineBudget;
36
+ if (!report)
37
+ return [];
38
+ return [
39
+ `Startup budget (${report.provider}): limit ${report.limit} tokens${report.disabled ? ' (guard disabled)' : ''}; selected ${report.selected_tokens} estimated tokens (${report.selected_bytes} bytes; ${report.estimate})`,
40
+ ...report.contributors.map(file => ` ${file.path}: ${file.bytes} bytes (${file.estimated_tokens} estimated tokens)`),
41
+ ];
42
+ }
34
43
  function formatFull(result) {
35
44
  const lines = [];
36
45
  lines.push(`${BOLD}AIWG Lint${RESET}`);
37
46
  lines.push(`Target: ${result.target}`);
38
47
  lines.push(`Rulesets: ${result.rulesets.join(', ')}`);
39
48
  lines.push(`Files checked: ${result.summary.filesChecked}`);
49
+ lines.push(...formatBudget(result));
40
50
  lines.push(`Rules applied: ${result.summary.rulesApplied} of ${result.summary.rulesSelected}`);
41
51
  lines.push('');
52
+ if (result.summary.coverageMessage)
53
+ lines.push(`! ${result.summary.coverageMessage}`);
54
+ if (result.ruleCoverage) {
55
+ lines.push('Rule coverage (files by rule):');
56
+ for (const [ruleId, files] of Object.entries(result.ruleCoverage)) {
57
+ lines.push(` ${ruleId}: ${files.length ? files.join(', ') : '(no files)'}`);
58
+ }
59
+ lines.push('');
60
+ }
42
61
  // A target that excludes every rule produces the same clean output as a
43
62
  // target that passes them, which is how 34 findings stayed invisible across a
44
63
  // long session (#2555). Say so before the verdict.
@@ -92,9 +111,14 @@ function formatFull(result) {
92
111
  * Format lint results as a summary (counts only)
93
112
  */
94
113
  function formatSummary(result) {
95
- const lines = [];
114
+ const lines = [...formatBudget(result)];
96
115
  lines.push(`Lint: ${result.summary.filesChecked} files, ${result.summary.errors} errors, ${result.summary.warnings} warnings, ${result.summary.infos} info`);
97
116
  lines.push(`Rules applied: ${result.summary.rulesApplied} of ${result.summary.rulesSelected}`);
117
+ if (result.summary.coverageMessage)
118
+ lines.push(`! ${result.summary.coverageMessage}`);
119
+ if (result.summary.inapplicableRules.length > 0) {
120
+ lines.push(`Inapplicable rules: ${result.summary.inapplicableRules.join(', ')}`);
121
+ }
98
122
  if (result.summary.rulesSelected > 0 && result.summary.rulesApplied === 0) {
99
123
  lines.push(`! No rule applies to this target — this is not a clean result (#2555).`);
100
124
  }
@@ -0,0 +1,43 @@
1
+ import { loadLocalCapabilityEntries, resolveRuleBindingTarget } from '../artifacts/query-engine.js';
2
+ import { parseRuleFrontmatter, RULE_BINDING_TYPES } from '../rules/activation.mjs';
3
+ export const ruleActivationRuleset = {
4
+ id: 'rule-activation', name: 'Rule activation', framework: 'core', version: '1.0.0',
5
+ description: 'Validate rule and behavior activation contracts and exact indexed bindings',
6
+ rules: [{
7
+ id: 'rules/activation', name: 'Rule activation contract', severity: 'error',
8
+ description: 'Validate activation, summaries, paths, bindings, and migration fallback',
9
+ appliesTo: { glob: '**/{rules/**/*.md,behaviors/**/BEHAVIOR.md}' },
10
+ checks: [{ type: 'rule-activation' }],
11
+ }],
12
+ };
13
+ export function lintRuleActivation(content, file, projectRoot, entries) {
14
+ // Generated structural indexes are not authored rules.
15
+ if (/^(?:RULES-INDEX|RULES-ONDEMAND)\.md$/.test(file.split('/').pop()))
16
+ return [];
17
+ const result = parseRuleFrontmatter(content);
18
+ const diagnostics = result.diagnostics.map(item => ({
19
+ ruleId: 'rules/activation', ruleName: 'Rule activation contract',
20
+ file, severity: item.severity, message: item.message,
21
+ }));
22
+ if (!result.rule)
23
+ return diagnostics;
24
+ const bindings = result.rule.bound_to;
25
+ if (!Object.values(bindings).some(list => list.length > 0))
26
+ return diagnostics;
27
+ // Reuse existing artifact index ownership and show precedence. No title guessing,
28
+ // corpus directory resolver, or extra binding registry.
29
+ const indexed = entries ?? loadLocalCapabilityEntries(projectRoot);
30
+ for (const key of Object.keys(RULE_BINDING_TYPES)) {
31
+ for (const id of bindings[key]) {
32
+ try {
33
+ resolveRuleBindingTarget(indexed, RULE_BINDING_TYPES[key], id);
34
+ }
35
+ catch (error) {
36
+ diagnostics.push({ ruleId: 'rules/activation', ruleName: 'Rule activation contract',
37
+ file, severity: 'error', message: error instanceof Error ? error.message : String(error) });
38
+ }
39
+ }
40
+ }
41
+ return diagnostics;
42
+ }
43
+ //# sourceMappingURL=rule-activation.js.map
@@ -7,27 +7,54 @@
7
7
  * @issue #810
8
8
  */
9
9
  import fs from 'fs';
10
- import { spawnSync } from 'child_process';
10
+ import { lintRuleActivation } from './rule-activation.js';
11
+ import { guardRulesInlineBudget } from '../rules/inline-budget.mjs';
12
+ import { dropGitignored } from '../config/gitignore.js';
11
13
  import fsp from 'fs/promises';
12
14
  import path from 'path';
13
15
  import { glob } from 'glob';
14
16
  import { minimatch } from 'minimatch';
17
+ import { parse } from 'yaml';
15
18
  /**
16
19
  * Parse YAML-style frontmatter from a markdown file
17
20
  * Returns key-value pairs from the --- delimited block
18
21
  */
19
22
  function parseFrontmatter(content) {
20
- const match = content.match(/^---\n([\s\S]*?)\n---/);
23
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
21
24
  if (!match)
22
25
  return {};
23
- const result = {};
24
- for (const line of match[1].split('\n')) {
25
- const kv = line.match(/^(\w[\w-]*)\s*:\s*(.+)$/);
26
- if (kv) {
27
- result[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, '');
26
+ try {
27
+ const parsed = parse(match[1]);
28
+ return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
29
+ ? parsed
30
+ : {};
31
+ }
32
+ catch {
33
+ // Invalid YAML cannot supply required metadata.
34
+ return {};
35
+ }
36
+ }
37
+ function isPresent(value) {
38
+ if (value == null)
39
+ return false;
40
+ if (typeof value === 'string')
41
+ return value.trim().length > 0;
42
+ if (Array.isArray(value))
43
+ return value.length > 0;
44
+ return true;
45
+ }
46
+ /** Resolve project-relative metadata from the nearest repository/workspace marker. */
47
+ function findProjectRoot(targetDir) {
48
+ let dir = path.resolve(targetDir);
49
+ while (true) {
50
+ if (fs.existsSync(path.join(dir, '.git')) || fs.existsSync(path.join(dir, '.aiwg'))) {
51
+ return dir;
28
52
  }
53
+ const parent = path.dirname(dir);
54
+ if (parent === dir)
55
+ return path.resolve(targetDir);
56
+ dir = parent;
29
57
  }
30
- return result;
31
58
  }
32
59
  const DEFAULT_REFERENCE_PATTERN = '\\bREF-\\d{3,}\\b';
33
60
  /**
@@ -215,8 +242,9 @@ function buildReferenceIndex(allFiles) {
215
242
  * Preserve support for references stored outside the lint target when a rule
216
243
  * explicitly supplies basePath. Accept both exact and slugged filenames.
217
244
  */
218
- function resolvesFromBasePath(refId, targetDir, basePath) {
245
+ function resolvesFromBasePath(refId, targetDir, basePath, projectRoot) {
219
246
  const candidateDirs = new Set([
247
+ path.resolve(projectRoot, basePath),
220
248
  path.resolve(targetDir, basePath),
221
249
  path.resolve(process.cwd(), basePath),
222
250
  ]);
@@ -237,14 +265,14 @@ function resolvesFromBasePath(refId, targetDir, basePath) {
237
265
  /**
238
266
  * Run a single check against a file's content and frontmatter
239
267
  */
240
- function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, referenceIndex) {
268
+ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, referenceIndex, projectRoot) {
241
269
  const diagnostics = [];
242
270
  switch (check.type) {
243
271
  case 'frontmatter-required': {
244
272
  if (!check.fields)
245
273
  break;
246
274
  for (const field of check.fields) {
247
- if (!frontmatter[field] || frontmatter[field].trim() === '') {
275
+ if (!isPresent(frontmatter[field])) {
248
276
  diagnostics.push({
249
277
  ruleId: '',
250
278
  ruleName: '',
@@ -261,7 +289,7 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
261
289
  if (!check.field || !check.pattern)
262
290
  break;
263
291
  const value = frontmatter[check.field];
264
- if (value && !new RegExp(check.pattern).test(value)) {
292
+ if (isPresent(value) && typeof value !== 'object' && !new RegExp(check.pattern).test(String(value))) {
265
293
  diagnostics.push({
266
294
  ruleId: '',
267
295
  ruleName: '',
@@ -282,7 +310,9 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
282
310
  let match;
283
311
  while ((match = regex.exec(lines[i])) !== null) {
284
312
  const refId = match[0];
285
- const basePath = check.basePath || '.aiwg/research/findings';
313
+ const basePaths = check.basePath
314
+ ? [check.basePath]
315
+ : ['.aiwg/research/findings', 'findings', 'documentation/references', '.'];
286
316
  // A corpus documents its deliberate gaps ("REF-2464 remains
287
317
  // unallocated after deduplication"). Reading that sentence as a
288
318
  // dangling reference left only two ways to silence an error: delete
@@ -290,7 +320,7 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
290
320
  // absent (#2555).
291
321
  if (absence.some((re) => re.test(lines[i])))
292
322
  continue;
293
- if (!referenceIndex.has(refId) && !resolvesFromBasePath(refId, targetDir, basePath)) {
323
+ if (!referenceIndex.has(refId) && !basePaths.some(basePath => resolvesFromBasePath(refId, targetDir, basePath, projectRoot))) {
294
324
  diagnostics.push({
295
325
  ruleId: '',
296
326
  ruleName: '',
@@ -376,9 +406,12 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
376
406
  if (!check.field)
377
407
  break;
378
408
  const refPath = frontmatter[check.field];
379
- if (refPath) {
380
- const resolved = path.resolve(targetDir, refPath);
381
- if (!fs.existsSync(resolved)) {
409
+ if (isPresent(refPath)) {
410
+ // Project-root-relative is canonical (#3145); target-relative paths
411
+ // written for the legacy layout keep resolving.
412
+ const found = typeof refPath === 'string' &&
413
+ [projectRoot, targetDir].some(base => fs.existsSync(path.resolve(base, refPath)));
414
+ if (!found) {
382
415
  diagnostics.push({
383
416
  ruleId: '',
384
417
  ruleName: '',
@@ -398,7 +431,8 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
398
431
  if (!check.pattern)
399
432
  break;
400
433
  const basename = path.basename(filePath, '.md');
401
- if (!new RegExp(check.pattern).test(basename)) {
434
+ const match = basename.match(new RegExp(check.pattern));
435
+ if (!match) {
402
436
  diagnostics.push({
403
437
  ruleId: '',
404
438
  ruleName: '',
@@ -408,6 +442,20 @@ function runCheck(check, content, frontmatter, filePath, targetDir, allFiles, re
408
442
  fix: `Rename to match the pattern ${check.pattern}`,
409
443
  });
410
444
  }
445
+ else if (check.field && isPresent(frontmatter[check.field])) {
446
+ const identifier = match[1] ?? match[0];
447
+ const value = frontmatter[check.field];
448
+ if (value !== identifier) {
449
+ diagnostics.push({
450
+ ruleId: '',
451
+ ruleName: '',
452
+ severity: 'warn',
453
+ file: filePath,
454
+ message: `File identifier '${identifier}' does not match frontmatter field '${check.field}': ${String(value)}`,
455
+ fix: `Make the filename identifier and '${check.field}' field agree`,
456
+ });
457
+ }
458
+ }
411
459
  break;
412
460
  }
413
461
  case 'cross-ref-bidirectional': {
@@ -473,15 +521,13 @@ export function ruleAppliesToFile(ruleGlob, file, targetDir) {
473
521
  /**
474
522
  * Run a single rule against all matching files in the target
475
523
  */
476
- async function runRule(rule, targetDir, allFiles, referenceIndex) {
524
+ async function runRule(rule, targetDir, allFiles, referenceIndex, projectRoot, artifactEntries) {
477
525
  const diagnostics = [];
478
- RULE_APPLIED.delete(rule.id);
479
526
  // Filter files matching the rule's glob
480
527
  const ruleGlob = rule.appliesTo.glob;
481
528
  const matchingFiles = allFiles.filter(f => ruleAppliesToFile(ruleGlob, f, targetDir));
482
529
  if (matchingFiles.length === 0)
483
- return diagnostics;
484
- RULE_APPLIED.add(rule.id);
530
+ return { diagnostics, files: matchingFiles };
485
531
  // Handle id-unique check at the ruleset level
486
532
  const uniqueCheck = rule.checks.find(c => c.type === 'id-unique');
487
533
  if (uniqueCheck) {
@@ -516,7 +562,11 @@ async function runRule(rule, targetDir, allFiles, referenceIndex) {
516
562
  for (const check of rule.checks) {
517
563
  if (check.type === 'id-unique')
518
564
  continue; // Already handled
519
- const checkDiagnostics = runCheck(check, content, frontmatter, file, targetDir, allFiles, referenceIndex);
565
+ if (check.type === 'rule-activation') {
566
+ diagnostics.push(...lintRuleActivation(content, file, projectRoot, artifactEntries));
567
+ continue;
568
+ }
569
+ const checkDiagnostics = runCheck(check, content, frontmatter, file, targetDir, allFiles, referenceIndex, projectRoot);
520
570
  for (const d of checkDiagnostics) {
521
571
  d.ruleId = rule.id;
522
572
  d.ruleName = rule.name;
@@ -525,10 +575,8 @@ async function runRule(rule, targetDir, allFiles, referenceIndex) {
525
575
  }
526
576
  }
527
577
  }
528
- return diagnostics;
578
+ return { diagnostics, files: matchingFiles };
529
579
  }
530
- /** Rule ids that selected at least one file in the current run (#2555). */
531
- const RULE_APPLIED = new Set();
532
580
  /**
533
581
  * Collect all files under a target directory
534
582
  */
@@ -547,37 +595,6 @@ async function collectFiles(targetDir, recursive, respectGitignore = true) {
547
595
  return [];
548
596
  }
549
597
  }
550
- /**
551
- * Drop files git ignores (#2555).
552
- *
553
- * Generated trees are regenerated, not authored: linting `indices/` reported an
554
- * error in text that documents a deliberate gap. `git check-ignore` is asked
555
- * once for the whole set so the semantics are git's own (negations, nested
556
- * `.gitignore`, `core.excludesFile`) rather than a re-implementation. Outside a
557
- * repository, or without git, every file is kept.
558
- */
559
- function dropGitignored(targetDir, files) {
560
- if (files.length === 0)
561
- return files;
562
- try {
563
- const result = spawnSync('git', ['check-ignore', '--stdin'], {
564
- cwd: targetDir,
565
- input: `${files.join('\n')}\n`,
566
- encoding: 'utf8',
567
- });
568
- // 0 = some paths ignored, 1 = none ignored, anything else = not a repo or
569
- // git unavailable, in which case nothing is filtered.
570
- if (result.error || (result.status !== 0 && result.status !== 1))
571
- return files;
572
- const ignored = new Set((result.stdout ?? '').split('\n').map((line) => line.trim()).filter(Boolean));
573
- if (ignored.size === 0)
574
- return files;
575
- return files.filter((file) => !ignored.has(file));
576
- }
577
- catch {
578
- return files;
579
- }
580
- }
581
598
  /**
582
599
  * Auto-detect which rulesets apply to a target path
583
600
  *
@@ -602,27 +619,74 @@ function autoDetectRulesets(target, available) {
602
619
  }
603
620
  }
604
621
  // If no auto-detection, return all available
605
- return matches.length > 0 ? matches : available;
622
+ return matches.length > 0
623
+ ? available.filter(ruleset => ruleset.id === 'rule-activation' || matches.includes(ruleset))
624
+ : available;
606
625
  }
607
626
  /**
608
627
  * Run lint on a target path with specified or auto-detected rulesets
609
628
  */
610
629
  export async function runLint(targetDir, rulesets, options = {}) {
611
630
  const recursive = options.recursive ?? true;
612
- const allFiles = await collectFiles(targetDir, recursive, options.respectGitignore ?? true);
631
+ const targetStat = await fsp.stat(targetDir).catch(() => null);
632
+ const scanDir = targetStat?.isFile() ? path.dirname(targetDir) : targetDir;
633
+ const projectRoot = findProjectRoot(scanDir);
634
+ const respectGitignore = options.respectGitignore ?? true;
635
+ let allFiles;
636
+ let targetMessage = '';
637
+ if (!targetStat) {
638
+ allFiles = [];
639
+ targetMessage = `Target does not exist or is inaccessible: ${targetDir}.`;
640
+ }
641
+ else if (targetStat.isFile()) {
642
+ const file = path.basename(targetDir);
643
+ if (!/\.(md|yaml|yml|json)$/.test(file)) {
644
+ allFiles = [];
645
+ targetMessage = `Unsupported file type: ${file}. Expected .md, .yaml, .yml or .json.`;
646
+ }
647
+ else {
648
+ allFiles = respectGitignore ? dropGitignored(scanDir, [file]) : [file];
649
+ }
650
+ }
651
+ else {
652
+ allFiles = await collectFiles(scanDir, recursive, respectGitignore);
653
+ }
613
654
  const referenceIndex = buildReferenceIndex(allFiles);
614
655
  const allDiagnostics = [];
615
656
  const inapplicableRules = [];
657
+ const ruleCoverage = {};
616
658
  let rulesSelected = 0;
617
659
  for (const ruleset of rulesets) {
618
660
  for (const rule of ruleset.rules) {
619
661
  rulesSelected += 1;
620
- const diagnostics = await runRule(rule, targetDir, allFiles, referenceIndex);
621
- if (!RULE_APPLIED.has(rule.id))
662
+ const { diagnostics, files } = await runRule(rule, scanDir, allFiles, referenceIndex, projectRoot, options.artifactEntries);
663
+ ruleCoverage[rule.id] = files;
664
+ if (files.length === 0)
622
665
  inapplicableRules.push(rule.id);
623
666
  allDiagnostics.push(...diagnostics);
624
667
  }
625
668
  }
669
+ let budget;
670
+ if (options.startupBudget) {
671
+ try {
672
+ budget = guardRulesInlineBudget({
673
+ ...options.startupBudget, reportOnly: options.ci ? false : (options.startupBudget.reportOnly ?? true),
674
+ });
675
+ }
676
+ catch (error) {
677
+ allDiagnostics.push({
678
+ ruleId: 'rules/inline-budget', ruleName: 'Rules inline budget', file: '(assembled startup)',
679
+ severity: 'error', message: error instanceof Error ? error.message : String(error),
680
+ });
681
+ }
682
+ }
683
+ if (budget) {
684
+ for (const item of budget.diagnostics)
685
+ allDiagnostics.push({
686
+ ruleId: 'rules/inline-budget', ruleName: 'Rules inline budget', file: '(assembled startup)',
687
+ severity: item.severity, message: item.message,
688
+ });
689
+ }
626
690
  const errors = allDiagnostics.filter(d => d.severity === 'error').length;
627
691
  const warnings = allDiagnostics.filter(d => d.severity === 'warn').length;
628
692
  const infos = allDiagnostics.filter(d => d.severity === 'info').length;
@@ -634,10 +698,20 @@ export async function runLint(targetDir, rulesets, options = {}) {
634
698
  passed = false;
635
699
  if (failOn === 'info' && allDiagnostics.length > 0)
636
700
  passed = false;
701
+ const rulesApplied = rulesSelected - inapplicableRules.length;
702
+ const coverageMessage = allFiles.length === 0
703
+ ? `No files checked. ${targetMessage || 'The target is empty, contains no supported files, or all files are ignored.'}`
704
+ : rulesApplied === 0
705
+ ? 'No rules applied. Check the target path and selected ruleset globs.'
706
+ : undefined;
707
+ if (options.ci && !options.allowEmpty && coverageMessage)
708
+ passed = false;
637
709
  return {
638
710
  target: targetDir,
639
711
  rulesets: rulesets.map(r => r.id),
640
712
  diagnostics: allDiagnostics,
713
+ ...(budget ? { inlineBudget: budget.report } : {}),
714
+ ruleCoverage,
641
715
  summary: {
642
716
  filesChecked: allFiles.length,
643
717
  errors,
@@ -647,8 +721,9 @@ export async function runLint(targetDir, rulesets, options = {}) {
647
721
  // A run where no rule selected a file must never read the same as a clean
648
722
  // run (#2555). Reporters surface this; callers can gate on it.
649
723
  rulesSelected,
650
- rulesApplied: rulesSelected - inapplicableRules.length,
724
+ rulesApplied,
651
725
  inapplicableRules,
726
+ coverageMessage,
652
727
  },
653
728
  timestamp: new Date().toISOString(),
654
729
  };