@aiwg/cli 2026.10.3 → 2026.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/README.md +2 -2
  2. package/agentic/code/providers/model-capabilities.v1.json +96 -4
  3. package/bin/aiwg.mjs +50 -27
  4. package/dist/src/agents/grounding/knowledge-base.js +54 -6
  5. package/dist/src/artifacts/browser-export.js +6 -0
  6. package/dist/src/artifacts/checksum-manifest.js +1 -0
  7. package/dist/src/artifacts/citation-parser.js +173 -92
  8. package/dist/src/artifacts/citation-table-schema.js +59 -0
  9. package/dist/src/artifacts/cli.js +69 -18
  10. package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
  11. package/dist/src/artifacts/corpus-tools/vision-extract.js +2 -0
  12. package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
  13. package/dist/src/artifacts/corpus-views/renderers.js +3 -3
  14. package/dist/src/artifacts/discovery-eval.js +6 -4
  15. package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
  16. package/dist/src/artifacts/fortemi-core-sync.js +166 -40
  17. package/dist/src/artifacts/framework-capabilities.js +171 -0
  18. package/dist/src/artifacts/framework-index-paths.js +73 -0
  19. package/dist/src/artifacts/framework-source-digest.js +75 -0
  20. package/dist/src/artifacts/index-builder.js +286 -131
  21. package/dist/src/artifacts/index-files.js +132 -18
  22. package/dist/src/artifacts/index-preparation.js +130 -0
  23. package/dist/src/artifacts/index-refresh.js +591 -0
  24. package/dist/src/artifacts/index-worker.mjs +11 -0
  25. package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
  26. package/dist/src/artifacts/prebuilt-deployment.js +46 -0
  27. package/dist/src/artifacts/prebuilt-relations.js +80 -0
  28. package/dist/src/artifacts/query-engine.js +410 -88
  29. package/dist/src/artifacts/relations-builder.js +168 -0
  30. package/dist/src/artifacts/relations.js +148 -0
  31. package/dist/src/artifacts/stats.js +5 -2
  32. package/dist/src/artifacts/types.js +30 -10
  33. package/dist/src/artifacts/watcher.js +1 -1
  34. package/dist/src/auth/credential-store.js +2 -1
  35. package/dist/src/catalog/cli.d.mts +5 -0
  36. package/dist/src/channel/manager.d.mts +20 -0
  37. package/dist/src/channel/manager.mjs +19 -2
  38. package/dist/src/cli/command-log.js +2 -3
  39. package/dist/src/cli/handlers/artifacts.js +3 -0
  40. package/dist/src/cli/handlers/auth.js +3 -0
  41. package/dist/src/cli/handlers/decision.js +19 -12
  42. package/dist/src/cli/handlers/diagnose.js +4 -3
  43. package/dist/src/cli/handlers/effect.js +4 -2
  44. package/dist/src/cli/handlers/evidence.js +3 -0
  45. package/dist/src/cli/handlers/help.js +1 -0
  46. package/dist/src/cli/handlers/index.js +3 -1
  47. package/dist/src/cli/handlers/init.js +4 -1
  48. package/dist/src/cli/handlers/lint.js +5 -0
  49. package/dist/src/cli/handlers/models.js +104 -8
  50. package/dist/src/cli/handlers/ralph-launcher.js +2 -0
  51. package/dist/src/cli/handlers/refresh.js +12 -0
  52. package/dist/src/cli/handlers/resource-versions.js +3 -0
  53. package/dist/src/cli/handlers/rules.js +195 -0
  54. package/dist/src/cli/handlers/run.js +4 -0
  55. package/dist/src/cli/handlers/runtime-info.js +1 -2
  56. package/dist/src/cli/handlers/script-runner.js +3 -2
  57. package/dist/src/cli/handlers/session.js +19 -9
  58. package/dist/src/cli/handlers/sessions.js +137 -43
  59. package/dist/src/cli/handlers/setup-manifest.js +39 -44
  60. package/dist/src/cli/handlers/setup.js +41 -0
  61. package/dist/src/cli/handlers/steward.js +11 -0
  62. package/dist/src/cli/handlers/subcommands.js +57 -2
  63. package/dist/src/cli/handlers/uhp.js +3 -0
  64. package/dist/src/cli/handlers/use.js +294 -55
  65. package/dist/src/cli/handlers/utilities.js +26 -10
  66. package/dist/src/cli/handlers/version.js +8 -0
  67. package/dist/src/cli/router.js +15 -1
  68. package/dist/src/cli/services/deployment-verification.js +19 -9
  69. package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
  70. package/dist/src/cli/skill-usage.js +2 -3
  71. package/dist/src/config/aiwg-config.js +87 -37
  72. package/dist/src/config/cli.js +111 -5
  73. package/dist/src/config/decision-config.js +106 -0
  74. package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
  75. package/dist/src/config/gitignore.js +50 -0
  76. package/dist/src/config/index-graph-overrides.js +36 -0
  77. package/dist/src/config/project-artifacts-health.d.mts +37 -0
  78. package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
  79. package/dist/src/config/user-config-dir.d.mts +9 -0
  80. package/dist/src/config/user-config.js +2 -1
  81. package/dist/src/config/user-registry.js +23 -15
  82. package/dist/src/config/user-state.js +7 -0
  83. package/dist/src/decision/ask.js +203 -43
  84. package/dist/src/decision/context-live-qualification.js +2 -2
  85. package/dist/src/decision/driver.js +13 -8
  86. package/dist/src/decision/ensemble/aggregate.js +23 -10
  87. package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
  88. package/dist/src/decision/entry.js +2 -15
  89. package/dist/src/decision/graph-live-qualification.js +1 -1
  90. package/dist/src/decision/graph-run.js +9 -0
  91. package/dist/src/decision/heldout/collector.js +5 -13
  92. package/dist/src/decision/heldout/contract.js +30 -7
  93. package/dist/src/decision/jev-credentials.js +15 -1
  94. package/dist/src/decision/ledger.js +131 -28
  95. package/dist/src/decision/offload-activation.js +137 -0
  96. package/dist/src/decision/offload.js +550 -0
  97. package/dist/src/decision/qualification/load.js +4 -6
  98. package/dist/src/decision/savings.js +28 -0
  99. package/dist/src/effects/types.js +5 -1
  100. package/dist/src/effects/verifiers/git.js +2 -1
  101. package/dist/src/effects/verifiers/tracker.js +26 -14
  102. package/dist/src/extensions/commands/definitions.js +19 -0
  103. package/dist/src/extensions/project-local-remove.js +36 -1
  104. package/dist/src/gates/providers/loader.js +61 -17
  105. package/dist/src/installation/manager-command.d.mts +18 -0
  106. package/dist/src/installation/manager-command.mjs +14 -2
  107. package/dist/src/installation/manager.d.mts +49 -0
  108. package/dist/src/installation/manager.mjs +78 -3
  109. package/dist/src/issues/cli.js +4 -4
  110. package/dist/src/issues/local.js +24 -5
  111. package/dist/src/jobs/runner.js +1 -1
  112. package/dist/src/lint/cli.js +27 -1
  113. package/dist/src/lint/loader.js +2 -1
  114. package/dist/src/lint/reporters.js +25 -1
  115. package/dist/src/lint/rule-activation.js +43 -0
  116. package/dist/src/lint/runner.js +137 -62
  117. package/dist/src/mcp/adapters/codex-runtime.js +7 -1
  118. package/dist/src/mcp/claude-install.d.mts +4 -0
  119. package/dist/src/mcp/claude-install.mjs +41 -0
  120. package/dist/src/mcp/cli.d.mts +1 -0
  121. package/dist/src/mcp/cli.mjs +36 -11
  122. package/dist/src/mcp/config-file.d.mts +28 -0
  123. package/dist/src/mcp/config-layers.d.mts +36 -0
  124. package/dist/src/mcp/credentials.d.mts +51 -0
  125. package/dist/src/mcp/grok-build-config.d.mts +6 -0
  126. package/dist/src/mcp/grok-build-config.mjs +1 -1
  127. package/dist/src/mcp/helpers.mjs +3 -2
  128. package/dist/src/mcp/muse-native-config.d.mts +13 -0
  129. package/dist/src/mcp/muse-native-config.mjs +1 -0
  130. package/dist/src/mcp/omp-config.d.mts +4 -0
  131. package/dist/src/mcp/registry.js +3 -93
  132. package/dist/src/mcp/registry.mjs +3 -87
  133. package/dist/src/mcp/server-config.d.mts +3 -0
  134. package/dist/src/mcp/server-config.mjs +89 -0
  135. package/dist/src/mcp/server.mjs +37 -375
  136. package/dist/src/mcp/test-simple.mjs +2 -1
  137. package/dist/src/mcp/toml-editor.d.mts +4 -0
  138. package/dist/src/mcp/toml-string.d.mts +1 -0
  139. package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
  140. package/dist/src/mcp/tool-filters.d.mts +46 -0
  141. package/dist/src/mcp/tools/decision.mjs +12 -11
  142. package/dist/src/mcp/tools/discovery.mjs +62 -55
  143. package/dist/src/mcp/tools/orchestration.mjs +12 -2
  144. package/dist/src/mcp/tools/worker-invoke.mjs +1340 -23
  145. package/dist/src/mcp/tools/worker-shell-control.mjs +52 -21
  146. package/dist/src/mcp/tools/worker-stdin-runtime.mjs +3 -3
  147. package/dist/src/mission-protocol/codecs.js +8 -0
  148. package/dist/src/models/config-loader.js +7 -2
  149. package/dist/src/models/model-capabilities.v1.json +96 -4
  150. package/dist/src/models/model-discovery.js +76 -11
  151. package/dist/src/models/provider-policy.js +101 -7
  152. package/dist/src/models/qualification-digest.d.mts +2 -0
  153. package/dist/src/models/resolver.js +12 -10
  154. package/dist/src/models/worker-direct-readiness.js +65 -44
  155. package/dist/src/models/worker-dispatch-offer.js +3 -3
  156. package/dist/src/models/worker-health-readiness.js +16 -3
  157. package/dist/src/models/worker-installation.d.mts +39 -0
  158. package/dist/src/models/worker-installation.mjs +135 -28
  159. package/dist/src/process/bounded-child-process.d.mts +84 -0
  160. package/dist/src/process/bounded-child-process.mjs +43 -0
  161. package/dist/src/process/cli-command.d.mts +16 -0
  162. package/dist/src/process/signal-child.d.mts +6 -0
  163. package/dist/src/process/signal-child.mjs +7 -0
  164. package/dist/src/providers/deployed-skill-roots.js +20 -0
  165. package/dist/src/providers/grok-build-acp.js +3 -2
  166. package/dist/src/providers/grok-build-headless.js +12 -4
  167. package/dist/src/providers/grok-build-inspect.js +1 -0
  168. package/dist/src/providers/omp-agent.d.mts +8 -0
  169. package/dist/src/providers/omp-diagnostics.d.mts +1 -0
  170. package/dist/src/providers/omp-paths.d.mts +13 -0
  171. package/dist/src/providers/skill-ownership.d.mts +9 -0
  172. package/dist/src/providers/skill-ownership.mjs +88 -0
  173. package/dist/src/rules/activation.d.mts +21 -0
  174. package/dist/src/rules/activation.mjs +62 -0
  175. package/dist/src/rules/inline-budget.d.mts +26 -0
  176. package/dist/src/rules/inline-budget.mjs +66 -0
  177. package/dist/src/rules/inventory.js +129 -0
  178. package/dist/src/rules/pin-state.js +73 -0
  179. package/dist/src/rules/pins.d.mts +14 -0
  180. package/dist/src/rules/pins.mjs +112 -0
  181. package/dist/src/rules/rule-frontmatter.schema.json +197 -0
  182. package/dist/src/serve/mission-conductor.js +38 -12
  183. package/dist/src/serve/worker-invocation.js +30 -10
  184. package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
  185. package/dist/src/sessions/adapter-registry.js +23 -19
  186. package/dist/src/sessions/adapters/claude.js +39 -54
  187. package/dist/src/sessions/adapters/codex.js +95 -67
  188. package/dist/src/sessions/adapters/copilot.js +4 -4
  189. package/dist/src/sessions/adapters/cursor.js +40 -57
  190. package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
  191. package/dist/src/sessions/adapters/factory.js +31 -27
  192. package/dist/src/sessions/adapters/generic.js +10 -10
  193. package/dist/src/sessions/adapters/grok-build.js +11 -11
  194. package/dist/src/sessions/adapters/grokbot.js +24 -13
  195. package/dist/src/sessions/adapters/hermes.js +27 -29
  196. package/dist/src/sessions/adapters/muse-workspace-scan.js +31 -11
  197. package/dist/src/sessions/adapters/muse.js +150 -93
  198. package/dist/src/sessions/adapters/omp.js +28 -14
  199. package/dist/src/sessions/adapters/openclaw.js +89 -79
  200. package/dist/src/sessions/adapters/opencode.js +27 -24
  201. package/dist/src/sessions/adapters/openhuman.js +18 -60
  202. package/dist/src/sessions/adapters/pi.js +29 -14
  203. package/dist/src/sessions/adapters/warp.js +3 -3
  204. package/dist/src/sessions/adapters/windsurf.js +19 -48
  205. package/dist/src/sessions/batch-contracts.js +16 -8
  206. package/dist/src/sessions/batch-import.js +252 -12
  207. package/dist/src/sessions/contracts.js +50 -3
  208. package/dist/src/sessions/coverage-preflight.js +27 -2
  209. package/dist/src/sessions/export-plan.js +4 -3
  210. package/dist/src/sessions/import-exclusions.js +72 -0
  211. package/dist/src/sessions/import-lease.js +34 -18
  212. package/dist/src/sessions/import-limits.js +37 -0
  213. package/dist/src/sessions/importer.js +60 -38
  214. package/dist/src/sessions/lifecycle.js +45 -0
  215. package/dist/src/sessions/policy.js +145 -26
  216. package/dist/src/sessions/readers.js +106 -53
  217. package/dist/src/sessions/refresh.js +105 -0
  218. package/dist/src/sessions/repository.js +151 -54
  219. package/dist/src/sessions/workspace-discovery.js +292 -60
  220. package/dist/src/sessions/workspace-matching.js +107 -0
  221. package/dist/src/skills/importer.js +1 -0
  222. package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
  223. package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
  224. package/dist/src/smiths/context-pipeline/finalization.js +6 -5
  225. package/dist/src/smiths/context-pipeline/generator.js +21 -4
  226. package/dist/src/smiths/context-pipeline/parallelism-section.js +7 -15
  227. package/dist/src/smiths/mcpsmith/generator.js +1 -1
  228. package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
  229. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +76 -18
  230. package/dist/src/storage/backends/fs.js +18 -76
  231. package/dist/src/storage/backends/obsidian.js +1 -0
  232. package/dist/src/tracker/forge-http.js +2 -1
  233. package/dist/src/update/checker.d.mts +2 -0
  234. package/dist/src/update/service.d.mts +22 -0
  235. package/dist/src/utils/contained-filesystem.d.mts +37 -0
  236. package/dist/src/utils/contained-filesystem.mjs +683 -0
  237. package/dist/src/utils/temporary-directory.js +36 -0
  238. package/dist/src/writing/example-generator.js +1 -1
  239. package/package.json +15 -2
  240. package/schemas/models/model-catalog.v1.schema.json +1 -1
  241. package/schemas/models/provider-model-capabilities.v1.schema.json +6 -0
  242. package/tools/_resolve-impl.mjs +13 -15
  243. package/tools/agents/deploy-agents.mjs +49 -21
  244. package/tools/agents/providers/base.mjs +104 -134
  245. package/tools/agents/providers/claude.mjs +8 -24
  246. package/tools/agents/providers/codex.mjs +18 -11
  247. package/tools/agents/providers/cursor.mjs +19 -18
  248. package/tools/agents/providers/grok-build.mjs +3 -1
  249. package/tools/agents/providers/hermes.mjs +57 -47
  250. package/tools/agents/providers/openclaw.mjs +9 -4
  251. package/tools/agents/providers/pi.mjs +5 -0
  252. package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
  253. package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
  254. package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
  255. package/tools/agents/providers/rule-delivery.mjs +1270 -0
  256. package/tools/agents/providers/warp.mjs +20 -26
  257. package/tools/cli/decision-offload-report.mjs +40 -0
  258. package/tools/cli/workspace-status.mjs +862 -0
  259. package/tools/plugin/package-plugins.mjs +186 -8
  260. package/tools/plugin/plugin-links.mjs +114 -0
  261. package/tools/providers/antigravity-transport.mjs +3 -1
  262. package/tools/providers/deepseek-harness-transport.mjs +6 -4
  263. package/tools/providers/omp-transport.mjs +4 -2
  264. package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
  265. package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
  266. package/tools/ralph-external/lib/omp-adapter.mjs +1 -1
  267. package/tools/ralph-external/lib/pi-adapter.mjs +0 -4
  268. package/tools/ralph-external/lib/provider-adapter.mjs +59 -1
  269. package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
  270. package/tools/ralph-external/lib/session-environment.mjs +28 -0
  271. package/tools/ralph-external/lib/systemd-client.mjs +49 -0
  272. package/tools/ralph-external/lib/worker-health.mjs +1 -1
  273. package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
  274. package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
  275. package/tools/ralph-external/process-monitor.mjs +1017 -0
  276. package/tools/ralph-external/session-launcher.mjs +5057 -0
  277. package/tools/scripts/resource-preflight.mjs +541 -0
  278. package/tools/skills/deploy-skills-codex.mjs +2 -1
  279. package/vscode-extension/schemas/aiwg.config.v1.json +1194 -231
