@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.17

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 (466) hide show
  1. package/README.md +21 -1
  2. package/bin/aiwg.mjs +349 -0
  3. package/dist/src/a2a/agent-card.js +145 -0
  4. package/dist/src/a2a/client.js +411 -0
  5. package/dist/src/a2a/hitl-cli.js +171 -0
  6. package/dist/src/a2a/hitl-driver.js +370 -0
  7. package/dist/src/a2a/hitl.js +181 -0
  8. package/dist/src/a2a/http.js +193 -0
  9. package/dist/src/a2a/jcs.js +128 -0
  10. package/dist/src/a2a/jws.js +187 -0
  11. package/dist/src/a2a/types.js +24 -0
  12. package/dist/src/a2a/webhook.js +240 -0
  13. package/dist/src/activity-log/cli.js +348 -0
  14. package/dist/src/activity-log/parser.js +81 -0
  15. package/dist/src/activity-log/types.js +50 -0
  16. package/dist/src/agents/agent-deployer.js +367 -0
  17. package/dist/src/agents/agent-packager.js +271 -0
  18. package/dist/src/agents/agent-validator.js +271 -0
  19. package/dist/src/agents/grounding/knowledge-base.js +161 -0
  20. package/dist/src/agents/grounding/types.js +12 -0
  21. package/dist/src/agents/index.js +10 -0
  22. package/dist/src/agents/packaged-agent-inventory.js +75 -0
  23. package/dist/src/agents/types.js +7 -0
  24. package/dist/src/api/index.d.ts +10 -0
  25. package/dist/src/api/index.js +10 -0
  26. package/dist/src/artifacts/address-parser.js +73 -0
  27. package/dist/src/artifacts/audit/cli.js +183 -0
  28. package/dist/src/artifacts/audit/drift.js +122 -0
  29. package/dist/src/artifacts/audit/types.js +12 -0
  30. package/dist/src/artifacts/backends/graphology-backend.js +160 -0
  31. package/dist/src/artifacts/backends/json-backend.js +129 -0
  32. package/dist/src/artifacts/backends/sqlite-backend.js +199 -0
  33. package/dist/src/artifacts/browser-export.js +622 -0
  34. package/dist/src/artifacts/capability-resolver.js +94 -0
  35. package/dist/src/artifacts/checksum-manifest.js +91 -0
  36. package/dist/src/artifacts/citation-parser.js +162 -0
  37. package/dist/src/artifacts/cli.js +1462 -0
  38. package/dist/src/artifacts/corpus-tools/citation-densify.js +311 -0
  39. package/dist/src/artifacts/corpus-tools/cli.js +393 -0
  40. package/dist/src/artifacts/corpus-tools/corpus-graph.js +225 -0
  41. package/dist/src/artifacts/corpus-tools/curator.js +186 -0
  42. package/dist/src/artifacts/corpus-tools/discovery-log.js +70 -0
  43. package/dist/src/artifacts/corpus-tools/funder-network.js +141 -0
  44. package/dist/src/artifacts/corpus-tools/induction-audit.js +233 -0
  45. package/dist/src/artifacts/corpus-tools/integrity-scan.js +202 -0
  46. package/dist/src/artifacts/corpus-tools/profile-communities.js +166 -0
  47. package/dist/src/artifacts/corpus-tools/profile-edges.js +72 -0
  48. package/dist/src/artifacts/corpus-tools/profile-embed.js +113 -0
  49. package/dist/src/artifacts/corpus-tools/profile-generate-fm.js +167 -0
  50. package/dist/src/artifacts/corpus-tools/profile-generate.js +181 -0
  51. package/dist/src/artifacts/corpus-tools/profile-metrics.js +98 -0
  52. package/dist/src/artifacts/corpus-tools/profile-status.js +86 -0
  53. package/dist/src/artifacts/corpus-tools/profile-temporal.js +139 -0
  54. package/dist/src/artifacts/corpus-tools/radar-init.js +93 -0
  55. package/dist/src/artifacts/corpus-tools/radar-report.js +118 -0
  56. package/dist/src/artifacts/corpus-tools/radar-shared.js +189 -0
  57. package/dist/src/artifacts/corpus-tools/radar-status.js +68 -0
  58. package/dist/src/artifacts/corpus-tools/sidecar-lint.js +233 -0
  59. package/dist/src/artifacts/corpus-tools/sidecar-repair.js +277 -0
  60. package/dist/src/artifacts/corpus-tools/snapshot.js +591 -0
  61. package/dist/src/artifacts/corpus-tools/source-types.js +164 -0
  62. package/dist/src/artifacts/corpus-tools/vision-extract.js +243 -0
  63. package/dist/src/artifacts/corpus-views/build.js +126 -0
  64. package/dist/src/artifacts/corpus-views/corpus-config.js +124 -0
  65. package/dist/src/artifacts/corpus-views/ref-parser.js +437 -0
  66. package/dist/src/artifacts/corpus-views/renderers.js +353 -0
  67. package/dist/src/artifacts/corpus-views/taxonomies.js +131 -0
  68. package/dist/src/artifacts/dep-graph.js +173 -0
  69. package/dist/src/artifacts/discover-facets.js +375 -0
  70. package/dist/src/artifacts/embedding-index.js +354 -0
  71. package/dist/src/artifacts/enrichment/cli.js +240 -0
  72. package/dist/src/artifacts/enrichment/prompt.js +47 -0
  73. package/dist/src/artifacts/enrichment/store.js +90 -0
  74. package/dist/src/artifacts/enrichment/types.js +12 -0
  75. package/dist/src/artifacts/fortemi-core-query-adapter.js +475 -0
  76. package/dist/src/artifacts/fortemi-core-sync.js +251 -0
  77. package/dist/src/artifacts/fortemi-shard-export.js +44 -0
  78. package/dist/src/artifacts/fulltext.js +108 -0
  79. package/dist/src/artifacts/graph-backend.js +51 -0
  80. package/dist/src/artifacts/graph-query.js +247 -0
  81. package/dist/src/artifacts/hybrid-query.js +225 -0
  82. package/dist/src/artifacts/index-builder.js +1089 -0
  83. package/dist/src/artifacts/index-reader.js +112 -0
  84. package/dist/src/artifacts/index-status.js +193 -0
  85. package/dist/src/artifacts/legacy-index-migration.js +169 -0
  86. package/dist/src/artifacts/move.js +154 -0
  87. package/dist/src/artifacts/operational-state.js +239 -0
  88. package/dist/src/artifacts/prebuilt-build-lock.js +49 -0
  89. package/dist/src/artifacts/query-engine.js +1955 -0
  90. package/dist/src/artifacts/source-graph.js +529 -0
  91. package/dist/src/artifacts/stats.js +169 -0
  92. package/dist/src/artifacts/types.js +606 -0
  93. package/dist/src/artifacts/views/cli.js +293 -0
  94. package/dist/src/artifacts/views/definition.js +170 -0
  95. package/dist/src/artifacts/views/store.js +149 -0
  96. package/dist/src/artifacts/views/types.js +8 -0
  97. package/dist/src/artifacts/watcher.js +255 -0
  98. package/dist/src/catalog/builtin-models.json +636 -0
  99. package/dist/src/catalog/cli.js +228 -0
  100. package/dist/src/catalog/cli.mjs +289 -0
  101. package/dist/src/catalog/index.js +15 -0
  102. package/dist/src/catalog/loader.js +217 -0
  103. package/dist/src/catalog/loader.mjs +251 -0
  104. package/dist/src/catalog/sources.json +41 -0
  105. package/dist/src/catalog/types.js +8 -0
  106. package/dist/src/channel/manager.mjs +504 -0
  107. package/dist/src/cli/agent-spawn.js +178 -0
  108. package/dist/src/cli/cli-extension-loader.js +245 -0
  109. package/dist/src/cli/command-log.js +275 -0
  110. package/dist/src/cli/config-loader.js +232 -0
  111. package/dist/src/cli/env.js +82 -0
  112. package/dist/src/cli/errors.js +150 -0
  113. package/dist/src/cli/find-package-root.js +40 -0
  114. package/dist/src/cli/git-hooks.js +250 -0
  115. package/dist/src/cli/handlers/agentcard.js +206 -0
  116. package/dist/src/cli/handlers/artifacts.js +76 -0
  117. package/dist/src/cli/handlers/best-practices-audit.js +280 -0
  118. package/dist/src/cli/handlers/cockpit.js +137 -0
  119. package/dist/src/cli/handlers/command-log.js +37 -0
  120. package/dist/src/cli/handlers/daemon.js +59 -0
  121. package/dist/src/cli/handlers/diagnose.js +300 -0
  122. package/dist/src/cli/handlers/execution-mode.js +105 -0
  123. package/dist/src/cli/handlers/feedback.js +341 -0
  124. package/dist/src/cli/handlers/help.js +147 -0
  125. package/dist/src/cli/handlers/index.js +302 -0
  126. package/dist/src/cli/handlers/init.js +179 -0
  127. package/dist/src/cli/handlers/install.js +129 -0
  128. package/dist/src/cli/handlers/issues.js +46 -0
  129. package/dist/src/cli/handlers/lint.js +42 -0
  130. package/dist/src/cli/handlers/local-executor.js +315 -0
  131. package/dist/src/cli/handlers/marketplace.js +168 -0
  132. package/dist/src/cli/handlers/mc.js +1010 -0
  133. package/dist/src/cli/handlers/models.js +352 -0
  134. package/dist/src/cli/handlers/packages.js +155 -0
  135. package/dist/src/cli/handlers/ralph-launcher.js +717 -0
  136. package/dist/src/cli/handlers/ralph.js +575 -0
  137. package/dist/src/cli/handlers/refresh.js +432 -0
  138. package/dist/src/cli/handlers/regenerate.js +336 -0
  139. package/dist/src/cli/handlers/repo-access.js +109 -0
  140. package/dist/src/cli/handlers/run.js +165 -0
  141. package/dist/src/cli/handlers/runtime-info.js +301 -0
  142. package/dist/src/cli/handlers/sandbox.js +197 -0
  143. package/dist/src/cli/handlers/scaffolding.js +149 -0
  144. package/dist/src/cli/handlers/script-runner.js +121 -0
  145. package/dist/src/cli/handlers/sdlc-accelerate.js +148 -0
  146. package/dist/src/cli/handlers/serve.js +1835 -0
  147. package/dist/src/cli/handlers/session.js +348 -0
  148. package/dist/src/cli/handlers/setup.js +440 -0
  149. package/dist/src/cli/handlers/skill-lint.js +367 -0
  150. package/dist/src/cli/handlers/skill-usage.js +74 -0
  151. package/dist/src/cli/handlers/steward.js +567 -0
  152. package/dist/src/cli/handlers/subcommands.js +1702 -0
  153. package/dist/src/cli/handlers/team.js +337 -0
  154. package/dist/src/cli/handlers/types.js +11 -0
  155. package/dist/src/cli/handlers/use.js +2772 -0
  156. package/dist/src/cli/handlers/utilities.js +703 -0
  157. package/dist/src/cli/handlers/version.js +134 -0
  158. package/dist/src/cli/handlers/workspace-context.js +93 -0
  159. package/dist/src/cli/handlers/workspace.js +126 -0
  160. package/dist/src/cli/help-generator.js +178 -0
  161. package/dist/src/cli/hooks/builtin/activity-log-hook.js +126 -0
  162. package/dist/src/cli/hooks/executor.js +96 -0
  163. package/dist/src/cli/hooks/index.js +15 -0
  164. package/dist/src/cli/hooks/registry.js +143 -0
  165. package/dist/src/cli/hooks/types.js +13 -0
  166. package/dist/src/cli/log.js +492 -0
  167. package/dist/src/cli/project-isolation/detect.js +70 -0
  168. package/dist/src/cli/project-isolation/index.js +7 -0
  169. package/dist/src/cli/project-isolation/signals.js +17 -0
  170. package/dist/src/cli/project-isolation/warning.js +102 -0
  171. package/dist/src/cli/prompt-utils.js +155 -0
  172. package/dist/src/cli/provider-deployment-plan.js +126 -0
  173. package/dist/src/cli/provider-resolution.js +119 -0
  174. package/dist/src/cli/router.js +305 -0
  175. package/dist/src/cli/scope-resolver.js +392 -0
  176. package/dist/src/cli/skill-usage.js +616 -0
  177. package/dist/src/cli/ui.js +224 -0
  178. package/dist/src/cli/watch-service.js +203 -0
  179. package/dist/src/cli/workflow-orchestrator.js +478 -0
  180. package/dist/src/cli/workspace-signals.js +321 -0
  181. package/dist/src/community/footer.js +14 -0
  182. package/dist/src/community/links.js +123 -0
  183. package/dist/src/community/milestones.js +46 -0
  184. package/dist/src/community/nudge-policy.js +93 -0
  185. package/dist/src/config/aiwg-config.js +883 -0
  186. package/dist/src/config/cli.js +703 -0
  187. package/dist/src/config/gitignore.js +156 -0
  188. package/dist/src/config/project-artifacts.js +76 -0
  189. package/dist/src/config/user-config.js +428 -0
  190. package/dist/src/config/user-registry.js +127 -0
  191. package/dist/src/config/workspace.js +276 -0
  192. package/dist/src/contributors/detect.js +39 -0
  193. package/dist/src/contributors/discover.js +172 -0
  194. package/dist/src/contributors/heuristic.js +186 -0
  195. package/dist/src/contributors/index.js +11 -0
  196. package/dist/src/contributors/types.js +13 -0
  197. package/dist/src/contributors/validation.js +116 -0
  198. package/dist/src/data/community.schema.json +43 -0
  199. package/dist/src/data/community.yaml +16 -0
  200. package/dist/src/extensions/capability-index.js +270 -0
  201. package/dist/src/extensions/claude-hooks-installer.js +268 -0
  202. package/dist/src/extensions/commands/definitions.js +3485 -0
  203. package/dist/src/extensions/deployment-registration.js +463 -0
  204. package/dist/src/extensions/index.js +22 -0
  205. package/dist/src/extensions/loader.js +132 -0
  206. package/dist/src/extensions/managed-marker.js +100 -0
  207. package/dist/src/extensions/manifest.js +196 -0
  208. package/dist/src/extensions/project-local-activity.js +114 -0
  209. package/dist/src/extensions/project-local-discovery.js +261 -0
  210. package/dist/src/extensions/project-local-doctor.js +281 -0
  211. package/dist/src/extensions/project-local-gitignore.js +176 -0
  212. package/dist/src/extensions/project-local-paths.js +121 -0
  213. package/dist/src/extensions/project-local-promote.js +218 -0
  214. package/dist/src/extensions/project-local-remove.js +373 -0
  215. package/dist/src/extensions/project-local-scaffold.js +252 -0
  216. package/dist/src/extensions/project-quickref.js +291 -0
  217. package/dist/src/extensions/registry.js +368 -0
  218. package/dist/src/extensions/shadow-resolver.js +271 -0
  219. package/dist/src/extensions/types.js +86 -0
  220. package/dist/src/extensions/upstream-registry.js +195 -0
  221. package/dist/src/extensions/validation.js +631 -0
  222. package/dist/src/features/catalog.js +88 -0
  223. package/dist/src/features/cli.js +197 -0
  224. package/dist/src/features/installer.js +57 -0
  225. package/dist/src/features/paths.js +14 -0
  226. package/dist/src/features/runtime.js +21 -0
  227. package/dist/src/features/status.js +134 -0
  228. package/dist/src/hooks/laziness-detection.js +532 -0
  229. package/dist/src/intake/git-history-analyzer.js +486 -0
  230. package/dist/src/intake/index.js +9 -0
  231. package/dist/src/issues/cli.js +327 -0
  232. package/dist/src/issues/index.js +5 -0
  233. package/dist/src/issues/live.js +154 -0
  234. package/dist/src/issues/local.js +666 -0
  235. package/dist/src/issues/sync.js +143 -0
  236. package/dist/src/issues/types.js +2 -0
  237. package/dist/src/issues/workflows.js +164 -0
  238. package/dist/src/kb/cli.js +173 -0
  239. package/dist/src/lint/cli.js +171 -0
  240. package/dist/src/lint/loader.js +225 -0
  241. package/dist/src/lint/reporters.js +141 -0
  242. package/dist/src/lint/runner.js +364 -0
  243. package/dist/src/lint/types.js +10 -0
  244. package/dist/src/marketplace/cache.js +110 -0
  245. package/dist/src/marketplace/identifier.js +63 -0
  246. package/dist/src/marketplace/registry.js +36 -0
  247. package/dist/src/marketplace/sources/clawhub.js +53 -0
  248. package/dist/src/marketplace/sources/git.js +45 -0
  249. package/dist/src/marketplace/types.js +9 -0
  250. package/dist/src/mcp/adapters/codex-runtime.js +224 -0
  251. package/dist/src/mcp/cli.mjs +1197 -0
  252. package/dist/src/mcp/elicitation.mjs +149 -0
  253. package/dist/src/mcp/helpers.mjs +287 -0
  254. package/dist/src/mcp/index.mjs +11 -0
  255. package/dist/src/mcp/profiles.js +263 -0
  256. package/dist/src/mcp/profiles.mjs +360 -0
  257. package/dist/src/mcp/registry.js +376 -0
  258. package/dist/src/mcp/registry.mjs +387 -0
  259. package/dist/src/mcp/server.mjs +633 -0
  260. package/dist/src/mcp/test-simple.mjs +271 -0
  261. package/dist/src/mcp/tools/command-run.mjs +101 -0
  262. package/dist/src/mcp/tools/discovery.mjs +291 -0
  263. package/dist/src/mcp/tools/interaction.mjs +87 -0
  264. package/dist/src/mcp/tools/orchestration.mjs +320 -0
  265. package/dist/src/mcp/tools/subsystems.mjs +640 -0
  266. package/dist/src/memory/cli.js +166 -0
  267. package/dist/src/memory/project-registry.js +282 -0
  268. package/dist/src/metrics/artifact-metrics.js +184 -0
  269. package/dist/src/metrics/context-budget.js +174 -0
  270. package/dist/src/metrics/token-counter.js +133 -0
  271. package/dist/src/models/config-loader.js +228 -0
  272. package/dist/src/models/index.js +22 -0
  273. package/dist/src/models/model-capabilities.v1.json +120 -0
  274. package/dist/src/models/model-catalog.v1.json +96 -0
  275. package/dist/src/models/model-discovery.js +521 -0
  276. package/dist/src/models/provider-models.js +73 -0
  277. package/dist/src/models/provider-policy.js +273 -0
  278. package/dist/src/models/resolver.js +245 -0
  279. package/dist/src/models/router.js +70 -0
  280. package/dist/src/models/types.js +8 -0
  281. package/dist/src/models/wrapper-deployment.js +178 -0
  282. package/dist/src/models/wrapper-route.js +54 -0
  283. package/dist/src/ops/cli.js +268 -0
  284. package/dist/src/ops/registry.js +623 -0
  285. package/dist/src/packages/adapters/clawhub.js +113 -0
  286. package/dist/src/packages/adapters/git.js +153 -0
  287. package/dist/src/packages/adapters/gitea.js +93 -0
  288. package/dist/src/packages/adapters/github.js +69 -0
  289. package/dist/src/packages/adapters/local-cache.js +89 -0
  290. package/dist/src/packages/package-registry.js +143 -0
  291. package/dist/src/packages/registry.js +238 -0
  292. package/dist/src/packages/types.js +11 -0
  293. package/dist/src/plugin/cross-framework-ops.js +475 -0
  294. package/dist/src/plugin/framework-config-loader.js +235 -0
  295. package/dist/src/plugin/framework-detector.js +186 -0
  296. package/dist/src/plugin/framework-isolator.js +341 -0
  297. package/dist/src/plugin/framework-migration.js +371 -0
  298. package/dist/src/plugin/metadata-validator.js +906 -0
  299. package/dist/src/plugin/plugin-installer.js +436 -0
  300. package/dist/src/plugin/plugin-status.js +369 -0
  301. package/dist/src/plugin/plugin-uninstaller.js +473 -0
  302. package/dist/src/plugin/registry-validator.js +344 -0
  303. package/dist/src/plugin/skill-command-translator.js +415 -0
  304. package/dist/src/plugin/workspace-creator.js +189 -0
  305. package/dist/src/plugin/workspace-migrator.js +821 -0
  306. package/dist/src/policy/authorization.js +390 -0
  307. package/dist/src/policy/repo-access.js +215 -0
  308. package/dist/src/provenance/cli.js +16 -0
  309. package/dist/src/providers/capability-matrix.js +300 -0
  310. package/dist/src/providers/capability-matrix.yaml +514 -0
  311. package/dist/src/providers/provider-definitions.js +977 -0
  312. package/dist/src/providers/provider-definitions.mjs +159 -0
  313. package/dist/src/providers/provider-inventory.js +169 -0
  314. package/dist/src/quality/feedback-ab.js +174 -0
  315. package/dist/src/quality/feedback-collector.js +176 -0
  316. package/dist/src/quality/feedback-tracker.js +123 -0
  317. package/dist/src/quality/patterns/adr.json +24 -0
  318. package/dist/src/quality/patterns/sad.json +24 -0
  319. package/dist/src/quality/patterns/test-plan.json +24 -0
  320. package/dist/src/quality/patterns/use-case.json +24 -0
  321. package/dist/src/quality/scoring.js +157 -0
  322. package/dist/src/reflections/cli.js +15 -0
  323. package/dist/src/release/plan.js +139 -0
  324. package/dist/src/research/cache/manager.js +227 -0
  325. package/dist/src/research/clients/arxiv.js +156 -0
  326. package/dist/src/research/clients/base.js +197 -0
  327. package/dist/src/research/clients/crossref.js +112 -0
  328. package/dist/src/research/clients/semantic-scholar.js +126 -0
  329. package/dist/src/research/clients/unpaywall.js +87 -0
  330. package/dist/src/research/index.js +14 -0
  331. package/dist/src/research/query-cli.js +336 -0
  332. package/dist/src/research/services/acquisition.js +313 -0
  333. package/dist/src/research/services/archival.js +225 -0
  334. package/dist/src/research/services/citation.js +279 -0
  335. package/dist/src/research/services/discovery.js +243 -0
  336. package/dist/src/research/services/documentation.js +269 -0
  337. package/dist/src/research/services/index.js +14 -0
  338. package/dist/src/research/services/provenance.js +279 -0
  339. package/dist/src/research/services/quality.js +370 -0
  340. package/dist/src/research/services/types.js +7 -0
  341. package/dist/src/research/storage-cli.js +20 -0
  342. package/dist/src/research/types.js +47 -0
  343. package/dist/src/resources/index.d.ts +2 -0
  344. package/dist/src/resources/index.js +2 -0
  345. package/dist/src/resources/web-release.d.ts +89 -0
  346. package/dist/src/resources/web-release.js +882 -0
  347. package/dist/src/rlm/cache/cli.js +162 -0
  348. package/dist/src/rlm/cache/hash.js +35 -0
  349. package/dist/src/rlm/cache/store.js +170 -0
  350. package/dist/src/rlm/cache/types.js +8 -0
  351. package/dist/src/rlm/cli.js +650 -0
  352. package/dist/src/serve/a2a-terminal-observer.js +120 -0
  353. package/dist/src/serve/agent-router.js +205 -0
  354. package/dist/src/serve/dispatch-router.js +171 -0
  355. package/dist/src/serve/executor-registry.js +715 -0
  356. package/dist/src/serve/mission-conductor.js +177 -0
  357. package/dist/src/serve/orchestrator-adapter.js +113 -0
  358. package/dist/src/serve/orchestrator-override.js +94 -0
  359. package/dist/src/serve/orchestrator-pty.js +133 -0
  360. package/dist/src/serve/pty-bridge.js +799 -0
  361. package/dist/src/serve/sandbox-registry.js +832 -0
  362. package/dist/src/serve/screen-reader.js +228 -0
  363. package/dist/src/serve/stack-adapters.js +68 -0
  364. package/dist/src/serve/telemetry.js +143 -0
  365. package/dist/src/skills/adapters/clawhub.js +250 -0
  366. package/dist/src/skills/adapters/local.js +335 -0
  367. package/dist/src/skills/adapters/openclaw.js +316 -0
  368. package/dist/src/skills/cli.js +334 -0
  369. package/dist/src/skills/registry.js +117 -0
  370. package/dist/src/skills/run.js +259 -0
  371. package/dist/src/skills/runtime.js +94 -0
  372. package/dist/src/skills/types.js +10 -0
  373. package/dist/src/smiths/agentsmith/demo.js +116 -0
  374. package/dist/src/smiths/agentsmith/examples.js +300 -0
  375. package/dist/src/smiths/agentsmith/generator.js +503 -0
  376. package/dist/src/smiths/agentsmith/index.js +11 -0
  377. package/dist/src/smiths/agentsmith/types.js +8 -0
  378. package/dist/src/smiths/commandsmith/example.js +220 -0
  379. package/dist/src/smiths/commandsmith/generator.js +288 -0
  380. package/dist/src/smiths/commandsmith/index.js +41 -0
  381. package/dist/src/smiths/commandsmith/templates.js +296 -0
  382. package/dist/src/smiths/commandsmith/types.js +7 -0
  383. package/dist/src/smiths/context-pipeline/aiwg-md.js +104 -0
  384. package/dist/src/smiths/context-pipeline/allowlist.js +195 -0
  385. package/dist/src/smiths/context-pipeline/claude-hook.js +127 -0
  386. package/dist/src/smiths/context-pipeline/discovery.js +187 -0
  387. package/dist/src/smiths/context-pipeline/external-links-section.js +49 -0
  388. package/dist/src/smiths/context-pipeline/finalization.js +147 -0
  389. package/dist/src/smiths/context-pipeline/generator.js +477 -0
  390. package/dist/src/smiths/context-pipeline/index.js +30 -0
  391. package/dist/src/smiths/context-pipeline/legacy-inject.js +103 -0
  392. package/dist/src/smiths/context-pipeline/managed-hook.js +95 -0
  393. package/dist/src/smiths/context-pipeline/overflow.js +212 -0
  394. package/dist/src/smiths/context-pipeline/parallelism-section.js +94 -0
  395. package/dist/src/smiths/context-pipeline/provider-policy.js +64 -0
  396. package/dist/src/smiths/context-pipeline/sanitizer.js +93 -0
  397. package/dist/src/smiths/context-pipeline/types.js +23 -0
  398. package/dist/src/smiths/context-pipeline/workspace-context.js +988 -0
  399. package/dist/src/smiths/hook-bridge/codex-translator.js +129 -0
  400. package/dist/src/smiths/hook-bridge/copilot-translator.js +64 -0
  401. package/dist/src/smiths/hook-bridge/factory-translator.js +43 -0
  402. package/dist/src/smiths/hook-bridge/hermes-translator.js +88 -0
  403. package/dist/src/smiths/hook-bridge/index.js +79 -0
  404. package/dist/src/smiths/hook-bridge/loader.js +116 -0
  405. package/dist/src/smiths/hook-bridge/shim.js +89 -0
  406. package/dist/src/smiths/hook-bridge/types.js +31 -0
  407. package/dist/src/smiths/index.js +39 -0
  408. package/dist/src/smiths/mcpsmith/analyzers/cli-analyzer.js +390 -0
  409. package/dist/src/smiths/mcpsmith/example.js +119 -0
  410. package/dist/src/smiths/mcpsmith/generator.js +236 -0
  411. package/dist/src/smiths/mcpsmith/index.js +17 -0
  412. package/dist/src/smiths/mcpsmith/types.js +10 -0
  413. package/dist/src/smiths/platform-paths.js +101 -0
  414. package/dist/src/smiths/skillsmith/codex-sidecar.js +85 -0
  415. package/dist/src/smiths/skillsmith/collision-detector.js +249 -0
  416. package/dist/src/smiths/skillsmith/demo.js +83 -0
  417. package/dist/src/smiths/skillsmith/examples.js +161 -0
  418. package/dist/src/smiths/skillsmith/generator.js +316 -0
  419. package/dist/src/smiths/skillsmith/index.js +12 -0
  420. package/dist/src/smiths/skillsmith/namespace-adapter.js +180 -0
  421. package/dist/src/smiths/skillsmith/platform-resolver.js +157 -0
  422. package/dist/src/smiths/skillsmith/types.js +9 -0
  423. package/dist/src/smiths/toolsmith/index.js +10 -0
  424. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +710 -0
  425. package/dist/src/smiths/toolsmith/types.js +8 -0
  426. package/dist/src/storage/backends/fortemi.js +227 -0
  427. package/dist/src/storage/backends/fs.js +134 -0
  428. package/dist/src/storage/backends/logseq.js +309 -0
  429. package/dist/src/storage/backends/obsidian.js +233 -0
  430. package/dist/src/storage/cli.js +468 -0
  431. package/dist/src/storage/config.js +272 -0
  432. package/dist/src/storage/index.js +108 -0
  433. package/dist/src/storage/subsystem-cli.js +201 -0
  434. package/dist/src/storage/types.js +33 -0
  435. package/dist/src/testing/corpus/corpus-builder.js +383 -0
  436. package/dist/src/testing/corpus/ground-truth-manager.js +460 -0
  437. package/dist/src/testing/corpus/index.js +10 -0
  438. package/dist/src/testing/fixtures/index.js +9 -0
  439. package/dist/src/testing/fixtures/test-data-factory.js +472 -0
  440. package/dist/src/testing/generators/index.js +11 -0
  441. package/dist/src/testing/generators/test-case-generator.js +393 -0
  442. package/dist/src/testing/generators/test-code-generator.js +384 -0
  443. package/dist/src/testing/generators/use-case-parser.js +325 -0
  444. package/dist/src/testing/index.js +11 -0
  445. package/dist/src/tracker/capability-protocol.js +118 -0
  446. package/dist/src/update/checker.mjs +396 -0
  447. package/dist/src/update/notifier.mjs +235 -0
  448. package/dist/src/writing/content-diversifier.js +804 -0
  449. package/dist/src/writing/example-generator.js +959 -0
  450. package/dist/src/writing/example-templates.js +99 -0
  451. package/dist/src/writing/pattern-library.js +486 -0
  452. package/dist/src/writing/patterns/banned-phrases.json +4413 -0
  453. package/dist/src/writing/patterns/formulaic-structures.json +1300 -0
  454. package/dist/src/writing/patterns/generic-adjectives.json +1510 -0
  455. package/dist/src/writing/patterns/hedging-language.json +2096 -0
  456. package/dist/src/writing/patterns/transition-words.json +1285 -0
  457. package/dist/src/writing/patterns/weak-verbs.json +1112 -0
  458. package/dist/src/writing/prompt-optimizer.js +660 -0
  459. package/dist/src/writing/prompt-templates.js +583 -0
  460. package/dist/src/writing/scoring-config-loader.js +168 -0
  461. package/dist/src/writing/validation-engine.js +595 -0
  462. package/dist/src/writing/validation-rules.js +380 -0
  463. package/dist/src/writing/voice-analyzer.js +439 -0
  464. package/dist/src/writing/voice-calibration.js +661 -0
  465. package/dist/src/writing/voice-profiles.json +588 -0
  466. package/package.json +64 -9
