@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,883 @@
1
+ /**
2
+ * Project-Level AIWG Config
3
+ *
4
+ * Manages `.aiwg/aiwg.config` — the project-level record of:
5
+ * - Which AI provider toolchains this project targets
6
+ * - Which frameworks/addons are deployed (with uninstall metadata)
7
+ * - User-defined scripts callable via `aiwg run`
8
+ *
9
+ * @implements #621
10
+ */
11
+ import { readFile, writeFile, mkdir, access, readdir, rename, unlink } from 'fs/promises';
12
+ import { createHash, randomBytes } from 'crypto';
13
+ import { resolve, join, isAbsolute } from 'path';
14
+ import { normalizeNamedCaptures } from '../artifacts/index-builder.js';
15
+ import { getProviderDefinition, PROVIDER_IDS, resolveProviderPathValue, } from '../providers/provider-definitions.js';
16
+ import { validateAuthorization, } from '../policy/authorization.js';
17
+ import { projectAiwgPath, resolveProjectAiwgDir } from './project-artifacts.js';
18
+ const CONFIG_FILENAME = 'aiwg.config';
19
+ /**
20
+ * Operations that a workspace may authorize for one member repository.
21
+ * Filesystem/tool capability never implies authorization; unlisted members
22
+ * and actions are denied by the workspace resolver.
23
+ *
24
+ * @implements #1764
25
+ */
26
+ export const WORKSPACE_REPO_ACTIONS = [
27
+ 'read',
28
+ 'write',
29
+ 'commit',
30
+ 'push',
31
+ 'issue-comment',
32
+ 'service-action',
33
+ 'destructive',
34
+ ];
35
+ const DEFAULT_BRANCH_NAMING = {
36
+ prefix_by_type: {
37
+ feat: 'feat/{issue}-{slug}',
38
+ fix: 'fix/{issue}-{slug}',
39
+ docs: 'docs/{slug}',
40
+ chore: 'chore/{slug}',
41
+ refactor: 'refactor/{slug}',
42
+ test: 'test/{slug}',
43
+ },
44
+ };
45
+ /**
46
+ * Resolve the delivery policy with defaults applied.
47
+ *
48
+ * Defaults are intentionally conservative — they match what AIWG agents
49
+ * naturally do today (PR-required, rebase-merge, no force pushes, post issue
50
+ * comments) so that adding the schema doesn't shift behavior for existing
51
+ * projects.
52
+ */
53
+ export function resolveDelivery(delivery) {
54
+ return {
55
+ mode: delivery?.mode ?? 'pr-required',
56
+ default_branch: delivery?.default_branch ?? 'main',
57
+ branch_naming: {
58
+ prefix_by_type: {
59
+ ...DEFAULT_BRANCH_NAMING.prefix_by_type,
60
+ ...(delivery?.branch_naming?.prefix_by_type ?? {}),
61
+ },
62
+ },
63
+ merge_style: delivery?.merge_style ?? 'rebase-merge',
64
+ delete_branch_on_merge: delivery?.delete_branch_on_merge ?? true,
65
+ require_ci_green: delivery?.require_ci_green ?? true,
66
+ require_signed_commits: delivery?.require_signed_commits ?? false,
67
+ committer: delivery?.committer,
68
+ signing: delivery?.signing,
69
+ release_signing: delivery?.release_signing,
70
+ force_push_policy: delivery?.force_push_policy ?? 'never',
71
+ auto_close_issues: delivery?.auto_close_issues ?? true,
72
+ issue_comment_on_cycle: delivery?.issue_comment_on_cycle ?? true,
73
+ };
74
+ }
75
+ /**
76
+ * Per-provider parallelism defaults. Conservative numbers for Anthropic-backed
77
+ * providers reflect Pro/Team-plan rate limits — operators on Enterprise tiers
78
+ * should bump via `aiwg config set --project parallelism.max_parallel_subagents N`.
79
+ *
80
+ * Sources for the numbers:
81
+ * - claude / claude-code: Anthropic per-key throttling at higher concurrency
82
+ * - codex / copilot / etc.: OpenAI / GitHub quotas are generally per-org and
83
+ * less aggressive at small fan-outs (10 is a safe middle ground)
84
+ * - hermes: MCP sidecar; rate-limit depends on upstream provider, operator
85
+ * should tune. Conservative 10 default.
86
+ * - unknown: conservative 4 default.
87
+ */
88
+ export const PROVIDER_PARALLELISM_DEFAULTS = {
89
+ claude: { max_parallel_subagents: 4, max_parallel_ralph_loops: 2, max_parallel_mc_missions: 4 },
90
+ codex: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
91
+ copilot: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
92
+ cursor: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
93
+ factory: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
94
+ opencode: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
95
+ warp: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
96
+ windsurf: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
97
+ openclaw: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
98
+ hermes: { max_parallel_subagents: 10, max_parallel_ralph_loops: 3, max_parallel_mc_missions: 6 },
99
+ };
100
+ const UNKNOWN_PROVIDER_PARALLELISM = {
101
+ max_parallel_subagents: 4,
102
+ max_parallel_ralph_loops: 2,
103
+ max_parallel_mc_missions: 4,
104
+ };
105
+ /**
106
+ * Return the provider's parallelism defaults, or the conservative fallback
107
+ * when the provider is unknown.
108
+ */
109
+ export function getProviderParallelismDefaults(provider) {
110
+ if (!provider)
111
+ return UNKNOWN_PROVIDER_PARALLELISM;
112
+ return PROVIDER_PARALLELISM_DEFAULTS[provider] ?? UNKNOWN_PROVIDER_PARALLELISM;
113
+ }
114
+ /**
115
+ * Resolve the parallelism caps with provider-aware defaults applied. The
116
+ * primary provider drives the default — typically the first entry in the
117
+ * project's `providers` array.
118
+ *
119
+ * When `parallelism` has explicit values, they override the provider default
120
+ * field-by-field. When no provider is supplied (or it's not in the defaults
121
+ * map), the conservative 4-subagent fallback applies.
122
+ *
123
+ * @implements #1359
124
+ */
125
+ export function resolveParallelism(parallelism, primaryProvider) {
126
+ const defaults = getProviderParallelismDefaults(primaryProvider);
127
+ const resolved = {
128
+ max_parallel_subagents: parallelism?.max_parallel_subagents ?? defaults.max_parallel_subagents,
129
+ max_parallel_ralph_loops: parallelism?.max_parallel_ralph_loops ?? defaults.max_parallel_ralph_loops,
130
+ max_parallel_mc_missions: parallelism?.max_parallel_mc_missions ?? defaults.max_parallel_mc_missions,
131
+ };
132
+ if (parallelism?.rationale !== undefined)
133
+ resolved.rationale = parallelism.rationale;
134
+ return resolved;
135
+ }
136
+ const GRAPH_BACKENDS = ['json', 'graphology', 'sqlite'];
137
+ const NODE_STRATEGIES = ['default', 'filename-metadata'];
138
+ const BUILD_TIERS = ['lightweight', 'standard', 'heavy'];
139
+ /**
140
+ * Validate an `index` config block, returning a list of human-readable error
141
+ * messages (empty = valid). Hand-rolled rather than ajv because aiwg.config has
142
+ * no runtime schema-validation pipeline and the codebase deliberately avoids
143
+ * pulling a validator dependency for config parsing (#1491).
144
+ *
145
+ * Catches the failure modes #1491 calls out: unknown graph type, missing
146
+ * scanDirs, bad regex, typo'd keys, malformed manifest. `aiwg index build` and
147
+ * `aiwg doctor` surface these at validate time instead of at runtime.
148
+ *
149
+ * @param index The value of `aiwg.config.index` (untrusted shape).
150
+ * @returns Array of error strings; empty when the block is valid or absent.
151
+ */
152
+ export function validateIndexConfig(index) {
153
+ const errors = [];
154
+ if (index === undefined || index === null)
155
+ return errors;
156
+ if (typeof index !== 'object' || Array.isArray(index)) {
157
+ return ['index: must be an object'];
158
+ }
159
+ const graphs = index.graphs;
160
+ if (graphs === undefined)
161
+ return errors; // index with no graphs is permissible
162
+ if (typeof graphs !== 'object' || graphs === null || Array.isArray(graphs)) {
163
+ return ['index.graphs: must be an object mapping graph names to definitions'];
164
+ }
165
+ const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');
166
+ for (const [name, rawDef] of Object.entries(graphs)) {
167
+ const where = `index.graphs.${name}`;
168
+ if (typeof rawDef !== 'object' || rawDef === null || Array.isArray(rawDef)) {
169
+ errors.push(`${where}: must be an object`);
170
+ continue;
171
+ }
172
+ const def = rawDef;
173
+ if (name === 'indices') {
174
+ // Markdown-view manifest (build.py).
175
+ const manifest = def.manifest;
176
+ if (!Array.isArray(manifest)) {
177
+ errors.push(`${where}.manifest: must be an array`);
178
+ continue;
179
+ }
180
+ manifest.forEach((entry, i) => {
181
+ if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {
182
+ errors.push(`${where}.manifest[${i}]: must be an object`);
183
+ return;
184
+ }
185
+ const e = entry;
186
+ if (typeof e.name !== 'string' || e.name.trim() === '') {
187
+ errors.push(`${where}.manifest[${i}]: 'name' is required and must be a non-empty string (it selects the renderer)`);
188
+ }
189
+ if (e.output !== undefined && typeof e.output !== 'string') {
190
+ errors.push(`${where}.manifest[${i}].output: must be a string`);
191
+ }
192
+ });
193
+ continue;
194
+ }
195
+ // JSON node/edge graph def.
196
+ if (!isStringArray(def.scanDirs) || def.scanDirs.length === 0) {
197
+ errors.push(`${where}.scanDirs: required, must be a non-empty array of strings`);
198
+ }
199
+ if (def.extensions !== undefined && !isStringArray(def.extensions)) {
200
+ errors.push(`${where}.extensions: must be an array of strings`);
201
+ }
202
+ if (def.nodeStrategy !== undefined && !NODE_STRATEGIES.includes(def.nodeStrategy)) {
203
+ errors.push(`${where}.nodeStrategy: must be one of ${NODE_STRATEGIES.join(' | ')}`);
204
+ }
205
+ if (def.graphBackend !== undefined && !GRAPH_BACKENDS.includes(def.graphBackend)) {
206
+ errors.push(`${where}.graphBackend: must be one of ${GRAPH_BACKENDS.join(' | ')}`);
207
+ }
208
+ if (def.buildTier !== undefined && !BUILD_TIERS.includes(def.buildTier)) {
209
+ errors.push(`${where}.buildTier: must be one of ${BUILD_TIERS.join(' | ')}`);
210
+ }
211
+ if (def.buildOrder !== undefined && (typeof def.buildOrder !== 'number' || !Number.isFinite(def.buildOrder))) {
212
+ errors.push(`${where}.buildOrder: must be a finite number`);
213
+ }
214
+ if (def.nodeStrategy === 'filename-metadata') {
215
+ if (typeof def.filenamePattern !== 'string' || def.filenamePattern.trim() === '') {
216
+ errors.push(`${where}.filenamePattern: required when nodeStrategy is 'filename-metadata'`);
217
+ }
218
+ }
219
+ if (def.filenamePattern !== undefined && typeof def.filenamePattern === 'string') {
220
+ try {
221
+ // Apply the same Python→JS named-capture normalization the builder uses
222
+ // (index-builder.ts buildFilenameMetadataEntry) so the validator doesn't
223
+ // reject patterns the builder would happily compile. Fixes #1514 —
224
+ // `aiwg` workspace refresh emits Python-style `(?P<name>)` patterns
225
+ // (port residue from the Python build.py); the builder is lenient, the
226
+ // validator wasn't, so legit configs failed up front.
227
+ // eslint-disable-next-line no-new
228
+ new RegExp(normalizeNamedCaptures(def.filenamePattern));
229
+ }
230
+ catch (err) {
231
+ errors.push(`${where}.filenamePattern: not a valid regular expression (${err.message})`);
232
+ }
233
+ }
234
+ if (def.edgeExtraction !== undefined) {
235
+ const ee = def.edgeExtraction;
236
+ if (typeof ee !== 'object' || ee === null || Array.isArray(ee)) {
237
+ errors.push(`${where}.edgeExtraction: must be an object`);
238
+ }
239
+ else {
240
+ const eo = ee;
241
+ if (eo.parser !== 'citation-sidecar') {
242
+ errors.push(`${where}.edgeExtraction.parser: must be 'citation-sidecar'`);
243
+ }
244
+ if (!Array.isArray(eo.edges)) {
245
+ errors.push(`${where}.edgeExtraction.edges: must be an array`);
246
+ }
247
+ else {
248
+ eo.edges.forEach((edge, i) => {
249
+ if (typeof edge !== 'object' || edge === null) {
250
+ errors.push(`${where}.edgeExtraction.edges[${i}]: must be an object`);
251
+ return;
252
+ }
253
+ const ed = edge;
254
+ for (const k of ['type', 'source', 'target']) {
255
+ if (typeof ed[k] !== 'string' || ed[k].trim() === '') {
256
+ errors.push(`${where}.edgeExtraction.edges[${i}].${k}: required, must be a non-empty string`);
257
+ }
258
+ }
259
+ });
260
+ }
261
+ }
262
+ }
263
+ }
264
+ return errors;
265
+ }
266
+ const EXTERNAL_LINK_KEY_PATTERN = /^[a-z][a-z0-9_-]*$/;
267
+ /**
268
+ * Validate project-defined external links without performing network access.
269
+ */
270
+ export function validateExternalLinks(externalLinks) {
271
+ if (externalLinks === undefined || externalLinks === null)
272
+ return [];
273
+ if (typeof externalLinks !== 'object' || Array.isArray(externalLinks)) {
274
+ return ['externalLinks: must be an object mapping stable identifiers to link definitions'];
275
+ }
276
+ const errors = [];
277
+ for (const [key, rawLink] of Object.entries(externalLinks)) {
278
+ const where = `externalLinks.${key}`;
279
+ if (!EXTERNAL_LINK_KEY_PATTERN.test(key)) {
280
+ errors.push(`${where}: key must start with a lowercase letter and contain only lowercase letters, numbers, underscores, or hyphens`);
281
+ }
282
+ if (!rawLink || typeof rawLink !== 'object' || Array.isArray(rawLink)) {
283
+ errors.push(`${where}: must be an object`);
284
+ continue;
285
+ }
286
+ const link = rawLink;
287
+ const allowedFields = new Set(['label', 'url', 'description', 'category', 'audience']);
288
+ for (const field of Object.keys(link)) {
289
+ if (!allowedFields.has(field)) {
290
+ errors.push(`${where}.${field}: unknown field`);
291
+ }
292
+ }
293
+ if (typeof link.label !== 'string' || link.label.trim() === '') {
294
+ errors.push(`${where}.label: required, must be a non-empty string`);
295
+ }
296
+ else if (link.label.length > 200) {
297
+ errors.push(`${where}.label: must be at most 200 characters`);
298
+ }
299
+ if (typeof link.url !== 'string' || link.url.trim() === '') {
300
+ errors.push(`${where}.url: required, must be an absolute HTTP(S) URL`);
301
+ }
302
+ else {
303
+ try {
304
+ const parsed = new URL(link.url);
305
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
306
+ errors.push(`${where}.url: protocol must be http or https`);
307
+ }
308
+ if (parsed.username || parsed.password) {
309
+ errors.push(`${where}.url: embedded credentials are not allowed`);
310
+ }
311
+ }
312
+ catch {
313
+ errors.push(`${where}.url: must be a valid absolute URL`);
314
+ }
315
+ }
316
+ for (const field of ['description', 'category', 'audience']) {
317
+ const value = link[field];
318
+ if (value !== undefined && (typeof value !== 'string' || value.trim() === '')) {
319
+ errors.push(`${where}.${field}: must be a non-empty string when provided`);
320
+ }
321
+ else if (typeof value === 'string' && value.length > 500) {
322
+ errors.push(`${where}.${field}: must be at most 500 characters`);
323
+ }
324
+ }
325
+ }
326
+ return errors;
327
+ }
328
+ /**
329
+ * Validate the general workspace-of-repositories blocks.
330
+ *
331
+ * This is intentionally runtime validation as well as schema documentation:
332
+ * CLI callers may not have editor/schema support, and authorization data must
333
+ * fail closed when malformed.
334
+ *
335
+ * @implements #1764
336
+ */
337
+ export function validateWorkspaceConfig(workspace, repos) {
338
+ const errors = [];
339
+ if (workspace === undefined && repos === undefined)
340
+ return errors;
341
+ if (!workspace || typeof workspace !== 'object' || Array.isArray(workspace)) {
342
+ return ['workspace: must be an object when workspace or repos is configured'];
343
+ }
344
+ const metadata = workspace;
345
+ for (const field of ['name', 'root', 'member_of']) {
346
+ if (metadata[field] !== undefined && (typeof metadata[field] !== 'string' || !metadata[field].trim())) {
347
+ errors.push(`workspace.${field}: must be a non-empty string`);
348
+ }
349
+ }
350
+ if (metadata.member_of !== undefined && repos !== undefined) {
351
+ errors.push('workspace.member_of: member back-references must not also declare repos');
352
+ }
353
+ if (repos === undefined)
354
+ return errors;
355
+ if (typeof metadata.name !== 'string' || !metadata.name.trim()) {
356
+ errors.push('workspace.name: required when repos is configured');
357
+ }
358
+ if (!Array.isArray(repos) || repos.length === 0) {
359
+ errors.push('repos: must be a non-empty array');
360
+ return errors;
361
+ }
362
+ const names = new Set();
363
+ const paths = new Set();
364
+ const allowedActions = new Set(WORKSPACE_REPO_ACTIONS);
365
+ repos.forEach((raw, index) => {
366
+ const where = `repos[${index}]`;
367
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
368
+ errors.push(`${where}: must be an object`);
369
+ return;
370
+ }
371
+ const repo = raw;
372
+ if (typeof repo.name !== 'string' || !repo.name.trim()) {
373
+ errors.push(`${where}.name: required and must be a non-empty string`);
374
+ }
375
+ else if (names.has(repo.name.trim())) {
376
+ errors.push(`${where}.name: duplicate member name '${repo.name.trim()}'`);
377
+ }
378
+ else {
379
+ names.add(repo.name.trim());
380
+ }
381
+ if (typeof repo.path !== 'string' || !repo.path.trim()) {
382
+ errors.push(`${where}.path: required and must be a non-empty string`);
383
+ }
384
+ else if (paths.has(repo.path.trim())) {
385
+ errors.push(`${where}.path: duplicate member path '${repo.path.trim()}'`);
386
+ }
387
+ else {
388
+ paths.add(repo.path.trim());
389
+ }
390
+ if (!Array.isArray(repo.allowed) || repo.allowed.length === 0) {
391
+ errors.push(`${where}.allowed: must be a non-empty array`);
392
+ }
393
+ else {
394
+ for (const action of repo.allowed) {
395
+ if (typeof action !== 'string' || !allowedActions.has(action)) {
396
+ errors.push(`${where}.allowed: invalid operation '${String(action)}'`);
397
+ }
398
+ }
399
+ }
400
+ if (repo.provider !== undefined && !['gitea', 'github', 'gitlab'].includes(String(repo.provider))) {
401
+ errors.push(`${where}.provider: must be gitea, github, or gitlab`);
402
+ }
403
+ if (repo.notes !== undefined && typeof repo.notes !== 'string') {
404
+ errors.push(`${where}.notes: must be a string`);
405
+ }
406
+ });
407
+ return errors;
408
+ }
409
+ /**
410
+ * Read the `index` block, preferring `.aiwg/aiwg.config` (the consolidated
411
+ * home, #1491) and falling back to the legacy `.aiwg/config.yaml` `index:`
412
+ * block. Returns `{ index, source }` where source is 'aiwg.config',
413
+ * 'config.yaml' (deprecated), or 'none'.
414
+ *
415
+ * The fallback keeps un-migrated corpora working; callers should surface a
416
+ * deprecation notice when `source === 'config.yaml'`.
417
+ */
418
+ export async function readIndexConfig(projectDir) {
419
+ const cfg = await readAiwgConfig(projectDir);
420
+ if (cfg?.index && typeof cfg.index === 'object') {
421
+ return { index: cfg.index, source: 'aiwg.config' };
422
+ }
423
+ // Fallback: legacy config.yaml in the resolved AIWG artifact directory (deprecated).
424
+ const yamlPath = projectAiwgPath(projectDir, 'config.yaml');
425
+ try {
426
+ await access(yamlPath);
427
+ const { load: loadYaml } = await import('js-yaml');
428
+ const raw = loadYaml(await readFile(yamlPath, 'utf-8'));
429
+ const idx = raw?.index;
430
+ if (idx && typeof idx === 'object') {
431
+ return { index: idx, source: 'config.yaml' };
432
+ }
433
+ }
434
+ catch {
435
+ /* no config.yaml or unreadable */
436
+ }
437
+ return { index: undefined, source: 'none' };
438
+ }
439
+ /**
440
+ * Provider tag for a given remote URL. Used by skills (issue-create,
441
+ * pr-review, commit-and-push) to pick the right CLI / MCP client when
442
+ * the operator didn't pass `--provider` explicitly.
443
+ *
444
+ * Recognized hosts:
445
+ * - github.com → 'github'
446
+ * - gitlab.com / gitlab.* → 'gitlab'
447
+ * - any host containing 'gitea' (or matching the typical Gitea path shape) → 'gitea'
448
+ *
449
+ * Returns 'unknown' for self-hosted instances we can't classify by host alone —
450
+ * callers should then prompt the operator or fall back to the configured
451
+ * AIWG provider list.
452
+ *
453
+ * @implements #997
454
+ */
455
+ export function resolveRemoteProvider(remoteUrl) {
456
+ if (!remoteUrl)
457
+ return 'unknown';
458
+ const lower = remoteUrl.toLowerCase();
459
+ // github.com (or git@github.com:owner/repo.git form)
460
+ if (/(^|[/@])github\.com[:/]/.test(lower))
461
+ return 'github';
462
+ // gitlab.com or self-hosted gitlab
463
+ if (/(^|[/@])gitlab\./.test(lower) || lower.includes('/gitlab/'))
464
+ return 'gitlab';
465
+ // gitea — identified by hostname token. Self-hosted Gitea instances often
466
+ // don't include 'gitea' in their hostname (e.g. corporate git servers), so
467
+ // 'unknown' is the honest answer there — callers should consult the
468
+ // configured AIWG provider list rather than guess.
469
+ if (lower.includes('gitea'))
470
+ return 'gitea';
471
+ return 'unknown';
472
+ }
473
+ /**
474
+ * Resolve the repo remote topology with defaults applied.
475
+ *
476
+ * Defaults:
477
+ * - `primary` defaults to "origin"
478
+ * - `issue_tracker` defaults to `primary`
479
+ * - `ci` defaults to `primary`
480
+ * - `secondary` defaults to `[]`
481
+ *
482
+ * Pass an absent or partial `remotes` block — every field comes back populated.
483
+ */
484
+ export function resolveRemotes(remotes) {
485
+ const primary = remotes?.primary ?? 'origin';
486
+ return {
487
+ primary,
488
+ issue_tracker: remotes?.issue_tracker ?? primary,
489
+ ci: remotes?.ci ?? primary,
490
+ tracker_actor: remotes?.tracker_actor,
491
+ transport: remotes?.transport,
492
+ secondary: remotes?.secondary ?? [],
493
+ };
494
+ }
495
+ /**
496
+ * Resolve stable semantic label roles to provider-native label strings.
497
+ * The same role therefore drives Gitea, GitHub, and local issue-store flows.
498
+ */
499
+ export function resolveIssueLabels(issues, provider) {
500
+ const diagnostics = validateIssueLabels(issues, { provider });
501
+ if (!issues?.labels) {
502
+ return {
503
+ labels: {},
504
+ diagnostics: [{
505
+ severity: 'warning',
506
+ code: 'fallback',
507
+ message: 'issues.labels is not configured; issue workflows retain legacy label-name behavior and must warn before guessing or provisioning labels.',
508
+ }],
509
+ };
510
+ }
511
+ const labels = Object.fromEntries(Object.entries(issues.labels).map(([role, definition]) => [
512
+ role,
513
+ {
514
+ ...definition,
515
+ role,
516
+ provider,
517
+ resolved_name: definition.provider_names?.[provider] ?? definition.name,
518
+ },
519
+ ]));
520
+ return { labels, diagnostics };
521
+ }
522
+ /**
523
+ * Validate taxonomy structure and, when supplied, tracker availability.
524
+ * This function is read-only: ordinary issue processing never provisions
525
+ * missing labels implicitly.
526
+ */
527
+ export function validateIssueLabels(issues, options = {}) {
528
+ if (!issues?.labels)
529
+ return [];
530
+ const diagnostics = [];
531
+ const seenNames = new Map();
532
+ const roles = new Set(Object.keys(issues.labels));
533
+ const available = options.availableLabels ? new Set(options.availableLabels) : undefined;
534
+ const categories = new Set([
535
+ 'type', 'area', 'priority', 'lifecycle', 'blocked-reason',
536
+ 'review-approval', 'ownership', 'automation-eligibility', 'human-interaction',
537
+ ]);
538
+ for (const [role, definition] of Object.entries(issues.labels)) {
539
+ const where = `issues.labels.${role}`;
540
+ if (!definition.name?.trim() || !definition.description?.trim() || !definition.category) {
541
+ diagnostics.push({
542
+ severity: 'error',
543
+ code: 'missing',
544
+ role,
545
+ message: `${where} must define non-empty name, description, and category fields.`,
546
+ });
547
+ continue;
548
+ }
549
+ if (!categories.has(definition.category)) {
550
+ diagnostics.push({
551
+ severity: 'error',
552
+ code: 'conflict',
553
+ role,
554
+ message: `${where}.category '${definition.category}' is not a supported semantic category.`,
555
+ });
556
+ }
557
+ if (typeof definition.requires_human !== 'boolean' || typeof definition.blocks_automation !== 'boolean') {
558
+ diagnostics.push({
559
+ severity: 'error',
560
+ code: 'missing',
561
+ role,
562
+ message: `${where} must explicitly define requires_human and blocks_automation booleans.`,
563
+ });
564
+ }
565
+ if (definition.blocks_automation && !definition.requires_human && !definition.resume_when) {
566
+ diagnostics.push({
567
+ severity: 'error',
568
+ code: 'conflict',
569
+ role,
570
+ message: `${where} blocks automation but declares neither human action nor a resume condition.`,
571
+ });
572
+ }
573
+ if (definition.blocks_automation && !definition.resume_when?.trim()) {
574
+ diagnostics.push({
575
+ severity: 'error',
576
+ code: 'missing',
577
+ role,
578
+ message: `${where}.resume_when is required when blocks_automation is true.`,
579
+ });
580
+ }
581
+ if (definition.transition_to && !roles.has(definition.transition_to)) {
582
+ diagnostics.push({
583
+ severity: 'error',
584
+ code: 'conflict',
585
+ role,
586
+ message: `${where}.transition_to references unknown semantic role '${definition.transition_to}'.`,
587
+ });
588
+ }
589
+ const resolvedName = options.provider
590
+ ? definition.provider_names?.[options.provider] ?? definition.name
591
+ : definition.name;
592
+ const normalized = resolvedName.trim().toLocaleLowerCase();
593
+ const previousRole = seenNames.get(normalized);
594
+ if (previousRole) {
595
+ diagnostics.push({
596
+ severity: 'error',
597
+ code: 'duplicate',
598
+ role,
599
+ message: `${where} resolves to '${resolvedName}', already used by role '${previousRole}'.`,
600
+ });
601
+ }
602
+ else {
603
+ seenNames.set(normalized, role);
604
+ }
605
+ if (available && !available.has(resolvedName)) {
606
+ diagnostics.push({
607
+ severity: 'error',
608
+ code: 'unavailable',
609
+ role,
610
+ message: `${where} resolves to unavailable tracker label '${resolvedName}'; provision it explicitly before issue processing.`,
611
+ });
612
+ }
613
+ }
614
+ return diagnostics;
615
+ }
616
+ export const VALID_PROVIDERS = PROVIDER_IDS.filter((provider) => provider !== 'generic');
617
+ /**
618
+ * Empty config template.
619
+ *
620
+ * Includes an explicit `delivery` block defaulting to `pr-required`. The
621
+ * runtime default in {@link resolveDelivery} is the same, so this is purely
622
+ * for visibility — new projects ship with the policy written down so users
623
+ * can see what their agents will do, and switch via `aiwg config set` or
624
+ * the AIWG Steward agent without first having to discover the field exists.
625
+ */
626
+ export function emptyConfig(providers = ['claude']) {
627
+ const primaryProvider = providers[0];
628
+ const parDefaults = getProviderParallelismDefaults(primaryProvider);
629
+ const knownProvider = primaryProvider && primaryProvider in PROVIDER_PARALLELISM_DEFAULTS;
630
+ return {
631
+ $schema: 'https://aiwg.io/schemas/aiwg.config.v1.json',
632
+ version: '1',
633
+ providers,
634
+ installed: {},
635
+ scripts: {},
636
+ delivery: {
637
+ mode: 'pr-required',
638
+ default_branch: 'main',
639
+ require_ci_green: true,
640
+ auto_close_issues: true,
641
+ issue_comment_on_cycle: true,
642
+ force_push_policy: 'never',
643
+ },
644
+ parallelism: {
645
+ max_parallel_subagents: parDefaults.max_parallel_subagents,
646
+ max_parallel_ralph_loops: parDefaults.max_parallel_ralph_loops,
647
+ max_parallel_mc_missions: parDefaults.max_parallel_mc_missions,
648
+ rationale: knownProvider
649
+ ? `Provider default for ${primaryProvider} — adjust via 'aiwg config set --project parallelism.max_parallel_subagents N'`
650
+ : `Conservative default (unknown provider) — adjust via 'aiwg config set --project parallelism.max_parallel_subagents N'`,
651
+ },
652
+ };
653
+ }
654
+ /**
655
+ * Resolve path to the project-level AIWG config.
656
+ *
657
+ * Defaults to `<project>/.aiwg/aiwg.config`; honors `AIWG_ARTIFACTS_PATH` so
658
+ * projects can rename or relocate the AIWG artifact directory.
659
+ */
660
+ export function getConfigPath(projectDir) {
661
+ return projectAiwgPath(projectDir, CONFIG_FILENAME);
662
+ }
663
+ /**
664
+ * Resolve the project directory for a handler invocation.
665
+ *
666
+ * Precedence:
667
+ * 1. `--target <path>` or `--prefix <path>` flag in args
668
+ * 2. The HandlerContext `cwd`, if provided
669
+ * 3. `process.cwd()`
670
+ *
671
+ * All three variants existed scattered across handlers (#919 cleanup).
672
+ * Use this helper so we have one authoritative resolution.
673
+ */
674
+ export function getProjectDir(ctx, args = []) {
675
+ const targetIdx = args.findIndex(a => a === '--target' || a === '--prefix');
676
+ const targetValue = targetIdx >= 0 ? args[targetIdx + 1] : undefined;
677
+ return targetValue || ctx?.cwd || process.cwd();
678
+ }
679
+ /**
680
+ * Read .aiwg/aiwg.config.
681
+ * Returns null if the file does not exist.
682
+ */
683
+ export async function readAiwgConfig(projectDir) {
684
+ const filePath = getConfigPath(projectDir);
685
+ try {
686
+ await access(filePath);
687
+ }
688
+ catch {
689
+ return null;
690
+ }
691
+ const content = await readFile(filePath, 'utf-8');
692
+ const parsed = JSON.parse(content);
693
+ // Ensure required fields exist (forward-compat)
694
+ if (!parsed.providers)
695
+ parsed.providers = ['claude'];
696
+ if (!parsed.installed)
697
+ parsed.installed = {};
698
+ if (!parsed.scripts)
699
+ parsed.scripts = {};
700
+ const externalLinkErrors = validateExternalLinks(parsed.externalLinks);
701
+ if (externalLinkErrors.length > 0) {
702
+ throw new Error(`Invalid .aiwg/aiwg.config:\n${externalLinkErrors.join('\n')}`);
703
+ }
704
+ const workspaceErrors = validateWorkspaceConfig(parsed.workspace, parsed.repos);
705
+ if (workspaceErrors.length > 0) {
706
+ throw new Error(`Invalid .aiwg/aiwg.config:\n${workspaceErrors.join('\n')}`);
707
+ }
708
+ const authorizationErrors = parsed.authorization
709
+ ? validateAuthorization(parsed.authorization).filter(item => item.severity === 'error')
710
+ : [];
711
+ if (authorizationErrors.length > 0) {
712
+ throw new Error(`Invalid .aiwg/aiwg.config:\n${authorizationErrors.map(item => item.message).join('\n')}`);
713
+ }
714
+ return parsed;
715
+ }
716
+ /**
717
+ * Write aiwg.config, creating the resolved AIWG artifact directory if needed.
718
+ */
719
+ export async function writeAiwgConfig(projectDir, config) {
720
+ const dir = resolveProjectAiwgDir(projectDir);
721
+ await mkdir(dir, { recursive: true });
722
+ const filePath = join(dir, CONFIG_FILENAME);
723
+ // Atomic write: emit to a temp sibling, fsync-ish via rename. Prevents a
724
+ // crash or kill mid-write from corrupting the config file. Rename is
725
+ // atomic on POSIX and on NTFS when both paths are on the same volume.
726
+ // The random suffix avoids collisions if two concurrent writers run.
727
+ const tmpPath = `${filePath}.${randomBytes(6).toString('hex')}.tmp`;
728
+ try {
729
+ await writeFile(tmpPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
730
+ await rename(tmpPath, filePath);
731
+ }
732
+ catch (err) {
733
+ // Best-effort cleanup of the temp file on failure, ignoring ENOENT.
734
+ try {
735
+ await unlink(tmpPath);
736
+ }
737
+ catch {
738
+ /* ignore */
739
+ }
740
+ throw err;
741
+ }
742
+ }
743
+ /**
744
+ * Update the `installed` record for a framework after a successful deployment.
745
+ * Returns the updated config (does not write to disk — caller must call writeAiwgConfig).
746
+ */
747
+ export function updateInstalled(config, name, provider, counts, opts) {
748
+ // Project-local invariant: `source: 'project-local'` requires localPath + localType
749
+ // (per ADR adr-unified-registry-shape §6 risk mitigation).
750
+ if (opts.source === 'project-local') {
751
+ if (!opts.localPath || !opts.localType) {
752
+ throw new Error(`updateInstalled: source 'project-local' requires localPath and localType (got ${JSON.stringify({ localPath: opts.localPath, localType: opts.localType })})`);
753
+ }
754
+ }
755
+ const existing = config.installed[name] ?? {
756
+ version: opts.version,
757
+ source: opts.source,
758
+ installedAt: new Date().toISOString(),
759
+ deployedTo: {},
760
+ manifestHash: opts.manifestHash,
761
+ };
762
+ existing.version = opts.version;
763
+ existing.source = opts.source;
764
+ existing.installedAt = new Date().toISOString();
765
+ existing.deployedTo[provider] = counts;
766
+ if (opts.manifestHash)
767
+ existing.manifestHash = opts.manifestHash;
768
+ if (opts.source === 'project-local') {
769
+ existing.localPath = opts.localPath;
770
+ existing.localType = opts.localType;
771
+ if (opts.manifestVersion)
772
+ existing.manifestVersion = opts.manifestVersion;
773
+ if (opts.artifactHashes)
774
+ existing.artifactHashes = opts.artifactHashes;
775
+ }
776
+ else {
777
+ // Clear stale project-local fields if a previously project-local entry is
778
+ // being overwritten by a non-project-local source.
779
+ delete existing.localPath;
780
+ delete existing.localType;
781
+ delete existing.manifestVersion;
782
+ delete existing.artifactHashes;
783
+ }
784
+ config.installed[name] = existing;
785
+ return config;
786
+ }
787
+ /**
788
+ * Aggregate deployment counts across all installed frameworks for a given provider.
789
+ * Returns the totals for agents, commands, skills, and rules.
790
+ * If no provider is specified, uses the first configured provider.
791
+ */
792
+ export function getDeploymentSummary(config, provider) {
793
+ const targetProvider = provider ?? config.providers[0] ?? 'claude';
794
+ const totals = { agents: 0, commands: 0, skills: 0, rules: 0 };
795
+ for (const entry of Object.values(config.installed)) {
796
+ const counts = entry.deployedTo[targetProvider];
797
+ if (!counts)
798
+ continue;
799
+ totals.agents += counts.agents;
800
+ totals.commands += counts.commands;
801
+ totals.skills += counts.skills;
802
+ totals.rules += counts.rules;
803
+ }
804
+ return totals;
805
+ }
806
+ /**
807
+ * Compute SHA-256 hash of a manifest.json file.
808
+ * Returns undefined if the file cannot be read.
809
+ */
810
+ export async function hashManifest(manifestPath) {
811
+ try {
812
+ const content = await readFile(manifestPath, 'utf-8');
813
+ return 'sha256:' + createHash('sha256').update(content).digest('hex');
814
+ }
815
+ catch {
816
+ return undefined;
817
+ }
818
+ }
819
+ function getProviderDeployDirs(provider, projectDir) {
820
+ const artifacts = getProviderDefinition(provider)?.paths.artifacts;
821
+ if (!artifacts)
822
+ return null;
823
+ return {
824
+ agents: resolveProviderPathValue(artifacts.agents, projectDir),
825
+ skills: resolveProviderPathValue(artifacts.skills, projectDir),
826
+ commands: resolveProviderPathValue(artifacts.commands, projectDir),
827
+ rules: resolveProviderPathValue(artifacts.rules, projectDir),
828
+ };
829
+ }
830
+ /**
831
+ * Count .md files or subdirectories in a deployment directory.
832
+ * Returns 0 if the directory does not exist.
833
+ */
834
+ async function countDeployedInDir(projectDir, relOrAbsDir, mode) {
835
+ if (!relOrAbsDir)
836
+ return 0;
837
+ const dir = isAbsolute(relOrAbsDir) ? relOrAbsDir : resolve(projectDir, relOrAbsDir);
838
+ try {
839
+ const entries = await readdir(dir, { withFileTypes: true });
840
+ if (mode === 'md')
841
+ return entries.filter(e => e.isFile() && e.name.endsWith('.md')).length;
842
+ return entries.filter(e => e.isDirectory()).length;
843
+ }
844
+ catch {
845
+ return 0;
846
+ }
847
+ }
848
+ /**
849
+ * Scan actual deployment directories and populate `deployedTo` for any
850
+ * `installed` entries that have an empty `deployedTo` map.
851
+ *
852
+ * Called by `aiwg init` when migrating a project that already has frameworks
853
+ * deployed but whose config was created before deployment-tracking was added.
854
+ *
855
+ * @implements #721
856
+ */
857
+ export async function populateDeployedTo(config, projectDir) {
858
+ const entriesNeedingPopulation = Object.entries(config.installed).filter(([, entry]) => Object.keys(entry.deployedTo).length === 0);
859
+ if (entriesNeedingPopulation.length === 0)
860
+ return config;
861
+ for (const provider of config.providers) {
862
+ const dirs = getProviderDeployDirs(provider, projectDir);
863
+ if (!dirs)
864
+ continue;
865
+ const counts = {
866
+ agents: await countDeployedInDir(projectDir, dirs.agents, 'md'),
867
+ commands: await countDeployedInDir(projectDir, dirs.commands, 'md'),
868
+ skills: await countDeployedInDir(projectDir, dirs.skills, 'dirs'),
869
+ rules: await countDeployedInDir(projectDir, dirs.rules, 'md'),
870
+ };
871
+ // Only populate if at least one artifact type is present
872
+ if (counts.agents + counts.commands + counts.skills + counts.rules === 0)
873
+ continue;
874
+ for (const [name, entry] of entriesNeedingPopulation) {
875
+ if (Object.keys(entry.deployedTo).length === 0) {
876
+ entry.deployedTo[provider] = counts;
877
+ config.installed[name] = entry;
878
+ }
879
+ }
880
+ }
881
+ return config;
882
+ }
883
+ //# sourceMappingURL=aiwg-config.js.map