@@ -202,10 +202,12 @@ export function registerDecisionToolset(server) {
202
202
  context: z.string().optional(),
203
203
  threshold: z.number().min(0).max(1).default(0.8),
204
204
  timeout_ms: z.number().int().positive().default(15000),
205
+ passes: z.number().int().positive().optional(),
206
+ escalation_passes: z.number().int().positive().optional(),
205
207
  caller: z.string().optional().describe('Optional decision-point attribution tag, recorded in the decision ledger (#2946)'),
206
208
  },
207
209
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
208
- }, async ({ question, yes_no, choices, scale, context, threshold, timeout_ms, caller }) => {
210
+ }, async ({ question, yes_no, choices, scale, context, threshold, timeout_ms, passes, escalation_passes, caller }) => {
209
211
  const modeCount = (yes_no ? 1 : 0) + (choices ? 1 : 0) + (scale ? 1 : 0);
210
212
  if (modeCount !== 1) throw new Error('Select exactly one of yes_no, choices, or scale');
211
213
  const driverModule = await driver();
@@ -216,22 +218,21 @@ export function registerDecisionToolset(server) {
216
218
  ...(context === undefined ? {} : { context }),
217
219
  threshold,
218
220
  timeoutMs: timeout_ms,
221
+ ...(passes === undefined ? {} : { passes }),
222
+ ...(escalation_passes === undefined ? {} : { escalationPasses: escalation_passes }),
219
223
  };
220
- const result = await driverModule.askDecision(input, opts);
221
- // Every decision-ask call records through the same ledger function the CLI
222
- // `ask` handler uses, tagged with this tool's transport (#2946). Attribution
223
- // resolution and the write both happen inside recordDecisionAsk's own
224
- // bounded, never-throwing step (review r1 findings 3 and 4): a provider-
225
- // detection failure, a slow/failed write, or an invalid caller tag can
226
- // never replace `result` with an error or hold up this tool call.
227
224
  const sanitizedCaller = typeof caller === 'string' && driverModule.ATTRIBUTION_FIELD_PATTERN.test(caller) ? caller : null;
228
- await driverModule.recordDecisionAsk(input, result, {
225
+ const invocation = await driverModule.runDecisionOffloadCheckpoint(input, {
229
226
  transport: 'mcp',
230
227
  projectRoot: opts.cwd,
231
228
  env: opts.env,
232
- caller: sanitizedCaller,
229
+ caller: sanitizedCaller ?? 'decision-mcp:ask',
230
+ ledgerCaller: sanitizedCaller,
231
+ category: sanitizedCaller ? undefined : 'unattributed',
232
+ askRuntime: opts,
233
233
  });
234
- return result;
234
+ if (!invocation.result) throw invocation.error ?? new Error('Decision ask was skipped');
235
+ return invocation.result;
235
236
  }, ASK);
236
237
 
237
238
  registerJsonTool(server, 'decision-setup-synthetic-classification', {
@@ -23,21 +23,22 @@
23
23
 
24
24
  import { z } from 'zod';
25
25
  import { runAiwgCli, mcpError, mcpJson, AIWG_ROOT } from '../helpers.mjs';
26
- import fs from 'node:fs/promises';
27
26
  import path from 'node:path';
27
+ import { pinContainedRoot, readContainedFile, listContainedFiles, validateContainedPath } from '../../utils/contained-filesystem.mjs';
28
28
 
29
29
  /**
30
30
  * Register discovery tools on the MCP server.
31
31
  *
32
32
  * @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
33
33
  */
34
- export function registerDiscoveryTools(server) {
34
+ export function registerDiscoveryTools(server, { corpusStore } = {}) {
35
+ const store = corpusStore ? Promise.resolve(corpusStore) : pinContainedRoot(path.resolve(AIWG_ROOT));
35
36
  // ============================================================
36
37
  // discover — cross-type semantic search
37
38
  // ============================================================
38
39
  server.registerTool('discover', {
39
40
  title: 'Discover AIWG Capabilities',
40
- description: 'Semantic search across AIWG operational assets: skills, agents, commands, rules, flows, runbooks, templates, and behaviors. Returns ranked candidates with capability summaries. Mirrors `aiwg discover --json`.',
41
+ description: 'Semantic search across AIWG operational assets: skills, agents, commands, rules, flows, runbooks, templates, and behaviors. Returns ranked candidates with capability summaries, governing rules, rule stats, and required fetch-and-follow checks before governed work. Mirrors `aiwg discover --json`.',
41
42
  inputSchema: {
42
43
  phrase: z.string().describe('Natural-language capability description (e.g. "create intake form")'),
43
44
  type: z.enum(['skill', 'agent', 'command', 'rule', 'flow', 'runbook', 'template', 'behavior']).optional().describe('Restrict to one artifact type'),
@@ -84,12 +85,13 @@ export function registerDiscoveryTools(server) {
84
85
  title: 'Show AIWG Skill',
85
86
  description: 'Fetch the full body of an AIWG SKILL.md by name. Returns path + content envelope.',
86
87
  inputSchema: {
88
+ bound_rule_bodies: z.boolean().optional().describe('Include full bound rule bodies'),
87
89
  name: z.string().describe('Skill name (slug; e.g. "intake-wizard")'),
88
90
  },
89
91
  annotations: { readOnlyHint: true },
90
- }, async ({ name }) => {
92
+ }, async ({ name, bound_rule_bodies }) => {
91
93
  try {
92
- const { stdout, code, stderr } = await runAiwgCli(['show', 'skill', name, '--json']);
94
+ const { stdout, code, stderr } = await runAiwgCli(['show', 'skill', name, '--json', ...(bound_rule_bodies ? ['--bound-rule-bodies'] : [])]);
93
95
  if (code !== 0) return mcpError(`skill-show failed: ${stderr}`);
94
96
  return mcpJson(stdout);
95
97
  } catch (err) {
@@ -138,6 +140,27 @@ export function registerDiscoveryTools(server) {
138
140
  // ============================================================
139
141
  // rule-list / rule-show (#1320)
140
142
  // ============================================================
143
+ server.registerTool('rule-inventory', {
144
+ title: 'Inventory configured AIWG rules',
145
+ description: 'Inspect scoped rule configuration and activation without asserting native session loading. Mirrors aiwg rules inventory --json.',
146
+ inputSchema: {
147
+ scope: z.enum(['workspace', 'user', 'installation', 'catalog']).default('workspace'),
148
+ capability: z.string().optional(), activation: z.string().optional(),
149
+ tier: z.string().optional(), provider: z.string().optional(), bodies: z.boolean().default(false),
150
+ },
151
+ annotations: { readOnlyHint: true },
152
+ }, async ({ scope, capability, activation, tier, provider, bodies }) => {
153
+ try {
154
+ const args = ['rules', 'inventory', '--scope', scope ?? 'workspace', '--json'];
155
+ for (const [flag, value] of [['--capability', capability], ['--activation', activation], ['--tier', tier], ['--provider', provider]]) {
156
+ if (value) args.push(flag, value);
157
+ }
158
+ if (bodies) args.push('--bodies');
159
+ const { stdout, code, stderr } = await runAiwgCli(args);
160
+ if (code !== 0) return mcpError(`rule-inventory failed: ${stderr || stdout}`);
161
+ return mcpJson(stdout);
162
+ } catch (err) { return mcpError(`rule-inventory: ${err.message}`); }
163
+ });
141
164
  server.registerTool('rule-list', {
142
165
  title: 'List AIWG Rules',
143
166
  description: 'Enumerate AIWG enforcement rules (e.g. skill-discovery, no-attribution, anti-laziness, citation-policy). Top-7 CRITICAL/HIGH rules are inlined into Hermes AGENTS.md priming (skill-discovery added #1347); this tool reaches the rest.',
@@ -181,12 +204,13 @@ export function registerDiscoveryTools(server) {
181
204
  title: 'Show AIWG Agent Definition',
182
205
  description: 'Fetch the full agent definition (system prompt + frontmatter) by name.',
183
206
  inputSchema: {
207
+ bound_rule_bodies: z.boolean().optional().describe('Include full bound rule bodies'),
184
208
  name: z.string().describe('Agent name (e.g. "test-engineer", "security-auditor")'),
185
209
  },
186
210
  annotations: { readOnlyHint: true },
187
- }, async ({ name }) => {
211
+ }, async ({ name, bound_rule_bodies }) => {
188
212
  try {
189
- const { stdout, code, stderr } = await runAiwgCli(['show', 'agent', name, '--json']);
213
+ const { stdout, code, stderr } = await runAiwgCli(['show', 'agent', name, '--json', ...(bound_rule_bodies ? ['--bound-rule-bodies'] : [])]);
190
214
  if (code !== 0) return mcpError(`agent-show failed: ${stderr}`);
191
215
  return mcpJson(stdout);
192
216
  } catch (err) {
@@ -207,7 +231,7 @@ export function registerDiscoveryTools(server) {
207
231
  annotations: { readOnlyHint: true },
208
232
  }, async ({ framework, filter }) => {
209
233
  try {
210
- const results = await scanTemplates(AIWG_ROOT, { framework, filter });
234
+ const results = await scanTemplates(await store, { framework, filter });
211
235
  return mcpJson({ count: results.length, templates: results });
212
236
  } catch (err) {
213
237
  return mcpError(`template-list: ${err.message}`);
@@ -223,21 +247,27 @@ export function registerDiscoveryTools(server) {
223
247
  annotations: { readOnlyHint: true },
224
248
  }, async ({ template }) => {
225
249
  try {
226
- // Allow caller to pass either a corpus-relative path or just the template filename
227
- const candidates = [
228
- path.join(AIWG_ROOT, 'agentic/code/frameworks', template),
229
- path.join(AIWG_ROOT, 'agentic/code/frameworks/sdlc-complete/templates', template),
230
- path.resolve(template),
231
- ];
232
- for (const c of candidates) {
250
+ validateContainedPath(template);
251
+ // Preserve corpus-relative and template-relative selection, but never
252
+ // try cwd/absolute candidates. Each candidate is read through one pin.
253
+ const root = await store;
254
+ const frameworks = 'agentic/code/frameworks';
255
+ const [framework, ...parts] = template.split('/');
256
+ const candidates = template.startsWith(`${frameworks}/`)
257
+ ? [template]
258
+ : [
259
+ `${frameworks}/${template}`,
260
+ `${frameworks}/${framework}/templates/${parts.join('/')}`,
261
+ `${frameworks}/sdlc-complete/templates/${template}`,
262
+ ];
263
+ for (const candidate of candidates) {
264
+ // Only template subtrees, including basename selection, are eligible.
265
+ if (!/^agentic\/code\/frameworks\/[^/]+\/templates\/.+/.test(candidate)) continue;
233
266
  try {
234
- // Anti-traversal: ensure resolved path stays inside AIWG_ROOT
235
- const resolved = path.resolve(c);
236
- if (!resolved.startsWith(path.resolve(AIWG_ROOT))) continue;
237
- const content = await fs.readFile(resolved, 'utf-8');
238
- return mcpJson({ path: resolved, content });
267
+ const content = await readContainedFile(root, candidate);
268
+ if (content !== null) return mcpJson({ path: path.join(root.root, candidate), content });
239
269
  } catch {
240
- // try next
270
+ // Try the next contained candidate; no alternate root is adopted.
241
271
  }
242
272
  }
243
273
  return mcpError(`template not found: ${template}`);
@@ -251,41 +281,18 @@ export function registerDiscoveryTools(server) {
251
281
  * Enumerate templates by walking the canonical corpus.
252
282
  * Restricted to the AIWG_ROOT subtree (no .aiwg/ project artifacts).
253
283
  */
254
- async function scanTemplates(aiwgRoot, { framework, filter } = {}) {
284
+ async function scanTemplates(store, { framework, filter } = {}) {
285
+ if (framework) validateContainedPath(framework);
286
+ const prefix = framework ? `agentic/code/frameworks/${framework}/templates/` : 'agentic/code/frameworks/';
287
+ const entries = await listContainedFiles(store, prefix);
255
288
  const results = [];
256
- const root = path.join(aiwgRoot, 'agentic/code/frameworks');
257
- let frameworks = [];
258
- try {
259
- frameworks = (await fs.readdir(root, { withFileTypes: true }))
260
- .filter(d => d.isDirectory())
261
- .map(d => d.name);
262
- } catch {
263
- return results;
264
- }
265
- for (const fw of frameworks) {
266
- if (framework && fw !== framework) continue;
267
- const tplRoot = path.join(root, fw, 'templates');
268
- await walkTemplates(tplRoot, tplRoot, fw, results, filter);
269
- }
270
- return results;
271
- }
272
-
273
- async function walkTemplates(base, dir, framework, out, filter) {
274
- let entries = [];
275
- try {
276
- entries = await fs.readdir(dir, { withFileTypes: true });
277
- } catch {
278
- return;
279
- }
280
289
  for (const entry of entries) {
281
- const full = path.join(dir, entry.name);
282
- if (entry.isDirectory()) {
283
- await walkTemplates(base, full, framework, out, filter);
284
- } else if (entry.isFile() && entry.name.endsWith('.md')) {
285
- const rel = path.relative(base, full);
286
- const name = entry.name.replace(/\.md$/, '');
287
- if (filter && !name.includes(filter) && !rel.includes(filter)) continue;
288
- out.push({ framework, name, relativePath: rel, path: full });
289
- }
290
+ const match = /^agentic\/code\/frameworks\/([^/]+)\/templates\/(.+\.md)$/.exec(entry.path);
291
+ if (!match) continue;
292
+ const [, fw, relativePath] = match;
293
+ const name = path.basename(relativePath, '.md');
294
+ if (filter && !name.includes(filter) && !relativePath.includes(filter)) continue;
295
+ results.push({ framework: fw, name, relativePath, path: path.join(store.root, entry.path) });
290
296
  }
297
+ return results;
291
298
  }
@@ -160,15 +160,25 @@ export function registerFlowToolset(server) {
160
160
  description: 'Fetch a declarative Flow playbook by name, including parsed step summary and the wrapper skill path when present.',
161
161
  inputSchema: {
162
162
  name: z.string().describe('Flow name or playbook file name (e.g. flow-release)'),
163
+ bound_rule_bodies: z.boolean().optional().describe('Include full bound rule bodies'),
163
164
  framework: z.string().optional().describe('Optional framework disambiguator'),
164
165
  },
165
166
  annotations: { readOnlyHint: true, openWorldHint: false },
166
- }, async ({ name, framework }) => {
167
+ }, async ({ name, framework, bound_rule_bodies }) => {
167
168
  try {
168
169
  const flow = await findFlow(name, framework);
169
170
  if (!flow) return mcpError(`flow-show: flow not found: ${name}`);
170
171
  flow.wrapper_skill.exists = await pathExists(flow.wrapper_skill.path);
171
- return mcpJson(flow);
172
+ const { stdout, stderr, code } = await runAiwgCli([
173
+ 'show', 'flow', flow.path, '--json',
174
+ ...(bound_rule_bodies ? ['--bound-rule-bodies'] : []),
175
+ ]);
176
+ if (code !== 0) return mcpError(`flow-show binding lookup failed: ${stderr}`);
177
+ const shown = JSON.parse(stdout);
178
+ return mcpJson({ ...flow, ...(shown.bound_rules ? { bound_rules: shown.bound_rules,
179
+ ...(shown.required_rule_checks ? { required_rule_checks: shown.required_rule_checks } : {}),
180
+ ...(shown.rule_stats ? { rule_stats: shown.rule_stats } : {}),
181
+ ...(shown.rule_check_obligation ? { rule_check_obligation: shown.rule_check_obligation } : {}) } : {}) });
172
182
  } catch (err) {
173
183
  return mcpError(`flow-show: ${err.message}`);
174
184
  }