@@ -0,0 +1,1702 @@
1
+ /**
2
+ * Subcommand Handlers
3
+ *
4
+ * Handlers for MCP, catalog, plugin, and other subcommands.
5
+ * Handles CLI subcommand routing.
6
+ *
7
+ * @implements @.aiwg/architecture/decisions/ADR-001-unified-extension-system.md
8
+ * @implements #56, #57
9
+ * @source @src/cli/router.ts
10
+ * @tests @test/unit/cli/handlers/subcommands.test.ts
11
+ * @issue #33
12
+ */
13
+ import { createScriptRunner } from "./script-runner.js";
14
+ import { getFrameworkRoot } from "../../channel/manager.mjs";
15
+ import { getRegistry } from "../../extensions/registry.js";
16
+ import { registerDeployedExtensions } from "../../extensions/deployment-registration.js";
17
+ import { discoverProjectLocalBundles } from "../../extensions/project-local-discovery.js";
18
+ import { buildUpstreamRegistry } from "../../extensions/upstream-registry.js";
19
+ import { resolveShadows } from "../../extensions/shadow-resolver.js";
20
+ import { sessionHandler } from "./session.js";
21
+ import { feedbackHandler } from "./feedback.js";
22
+ import { handlerResultFromError } from "../errors.js";
23
+ import { getProjectDir } from "../../config/aiwg-config.js";
24
+ import { formatDeployedWorkspaceSignalPlan, readWorkspaceSignalPlan } from "../workspace-signals.js";
25
+ import * as path from "node:path";
26
+ import * as fsSync from "node:fs";
27
+ /** Generate or deploy the canonical project quickref. */
28
+ export const quickrefHandler = {
29
+ id: 'quickref',
30
+ name: 'Project Quickref',
31
+ description: 'Generate and deploy an always-visible project quickref',
32
+ category: 'project',
33
+ aliases: [],
34
+ async execute(ctx) {
35
+ const action = ctx.args.find(arg => !arg.startsWith('-')) ?? 'generate';
36
+ if (!ctx.args.includes('--project')) {
37
+ return { exitCode: 1, message: 'Error: project quickrefs require --project\n\nUsage: aiwg quickref generate|deploy --project [--provider <id>] [--dry-run]' };
38
+ }
39
+ if (!['generate', 'deploy'].includes(action)) {
40
+ return { exitCode: 1, message: `Error: unknown quickref action '${action}' (expected generate or deploy)` };
41
+ }
42
+ const { generateProjectQuickref, deployProjectQuickref, } = await import('../../extensions/project-quickref.js');
43
+ try {
44
+ if (action === 'generate') {
45
+ const result = await generateProjectQuickref(ctx.cwd, { dryRun: ctx.dryRun });
46
+ const verb = ctx.dryRun ? 'Would generate' : result.changed ? 'Generated' : 'Unchanged';
47
+ console.log(`${verb} ${result.skillName}`);
48
+ console.log(` Source: ${result.sourcePath}`);
49
+ console.log(` Output: ${result.outputPath}`);
50
+ if (ctx.dryRun) {
51
+ console.log('\n--- preview ---\n');
52
+ console.log(result.content);
53
+ }
54
+ return { exitCode: 0 };
55
+ }
56
+ const providerIndex = ctx.args.indexOf('--provider');
57
+ const explicitProvider = providerIndex >= 0 ? ctx.args[providerIndex + 1] : undefined;
58
+ const { readAiwgConfig } = await import('../../config/aiwg-config.js');
59
+ const config = await readAiwgConfig(ctx.cwd);
60
+ const providers = explicitProvider ? [explicitProvider] : (config?.providers ?? []);
61
+ if (providers.length === 0) {
62
+ return { exitCode: 1, message: 'No providers configured. Pass --provider <id> or add providers to .aiwg/aiwg.config.' };
63
+ }
64
+ for (const provider of providers) {
65
+ const result = await deployProjectQuickref(ctx.cwd, provider, { dryRun: ctx.dryRun });
66
+ const verb = ctx.dryRun ? 'Would deploy' : result.changed ? 'Deployed' : 'Unchanged';
67
+ console.log(`${verb} ${result.skillName} -> ${result.provider}: ${result.targetPath}${result.emulated ? ' (emulated skill surface)' : ''}`);
68
+ for (const stale of result.pruned) {
69
+ console.log(` ${ctx.dryRun ? 'Would prune' : 'Pruned'} stale managed quickref: ${stale}`);
70
+ }
71
+ }
72
+ return { exitCode: 0 };
73
+ }
74
+ catch (error) {
75
+ return { exitCode: 1, message: `Project quickref failed: ${error.message}` };
76
+ }
77
+ },
78
+ };
79
+ const LIST_PROVIDER_TARGETS = [
80
+ { name: 'claude', root: '.claude', agentsPath: '.claude/agents', skillsPath: '.claude/skills', commandsPath: '.claude/commands' },
81
+ { name: 'codex', root: '.codex', agentsPath: '.codex/agents', skillsPath: '.codex/skills', commandsPath: '.codex/commands' },
82
+ { name: 'copilot', root: '.github', agentsPath: '.github/agents', skillsPath: '.github/skills', commandsPath: '.github/prompts' },
83
+ { name: 'cursor', root: '.cursor', agentsPath: '.cursor/agents', skillsPath: '.cursor/skills', commandsPath: '.cursor/commands' },
84
+ { name: 'opencode', root: '.opencode', agentsPath: '.opencode/agent', skillsPath: '.opencode/skill', commandsPath: '.opencode/command' },
85
+ { name: 'warp', root: '.warp', agentsPath: '.warp/agents', skillsPath: '.warp/skills', commandsPath: '.warp/commands' },
86
+ { name: 'factory', root: '.factory', agentsPath: '.factory/droids', skillsPath: '.factory/skills', commandsPath: '.factory/commands' },
87
+ { name: 'windsurf', root: '.windsurf', agentsPath: '.windsurf/agents', skillsPath: '.windsurf/skills', commandsPath: '.windsurf/workflows' },
88
+ { name: 'universal', root: '.agents', agentsPath: '.agents/agents', skillsPath: '.agents/skills', commandsPath: '.agents/commands' },
89
+ ];
90
+ function hasAnyPopulated(cwd, p) {
91
+ const candidates = [p.agentsPath, p.skillsPath, p.commandsPath];
92
+ for (const rel of candidates) {
93
+ const abs = path.join(cwd, rel);
94
+ try {
95
+ if (fsSync.statSync(abs).isDirectory() && fsSync.readdirSync(abs).length > 0)
96
+ return true;
97
+ }
98
+ catch {
99
+ // dir doesn't exist or unreadable — skip
100
+ }
101
+ }
102
+ return false;
103
+ }
104
+ function detectDeployedProviders(cwd) {
105
+ return LIST_PROVIDER_TARGETS.filter(p => hasAnyPopulated(cwd, p));
106
+ }
107
+ const REMOVE_FLAGS_WITH_VALUES = new Set([
108
+ '--provider',
109
+ '--platform',
110
+ '--scope',
111
+ '--target',
112
+ ]);
113
+ function firstRemovePositional(args) {
114
+ for (let i = 0; i < args.length; i += 1) {
115
+ const arg = args[i];
116
+ if (REMOVE_FLAGS_WITH_VALUES.has(arg)) {
117
+ i += 1;
118
+ continue;
119
+ }
120
+ if (!arg.startsWith('-'))
121
+ return arg;
122
+ }
123
+ return undefined;
124
+ }
125
+ function parseRemoveProvider(args) {
126
+ const idx = args.findIndex(a => a === '--provider' || a === '--platform');
127
+ if (idx < 0)
128
+ return {};
129
+ const provider = args[idx + 1];
130
+ if (!provider || provider.startsWith('-')) {
131
+ return { error: 'Error: --provider requires a provider name' };
132
+ }
133
+ return { provider };
134
+ }
135
+ /**
136
+ * MCP server command handler
137
+ *
138
+ * Dynamically imports and delegates to src/mcp/cli.mjs.
139
+ * Handles subcommands: serve, install, info
140
+ */
141
+ export const mcpHandler = {
142
+ id: "aiwg-mcp-server",
143
+ name: "AIWG MCP Server",
144
+ description: "AIWG MCP server commands (serve, install, add, remove, update, list, inject, info)",
145
+ category: "mcp",
146
+ aliases: ["mcp", "aiwg-mcp"],
147
+ async execute(ctx) {
148
+ try {
149
+ // Dynamic import to avoid loading MCP dependencies unless needed
150
+ const { main } = await import("../../mcp/cli.mjs");
151
+ await main(ctx.args);
152
+ return {
153
+ exitCode: 0,
154
+ };
155
+ }
156
+ catch (error) {
157
+ const result = handlerResultFromError(error);
158
+ return { ...result, message: `MCP command failed: ${result.message}` };
159
+ }
160
+ },
161
+ };
162
+ /**
163
+ * Model catalog command handler
164
+ *
165
+ * Dynamically imports and delegates to src/catalog/cli.mjs.
166
+ * Handles subcommands: list, info, search
167
+ */
168
+ export const catalogHandler = {
169
+ id: "catalog",
170
+ name: "Model Catalog",
171
+ description: "Model catalog commands (list, info, search)",
172
+ category: "catalog",
173
+ aliases: [],
174
+ async execute(ctx) {
175
+ try {
176
+ // Dynamic import to avoid loading catalog dependencies unless needed
177
+ const { main } = await import("../../catalog/cli.mjs");
178
+ await main(ctx.args);
179
+ return {
180
+ exitCode: 0,
181
+ };
182
+ }
183
+ catch (error) {
184
+ const result = handlerResultFromError(error);
185
+ return { ...result, message: `Catalog command failed: ${result.message}` };
186
+ }
187
+ },
188
+ };
189
+ /**
190
+ * List frameworks handler
191
+ *
192
+ * Lists deployed extensions from the registry.
193
+ * Falls back to legacy plugin-status script if needed.
194
+ */
195
+ export const listHandler = {
196
+ id: "list",
197
+ name: "List Frameworks",
198
+ description: "List installed frameworks and plugins",
199
+ category: "framework",
200
+ aliases: ["ls"],
201
+ async execute(ctx) {
202
+ // Filter args: positional type filter, plus --project-local flag (#1034)
203
+ const projectLocalOnly = ctx.args.includes('--project-local');
204
+ const shadowsOnly = ctx.args.includes('--shadows');
205
+ const deployedOnly = ctx.args.includes('--deployed');
206
+ const filterType = ctx.args.find((a) => !a.startsWith('--')); // 'agents'|'skills'|'commands'|'all'|undefined
207
+ // #1156 Phase 1 — --scope user / --user surfaces the per-user registry
208
+ // (~/.aiwg/installed.json) instead of the project-scope deployed-extensions
209
+ // registry. Works from any cwd; does not require a project to be present.
210
+ const userScopeRequested = ctx.args.includes('--user') || isScopeUser(ctx.args);
211
+ if (userScopeRequested) {
212
+ return await formatUserScopeRegistry();
213
+ }
214
+ // Project-local bundle discovery (#1034) — read-only scan, no deploy
215
+ const projectLocal = await discoverProjectLocalBundles(ctx.cwd);
216
+ if (shadowsOnly) {
217
+ // #1036 — surface only artifacts that shadow upstream
218
+ return await formatShadowsOnly(projectLocal);
219
+ }
220
+ if (projectLocalOnly) {
221
+ // --project-local: only show project-local bundles; skip the deployed-
222
+ // extension registry read entirely
223
+ return formatProjectLocalOnly(projectLocal);
224
+ }
225
+ // Ensure registry is populated with deployed extensions
226
+ const registry = getRegistry();
227
+ // If registry is empty, try to populate it from EVERY deployed provider
228
+ // in the workspace (not just claude). Fixes #1530: in a Codex-only
229
+ // workspace the legacy hard-coded `.claude/...` lookup reported zero
230
+ // extensions even though `.codex/` was populated. Detection mirrors
231
+ // `tools/cli/workspace-status.mjs` so `aiwg list` and `aiwg status`
232
+ // agree on what counts as deployed.
233
+ //
234
+ // `--provider <name>` narrows registration to one provider; otherwise
235
+ // we register the union of everything detected so a multi-provider
236
+ // workspace shows everything in a single inventory.
237
+ if (registry.size === 0) {
238
+ try {
239
+ const provIdx = ctx.args.findIndex((a) => a === '--provider' || a === '--platform');
240
+ const requestedProvider = provIdx >= 0 ? ctx.args[provIdx + 1] : undefined;
241
+ let targets = detectDeployedProviders(ctx.cwd);
242
+ if (requestedProvider) {
243
+ targets = targets.filter((p) => p.name === requestedProvider);
244
+ if (targets.length === 0) {
245
+ return {
246
+ exitCode: 1,
247
+ message: `Error: provider '${requestedProvider}' is not deployed in this workspace.\n\nRun 'aiwg status' to see deployed providers.`,
248
+ };
249
+ }
250
+ }
251
+ if (targets.length === 0) {
252
+ // No deployed providers detected → return a clean empty-inventory
253
+ // message rather than dispatching to the legacy script (which
254
+ // requires a path argument it doesn't get here). Matches the
255
+ // legacy script's helpful guidance from #1530.
256
+ return {
257
+ exitCode: 0,
258
+ message: 'No agents, skills, or commands deployed in this workspace.\n\n' +
259
+ 'Tip: Deploy a framework with "aiwg use sdlc" (or another framework) to get started.\n' +
260
+ 'Run "aiwg status" for workspace health detail.\n',
261
+ };
262
+ }
263
+ for (const target of targets) {
264
+ await registerDeployedExtensions(registry, {
265
+ agentsPath: target.agentsPath,
266
+ skillsPath: target.skillsPath,
267
+ commandsPath: target.commandsPath,
268
+ provider: target.name,
269
+ cwd: ctx.cwd,
270
+ });
271
+ }
272
+ }
273
+ catch (error) {
274
+ // If registry population fails, fall back to legacy script
275
+ const frameworkRoot = await getFrameworkRoot();
276
+ const runner = createScriptRunner(frameworkRoot);
277
+ return runner.run("tools/plugin/plugin-status-cli.mjs", ctx.args, {
278
+ cwd: ctx.cwd,
279
+ });
280
+ }
281
+ }
282
+ // Determine what to show
283
+ const showAgents = !filterType || filterType === 'agents' || filterType === 'all';
284
+ const showSkills = !filterType || filterType === 'skills' || filterType === 'all';
285
+ const showCommands = !filterType || filterType === 'commands' || filterType === 'all';
286
+ let output = '';
287
+ if (showAgents) {
288
+ const agents = registry.getByType('agent');
289
+ output += `\nAgents (${agents.length}):\n`;
290
+ output += '─'.repeat(60) + '\n';
291
+ if (agents.length === 0) {
292
+ output += ' No agents deployed\n';
293
+ }
294
+ else {
295
+ for (const agent of agents.slice(0, 20)) { // Limit to 20 for readability
296
+ output += ` ${agent.name}\n`;
297
+ output += ` ID: ${agent.id}\n`;
298
+ output += ` Description: ${agent.description.slice(0, 80)}${agent.description.length > 80 ? '...' : ''}\n`;
299
+ if (agent.installation) {
300
+ output += ` Path: ${agent.installation.installedPath}\n`;
301
+ }
302
+ output += '\n';
303
+ }
304
+ if (agents.length > 20) {
305
+ output += ` ... and ${agents.length - 20} more\n`;
306
+ }
307
+ }
308
+ }
309
+ if (showSkills) {
310
+ const skills = registry.getByType('skill');
311
+ output += `\nSkills (${skills.length}):\n`;
312
+ output += '─'.repeat(60) + '\n';
313
+ if (skills.length === 0) {
314
+ output += ' No skills deployed\n';
315
+ }
316
+ else {
317
+ for (const skill of skills.slice(0, 20)) {
318
+ output += ` ${skill.name}\n`;
319
+ output += ` ID: ${skill.id}\n`;
320
+ output += ` Description: ${skill.description.slice(0, 80)}${skill.description.length > 80 ? '...' : ''}\n`;
321
+ if (skill.installation) {
322
+ output += ` Path: ${skill.installation.installedPath}\n`;
323
+ }
324
+ output += '\n';
325
+ }
326
+ if (skills.length > 20) {
327
+ output += ` ... and ${skills.length - 20} more\n`;
328
+ }
329
+ }
330
+ }
331
+ if (showCommands) {
332
+ const commands = registry.getByType('command');
333
+ output += `\nCommands (${commands.length}):\n`;
334
+ output += '─'.repeat(60) + '\n';
335
+ if (commands.length === 0) {
336
+ output += ' No commands registered\n';
337
+ }
338
+ else {
339
+ for (const command of commands.slice(0, 20)) {
340
+ output += ` ${command.name}\n`;
341
+ output += ` ID: ${command.id}\n`;
342
+ output += ` Description: ${command.description.slice(0, 80)}${command.description.length > 80 ? '...' : ''}\n`;
343
+ output += '\n';
344
+ }
345
+ if (commands.length > 20) {
346
+ output += ` ... and ${commands.length - 20} more\n`;
347
+ }
348
+ }
349
+ }
350
+ // Project-local bundles (#1034) — surfaced as a separate section with
351
+ // [project] source label
352
+ const totalProjectLocal = projectLocal.counts.extension +
353
+ projectLocal.counts.addon +
354
+ projectLocal.counts.framework +
355
+ projectLocal.counts.plugin;
356
+ if (totalProjectLocal > 0 || projectLocal.errors.length > 0) {
357
+ output += `\nProject-local bundles (${totalProjectLocal}):\n`;
358
+ output += '─'.repeat(60) + '\n';
359
+ for (const b of projectLocal.bundles) {
360
+ output += ` ${b.id} [project] [${b.type}]\n`;
361
+ output += ` Path: ${b.localPath}\n`;
362
+ output += ` Description: ${b.manifest.description.slice(0, 80)}${b.manifest.description.length > 80 ? '...' : ''}\n\n`;
363
+ }
364
+ if (projectLocal.errors.length > 0) {
365
+ output += ` ⚠ ${projectLocal.errors.length} validation error(s) — see "aiwg doctor" for details\n`;
366
+ }
367
+ }
368
+ // Summary
369
+ const totalAgents = registry.getByType('agent').length;
370
+ const totalSkills = registry.getByType('skill').length;
371
+ const totalCommands = registry.getByType('command').length;
372
+ const total = totalAgents + totalSkills + totalCommands;
373
+ output += '\n' + '═'.repeat(60) + '\n';
374
+ output += `Total: ${total} extensions (${totalAgents} agents, ${totalSkills} skills, ${totalCommands} commands)`;
375
+ if (totalProjectLocal > 0) {
376
+ output += ` + ${totalProjectLocal} project-local`;
377
+ }
378
+ output += '\n';
379
+ if (total === 0 && totalProjectLocal === 0) {
380
+ output += '\nTip: Deploy a framework with "aiwg use sdlc" to get started\n';
381
+ }
382
+ else if (totalCommands === 0 && totalAgents > 0) {
383
+ // Skill-only model (Claude Code default): commands aren't deployed as
384
+ // slash commands; capabilities reach the agent via natural language or
385
+ // `aiwg discover` (#1228). Surface this so 0 commands doesn't look like
386
+ // a deploy failure.
387
+ output += '\nNote: 0 commands is expected on Claude Code — capabilities are reached via natural language or `aiwg discover "<phrase>"`.\n';
388
+ }
389
+ if (deployedOnly) {
390
+ const projectDir = getProjectDir(ctx, ctx.args);
391
+ const plan = await readWorkspaceSignalPlan(projectDir);
392
+ if (plan) {
393
+ output += formatDeployedWorkspaceSignalPlan(plan);
394
+ }
395
+ else {
396
+ output += '\nWorkspace skill filter: no recorded plan found.\n';
397
+ output += 'Run `aiwg use --profile <name>` to record workspace-aware include/exclude reasons.\n';
398
+ }
399
+ }
400
+ return {
401
+ exitCode: 0,
402
+ message: output,
403
+ };
404
+ },
405
+ };
406
+ /**
407
+ * Format `aiwg list --project-local` output: only project-local bundles, with
408
+ * per-type breakdown and any validation errors surfaced. (#1034)
409
+ */
410
+ function formatProjectLocalOnly(result) {
411
+ let output = '';
412
+ const total = result.counts.extension +
413
+ result.counts.addon +
414
+ result.counts.framework +
415
+ result.counts.plugin;
416
+ if (total === 0 && result.errors.length === 0) {
417
+ output += '\nNo project-local bundles found.\n';
418
+ output += '\nTip: place a manifest.json under the configured AIWG artifact root at {extensions,addons,frameworks,plugins,providers}/<name>/ to author a project-local artifact.\n';
419
+ return { exitCode: 0, message: output };
420
+ }
421
+ output += `\nProject-local bundles (${total}):\n`;
422
+ output += '─'.repeat(60) + '\n';
423
+ for (const b of result.bundles) {
424
+ output += ` ${b.id} [project] [${b.type}] v${b.manifest.version}\n`;
425
+ output += ` Path: ${b.localPath}\n`;
426
+ output += ` Description: ${b.manifest.description.slice(0, 80)}${b.manifest.description.length > 80 ? '...' : ''}\n\n`;
427
+ }
428
+ if (result.errors.length > 0) {
429
+ output += '\nValidation errors:\n';
430
+ output += '─'.repeat(60) + '\n';
431
+ for (const e of result.errors.slice(0, 10)) {
432
+ output += ` [${e.severity}] ${e.path}\n`;
433
+ output += ` ${e.field}: expected ${e.expected}, got ${e.actual}\n`;
434
+ if (e.hint)
435
+ output += ` hint: ${e.hint}\n`;
436
+ }
437
+ if (result.errors.length > 10) {
438
+ output += ` ... and ${result.errors.length - 10} more\n`;
439
+ }
440
+ }
441
+ output += '\n' + '═'.repeat(60) + '\n';
442
+ output += `Counts by type: extension=${result.counts.extension} addon=${result.counts.addon} framework=${result.counts.framework} plugin=${result.counts.plugin}\n`;
443
+ return { exitCode: 0, message: output };
444
+ }
445
+ /**
446
+ * Format `aiwg list --shadows` output: only artifacts that currently shadow
447
+ * an upstream artifact, with safety-critical and override status. (#1036)
448
+ */
449
+ async function formatShadowsOnly(projectLocal) {
450
+ let output = '';
451
+ if (projectLocal.bundles.length === 0) {
452
+ output += '\nNo project-local bundles — no shadows possible.\n';
453
+ return { exitCode: 0, message: output };
454
+ }
455
+ const { getFrameworkRoot: gfr } = await import('../../channel/manager.mjs');
456
+ const frameworkRoot = await gfr();
457
+ const upstream = await buildUpstreamRegistry({ frameworkRoot });
458
+ const result = await resolveShadows(projectLocal.bundles, upstream);
459
+ if (result.shadows.length === 0) {
460
+ output += '\nNo active shadows.\n';
461
+ output += '\nProject-local bundles deploy alongside upstream without collision.\n';
462
+ return { exitCode: 0, message: output };
463
+ }
464
+ output += `\nActive shadows (${result.shadows.length}):\n`;
465
+ output += '─'.repeat(60) + '\n';
466
+ for (const r of result.shadows) {
467
+ const sc = r.upstream?.safetyCritical ? ' [SAFETY-CRITICAL]' : '';
468
+ output += ` ${r.artifactType}/${r.artifactId}${sc}\n`;
469
+ output += ` Bundle: ${r.bundleId} (${r.bundleLocalPath})\n`;
470
+ output += ` Project-local: ${r.artifactSourcePath}\n`;
471
+ if (r.upstream) {
472
+ output += ` Shadows ${r.upstream.source}: ${r.upstream.sourcePath}\n`;
473
+ }
474
+ output += ` Verdict: ${r.verdict}\n\n`;
475
+ }
476
+ if (result.blockedBundleIds.size > 0) {
477
+ output += `\n⚠ ${result.blockedBundleIds.size} bundle(s) blocked from deployment due to unsafe shadows.\n`;
478
+ }
479
+ return { exitCode: 0, message: output };
480
+ }
481
+ /**
482
+ * #1156 Phase 1 — `--scope user` detection. Mirrors `detectScope()` from
483
+ * scope-resolver but tolerates the absence of the flag (no throw on absent).
484
+ * Returns true when args contain `--scope user`.
485
+ */
486
+ function isScopeUser(args) {
487
+ const idx = args.findIndex((a) => a === '--scope');
488
+ if (idx === -1)
489
+ return false;
490
+ return args[idx + 1] === 'user';
491
+ }
492
+ /**
493
+ * #1156 Phase 1 — Format the per-user registry (~/.aiwg/installed.json) as a
494
+ * human-readable inventory. Used by `aiwg list --scope user` / `aiwg list
495
+ * --user`. Independent of any project — works from any cwd.
496
+ */
497
+ async function formatUserScopeRegistry() {
498
+ const { readUserRegistry, userRegistryPath } = await import('../../config/user-registry.js');
499
+ const registry = await readUserRegistry();
500
+ const frameworks = Object.entries(registry.installed);
501
+ let output = '';
502
+ if (frameworks.length === 0) {
503
+ output += '\nNo frameworks deployed at user scope.\n';
504
+ output += `\nRegistry path: ${userRegistryPath()}\n`;
505
+ output += '\nTip: run `aiwg use <framework> --provider <p> --scope user` to install at user scope.\n';
506
+ return { exitCode: 0, message: output };
507
+ }
508
+ output += `\nUser-scope deployments (${frameworks.length}):\n`;
509
+ output += '─'.repeat(60) + '\n';
510
+ for (const [name, entry] of frameworks) {
511
+ output += ` ${name} v${entry.version} [${entry.source}]\n`;
512
+ output += ` Installed: ${entry.installedAt}\n`;
513
+ const providers = Object.entries(entry.deployedTo);
514
+ for (const [provider, counts] of providers) {
515
+ const parts = [];
516
+ if (counts.agents > 0)
517
+ parts.push(`${counts.agents} agents`);
518
+ if (counts.commands > 0)
519
+ parts.push(`${counts.commands} commands`);
520
+ if (counts.skills > 0)
521
+ parts.push(`${counts.skills} skills`);
522
+ if (counts.rules > 0)
523
+ parts.push(`${counts.rules} rules`);
524
+ output += ` ${provider}: ${parts.length > 0 ? parts.join(', ') : '(empty)'}\n`;
525
+ }
526
+ output += '\n';
527
+ }
528
+ output += '═'.repeat(60) + '\n';
529
+ output += `Registry path: ${userRegistryPath()}\n`;
530
+ return { exitCode: 0, message: output };
531
+ }
532
+ /**
533
+ * #1156 Phase 1 — Revert a user-scope mirror.
534
+ *
535
+ * Reads `~/.aiwg/installed.json`, looks up the framework + provider entry,
536
+ * and deletes the specific artifact entries this deploy created (recorded
537
+ * by the mirror in Cycle 3). With `--dry-run`, lists what would be removed
538
+ * without touching the filesystem.
539
+ *
540
+ * Back-compat: registry entries written before Cycle 3 lack the `entries`
541
+ * snapshot. For those, the handler falls back to the conservative
542
+ * registry-only revert and tells the operator to clean up manually.
543
+ *
544
+ * Multi-provider: if `--provider` is omitted, all of the framework's
545
+ * provider deployments are reverted in one pass.
546
+ */
547
+ async function removeUserScopeDeploy(args) {
548
+ const positional = firstRemovePositional(args);
549
+ if (!positional) {
550
+ return {
551
+ exitCode: 1,
552
+ message: 'Error: framework name required\n\nUsage: aiwg remove <framework> --scope user [--provider <p>] [--dry-run]',
553
+ };
554
+ }
555
+ const dryRun = args.includes('--dry-run');
556
+ const providerParse = parseRemoveProvider(args);
557
+ if (providerParse.error) {
558
+ return {
559
+ exitCode: 1,
560
+ message: `${providerParse.error}\n\nUsage: aiwg remove <framework> --scope user [--provider <p>] [--dry-run]`,
561
+ };
562
+ }
563
+ const provider = providerParse.provider;
564
+ const { readUserRegistry, removeUserDeploy } = await import('../../config/user-registry.js');
565
+ const { USER_SCOPE_PATHS } = await import('../scope-resolver.js');
566
+ const registry = await readUserRegistry();
567
+ const entry = registry.installed[positional];
568
+ if (!entry) {
569
+ return {
570
+ exitCode: 1,
571
+ message: `Error: framework '${positional}' is not deployed at user scope.\n\nRun 'aiwg list --scope user' to see installed frameworks.`,
572
+ };
573
+ }
574
+ const providersToRevert = provider ? [provider] : Object.keys(entry.deployedTo);
575
+ if (provider && !entry.deployedTo[provider]) {
576
+ return {
577
+ exitCode: 1,
578
+ message: `Error: framework '${positional}' is not deployed at user scope for provider '${provider}'.\n\nDeployed providers: ${Object.keys(entry.deployedTo).join(', ') || '(none)'}`,
579
+ };
580
+ }
581
+ const fs = await import('node:fs/promises');
582
+ const path = await import('node:path');
583
+ const linesOut = [];
584
+ if (dryRun)
585
+ linesOut.push(`[dry-run] Plan for user-scope remove of '${positional}':`);
586
+ else
587
+ linesOut.push(`Removing user-scope mirror of '${positional}':`);
588
+ let totalDeleted = 0;
589
+ let conservativeFallbackUsed = false;
590
+ for (const p of providersToRevert) {
591
+ const userPaths = USER_SCOPE_PATHS[p];
592
+ if (!userPaths) {
593
+ linesOut.push(` ⚠ ${p}: no user-scope paths registered — skipping (manual cleanup may be needed)`);
594
+ continue;
595
+ }
596
+ // Cast through unknown to access the optional `entries` snapshot recorded
597
+ // by the Cycle 3 mirror. Older registry entries won't have it.
598
+ const providerEntry = entry.deployedTo[p];
599
+ const recorded = providerEntry?.entries;
600
+ if (!recorded) {
601
+ // Pre-Cycle-3 entry: surface the deploy paths and let the operator
602
+ // clean them up manually. We can't safely auto-delete because the dirs
603
+ // are shared with other frameworks.
604
+ conservativeFallbackUsed = true;
605
+ const existingDirs = [
606
+ { type: 'agents', path: userPaths.agents },
607
+ { type: 'commands', path: userPaths.commands },
608
+ { type: 'skills', path: userPaths.skills },
609
+ { type: 'rules', path: userPaths.rules },
610
+ { type: 'behaviors', path: userPaths.behaviors },
611
+ ].filter(t => t.path);
612
+ linesOut.push(` ⚠ ${p}: registry entry has no per-artifact manifest (deployed before Cycle 3). Manual cleanup of these dirs may be needed:`);
613
+ for (const t of existingDirs) {
614
+ const stat = await fs.stat(t.path).catch(() => null);
615
+ if (stat && stat.isDirectory()) {
616
+ linesOut.push(` - ${t.path}`);
617
+ }
618
+ }
619
+ continue;
620
+ }
621
+ // Precise revert — walk the recorded entry names and delete each one
622
+ // from its corresponding user-scope dir.
623
+ const sets = [
624
+ ['agents', userPaths.agents, recorded.agents],
625
+ ['commands', userPaths.commands, recorded.commands],
626
+ ['skills', userPaths.skills, recorded.skills],
627
+ ['rules', userPaths.rules, recorded.rules],
628
+ ['behaviors', userPaths.behaviors, recorded.behaviors],
629
+ ];
630
+ for (const [type, dir, names] of sets) {
631
+ if (!dir || !names || names.length === 0)
632
+ continue;
633
+ let deletedHere = 0;
634
+ for (const name of names) {
635
+ const target = path.join(dir, name);
636
+ if (dryRun) {
637
+ linesOut.push(` · ${p} ${type}: ${target}`);
638
+ deletedHere++;
639
+ continue;
640
+ }
641
+ try {
642
+ await fs.rm(target, { recursive: true, force: true });
643
+ deletedHere++;
644
+ totalDeleted++;
645
+ }
646
+ catch (err) {
647
+ linesOut.push(` ⚠ ${p} ${type}: failed to remove ${target}: ${err instanceof Error ? err.message : String(err)}`);
648
+ }
649
+ }
650
+ if (!dryRun && deletedHere > 0) {
651
+ linesOut.push(` ✓ ${p} ${type}: removed ${deletedHere} entry/entries from ${dir}`);
652
+ }
653
+ else if (dryRun) {
654
+ linesOut.push(` (${deletedHere} ${type} would be removed from ${dir})`);
655
+ }
656
+ }
657
+ }
658
+ if (!dryRun) {
659
+ if (provider) {
660
+ await removeUserDeploy({ framework: positional, provider });
661
+ }
662
+ else {
663
+ await removeUserDeploy({ framework: positional });
664
+ }
665
+ linesOut.push('');
666
+ if (conservativeFallbackUsed) {
667
+ linesOut.push('Registry updated. Some providers had no per-artifact manifest (pre-Cycle-3 deploys); inspect the dirs listed above and clean up manually if needed.');
668
+ }
669
+ else {
670
+ linesOut.push(`Registry updated. ${totalDeleted} artifact entry/entries removed.`);
671
+ }
672
+ }
673
+ return {
674
+ exitCode: 0,
675
+ message: linesOut.join('\n') + '\n',
676
+ };
677
+ }
678
+ /**
679
+ * Remove framework handler
680
+ *
681
+ * Delegates to tools/plugin/plugin-uninstaller-cli.mjs
682
+ */
683
+ export const removeHandler = {
684
+ id: "remove",
685
+ name: "Remove Framework",
686
+ description: "Remove installed framework, plugin, or project-local bundle",
687
+ category: "framework",
688
+ aliases: [],
689
+ async execute(ctx) {
690
+ // #1156 Phase 1 — `--scope user` / `--user`: revert the user-scope mirror
691
+ // for the given framework. Independent of any project; reads the per-user
692
+ // registry at ~/.aiwg/installed.json to find what was deployed, deletes
693
+ // the mirrored artifacts under the provider's USER_SCOPE_PATHS, and
694
+ // updates the registry.
695
+ if (ctx.args.includes('--user') || isScopeUser(ctx.args)) {
696
+ return await removeUserScopeDeploy(ctx.args);
697
+ }
698
+ // #1037 — Project-local-aware remove. If the first positional arg matches
699
+ // a project-local entry in `installed`, route to the new handler.
700
+ // Otherwise fall through to the existing plugin-uninstaller flow.
701
+ const positionalArg = firstRemovePositional(ctx.args);
702
+ const providerParse = parseRemoveProvider(ctx.args);
703
+ if (providerParse.error) {
704
+ return {
705
+ exitCode: 1,
706
+ message: `${providerParse.error}\n\nUsage: aiwg remove <id> [--force] [--dry-run] [--provider <p>] [--keep-registry]`,
707
+ };
708
+ }
709
+ if (!positionalArg) {
710
+ return {
711
+ exitCode: 1,
712
+ message: 'Error: framework or bundle id required\n\nUsage: aiwg remove <id> [--force] [--dry-run] [--provider <p>] [--keep-registry]',
713
+ };
714
+ }
715
+ if (positionalArg) {
716
+ try {
717
+ const { readAiwgConfig, writeAiwgConfig, getProjectDir } = await import('../../config/aiwg-config.js');
718
+ const { removeProjectLocalBundle } = await import('../../extensions/project-local-remove.js');
719
+ const projectDir = getProjectDir({ cwd: ctx.cwd }, ctx.args);
720
+ const config = await readAiwgConfig(projectDir);
721
+ const entry = config?.installed?.[positionalArg];
722
+ if (config && entry?.source === 'project-local') {
723
+ const force = ctx.args.includes('--force');
724
+ const dryRun = ctx.args.includes('--dry-run');
725
+ const keepRegistry = ctx.args.includes('--keep-registry');
726
+ const provider = providerParse.provider;
727
+ const result = await removeProjectLocalBundle(config, projectDir, positionalArg, { force, dryRun, keepRegistry, provider });
728
+ // Print outcome summary
729
+ const lines = [];
730
+ if (dryRun)
731
+ lines.push(`[dry-run] Plan for project-local '${positionalArg}':`);
732
+ for (const o of result.outcomes) {
733
+ const marker = o.reverted ? '✓' : '⚠';
734
+ lines.push(` ${marker} ${o.provider} :: ${o.artifactPath} [${o.case}] ${o.message}`);
735
+ }
736
+ if (result.revertedProviders.length > 0) {
737
+ lines.push(`Fully reverted: ${result.revertedProviders.join(', ')}`);
738
+ }
739
+ if (result.partialProviders.length > 0) {
740
+ lines.push(`Partial (registry preserved): ${result.partialProviders.join(', ')}`);
741
+ }
742
+ if (lines.length > 0)
743
+ console.log(lines.join('\n'));
744
+ if (!dryRun) {
745
+ await writeAiwgConfig(projectDir, config);
746
+ }
747
+ // Note: source under .aiwg/<type>/<name>/ is intentionally NOT
748
+ // deleted (load-bearing invariant from #1048 design).
749
+ return {
750
+ exitCode: result.partialProviders.length > 0 ? 1 : 0,
751
+ message: result.partialProviders.length > 0
752
+ ? `Some artifacts skipped (see above). Use --force to override mutation refusal.`
753
+ : '',
754
+ };
755
+ }
756
+ }
757
+ catch (err) {
758
+ // Fall through to upstream remove on any error in the project-local path
759
+ const msg = err instanceof Error ? err.message : String(err);
760
+ process.stderr.write(`project-local remove pre-check failed (falling through): ${msg}\n`);
761
+ }
762
+ }
763
+ if (providerParse.provider) {
764
+ return {
765
+ exitCode: 1,
766
+ message: `Error: --provider is only supported for project-local or user-scope remove. '${positionalArg}' is not a project-local bundle.\n\nUse 'aiwg remove ${positionalArg}' without --provider, or 'aiwg remove ${positionalArg} --scope user --provider ${providerParse.provider}' for a user-scope mirror. Refs #1610.`,
767
+ };
768
+ }
769
+ const frameworkRoot = await getFrameworkRoot();
770
+ const runner = createScriptRunner(frameworkRoot);
771
+ return runner.run("tools/plugin/plugin-uninstaller-cli.mjs", ctx.args, {
772
+ cwd: ctx.cwd,
773
+ });
774
+ },
775
+ };
776
+ /**
777
+ * Promote handler — graduate a project-local bundle to upstream or to a
778
+ * private corpus path. Implements the design at
779
+ * @.aiwg/architecture/design-doctor-log-promote.md (#1049).
780
+ *
781
+ * Usage:
782
+ * aiwg promote <name> # default: --to upstream
783
+ * aiwg promote <name> --to upstream
784
+ * aiwg promote <name> --to corpus <path>
785
+ * aiwg promote <name> --dry-run
786
+ * aiwg promote <name> --cleanup
787
+ * aiwg promote <name> --force
788
+ *
789
+ * @implements #1037
790
+ */
791
+ export const promoteHandler = {
792
+ id: 'promote',
793
+ name: 'Promote',
794
+ description: 'Graduate a project-local bundle to upstream or a corpus path',
795
+ category: 'framework',
796
+ aliases: ['-promote', '--promote', 'graduate'],
797
+ async execute(ctx) {
798
+ const args = ctx.args;
799
+ const positional = args.find(a => !a.startsWith('-'));
800
+ if (!positional) {
801
+ return { exitCode: 1, message: 'Error: bundle name required\n\nUsage: aiwg promote <name> [--to upstream|corpus <path>] [--dry-run] [--cleanup] [--force]' };
802
+ }
803
+ const toIdx = args.findIndex(a => a === '--to');
804
+ const toValue = toIdx >= 0 ? args[toIdx + 1] : 'upstream';
805
+ let corpusPath;
806
+ if (toValue === 'corpus') {
807
+ // The argument *after* "corpus" is the path
808
+ corpusPath = args[toIdx + 2];
809
+ if (!corpusPath || corpusPath.startsWith('-')) {
810
+ return { exitCode: 1, message: 'Error: --to corpus requires a path argument' };
811
+ }
812
+ }
813
+ else if (toValue !== 'upstream') {
814
+ return { exitCode: 1, message: `Error: --to must be 'upstream' or 'corpus' (got '${toValue}')` };
815
+ }
816
+ const dryRun = args.includes('--dry-run');
817
+ const cleanup = args.includes('--cleanup');
818
+ const force = args.includes('--force');
819
+ try {
820
+ const { readAiwgConfig, writeAiwgConfig, getProjectDir } = await import('../../config/aiwg-config.js');
821
+ const { promoteProjectLocalBundle } = await import('../../extensions/project-local-promote.js');
822
+ const projectDir = getProjectDir({ cwd: ctx.cwd }, args);
823
+ const config = await readAiwgConfig(projectDir);
824
+ if (!config) {
825
+ return { exitCode: 1, message: 'Error: no .aiwg/aiwg.config found — run `aiwg init` first' };
826
+ }
827
+ const fr = await getFrameworkRoot();
828
+ const result = await promoteProjectLocalBundle(config, projectDir, positional, {
829
+ to: toValue,
830
+ corpusPath,
831
+ dryRun,
832
+ cleanup,
833
+ force,
834
+ frameworkRoot: fr,
835
+ });
836
+ if (!result.ok) {
837
+ return { exitCode: 1, message: `Error: ${result.message ?? result.failureReason}` };
838
+ }
839
+ if (dryRun && result.plan) {
840
+ console.log('[dry-run] Would copy:');
841
+ console.log(` ${result.plan.source} → ${result.plan.destination}`);
842
+ console.log(` Files: ${result.plan.files.length}, ${result.plan.totalBytes} bytes`);
843
+ console.log(' Pre-flight: ✓ manifest valid ✓ destination clean');
844
+ console.log(' Hash verification: skipped (dry-run)');
845
+ console.log(` Registry update: source: project-local → ${toValue === 'upstream' ? 'bundled' : 'corpus'}`);
846
+ console.log(` Cleanup: ${cleanup ? 'will remove .aiwg source after copy' : 'skipped (--cleanup not set)'}`);
847
+ return { exitCode: 0 };
848
+ }
849
+ await writeAiwgConfig(projectDir, config);
850
+ console.log(`✓ Promoted '${positional}' → ${result.plan?.destination}`);
851
+ if (cleanup) {
852
+ console.log(' Source removed from .aiwg/');
853
+ }
854
+ return { exitCode: 0 };
855
+ }
856
+ catch (err) {
857
+ const msg = err instanceof Error ? err.message : String(err);
858
+ return { exitCode: 1, message: `promote failed: ${msg}` };
859
+ }
860
+ },
861
+ };
862
+ /**
863
+ * New bundle handler — scaffolds a project-local bundle under the configured
864
+ * AIWG artifact root with a valid manifest, starter artifact, and a
865
+ * README that includes the identical-form portability reminder.
866
+ *
867
+ * Usage:
868
+ * aiwg new-bundle <name> # default: --type extension --starter skill
869
+ * aiwg new-bundle <name> --type addon
870
+ * aiwg new-bundle <name> --type framework --starter minimal
871
+ * aiwg new-bundle <name> --starter rule --description "Custom rule"
872
+ *
873
+ * @implements #1050
874
+ */
875
+ export const newBundleHandler = {
876
+ id: 'new-bundle',
877
+ name: 'New Bundle',
878
+ description: 'Scaffold a project-local bundle under the configured AIWG artifact root',
879
+ category: 'scaffolding',
880
+ aliases: ['new-extension', 'new-addon', 'new-framework', 'new-plugin', 'new-provider'],
881
+ async execute(ctx) {
882
+ const args = ctx.args;
883
+ const positional = args.find(a => !a.startsWith('-'));
884
+ if (!positional) {
885
+ return {
886
+ exitCode: 1,
887
+ message: 'Error: bundle name required\n\nUsage: aiwg new-bundle <name> [--type extension|addon|framework|plugin|provider] [--starter skill|rule|agent|minimal] [--description "..."]',
888
+ };
889
+ }
890
+ // Type can be inferred from the alias used to invoke (new-extension etc.)
891
+ const aliasMap = {
892
+ 'new-extension': 'extension',
893
+ 'new-addon': 'addon',
894
+ 'new-framework': 'framework',
895
+ 'new-plugin': 'plugin',
896
+ 'new-provider': 'provider',
897
+ };
898
+ const invoked = ctx.rawArgs[0] ?? '';
899
+ const aliasType = aliasMap[invoked];
900
+ const typeIdx = args.findIndex(a => a === '--type');
901
+ const typeFlag = typeIdx >= 0 ? args[typeIdx + 1] : undefined;
902
+ const type = (typeFlag ?? aliasType ?? 'extension');
903
+ if (!['extension', 'addon', 'framework', 'plugin', 'provider'].includes(type)) {
904
+ return { exitCode: 1, message: `Error: --type must be one of extension|addon|framework|plugin|provider (got '${type}')` };
905
+ }
906
+ const starterIdx = args.findIndex(a => a === '--starter');
907
+ const starter = starterIdx >= 0 ? args[starterIdx + 1] : undefined;
908
+ if (starter && !['skill', 'rule', 'agent', 'minimal'].includes(starter)) {
909
+ return { exitCode: 1, message: `Error: --starter must be one of skill|rule|agent|minimal (got '${starter}')` };
910
+ }
911
+ const descIdx = args.findIndex(a => a === '--description');
912
+ const description = descIdx >= 0 ? args[descIdx + 1] : undefined;
913
+ const dryRun = args.includes('--dry-run');
914
+ const { scaffoldProjectLocalBundle } = await import('../../extensions/project-local-scaffold.js');
915
+ try {
916
+ const result = await scaffoldProjectLocalBundle({
917
+ type,
918
+ name: positional,
919
+ description,
920
+ starter,
921
+ projectDir: ctx.cwd,
922
+ dryRun,
923
+ });
924
+ if (result.alreadyExists) {
925
+ return {
926
+ exitCode: 1,
927
+ message: `Refused: bundle already exists at ${result.bundlePath}. Remove it first or pick a different name.`,
928
+ };
929
+ }
930
+ if (dryRun) {
931
+ console.log(`[DRY RUN] Would scaffold project-local ${type} '${positional}' at ${result.bundlePath}`);
932
+ console.log(' Files that would be created:');
933
+ for (const f of result.filesCreated)
934
+ console.log(` + ${f}`);
935
+ console.log('');
936
+ console.log('No files written. Re-run without --dry-run to create.');
937
+ return { exitCode: 0 };
938
+ }
939
+ console.log(`✓ Scaffolded project-local ${type} '${positional}' at ${result.bundlePath}`);
940
+ console.log(' Files created:');
941
+ for (const f of result.filesCreated)
942
+ console.log(` + ${f}`);
943
+ // #1085 — when the project blanket-ignores .aiwg/, the new bundle's
944
+ // source would be silently dropped from version control. Detect and
945
+ // self-heal idempotently.
946
+ try {
947
+ const { appendAiwgSourceTrackBlock } = await import('../../extensions/project-local-gitignore.js');
948
+ const ig = await appendAiwgSourceTrackBlock(ctx.cwd);
949
+ if (ig.added) {
950
+ console.log('');
951
+ console.log(` → ${ig.reason}`);
952
+ console.log(' .aiwg/{addons,extensions,frameworks,plugins,providers}/ now tracked by git.');
953
+ console.log(' Generated state under .aiwg/ (working/, ralph/, research/, ...) stays ignored.');
954
+ }
955
+ }
956
+ catch {
957
+ // .gitignore management is best-effort; don't fail the scaffold
958
+ }
959
+ // #1235 / #1758 — auto-rebuild the project graph and refresh the
960
+ // Fortemi Core static cache so the new bundle is immediately
961
+ // discoverable via top-level `aiwg discover` / `aiwg show`.
962
+ // Best-effort: don't fail the scaffold if indexing hiccups.
963
+ let indexedOk = false;
964
+ let fortemiSyncedOk = false;
965
+ try {
966
+ const { buildIndex } = await import('../../artifacts/index-builder.js');
967
+ await buildIndex(ctx.cwd, { graph: 'project', force: false, explicit: true });
968
+ indexedOk = true;
969
+ const { syncFortemiCoreIndex } = await import('../../artifacts/fortemi-core-sync.js');
970
+ syncFortemiCoreIndex(ctx.cwd, { graph: 'project' });
971
+ fortemiSyncedOk = true;
972
+ }
973
+ catch {
974
+ // ignore — surface via next-steps hint instead
975
+ }
976
+ console.log('');
977
+ console.log('Next steps:');
978
+ console.log(` 1. Edit manifest.json (description, version, keywords)`);
979
+ console.log(` 2. Customize the starter artifact under ${result.bundlePath}/`);
980
+ if (indexedOk && fortemiSyncedOk) {
981
+ console.log(` 3. Discoverable now via: aiwg discover "${positional}"`);
982
+ }
983
+ else if (indexedOk) {
984
+ console.log(` 3. Sync project search cache: aiwg index sync --graph project`);
985
+ console.log(` then: aiwg discover "${positional}"`);
986
+ }
987
+ else {
988
+ console.log(` 3. Rebuild project index: aiwg index build --graph project`);
989
+ console.log(` then sync search cache: aiwg index sync --graph project`);
990
+ console.log(` then: aiwg discover "${positional}"`);
991
+ }
992
+ console.log(` 4. Deploy: aiwg use ${positional}`);
993
+ console.log(` 5. Inspect: aiwg doctor --project-local`);
994
+ console.log(` 6. When mature, promote: aiwg promote ${positional}`);
995
+ return { exitCode: 0 };
996
+ }
997
+ catch (err) {
998
+ const msg = err instanceof Error ? err.message : String(err);
999
+ return { exitCode: 1, message: `Error: ${msg}` };
1000
+ }
1001
+ },
1002
+ };
1003
+ /**
1004
+ * New project handler
1005
+ *
1006
+ * Delegates to tools/install/new-project.mjs
1007
+ */
1008
+ export const newProjectHandler = {
1009
+ id: "new",
1010
+ name: "New Project",
1011
+ description: "Scaffold a new project with AIWG",
1012
+ category: "project",
1013
+ aliases: ["-new", "--new"],
1014
+ async execute(ctx) {
1015
+ const frameworkRoot = await getFrameworkRoot();
1016
+ const runner = createScriptRunner(frameworkRoot);
1017
+ const result = await runner.run("tools/install/new-project.mjs", ctx.args, {
1018
+ cwd: ctx.cwd,
1019
+ });
1020
+ if (result.exitCode === 0) {
1021
+ // The real scaffolder always runs in an existing target directory. Keep
1022
+ // mocked/script-runner-only calls side-effect free when their synthetic
1023
+ // cwd does not exist.
1024
+ const { access } = await import('node:fs/promises');
1025
+ const { constants } = await import('node:fs');
1026
+ try {
1027
+ await access(ctx.cwd, constants.W_OK);
1028
+ const { ensureWorkspaceContext } = await import('../../smiths/context-pipeline/workspace-context.js');
1029
+ await ensureWorkspaceContext(ctx.cwd);
1030
+ }
1031
+ catch (error) {
1032
+ if (!['ENOENT', 'EACCES'].includes(error.code ?? ''))
1033
+ throw error;
1034
+ }
1035
+ const { formatStarNudge } = await import("../../community/links.js");
1036
+ const { markNudgeShown, shouldShowNudge } = await import("../../community/nudge-policy.js");
1037
+ if (shouldShowNudge('intake')) {
1038
+ const nudge = formatStarNudge();
1039
+ if (nudge) {
1040
+ console.log('');
1041
+ console.log(nudge);
1042
+ markNudgeShown('intake');
1043
+ }
1044
+ }
1045
+ }
1046
+ return result;
1047
+ },
1048
+ };
1049
+ /**
1050
+ * Install plugin handler
1051
+ *
1052
+ * Delegates to tools/plugin/plugin-installer-cli.mjs
1053
+ */
1054
+ export const installPluginHandler = {
1055
+ id: "install-plugin",
1056
+ name: "Install Plugin",
1057
+ description: "Install a plugin from the registry",
1058
+ category: "plugin",
1059
+ aliases: ["-install-plugin", "--install-plugin"],
1060
+ async execute(ctx) {
1061
+ const frameworkRoot = await getFrameworkRoot();
1062
+ const runner = createScriptRunner(frameworkRoot);
1063
+ return runner.run("tools/plugin/plugin-installer-cli.mjs", ctx.args, {
1064
+ cwd: ctx.cwd,
1065
+ });
1066
+ },
1067
+ };
1068
+ /**
1069
+ * Uninstall plugin handler
1070
+ *
1071
+ * Delegates to tools/plugin/plugin-uninstaller-cli.mjs
1072
+ */
1073
+ export const uninstallPluginHandler = {
1074
+ id: "uninstall-plugin",
1075
+ name: "Uninstall Plugin",
1076
+ description: "Uninstall a plugin",
1077
+ category: "plugin",
1078
+ aliases: ["-uninstall-plugin", "--uninstall-plugin"],
1079
+ async execute(ctx) {
1080
+ const frameworkRoot = await getFrameworkRoot();
1081
+ const runner = createScriptRunner(frameworkRoot);
1082
+ return runner.run("tools/plugin/plugin-uninstaller-cli.mjs", ctx.args, {
1083
+ cwd: ctx.cwd,
1084
+ });
1085
+ },
1086
+ };
1087
+ /**
1088
+ * Plugin status handler
1089
+ *
1090
+ * Delegates to tools/plugin/plugin-status-cli.mjs
1091
+ */
1092
+ export const pluginStatusHandler = {
1093
+ id: "plugin-status",
1094
+ name: "Plugin Status",
1095
+ description: "Show plugin status and installation details",
1096
+ category: "plugin",
1097
+ aliases: ["-plugin-status", "--plugin-status"],
1098
+ async execute(ctx) {
1099
+ const frameworkRoot = await getFrameworkRoot();
1100
+ const runner = createScriptRunner(frameworkRoot);
1101
+ return runner.run("tools/plugin/plugin-status-cli.mjs", ctx.args, {
1102
+ cwd: ctx.cwd,
1103
+ });
1104
+ },
1105
+ };
1106
+ /**
1107
+ * Package plugin handler
1108
+ *
1109
+ * Delegates to tools/plugin/package-plugins.mjs
1110
+ */
1111
+ export const packagePluginHandler = {
1112
+ id: "package-plugin",
1113
+ name: "Package Plugin",
1114
+ description: "Package a plugin for distribution",
1115
+ category: "plugin",
1116
+ aliases: ["-package-plugin", "--package-plugin"],
1117
+ async execute(ctx) {
1118
+ const frameworkRoot = await getFrameworkRoot();
1119
+ const runner = createScriptRunner(frameworkRoot);
1120
+ return runner.run("tools/plugin/package-plugins.mjs", ctx.args, {
1121
+ cwd: ctx.cwd,
1122
+ });
1123
+ },
1124
+ };
1125
+ /**
1126
+ * Package all plugins handler
1127
+ *
1128
+ * Delegates to tools/plugin/package-plugins.mjs with --all flag
1129
+ */
1130
+ export const packageAllPluginsHandler = {
1131
+ id: "package-all-plugins",
1132
+ name: "Package All Plugins",
1133
+ description: "Package all plugins for distribution",
1134
+ category: "plugin",
1135
+ aliases: ["-package-all-plugins", "--package-all-plugins"],
1136
+ async execute(ctx) {
1137
+ const frameworkRoot = await getFrameworkRoot();
1138
+ const runner = createScriptRunner(frameworkRoot);
1139
+ return runner.run("tools/plugin/package-plugins.mjs", ["--all", ...ctx.args], {
1140
+ cwd: ctx.cwd,
1141
+ });
1142
+ },
1143
+ };
1144
+ /**
1145
+ * Artifact index command handler
1146
+ *
1147
+ * Dynamically imports and delegates to src/artifacts/cli.mjs.
1148
+ * Handles subcommands: build, query, deps, stats
1149
+ *
1150
+ * @implements #420
1151
+ */
1152
+ export const indexHandler = {
1153
+ id: "index",
1154
+ name: "Artifact Index",
1155
+ description: "Artifact index commands (build, query, deps, stats)",
1156
+ category: "index",
1157
+ aliases: [],
1158
+ async execute(ctx) {
1159
+ try {
1160
+ const { main } = await import("../../artifacts/cli.js");
1161
+ await main(ctx.args);
1162
+ return {
1163
+ exitCode: 0,
1164
+ };
1165
+ }
1166
+ catch (error) {
1167
+ const result = handlerResultFromError(error);
1168
+ return { ...result, message: `Index command failed: ${result.message}` };
1169
+ }
1170
+ },
1171
+ };
1172
+ /**
1173
+ * `aiwg corpus` — research-corpus tools (radar/freshness subsystem, #1498).
1174
+ * Delegates to the corpus-tools router, mirroring indexHandler.
1175
+ */
1176
+ export const corpusHandler = {
1177
+ id: "corpus",
1178
+ name: "Research Corpus Tools",
1179
+ description: "Research-corpus tools (radar-init, radar-status, radar-report)",
1180
+ category: "index",
1181
+ aliases: [],
1182
+ async execute(ctx) {
1183
+ try {
1184
+ const { corpusMain } = await import("../../artifacts/corpus-tools/cli.js");
1185
+ await corpusMain(ctx.args, ctx.cwd);
1186
+ return { exitCode: 0 };
1187
+ }
1188
+ catch (error) {
1189
+ const result = handlerResultFromError(error);
1190
+ return { ...result, message: `Corpus command failed: ${result.message}` };
1191
+ }
1192
+ },
1193
+ };
1194
+ /**
1195
+ * Discovery command handler — first-class top-level verb (#1212).
1196
+ *
1197
+ * Forwards to the same implementation as `aiwg index discover` but
1198
+ * exposes discovery as its own command so agents don't conflate it
1199
+ * with the project's general-purpose artifact graph indices.
1200
+ *
1201
+ * aiwg discover "<phrase>" [--limit N] [--type skill,agent,...] [--json]
1202
+ * [--resource-source local|web|auto] [--aiwg-version <exact-or-channel>] [--offline]
1203
+ */
1204
+ export const discoverHandler = {
1205
+ id: "discover",
1206
+ name: "Discover",
1207
+ description: "Find AIWG operational assets by capability — index-driven on-demand discovery",
1208
+ category: "index",
1209
+ aliases: [],
1210
+ async execute(ctx) {
1211
+ try {
1212
+ // Delegate to the same handler `aiwg index discover` uses, by
1213
+ // prepending the `discover` subcommand and reusing the artifacts
1214
+ // CLI router. This keeps a single implementation path.
1215
+ const { main } = await import("../../artifacts/cli.js");
1216
+ await main(["discover", ...ctx.args]);
1217
+ return { exitCode: 0 };
1218
+ }
1219
+ catch (error) {
1220
+ const result = handlerResultFromError(error);
1221
+ return { ...result, message: `Discover command failed: ${result.message}` };
1222
+ }
1223
+ },
1224
+ };
1225
+ /**
1226
+ * Features command handler — manage AIWG's optional runtime features (#1219).
1227
+ *
1228
+ * Subcommands: status / info / install / remove. Native feature installs use
1229
+ * a user-owned package root with explicit package-level script approval.
1230
+ */
1231
+ export const featuresHandler = {
1232
+ id: "features",
1233
+ name: "Features",
1234
+ description: "List, inspect, and install AIWG's optional runtime features",
1235
+ category: "maintenance",
1236
+ aliases: [],
1237
+ async execute(ctx) {
1238
+ try {
1239
+ const { main } = await import("../../features/cli.js");
1240
+ await main(ctx.args);
1241
+ return { exitCode: 0 };
1242
+ }
1243
+ catch (error) {
1244
+ const result = handlerResultFromError(error);
1245
+ return { ...result, message: `Features command failed: ${result.message}` };
1246
+ }
1247
+ },
1248
+ };
1249
+ /**
1250
+ * Show command handler — fetch the full text of a specific artifact (#1218).
1251
+ *
1252
+ * Forwards to the same implementation as `aiwg index show`. Companion to
1253
+ * `aiwg discover`: where discover ranks candidates, show fetches the body
1254
+ * so consumers don't need to navigate AIWG's storage paths themselves.
1255
+ *
1256
+ * aiwg show <name> [--type skill,agent,...] [--json] [--first]
1257
+ * [--resource-source local|web|auto] [--aiwg-version <exact-or-channel>] [--offline]
1258
+ */
1259
+ export const showHandler = {
1260
+ id: "show",
1261
+ name: "Show",
1262
+ description: "Print the full text of a specific AIWG skill, agent, command, or rule by name",
1263
+ category: "index",
1264
+ aliases: [],
1265
+ async execute(ctx) {
1266
+ try {
1267
+ const { main } = await import("../../artifacts/cli.js");
1268
+ await main(["show", ...ctx.args]);
1269
+ return { exitCode: 0 };
1270
+ }
1271
+ catch (error) {
1272
+ const result = handlerResultFromError(error);
1273
+ return { ...result, message: `Show command failed: ${result.message}` };
1274
+ }
1275
+ },
1276
+ };
1277
+ /**
1278
+ * Skills command handler
1279
+ *
1280
+ * Dynamically imports and delegates to src/skills/cli.ts.
1281
+ * Handles subcommands: search, info, list, install, publish
1282
+ *
1283
+ * @implements #539
1284
+ */
1285
+ export const skillsHandler = {
1286
+ id: "skills",
1287
+ name: "Skills Registry",
1288
+ description: "Skill commands (search, info, list, install, publish)",
1289
+ category: "catalog",
1290
+ aliases: [],
1291
+ async execute(ctx) {
1292
+ try {
1293
+ const { main } = await import("../../skills/cli.js");
1294
+ await main(ctx.args);
1295
+ return {
1296
+ exitCode: 0,
1297
+ };
1298
+ }
1299
+ catch (error) {
1300
+ const result = handlerResultFromError(error);
1301
+ return { ...result, message: `Skills command failed: ${result.message}` };
1302
+ }
1303
+ },
1304
+ };
1305
+ /**
1306
+ * Config command handler
1307
+ *
1308
+ * Dynamically imports and delegates to src/config/cli.ts.
1309
+ * Handles subcommands: get, set, list, validate, reset, path, edit
1310
+ *
1311
+ * @implements #545
1312
+ */
1313
+ export const configHandler = {
1314
+ id: "config",
1315
+ name: "Config",
1316
+ description: "User config commands (get, set, list, validate, reset, path, edit)",
1317
+ category: "config",
1318
+ aliases: [],
1319
+ async execute(ctx) {
1320
+ try {
1321
+ const { main } = await import("../../config/cli.js");
1322
+ await main(ctx.args);
1323
+ return {
1324
+ exitCode: 0,
1325
+ };
1326
+ }
1327
+ catch (error) {
1328
+ const result = handlerResultFromError(error);
1329
+ return { ...result, message: `Config command failed: ${result.message}` };
1330
+ }
1331
+ },
1332
+ };
1333
+ /**
1334
+ * Ops command handler
1335
+ *
1336
+ * Dynamically imports and delegates to src/ops/cli.ts.
1337
+ * Handles subcommands: init, status, use, list, push
1338
+ *
1339
+ * @implements #544
1340
+ */
1341
+ export const opsHandler = {
1342
+ id: "ops",
1343
+ name: "Ops",
1344
+ description: "Ops ecosystem commands (init, status, use, list, push)",
1345
+ category: "ops",
1346
+ aliases: [],
1347
+ async execute(ctx) {
1348
+ try {
1349
+ const { main } = await import("../../ops/cli.js");
1350
+ await main(ctx.args);
1351
+ return {
1352
+ exitCode: 0,
1353
+ };
1354
+ }
1355
+ catch (error) {
1356
+ const result = handlerResultFromError(error);
1357
+ return { ...result, message: `Ops command failed: ${result.message}` };
1358
+ }
1359
+ },
1360
+ };
1361
+ /**
1362
+ * Activity-log command handler
1363
+ *
1364
+ * Dynamically imports and delegates to src/activity-log/cli.ts.
1365
+ * Handles subcommands: show, append, stats. Persistence routes through
1366
+ * resolveStorage('activity_log') so the log honors any storage.config
1367
+ * override (#934).
1368
+ *
1369
+ * @implements #934
1370
+ * @implements #964
1371
+ */
1372
+ export const activityLogHandler = {
1373
+ id: 'activity-log',
1374
+ name: 'Activity Log',
1375
+ description: 'Query and manage .aiwg/activity.log (show, append, stats)',
1376
+ category: 'utility',
1377
+ aliases: [],
1378
+ async execute(ctx) {
1379
+ try {
1380
+ const { main } = await import('../../activity-log/cli.js');
1381
+ await main(ctx.args);
1382
+ return { exitCode: 0 };
1383
+ }
1384
+ catch (error) {
1385
+ const result = handlerResultFromError(error);
1386
+ return { ...result, message: `activity-log command failed: ${result.message}` };
1387
+ }
1388
+ },
1389
+ };
1390
+ /**
1391
+ * Provenance command handler — routes \`aiwg provenance\` through
1392
+ * resolveStorage('provenance') for provenance-* skills (#968).
1393
+ *
1394
+ * @implements #934
1395
+ * @implements #968
1396
+ */
1397
+ export const provenanceHandler = {
1398
+ id: 'provenance',
1399
+ name: 'Provenance',
1400
+ description: 'Provenance subsystem storage operations (path, list, get, put, delete, append-log)',
1401
+ category: 'utility',
1402
+ aliases: [],
1403
+ async execute(ctx) {
1404
+ try {
1405
+ const { main } = await import('../../provenance/cli.js');
1406
+ await main(ctx.args);
1407
+ return { exitCode: 0 };
1408
+ }
1409
+ catch (error) {
1410
+ const result = handlerResultFromError(error);
1411
+ return { ...result, message: `provenance command failed: ${result.message}` };
1412
+ }
1413
+ },
1414
+ };
1415
+ /**
1416
+ * Research storage command handler — routes \`aiwg research-store\`
1417
+ * through resolveStorage('research') for research-acquire / corpus-*
1418
+ * skills (#968). Disambiguated from existing research-* workflow
1419
+ * commands by the \`-store\` suffix.
1420
+ *
1421
+ * @implements #934
1422
+ * @implements #968
1423
+ */
1424
+ export const researchStoreHandler = {
1425
+ id: 'research-store',
1426
+ name: 'Research Store',
1427
+ description: 'Research subsystem storage operations (path, list, get, put, delete, append-log)',
1428
+ category: 'utility',
1429
+ aliases: [],
1430
+ async execute(ctx) {
1431
+ try {
1432
+ const { main } = await import('../../research/storage-cli.js');
1433
+ await main(ctx.args);
1434
+ return { exitCode: 0 };
1435
+ }
1436
+ catch (error) {
1437
+ const result = handlerResultFromError(error);
1438
+ return { ...result, message: `research-store command failed: ${result.message}` };
1439
+ }
1440
+ },
1441
+ };
1442
+ /** Executable source-selection companion to the research-query skill. */
1443
+ export const researchQueryHandler = {
1444
+ id: 'research-query',
1445
+ name: 'Research Query',
1446
+ description: 'Select research sources for a question with local or Fortemi Core retrieval',
1447
+ category: 'index',
1448
+ aliases: [],
1449
+ async execute(ctx) {
1450
+ try {
1451
+ const { main } = await import('../../research/query-cli.js');
1452
+ await main(ctx.args, ctx.cwd);
1453
+ return { exitCode: 0 };
1454
+ }
1455
+ catch (error) {
1456
+ const result = handlerResultFromError(error);
1457
+ return { ...result, message: `research-query command failed: ${result.message}` };
1458
+ }
1459
+ },
1460
+ };
1461
+ /**
1462
+ * Reflections command handler
1463
+ *
1464
+ * Routes \`aiwg reflections <subcommand>\` through resolveStorage('reflections')
1465
+ * for ralph-reflect / reflection-injection skills (#967).
1466
+ *
1467
+ * @implements #934
1468
+ * @implements #967
1469
+ */
1470
+ export const reflectionsHandler = {
1471
+ id: 'reflections',
1472
+ name: 'Reflections',
1473
+ description: 'Reflections subsystem storage operations (path, list, get, put, delete, append-log)',
1474
+ category: 'utility',
1475
+ aliases: [],
1476
+ async execute(ctx) {
1477
+ try {
1478
+ const { main } = await import('../../reflections/cli.js');
1479
+ await main(ctx.args);
1480
+ return { exitCode: 0 };
1481
+ }
1482
+ catch (error) {
1483
+ const result = handlerResultFromError(error);
1484
+ return { ...result, message: `reflections command failed: ${result.message}` };
1485
+ }
1486
+ },
1487
+ };
1488
+ /**
1489
+ * Memory command handler
1490
+ *
1491
+ * Routes \`aiwg memory <subcommand>\` through resolveStorage('memory') so
1492
+ * the four memory skills (memory-ingest, memory-lint, memory-log-append,
1493
+ * memory-query-capture) honor any storage.config redirection.
1494
+ *
1495
+ * @implements #934
1496
+ * @implements #966
1497
+ */
1498
+ export const memoryHandler = {
1499
+ id: 'memory',
1500
+ name: 'Memory',
1501
+ description: 'Memory subsystem storage operations (path, list, get, put, delete, append-log)',
1502
+ category: 'utility',
1503
+ aliases: [],
1504
+ async execute(ctx) {
1505
+ try {
1506
+ const { main } = await import('../../memory/cli.js');
1507
+ await main(ctx.args);
1508
+ return { exitCode: 0 };
1509
+ }
1510
+ catch (error) {
1511
+ const result = handlerResultFromError(error);
1512
+ return { ...result, message: `memory command failed: ${result.message}` };
1513
+ }
1514
+ },
1515
+ };
1516
+ /**
1517
+ * Knowledge-base command handler
1518
+ *
1519
+ * Routes \`aiwg kb <subcommand>\` through resolveStorage('kb') so the KB
1520
+ * honors any storage.config redirection without each kb skill
1521
+ * hardcoding `.aiwg/kb/`.
1522
+ *
1523
+ * @implements #934
1524
+ * @implements #965
1525
+ */
1526
+ export const kbHandler = {
1527
+ id: 'kb',
1528
+ name: 'Knowledge Base',
1529
+ description: 'Knowledge base storage operations (path, list, get, put, delete)',
1530
+ category: 'utility',
1531
+ aliases: [],
1532
+ async execute(ctx) {
1533
+ try {
1534
+ const { main } = await import('../../kb/cli.js');
1535
+ await main(ctx.args);
1536
+ return { exitCode: 0 };
1537
+ }
1538
+ catch (error) {
1539
+ const result = handlerResultFromError(error);
1540
+ return { ...result, message: `kb command failed: ${result.message}` };
1541
+ }
1542
+ },
1543
+ };
1544
+ /**
1545
+ * Storage command handler
1546
+ *
1547
+ * Dynamically imports and delegates to src/storage/cli.ts.
1548
+ * Handles subcommands: show, list-backends, test
1549
+ *
1550
+ * @implements #934
1551
+ * @implements #954
1552
+ */
1553
+ export const storageHandler = {
1554
+ id: 'storage',
1555
+ name: 'Storage',
1556
+ description: 'Storage adapter commands (show, list-backends, test)',
1557
+ category: 'utility',
1558
+ aliases: [],
1559
+ async execute(ctx) {
1560
+ try {
1561
+ const { main } = await import('../../storage/cli.js');
1562
+ await main(ctx.args);
1563
+ return { exitCode: 0 };
1564
+ }
1565
+ catch (error) {
1566
+ const result = handlerResultFromError(error);
1567
+ return { ...result, message: `Storage command failed: ${result.message}` };
1568
+ }
1569
+ },
1570
+ };
1571
+ /**
1572
+ * RLM agentic tools handler
1573
+ *
1574
+ * Routes `aiwg chunk`, `aiwg fanout`, `aiwg rlm-prep`, `aiwg rlm-search`,
1575
+ * and `aiwg rlm-status` to src/rlm/cli.ts.
1576
+ *
1577
+ * These are support tools for agentic sessions — callable by users but
1578
+ * primarily used by RLM agents during recursive and fanout operations.
1579
+ *
1580
+ * @implements #559
1581
+ */
1582
+ export const rlmToolsHandler = {
1583
+ id: 'rlm-tools',
1584
+ name: 'RLM Tools',
1585
+ description: 'Agentic support tools for RLM operations (chunk, fanout, rlm-prep, rlm-search, rlm-status)',
1586
+ category: 'agentic-tools',
1587
+ aliases: [],
1588
+ async execute(ctx) {
1589
+ try {
1590
+ const { main } = await import('../../rlm/cli.js');
1591
+ await main(ctx.args);
1592
+ return {
1593
+ exitCode: 0,
1594
+ };
1595
+ }
1596
+ catch (error) {
1597
+ const result = handlerResultFromError(error);
1598
+ return { ...result, message: `RLM tools command failed: ${result.message}` };
1599
+ }
1600
+ },
1601
+ };
1602
+ // Individual handlers that delegate to rlmToolsHandler with their command prepended
1603
+ export const chunkHandler = {
1604
+ id: 'chunk',
1605
+ name: 'Chunk',
1606
+ description: 'Split a file into overlapping chunks for parallel fanout processing',
1607
+ category: 'agentic-tools',
1608
+ aliases: [],
1609
+ async execute(ctx) {
1610
+ return rlmToolsHandler.execute({ ...ctx, args: ['chunk', ...ctx.args] });
1611
+ },
1612
+ };
1613
+ export const fanoutHandler = {
1614
+ id: 'fanout',
1615
+ name: 'Fanout',
1616
+ description: 'Dispatch parallel subagent queries across a chunk manifest',
1617
+ category: 'agentic-tools',
1618
+ aliases: [],
1619
+ async execute(ctx) {
1620
+ return rlmToolsHandler.execute({ ...ctx, args: ['fanout', ...ctx.args] });
1621
+ },
1622
+ };
1623
+ export const rlmPrepHandler = {
1624
+ id: 'rlm-prep',
1625
+ name: 'RLM Prep',
1626
+ description: 'Prepare source content for RLM processing (chunk + index + manifest)',
1627
+ category: 'agentic-tools',
1628
+ aliases: [],
1629
+ async execute(ctx) {
1630
+ return rlmToolsHandler.execute({ ...ctx, args: ['rlm-prep', ...ctx.args] });
1631
+ },
1632
+ };
1633
+ export const rlmSearchHandler = {
1634
+ id: 'rlm-search',
1635
+ name: 'RLM Search',
1636
+ description: 'Full recursive search pipeline: decompose source, fanout query, synthesize results',
1637
+ category: 'agentic-tools',
1638
+ aliases: [],
1639
+ async execute(ctx) {
1640
+ return rlmToolsHandler.execute({ ...ctx, args: ['rlm-search', ...ctx.args] });
1641
+ },
1642
+ };
1643
+ export const rlmStatusCliHandler = {
1644
+ id: 'rlm-status',
1645
+ name: 'RLM Status',
1646
+ description: 'Show active RLM task tree, progress, and cost breakdown',
1647
+ category: 'agentic-tools',
1648
+ aliases: [],
1649
+ async execute(ctx) {
1650
+ return rlmToolsHandler.execute({ ...ctx, args: ['rlm-status', ...ctx.args] });
1651
+ },
1652
+ };
1653
+ /** RLM result cache (#1203). */
1654
+ export const rlmCacheHandler = {
1655
+ id: 'rlm-cache',
1656
+ name: 'RLM Cache',
1657
+ description: 'Manage cached RLM results (list, stats, evict, clear) — keyed by index content-hash',
1658
+ category: 'agentic-tools',
1659
+ aliases: [],
1660
+ async execute(ctx) {
1661
+ return rlmToolsHandler.execute({ ...ctx, args: ['rlm-cache', ...ctx.args] });
1662
+ },
1663
+ };
1664
+ /**
1665
+ * All subcommand handlers
1666
+ */
1667
+ export const subcommandHandlers = [
1668
+ mcpHandler,
1669
+ catalogHandler,
1670
+ listHandler,
1671
+ removeHandler,
1672
+ newProjectHandler,
1673
+ installPluginHandler,
1674
+ uninstallPluginHandler,
1675
+ pluginStatusHandler,
1676
+ packagePluginHandler,
1677
+ packageAllPluginsHandler,
1678
+ indexHandler,
1679
+ discoverHandler,
1680
+ showHandler,
1681
+ featuresHandler,
1682
+ skillsHandler,
1683
+ configHandler,
1684
+ opsHandler,
1685
+ storageHandler,
1686
+ activityLogHandler,
1687
+ kbHandler,
1688
+ memoryHandler,
1689
+ reflectionsHandler,
1690
+ provenanceHandler,
1691
+ researchStoreHandler,
1692
+ researchQueryHandler,
1693
+ chunkHandler,
1694
+ fanoutHandler,
1695
+ rlmPrepHandler,
1696
+ rlmSearchHandler,
1697
+ rlmStatusCliHandler,
1698
+ rlmCacheHandler,
1699
+ sessionHandler,
1700
+ feedbackHandler,
1701
+ ];
1702
+ //# sourceMappingURL=subcommands.js.map