@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,988 @@
1
+ /**
2
+ * Canonical cross-provider workspace context graph (#1811).
3
+ *
4
+ * WORKSPACE.md owns provider-neutral project/operator context. Provider startup
5
+ * files are compiled adapters that load or explicitly direct the harness to
6
+ * WORKSPACE.md first and AIWG.md second. Existing layouts remain readable until
7
+ * an operator runs the explicit migration workflow.
8
+ */
9
+ import { createHash } from 'node:crypto';
10
+ import { promises as fs } from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import { buildAiwgMdContent } from './aiwg-md.js';
13
+ import { buildNormalizedAiwgMd } from './finalization.js';
14
+ import { getProviderDefinition, listProviderDefinitions, } from '../../providers/provider-definitions.js';
15
+ import { projectAiwgPath, resolveProjectAiwgDir } from '../../config/project-artifacts.js';
16
+ export const WORKSPACE_MANAGED_START = '<!-- AIWG:workspace-context:start -->';
17
+ export const WORKSPACE_MANAGED_END = '<!-- AIWG:workspace-context:end -->';
18
+ export const WORKSPACE_OPERATOR_START = '<!-- AIWG:workspace-operator:start -->';
19
+ export const WORKSPACE_OPERATOR_END = '<!-- AIWG:workspace-operator:end -->';
20
+ export const PROJECT_EXTRACTION_START = '<!-- AIWG:project-extraction:start -->';
21
+ export const PROJECT_EXTRACTION_END = '<!-- AIWG:project-extraction:end -->';
22
+ export const PROVIDER_BOOTSTRAP_START = '<!-- AIWG:provider-bootstrap:start -->';
23
+ export const PROVIDER_BOOTSTRAP_END = '<!-- AIWG:provider-bootstrap:end -->';
24
+ export const WORKSPACE_SIGNATURE = '<!-- aiwg-managed -->';
25
+ const LEGACY_ROOT_FILES = [
26
+ 'CLAUDE.md',
27
+ 'AGENTS.md',
28
+ 'AGENTS.override.md',
29
+ 'WARP.md',
30
+ '.hermes.md',
31
+ '.github/copilot-instructions.md',
32
+ 'AIWG.md',
33
+ ];
34
+ const GENERATED_BLOCKS = [
35
+ [PROVIDER_BOOTSTRAP_START, PROVIDER_BOOTSTRAP_END],
36
+ ['<!-- AIWG:context-hook:start -->', '<!-- AIWG:context-hook:end -->'],
37
+ ['<!-- AIWG:claude-md-hook:start -->', '<!-- AIWG:claude-md-hook:end -->'],
38
+ ['<!-- BEGIN AIWG -->', '<!-- END AIWG -->'],
39
+ [WORKSPACE_MANAGED_START, WORKSPACE_MANAGED_END],
40
+ ['<!-- spillover-from-AGENTS.md:START -->', '<!-- spillover-from-AGENTS.md:END -->'],
41
+ ];
42
+ const PROJECT_CONTEXT_PLACEHOLDER = [
43
+ '## Project Context',
44
+ '',
45
+ 'Add project conventions, local hook/context pointers, and links to deeper project documents here.',
46
+ ].join('\n');
47
+ function sha256(content) {
48
+ return createHash('sha256').update(content).digest('hex');
49
+ }
50
+ async function readOptional(filePath) {
51
+ try {
52
+ return await fs.readFile(filePath, 'utf8');
53
+ }
54
+ catch (error) {
55
+ if (error.code === 'ENOENT')
56
+ return null;
57
+ throw error;
58
+ }
59
+ }
60
+ async function atomicWrite(filePath, content) {
61
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
62
+ const temporary = path.join(path.dirname(filePath), `.${path.basename(filePath)}.tmp.${process.pid}`);
63
+ await fs.writeFile(temporary, content, 'utf8');
64
+ try {
65
+ await fs.rename(temporary, filePath);
66
+ }
67
+ catch (error) {
68
+ await fs.rm(temporary, { force: true }).catch(() => undefined);
69
+ throw error;
70
+ }
71
+ }
72
+ function resolveProjectRelative(projectPath, relativePath) {
73
+ if (path.isAbsolute(relativePath))
74
+ throw new Error(`Unsafe absolute migration path: ${relativePath}`);
75
+ const root = path.resolve(projectPath);
76
+ const resolved = path.resolve(root, relativePath);
77
+ const artifactRoot = path.resolve(resolveProjectAiwgDir(projectPath));
78
+ const insideProject = resolved === root || resolved.startsWith(`${root}${path.sep}`);
79
+ const insideArtifactRoot = resolved === artifactRoot || resolved.startsWith(`${artifactRoot}${path.sep}`);
80
+ if (!insideProject && !insideArtifactRoot) {
81
+ throw new Error(`Unsafe migration path outside project: ${relativePath}`);
82
+ }
83
+ return resolved;
84
+ }
85
+ function replaceBlock(content, start, end, block) {
86
+ const startIndex = content.indexOf(start);
87
+ const endIndex = content.indexOf(end);
88
+ if (startIndex < 0 && endIndex < 0)
89
+ return null;
90
+ if (startIndex < 0 || endIndex < startIndex)
91
+ throw new Error(`Malformed managed block: ${start} / ${end}`);
92
+ return content.slice(0, startIndex) + block + content.slice(endIndex + end.length);
93
+ }
94
+ function stripGeneratedBlocks(content) {
95
+ let stripped = content;
96
+ for (const [start, end] of GENERATED_BLOCKS) {
97
+ while (stripped.includes(start) || stripped.includes(end)) {
98
+ const replaced = replaceBlock(stripped, start, end, '');
99
+ if (replaced === null)
100
+ break;
101
+ stripped = replaced;
102
+ }
103
+ }
104
+ return stripped
105
+ .replace(/^<!-- aiwg-managed -->\s*$/gm, '')
106
+ .replace(/^<!-- Generated by AIWG[^\n]*-->\s*$/gm, '')
107
+ .trim();
108
+ }
109
+ function isGeneratedRootContext(relativePath, content) {
110
+ if (content.includes(WORKSPACE_SIGNATURE))
111
+ return true;
112
+ const head = content.split('\n').slice(0, 12).join('\n');
113
+ if (/<!--\s*Generated by\s+(?:AIWG|aiwg)(?:\s+use)?\b[^>]*-->/i.test(head))
114
+ return true;
115
+ return relativePath === 'AIWG.md' && /^# AIWG Framework Context\b/m.test(head);
116
+ }
117
+ function cleanInlineMarkdown(value) {
118
+ return value
119
+ .replace(/<!--.*?-->/g, ' ')
120
+ .replace(/!\[[^\]]*\]\([^)]*\)/g, ' ')
121
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
122
+ .replace(/[`*_~#|]/g, ' ')
123
+ .replace(/\s+/g, ' ')
124
+ .trim();
125
+ }
126
+ function truncateAtWord(value, limit) {
127
+ if (value.length <= limit)
128
+ return value;
129
+ const candidate = value.slice(0, limit + 1);
130
+ const boundary = candidate.lastIndexOf(' ');
131
+ return `${candidate.slice(0, boundary > Math.floor(limit * 0.7) ? boundary : limit).trimEnd()}…`;
132
+ }
133
+ function projectLink(relativePath) {
134
+ const normalized = relativePath.replace(/\\/g, '/');
135
+ return `[\`${normalized}\`](./${normalized})`;
136
+ }
137
+ async function firstReadmePurpose(projectPath) {
138
+ for (const source of ['README.md', 'README.mdx', 'README.rst', 'README.txt']) {
139
+ const content = await readOptional(path.join(projectPath, source));
140
+ if (!content || isGeneratedRootContext(source, content))
141
+ continue;
142
+ const blocks = content.replace(/\r\n/g, '\n').split(/\n\s*\n/);
143
+ for (const block of blocks) {
144
+ const lines = block.split('\n').filter((line) => {
145
+ const trimmed = line.trim();
146
+ return trimmed
147
+ && !trimmed.startsWith('#')
148
+ && !trimmed.startsWith('![')
149
+ && !trimmed.startsWith('[![')
150
+ && !trimmed.startsWith('<')
151
+ && !/^[-*+]\s/.test(trimmed)
152
+ && !/^```/.test(trimmed);
153
+ });
154
+ const purpose = cleanInlineMarkdown(lines.join(' ')).slice(0, 360).trim();
155
+ if (purpose.length >= 24)
156
+ return { source, purpose };
157
+ }
158
+ }
159
+ return null;
160
+ }
161
+ async function existingPaths(projectPath, candidates) {
162
+ const found = [];
163
+ for (const candidate of candidates) {
164
+ try {
165
+ await fs.access(path.join(projectPath, candidate));
166
+ found.push(candidate);
167
+ }
168
+ catch {
169
+ // Optional project evidence.
170
+ }
171
+ }
172
+ return found;
173
+ }
174
+ async function workflowFiles(projectPath) {
175
+ const files = [];
176
+ for (const directory of ['.gitea/workflows', '.github/workflows']) {
177
+ let entries;
178
+ try {
179
+ entries = await fs.readdir(path.join(projectPath, directory), { withFileTypes: true });
180
+ }
181
+ catch {
182
+ continue;
183
+ }
184
+ for (const entry of entries) {
185
+ if (entry.isFile() && /^[A-Za-z0-9._-]+\.ya?ml$/i.test(entry.name))
186
+ files.push(`${directory}/${entry.name}`);
187
+ }
188
+ }
189
+ return files.sort((left, right) => left.localeCompare(right));
190
+ }
191
+ export async function extractExistingProjectContext(projectPath) {
192
+ const lines = [
193
+ PROJECT_EXTRACTION_START,
194
+ '',
195
+ '## Existing Project Snapshot',
196
+ '',
197
+ '<!-- Generated from stable project metadata. Edit the linked sources, not this block. -->',
198
+ ];
199
+ const sources = new Set();
200
+ let sensitiveFindings = [];
201
+ const packageContent = await readOptional(path.join(projectPath, 'package.json'));
202
+ if (packageContent) {
203
+ try {
204
+ const manifest = JSON.parse(packageContent);
205
+ const facts = [];
206
+ if (typeof manifest.name === 'string' && manifest.name.trim())
207
+ facts.push(`- Name: \`${cleanInlineMarkdown(manifest.name).slice(0, 120)}\``);
208
+ if (typeof manifest.description === 'string' && manifest.description.trim()) {
209
+ facts.push(`- Description: ${truncateAtWord(cleanInlineMarkdown(manifest.description), 360)}`);
210
+ }
211
+ if (typeof manifest.packageManager === 'string' && manifest.packageManager.trim()) {
212
+ facts.push(`- Package manager: \`${cleanInlineMarkdown(manifest.packageManager).slice(0, 120)}\``);
213
+ }
214
+ if (manifest.engines && typeof manifest.engines === 'object' && !Array.isArray(manifest.engines)) {
215
+ const engines = Object.entries(manifest.engines)
216
+ .filter((entry) => typeof entry[1] === 'string')
217
+ .sort(([left], [right]) => left.localeCompare(right))
218
+ .map(([name, constraint]) => `${name} ${cleanInlineMarkdown(constraint).slice(0, 80)}`);
219
+ if (engines.length)
220
+ facts.push(`- Runtime: ${engines.map((engine) => `\`${engine}\``).join(', ')}`);
221
+ }
222
+ if (facts.length) {
223
+ lines.push('', `### Package (source: ${projectLink('package.json')})`, '', ...facts);
224
+ sources.add('package.json');
225
+ }
226
+ if (manifest.scripts && typeof manifest.scripts === 'object' && !Array.isArray(manifest.scripts)) {
227
+ const preferred = ['build', 'test', 'lint', 'typecheck', 'check', 'start', 'dev'];
228
+ const available = preferred.filter((name) => typeof manifest.scripts[name] === 'string');
229
+ if (available.length) {
230
+ lines.push('', `### Common Commands (source: ${projectLink('package.json')})`, '', ...available.map((name) => `- \`npm run ${name}\``));
231
+ sources.add('package.json');
232
+ }
233
+ }
234
+ }
235
+ catch {
236
+ // Invalid package metadata remains the owning tool's concern; extraction skips it.
237
+ }
238
+ }
239
+ const readme = await firstReadmePurpose(projectPath);
240
+ if (readme) {
241
+ lines.push('', `### Purpose (source: ${projectLink(readme.source)})`, '', readme.purpose);
242
+ sources.add(readme.source);
243
+ }
244
+ const stackSignals = await existingPaths(projectPath, [
245
+ 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lock', 'bun.lockb',
246
+ 'tsconfig.json', 'deno.json', 'deno.jsonc', 'pyproject.toml', 'requirements.txt',
247
+ 'Pipfile', 'poetry.lock', 'Cargo.toml', 'Cargo.lock', 'go.mod', 'Gemfile',
248
+ 'composer.json', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'Makefile',
249
+ ]);
250
+ if (stackSignals.length) {
251
+ lines.push('', '### Stack and Tooling', '', ...stackSignals.map((source) => `- ${projectLink(source)}`));
252
+ for (const source of stackSignals)
253
+ sources.add(source);
254
+ }
255
+ const architecture = await existingPaths(projectPath, [
256
+ 'ARCHITECTURE.md', 'docs/architecture.md', 'docs/architecture', 'docs/adr', 'docs/adrs',
257
+ 'src', 'app', 'apps', 'packages', 'services', 'crates',
258
+ ]);
259
+ const tests = await existingPaths(projectPath, [
260
+ 'test', 'tests', '__tests__', 'vitest.config.ts', 'vitest.config.js', 'vitest.config.mts',
261
+ 'jest.config.js', 'jest.config.ts', 'pytest.ini', 'tox.ini', 'playwright.config.ts',
262
+ ]);
263
+ const workflows = await workflowFiles(projectPath);
264
+ if (architecture.length) {
265
+ lines.push('', '### Architecture and Topology', '', ...architecture.map((source) => `- ${projectLink(source)}`));
266
+ }
267
+ if (tests.length) {
268
+ lines.push('', '### Testing', '', ...tests.map((source) => `- ${projectLink(source)}`));
269
+ }
270
+ if (workflows.length) {
271
+ lines.push('', '### Continuous Integration', '', ...workflows.map((source) => `- ${projectLink(source)}`));
272
+ }
273
+ for (const source of [...architecture, ...tests, ...workflows])
274
+ sources.add(source);
275
+ const orderedSources = [...sources].sort((left, right) => left.localeCompare(right));
276
+ if (orderedSources.length === 0)
277
+ return { content: '', sources: [], sensitiveFindings };
278
+ lines.push('', PROJECT_EXTRACTION_END);
279
+ const content = lines.join('\n');
280
+ sensitiveFindings = sensitiveEvidence(content).map((evidence) => ({ path: 'project extraction', evidence }));
281
+ return { content, sources: orderedSources, sensitiveFindings };
282
+ }
283
+ function mergeProjectExtraction(operatorContent, extraction) {
284
+ const existingStart = operatorContent.indexOf(PROJECT_EXTRACTION_START);
285
+ const existingEnd = operatorContent.indexOf(PROJECT_EXTRACTION_END);
286
+ let preserved = operatorContent.trim();
287
+ if (existingStart >= 0 || existingEnd >= 0) {
288
+ const replaced = replaceBlock(preserved, PROJECT_EXTRACTION_START, PROJECT_EXTRACTION_END, '');
289
+ preserved = (replaced ?? preserved).trim();
290
+ }
291
+ if (preserved === PROJECT_CONTEXT_PLACEHOLDER || preserved === [
292
+ '## Project Context',
293
+ '',
294
+ 'Add provider-neutral project conventions and links here.',
295
+ ].join('\n'))
296
+ preserved = '';
297
+ if (!extraction)
298
+ return preserved || PROJECT_CONTEXT_PLACEHOLDER;
299
+ return [preserved, extraction].filter(Boolean).join('\n\n');
300
+ }
301
+ function providerForPath(relativePath) {
302
+ for (const definition of listProviderDefinitions()) {
303
+ if (definition.context.startupFiles.includes(relativePath) || definition.context.bootstrapTargets.includes(relativePath)) {
304
+ return definition.id;
305
+ }
306
+ }
307
+ return null;
308
+ }
309
+ function projectArtifactMarkdownPath(projectPath, ...segments) {
310
+ const rel = path.relative(projectPath, projectAiwgPath(projectPath, ...segments)).replace(/\\/g, '/');
311
+ if (rel === '')
312
+ return '.';
313
+ return rel.startsWith('.') ? rel : `./${rel}`;
314
+ }
315
+ function workspaceLinks(projectPath, providerFiles = []) {
316
+ const links = new Set([
317
+ '[AIWG framework context](./AIWG.md)',
318
+ `[AIWG project configuration](${projectArtifactMarkdownPath(projectPath, 'aiwg.config')})`,
319
+ ]);
320
+ if (providerFiles.length > 0) {
321
+ for (const file of providerFiles)
322
+ links.add(`[Provider-specific context](./${file.replace(/\\/g, '/')})`);
323
+ }
324
+ // The quickref source is linked, not copied into each provider directory.
325
+ links.add(`[Project-local quickref](${projectArtifactMarkdownPath(projectPath, 'quickref.json')}) (when configured)`);
326
+ return [...links];
327
+ }
328
+ export function buildWorkspaceManagedBlock(projectPath, providerFiles = []) {
329
+ const links = workspaceLinks(projectPath, providerFiles);
330
+ return [
331
+ WORKSPACE_MANAGED_START,
332
+ '',
333
+ '## AIWG Context Graph',
334
+ '',
335
+ 'This file is the canonical provider-neutral home for project and operator context.',
336
+ 'Provider startup files are generated adapters: they direct the harness here first,',
337
+ 'then to AIWG.md for framework discovery and routing.',
338
+ '',
339
+ '### Precedence',
340
+ '',
341
+ '1. Provider, system, and organization instructions retain their native authority.',
342
+ '2. Root WORKSPACE.md supplies shared project/operator context.',
343
+ '3. AIWG.md supplies generated framework/discovery context.',
344
+ '4. Narrower linked files and provider-native subtree instructions govern their declared scope.',
345
+ '',
346
+ '### Ownership',
347
+ '',
348
+ '- Edit project-neutral notes only inside the protected Project Context section below.',
349
+ '- Keep detailed policies, runbooks, hooks, and quickrefs in linked files.',
350
+ '- Keep provider-only directives in `.aiwg/context/providers/`.',
351
+ '- Never store secrets, tokens, credentials, or machine-local sensitive values here.',
352
+ '',
353
+ '### Linked Context',
354
+ '',
355
+ ...links.map((link) => `- ${link}`),
356
+ '',
357
+ WORKSPACE_MANAGED_END,
358
+ ].join('\n');
359
+ }
360
+ export function buildWorkspaceDocument(projectPath, operatorContent = '', providerFiles = []) {
361
+ const content = operatorContent.trim() || PROJECT_CONTEXT_PLACEHOLDER;
362
+ return [
363
+ '# WORKSPACE.md',
364
+ WORKSPACE_SIGNATURE,
365
+ '<!-- Generated structure by AIWG; operator content is protected by markers. -->',
366
+ '',
367
+ buildWorkspaceManagedBlock(projectPath, providerFiles),
368
+ '',
369
+ WORKSPACE_OPERATOR_START,
370
+ '',
371
+ content,
372
+ '',
373
+ WORKSPACE_OPERATOR_END,
374
+ '',
375
+ ].join('\n');
376
+ }
377
+ export async function ensureWorkspaceContext(projectPath, options = {}) {
378
+ const workspacePath = path.join(projectPath, 'WORKSPACE.md');
379
+ const warnings = [];
380
+ const existing = await readOptional(workspacePath);
381
+ if (existing === null) {
382
+ await atomicWrite(workspacePath, buildWorkspaceDocument(projectPath, '', options.providerFiles));
383
+ return { path: workspacePath, action: 'created', warnings };
384
+ }
385
+ const block = buildWorkspaceManagedBlock(projectPath, options.providerFiles);
386
+ if (existing.includes(WORKSPACE_MANAGED_START) || existing.includes(WORKSPACE_MANAGED_END)) {
387
+ const updated = replaceBlock(existing, WORKSPACE_MANAGED_START, WORKSPACE_MANAGED_END, block);
388
+ if (updated === existing)
389
+ return { path: workspacePath, action: 'unchanged', warnings };
390
+ await atomicWrite(workspacePath, updated);
391
+ return { path: workspacePath, action: 'updated', warnings };
392
+ }
393
+ if (!options.force) {
394
+ warnings.push('WORKSPACE.md is operator-owned and has no AIWG markers; left untouched. Use workspace-context migrate to adopt it safely.');
395
+ return { path: workspacePath, action: 'preserved', warnings };
396
+ }
397
+ const backupPath = `${workspacePath}.bak.${new Date().toISOString().replace(/[:.]/g, '-')}`;
398
+ await fs.writeFile(backupPath, existing, 'utf8');
399
+ await atomicWrite(workspacePath, buildWorkspaceDocument(projectPath, existing, options.providerFiles));
400
+ return { path: workspacePath, action: 'updated', backupPath, warnings };
401
+ }
402
+ export function buildProviderBootstrapBlock(provider) {
403
+ const definition = getProviderDefinition(provider);
404
+ const contract = definition?.context;
405
+ if (!definition || !contract || contract.loadMode === 'unsupported') {
406
+ return [
407
+ PROVIDER_BOOTSTRAP_START,
408
+ '',
409
+ '# Provider workspace bootstrap',
410
+ '',
411
+ 'This provider has no verified project-local automatic context loader.',
412
+ 'If the harness exposes file-reading tools, read WORKSPACE.md first and AIWG.md second.',
413
+ '',
414
+ PROVIDER_BOOTSTRAP_END,
415
+ ].join('\n');
416
+ }
417
+ const loading = contract.loadMode === 'native-include'
418
+ ? [
419
+ 'Load the canonical project context first, then the generated AIWG framework context:',
420
+ '',
421
+ '@WORKSPACE.md',
422
+ '@AIWG.md',
423
+ ]
424
+ : contract.loadMode === 'config-registration'
425
+ ? [
426
+ 'WORKSPACE.md and AIWG.md are registered through the provider configuration.',
427
+ 'Read and follow WORKSPACE.md first; use AIWG.md second for AIWG discovery and routing.',
428
+ ]
429
+ : [
430
+ 'Read and follow [WORKSPACE.md](./WORKSPACE.md) first.',
431
+ 'Then read [AIWG.md](./AIWG.md) for AIWG discovery, quickrefs, and framework routing.',
432
+ '',
433
+ 'These are explicit reading instructions. Plain Markdown links are not claimed to auto-load.',
434
+ ];
435
+ return [
436
+ PROVIDER_BOOTSTRAP_START,
437
+ '',
438
+ '# Provider workspace bootstrap',
439
+ '',
440
+ ...loading,
441
+ '',
442
+ PROVIDER_BOOTSTRAP_END,
443
+ ].join('\n');
444
+ }
445
+ export function buildProviderBootstrapFile(provider) {
446
+ return [
447
+ '# Provider workspace bootstrap',
448
+ WORKSPACE_SIGNATURE,
449
+ '<!-- Generated by AIWG. Project/operator context belongs in WORKSPACE.md. -->',
450
+ '',
451
+ buildProviderBootstrapBlock(provider),
452
+ '',
453
+ ].join('\n');
454
+ }
455
+ export async function registerProviderContext(provider, projectPath) {
456
+ const contract = getProviderDefinition(provider)?.context;
457
+ if (!contract?.configRegistration)
458
+ return null;
459
+ const configPath = path.join(projectPath, contract.configRegistration.file);
460
+ const existing = await readOptional(configPath);
461
+ let config = {};
462
+ if (existing !== null) {
463
+ try {
464
+ config = JSON.parse(existing);
465
+ }
466
+ catch {
467
+ return { path: configPath, changed: false, warning: `${contract.configRegistration.file} is not valid JSON; context registration was not changed.` };
468
+ }
469
+ }
470
+ const key = contract.configRegistration.key;
471
+ const current = Array.isArray(config[key]) ? config[key].filter((item) => typeof item === 'string') : [];
472
+ const next = [...new Set([...current, 'WORKSPACE.md', 'AIWG.md'])];
473
+ if (JSON.stringify(current) === JSON.stringify(next))
474
+ return { path: configPath, changed: false };
475
+ config[key] = next;
476
+ if (!('$schema' in config) && path.basename(configPath) === 'opencode.json') {
477
+ config = { $schema: 'https://opencode.ai/config.json', ...config };
478
+ }
479
+ await atomicWrite(configPath, `${JSON.stringify(config, null, 2)}\n`);
480
+ return { path: configPath, changed: true };
481
+ }
482
+ function directives(content) {
483
+ return [...new Set(content
484
+ .split('\n')
485
+ .map((line) => line.replace(/^\s*[-*+]\s+/, '').replace(/^#+\s+/, '').trim())
486
+ .filter((line) => line.length >= 8 && !line.startsWith('<!--') && !/^https?:\/\//i.test(line)))];
487
+ }
488
+ function directiveKey(directive) {
489
+ if (!/^(always|never|must|do not|don't|required|prefer|use|avoid|keep|preserve)\b/i.test(directive))
490
+ return null;
491
+ return directive.toLowerCase()
492
+ .replace(/[^a-z0-9\s]/g, '')
493
+ .replace(/^(?:always|never|must|required|prefer|avoid|keep|preserve|do not|dont)\s+/, '')
494
+ .replace(/^use\s+/, '')
495
+ .split(/\s+/).slice(0, 5).join(' ');
496
+ }
497
+ function directivePolarity(directive) {
498
+ return /^(?:never|do not|don't|avoid)\b/i.test(directive) ? 'negative' : 'positive';
499
+ }
500
+ function sensitiveEvidence(content) {
501
+ const findings = [];
502
+ for (const line of content.split('\n')) {
503
+ if (/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/.test(line)) {
504
+ findings.push(`private-key material (${sha256(line).slice(0, 12)})`);
505
+ }
506
+ if (/\b(?:api[_-]?key|token|secret|password)\s*[:=]\s*(?!<|\$\{|\*{3}|example|placeholder)["']?[A-Za-z0-9_\-/.+=]{12,}/i.test(line)) {
507
+ findings.push(`credential-like assignment (${sha256(line).slice(0, 12)})`);
508
+ }
509
+ }
510
+ return findings;
511
+ }
512
+ async function nestedInstructionFiles(projectPath) {
513
+ const found = [];
514
+ const ignored = new Set(['.git', 'node_modules', 'dist', 'build', 'coverage', '.aiwg']);
515
+ async function walk(directory) {
516
+ let entries;
517
+ try {
518
+ entries = await fs.readdir(directory, { withFileTypes: true });
519
+ }
520
+ catch {
521
+ return;
522
+ }
523
+ for (const entry of entries) {
524
+ if (entry.isDirectory()) {
525
+ if (!ignored.has(entry.name) && !entry.name.startsWith('.context-migration-'))
526
+ await walk(path.join(directory, entry.name));
527
+ }
528
+ else if (['AGENTS.md', 'CLAUDE.md', 'WARP.md'].includes(entry.name)) {
529
+ const relative = path.relative(projectPath, path.join(directory, entry.name)).replace(/\\/g, '/');
530
+ const segments = relative.split('/');
531
+ const generatedArtifactPath = segments.includes('templates') || segments.includes('fixtures');
532
+ if (!generatedArtifactPath && !LEGACY_ROOT_FILES.includes(relative))
533
+ found.push(relative);
534
+ }
535
+ }
536
+ }
537
+ await walk(projectPath);
538
+ return found.sort((a, b) => a.localeCompare(b));
539
+ }
540
+ async function migratedProviderFiles(projectPath) {
541
+ const directory = projectAiwgPath(projectPath, 'context', 'providers');
542
+ try {
543
+ return (await fs.readdir(directory, { withFileTypes: true }))
544
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.md'))
545
+ .map((entry) => projectOutputPath(projectPath, path.join(directory, entry.name)))
546
+ .sort();
547
+ }
548
+ catch {
549
+ return [];
550
+ }
551
+ }
552
+ export async function auditWorkspaceContext(projectPath) {
553
+ const extractedProject = await extractExistingProjectContext(projectPath);
554
+ const candidates = new Set([
555
+ 'WORKSPACE.md',
556
+ ...LEGACY_ROOT_FILES,
557
+ ...await nestedInstructionFiles(projectPath),
558
+ ...await migratedProviderFiles(projectPath),
559
+ ]);
560
+ const sources = [];
561
+ const sensitiveFindings = [...extractedProject.sensitiveFindings];
562
+ for (const relativePath of [...candidates].sort((a, b) => a.localeCompare(b))) {
563
+ const content = await readOptional(path.join(projectPath, relativePath));
564
+ if (content === null)
565
+ continue;
566
+ const operatorContent = relativePath === 'WORKSPACE.md'
567
+ ? (() => {
568
+ const start = content.indexOf(WORKSPACE_OPERATOR_START);
569
+ const end = content.indexOf(WORKSPACE_OPERATOR_END);
570
+ return start >= 0 && end > start
571
+ ? content.slice(start + WORKSPACE_OPERATOR_START.length, end).trim()
572
+ : stripGeneratedBlocks(content);
573
+ })()
574
+ : isGeneratedRootContext(relativePath, content)
575
+ ? ''
576
+ : stripGeneratedBlocks(content);
577
+ for (const evidence of sensitiveEvidence(operatorContent))
578
+ sensitiveFindings.push({ path: relativePath, evidence });
579
+ sources.push({
580
+ path: relativePath,
581
+ provider: providerForPath(relativePath),
582
+ scope: LEGACY_ROOT_FILES.includes(relativePath) || relativePath === 'WORKSPACE.md' ? 'root' : 'nested',
583
+ managed: content.includes(WORKSPACE_SIGNATURE) || content.includes('AIWG:context-hook:start') || content.includes('AIWG:claude-md-hook:start'),
584
+ operatorContent,
585
+ checksum: sha256(content),
586
+ });
587
+ }
588
+ const byDirective = new Map();
589
+ for (const source of sources) {
590
+ for (const directive of directives(source.operatorContent)) {
591
+ const paths = byDirective.get(directive) ?? [];
592
+ paths.push(source.path);
593
+ byDirective.set(directive, paths);
594
+ }
595
+ }
596
+ const identical = [...byDirective]
597
+ .filter(([, paths]) => paths.length > 1)
598
+ .map(([directive, paths]) => ({ sources: [...paths].sort(), directives: [directive] }));
599
+ const overlaps = [];
600
+ for (let index = 0; index < sources.length; index += 1) {
601
+ const left = new Set(directives(sources[index].operatorContent));
602
+ for (let rightIndex = index + 1; rightIndex < sources.length; rightIndex += 1) {
603
+ const common = directives(sources[rightIndex].operatorContent).filter((item) => left.has(item));
604
+ if (common.length > 0)
605
+ overlaps.push({ sources: [sources[index].path, sources[rightIndex].path], directives: common.sort() });
606
+ }
607
+ }
608
+ const conflictMap = new Map();
609
+ for (const source of sources) {
610
+ for (const directive of directives(source.operatorContent)) {
611
+ const key = directiveKey(directive);
612
+ if (!key)
613
+ continue;
614
+ const values = conflictMap.get(key) ?? [];
615
+ values.push({ path: source.path, directive, polarity: directivePolarity(directive) });
616
+ conflictMap.set(key, values);
617
+ }
618
+ }
619
+ const conflicts = [...conflictMap]
620
+ .filter(([, values]) => new Set(values.map((value) => value.polarity)).size > 1)
621
+ .map(([key, values]) => ({ key, sources: values.map(({ path: sourcePath, directive }) => ({ path: sourcePath, directive })).sort((a, b) => a.path.localeCompare(b.path)) }));
622
+ const rootOperator = sources.filter((source) => source.scope === 'root' && source.operatorContent.trim());
623
+ // Provider startup roots remain attributed provider context even when one
624
+ // directive is duplicated elsewhere. Promoting an entire root file because
625
+ // of one matching line can copy large provider/framework bodies into the
626
+ // provider-neutral WORKSPACE.md operator region.
627
+ const neutralSources = rootOperator.filter((source) => source.path === 'WORKSPACE.md').map((source) => source.path);
628
+ const providerSources = rootOperator.filter((source) => source.path !== 'WORKSPACE.md' && !neutralSources.includes(source.path)).map((source) => source.path);
629
+ const providerOutputs = providerSources.map((source) => providerContextOutput(projectPath, source));
630
+ const workspaceExists = sources.some((source) => source.path === 'WORKSPACE.md');
631
+ return {
632
+ version: 1,
633
+ projectPath,
634
+ workspaceExists,
635
+ legacyCompatible: !workspaceExists && sources.some((source) => LEGACY_ROOT_FILES.includes(source.path)),
636
+ sources,
637
+ identical,
638
+ overlaps,
639
+ conflicts,
640
+ sensitiveFindings,
641
+ plan: {
642
+ neutralSources,
643
+ providerSources,
644
+ nestedSources: sources.filter((source) => source.scope === 'nested').map((source) => source.path),
645
+ projectSources: extractedProject.sources,
646
+ outputs: ['WORKSPACE.md', ...providerOutputs, ...listProviderDefinitions().flatMap((definition) => definition.context.bootstrapTargets)].filter((value, index, all) => all.indexOf(value) === index).sort(),
647
+ },
648
+ };
649
+ }
650
+ function projectOutputPath(projectPath, absPath) {
651
+ return path.relative(projectPath, absPath).replace(/\\/g, '/');
652
+ }
653
+ function providerContextOutput(projectPath, sourcePath) {
654
+ return projectOutputPath(projectPath, projectAiwgPath(projectPath, 'context', 'providers', sourcePath.replace(/[^A-Za-z0-9.-]+/g, '-').replace(/^-+/, '')));
655
+ }
656
+ function neutralMigrationContent(audit) {
657
+ const selected = audit.sources.filter((source) => audit.plan.neutralSources.includes(source.path));
658
+ const seen = new Set();
659
+ const lines = ['## Project Context', ''];
660
+ for (const source of selected) {
661
+ const unique = directives(source.operatorContent).filter((directive) => !seen.has(directive));
662
+ for (const directive of unique)
663
+ seen.add(directive);
664
+ if (unique.length === 0)
665
+ continue;
666
+ lines.push(`### From ${source.path}`, '', ...unique.map((directive) => `- ${directive}`), '');
667
+ }
668
+ if (lines.length === 2)
669
+ lines.push('Add project conventions, local hook/context pointers, and links to deeper project documents here.');
670
+ return lines.join('\n').trim();
671
+ }
672
+ function providerMigrationContent(source) {
673
+ return [
674
+ `# Provider-specific context from ${source.path}`,
675
+ '',
676
+ `Source attribution: migrated from \`${source.path}\`; checksum \`${source.checksum}\`.`,
677
+ '',
678
+ source.operatorContent.trim() || '(No operator-authored content remained after managed blocks were removed.)',
679
+ '',
680
+ ].join('\n');
681
+ }
682
+ async function configuredProviders(projectPath) {
683
+ const config = await readOptional(projectAiwgPath(projectPath, 'aiwg.config'));
684
+ if (config) {
685
+ try {
686
+ const parsed = JSON.parse(config);
687
+ if (Array.isArray(parsed.providers))
688
+ return parsed.providers.filter((provider) => typeof provider === 'string');
689
+ }
690
+ catch {
691
+ // Audit/migration reports malformed provider config through the normal CLI path.
692
+ }
693
+ }
694
+ return ['claude'];
695
+ }
696
+ async function stageMigrationWrites(projectPath, audit, options = {}) {
697
+ const writes = new Map();
698
+ for (const source of audit.sources.filter((item) => audit.plan.providerSources.includes(item.path))) {
699
+ writes.set(providerContextOutput(projectPath, source.path), providerMigrationContent(source));
700
+ }
701
+ const providerFiles = [...new Set([
702
+ ...audit.sources.filter((source) => source.path.replace(/\\/g, '/').includes('/context/providers/')).map((source) => source.path),
703
+ ...writes.keys(),
704
+ ])].sort();
705
+ const existingWorkspace = audit.sources.find((source) => source.path === 'WORKSPACE.md');
706
+ let workspaceOperatorContent = existingWorkspace?.managed
707
+ ? existingWorkspace.operatorContent
708
+ : neutralMigrationContent(audit);
709
+ if (options.extractProject) {
710
+ const extracted = await extractExistingProjectContext(projectPath);
711
+ workspaceOperatorContent = mergeProjectExtraction(workspaceOperatorContent, extracted.content);
712
+ }
713
+ writes.set('WORKSPACE.md', buildWorkspaceDocument(projectPath, workspaceOperatorContent, providerFiles));
714
+ const providers = await configuredProviders(projectPath);
715
+ const targetProviders = new Map();
716
+ for (const provider of providers) {
717
+ const definition = getProviderDefinition(provider);
718
+ if (!definition)
719
+ continue;
720
+ for (const target of definition.context.bootstrapTargets) {
721
+ const values = targetProviders.get(target) ?? [];
722
+ values.push(provider);
723
+ targetProviders.set(target, values);
724
+ }
725
+ }
726
+ for (const [target, targetProviderIds] of targetProviders) {
727
+ // Shared AGENTS.md is deliberately provider-neutral prose so sequential
728
+ // multi-provider deployment cannot make the last provider win.
729
+ const provider = targetProviderIds.length === 1 ? targetProviderIds[0] : 'generic';
730
+ const content = provider === 'generic'
731
+ ? [
732
+ '# Provider workspace bootstrap', WORKSPACE_SIGNATURE,
733
+ '<!-- Generated by AIWG. Project/operator context belongs in WORKSPACE.md. -->', '',
734
+ PROVIDER_BOOTSTRAP_START, '',
735
+ 'Read and follow [WORKSPACE.md](./WORKSPACE.md) first.',
736
+ 'Then read [AIWG.md](./AIWG.md) for AIWG discovery and framework routing.',
737
+ 'These are explicit reading instructions; a plain Markdown link is not claimed to auto-load.', '',
738
+ PROVIDER_BOOTSTRAP_END, '',
739
+ ].join('\n')
740
+ : buildProviderBootstrapFile(provider);
741
+ writes.set(target, content);
742
+ }
743
+ // Any detected operator-owned root startup file participates in the explicit
744
+ // adoption even when that provider is not currently enabled. Its authored
745
+ // content is already staged in an attributed provider file above; replacing
746
+ // the active root with a bootstrap completes the move and prevents two
747
+ // divergent sources of truth.
748
+ for (const source of audit.sources.filter((item) => audit.plan.providerSources.includes(item.path))) {
749
+ if (source.scope === 'root' && source.provider && source.path !== 'AIWG.md' && !targetProviders.has(source.path)) {
750
+ writes.set(source.path, buildProviderBootstrapFile(source.provider));
751
+ }
752
+ }
753
+ const activeCodexOverride = audit.sources.find((source) => source.path === 'AGENTS.override.md' && source.operatorContent.trim());
754
+ if (providers.includes('codex') && activeCodexOverride) {
755
+ writes.set('AGENTS.override.md', buildProviderBootstrapFile('codex'));
756
+ }
757
+ for (const provider of providers) {
758
+ const contract = getProviderDefinition(provider)?.context;
759
+ if (!contract?.configRegistration)
760
+ continue;
761
+ const configPath = contract.configRegistration.file;
762
+ const existing = await readOptional(path.join(projectPath, configPath));
763
+ let config = {};
764
+ if (existing !== null)
765
+ config = JSON.parse(existing);
766
+ const key = contract.configRegistration.key;
767
+ const current = Array.isArray(config[key]) ? config[key].filter((item) => typeof item === 'string') : [];
768
+ config[key] = [...new Set([...current, 'WORKSPACE.md', 'AIWG.md'])];
769
+ if (!('$schema' in config) && path.basename(configPath) === 'opencode.json')
770
+ config = { $schema: 'https://opencode.ai/config.json', ...config };
771
+ writes.set(configPath, `${JSON.stringify(config, null, 2)}\n`);
772
+ }
773
+ if (options.includeGeneratedContext) {
774
+ const normalizedPath = projectOutputPath(projectPath, projectAiwgPath(projectPath, 'AIWG.md'));
775
+ const existingNormalized = await readOptional(path.join(projectPath, normalizedPath)) ?? '';
776
+ writes.set(normalizedPath, await buildNormalizedAiwgMd(projectPath, existingNormalized));
777
+ const stagedClaude = writes.has('CLAUDE.md')
778
+ ? writes.get('CLAUDE.md')
779
+ : await readOptional(path.join(projectPath, 'CLAUDE.md'));
780
+ writes.set('AIWG.md', await buildAiwgMdContent(projectPath, stagedClaude));
781
+ }
782
+ return writes;
783
+ }
784
+ function safePreimageName(relativePath) {
785
+ return `${sha256(relativePath).slice(0, 16)}-${path.basename(relativePath)}`;
786
+ }
787
+ export async function migrateWorkspaceContext(projectPath, options = {}) {
788
+ const audit = await auditWorkspaceContext(projectPath);
789
+ const sensitiveFindingCount = audit.sensitiveFindings.length;
790
+ if (sensitiveFindingCount > 0) {
791
+ throw new Error(`Migration refused: ${sensitiveFindingCount} possible secret/credential value(s) found. Remove them before migration.`);
792
+ }
793
+ if (audit.conflicts.length > 0 && !options.allowConflicts) {
794
+ throw new Error(`Migration refused: ${audit.conflicts.length} ambiguous directive conflict(s). Review the deterministic audit or pass --allow-conflicts to preserve each source separately.`);
795
+ }
796
+ const writes = await stageMigrationWrites(projectPath, audit, {
797
+ extractProject: options.extractProject,
798
+ includeGeneratedContext: options.includeGeneratedContext,
799
+ });
800
+ const changedEntries = [];
801
+ for (const [relativePath, content] of writes) {
802
+ if (await readOptional(path.join(projectPath, relativePath)) !== content)
803
+ changedEntries.push([relativePath, content]);
804
+ }
805
+ if (options.dryRun || !options.apply) {
806
+ return { audit, dryRun: true, changed: changedEntries.length > 0, written: changedEntries.map(([relative]) => relative), backups: [] };
807
+ }
808
+ if (changedEntries.length === 0)
809
+ return { audit, dryRun: false, changed: false, written: [], backups: [] };
810
+ const createdAt = new Date().toISOString();
811
+ const id = `${createdAt.replace(/[:.]/g, '-')}-${sha256(JSON.stringify(audit.plan)).slice(0, 8)}`;
812
+ const transactionDir = projectAiwgPath(projectPath, 'context-migrations', id);
813
+ const preimageDir = path.join(transactionDir, 'preimages');
814
+ await fs.mkdir(preimageDir, { recursive: true });
815
+ const manifest = { version: 1, id, createdAt, projectPath, status: 'prepared', files: [] };
816
+ const backups = [];
817
+ for (const [relativePath, content] of changedEntries) {
818
+ const target = path.join(projectPath, relativePath);
819
+ const existing = await readOptional(target);
820
+ let preimage = null;
821
+ if (existing !== null) {
822
+ preimage = path.relative(projectPath, path.join(preimageDir, safePreimageName(relativePath))).replace(/\\/g, '/');
823
+ await fs.writeFile(path.join(projectPath, preimage), existing, 'utf8');
824
+ backups.push(preimage);
825
+ }
826
+ manifest.files.push({ path: relativePath, existed: existing !== null, preimage, outputChecksum: sha256(content) });
827
+ }
828
+ const manifestPath = path.join(transactionDir, 'manifest.json');
829
+ await atomicWrite(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
830
+ try {
831
+ for (const [relativePath, content] of changedEntries.sort(([left], [right]) => left.localeCompare(right))) {
832
+ await atomicWrite(path.join(projectPath, relativePath), content);
833
+ }
834
+ manifest.status = 'applied';
835
+ await atomicWrite(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
836
+ }
837
+ catch (error) {
838
+ await restoreMigrationManifest(projectPath, manifest);
839
+ throw error;
840
+ }
841
+ return { audit, dryRun: false, changed: true, transactionId: id, written: changedEntries.map(([relative]) => relative).sort(), backups };
842
+ }
843
+ async function restoreMigrationManifest(projectPath, manifest) {
844
+ for (const file of [...manifest.files].reverse()) {
845
+ const target = resolveProjectRelative(projectPath, file.path);
846
+ if (file.existed && file.preimage) {
847
+ const preimage = await fs.readFile(resolveProjectRelative(projectPath, file.preimage), 'utf8');
848
+ await atomicWrite(target, preimage);
849
+ }
850
+ else {
851
+ await fs.rm(target, { force: true });
852
+ }
853
+ }
854
+ }
855
+ export async function rollbackWorkspaceContext(projectPath, requestedId) {
856
+ const root = projectAiwgPath(projectPath, 'context-migrations');
857
+ let ids;
858
+ try {
859
+ ids = (await fs.readdir(root)).sort().reverse();
860
+ }
861
+ catch {
862
+ throw new Error('No workspace-context migration transactions found.');
863
+ }
864
+ const id = requestedId ?? ids[0];
865
+ if (!id || id.includes('/') || id.includes('\\'))
866
+ throw new Error('Invalid workspace-context migration id.');
867
+ const manifestPath = path.join(root, id, 'manifest.json');
868
+ const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
869
+ if (manifest.status === 'rolled-back')
870
+ return { id, restored: [] };
871
+ for (const file of manifest.files) {
872
+ const current = await readOptional(resolveProjectRelative(projectPath, file.path));
873
+ if (current === null || sha256(current) !== file.outputChecksum) {
874
+ throw new Error(`Rollback refused: ${file.path} changed after migration. Preserve or reconcile that work before restoring transaction ${id}.`);
875
+ }
876
+ }
877
+ await restoreMigrationManifest(projectPath, manifest);
878
+ manifest.status = 'rolled-back';
879
+ await atomicWrite(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
880
+ return { id, restored: manifest.files.map((file) => file.path) };
881
+ }
882
+ function markdownLinks(content) {
883
+ return [...content.matchAll(/\[[^\]]+\]\((\.\/?[^)#]+)(?:#[^)]+)?\)/g)].map((match) => match[1]);
884
+ }
885
+ export async function workspaceLinkedFiles(projectPath) {
886
+ const content = await readOptional(path.join(projectPath, 'WORKSPACE.md'));
887
+ if (!content)
888
+ return [];
889
+ const files = [];
890
+ for (const link of markdownLinks(content)) {
891
+ const normalized = link.replace(/^\.\//, '');
892
+ const resolved = path.resolve(projectPath, normalized);
893
+ if (resolved !== projectPath && !resolved.startsWith(`${path.resolve(projectPath)}${path.sep}`))
894
+ continue;
895
+ try {
896
+ const stat = await fs.stat(resolved);
897
+ if (stat.isFile())
898
+ files.push(resolved);
899
+ }
900
+ catch {
901
+ // Missing optional linked files are reported by doctor, not index builds.
902
+ }
903
+ }
904
+ return [...new Set(files)].sort();
905
+ }
906
+ export async function diagnoseWorkspaceContext(projectPath) {
907
+ const diagnostics = [];
908
+ const audit = await auditWorkspaceContext(projectPath);
909
+ const workspacePath = path.join(projectPath, 'WORKSPACE.md');
910
+ const workspace = await readOptional(workspacePath);
911
+ if (!workspace) {
912
+ diagnostics.push({ severity: 'info', code: 'legacy-layout', message: 'Legacy provider context layout is supported; run `aiwg workspace-context migrate --dry-run` for opt-in conversion.' });
913
+ return diagnostics;
914
+ }
915
+ if (!workspace.includes(WORKSPACE_MANAGED_START) || !workspace.includes(WORKSPACE_OPERATOR_START)) {
916
+ diagnostics.push({ severity: 'warning', code: 'workspace-unmanaged', message: 'WORKSPACE.md lacks complete AIWG ownership markers.', path: 'WORKSPACE.md' });
917
+ }
918
+ if (workspace.includes(PROVIDER_BOOTSTRAP_START)) {
919
+ diagnostics.push({ severity: 'error', code: 'include-loop', message: 'WORKSPACE.md contains a provider bootstrap marker and could create a self-referential context loop.', path: 'WORKSPACE.md' });
920
+ }
921
+ for (const link of markdownLinks(workspace)) {
922
+ const normalized = link.replace(/^\.\//, '');
923
+ if (normalized.includes('WORKSPACE.md'))
924
+ continue;
925
+ let linkedPath;
926
+ try {
927
+ linkedPath = resolveProjectRelative(projectPath, normalized);
928
+ }
929
+ catch {
930
+ diagnostics.push({ severity: 'error', code: 'unsafe-link', message: `Linked context path escapes the project: ${normalized}`, path: 'WORKSPACE.md' });
931
+ continue;
932
+ }
933
+ let exists = false;
934
+ try {
935
+ await fs.stat(linkedPath);
936
+ exists = true;
937
+ }
938
+ catch {
939
+ exists = false;
940
+ }
941
+ if (!exists && !normalized.endsWith('quickref.json')) {
942
+ diagnostics.push({ severity: 'warning', code: 'missing-link', message: `Linked context file is missing: ${normalized}`, path: 'WORKSPACE.md' });
943
+ }
944
+ }
945
+ for (const conflict of audit.conflicts) {
946
+ diagnostics.push({ severity: 'error', code: 'directive-conflict', message: `Conflicting duplicate directive group '${conflict.key}' appears in ${conflict.sources.map((source) => source.path).join(', ')}.` });
947
+ }
948
+ for (const overlap of audit.identical) {
949
+ diagnostics.push({ severity: 'warning', code: 'duplicate-directive', message: `Identical directive is duplicated across ${overlap.sources.join(', ')}.` });
950
+ }
951
+ for (const finding of audit.sensitiveFindings) {
952
+ diagnostics.push({ severity: 'error', code: 'possible-secret', message: 'Possible credential value found in context; remove it.', path: finding.path });
953
+ }
954
+ const providers = await configuredProviders(projectPath);
955
+ for (const provider of providers) {
956
+ const definition = getProviderDefinition(provider);
957
+ if (!definition)
958
+ continue;
959
+ for (const target of definition.context.bootstrapTargets) {
960
+ const targetContent = await readOptional(path.join(projectPath, target));
961
+ if (targetContent?.includes(WORKSPACE_SIGNATURE) && !targetContent.includes('WORKSPACE.md')) {
962
+ diagnostics.push({ severity: 'error', code: 'bootstrap-drift', message: `${target} is AIWG-managed but no longer points to WORKSPACE.md first.`, path: target });
963
+ }
964
+ }
965
+ if (definition.context.configRegistration) {
966
+ const registration = definition.context.configRegistration;
967
+ const config = await readOptional(path.join(projectPath, registration.file));
968
+ if (config) {
969
+ try {
970
+ const parsed = JSON.parse(config);
971
+ const values = Array.isArray(parsed[registration.key]) ? parsed[registration.key] : [];
972
+ if (!values.includes('WORKSPACE.md'))
973
+ diagnostics.push({ severity: 'error', code: 'registration-drift', message: `${registration.file} does not register WORKSPACE.md.`, path: registration.file });
974
+ }
975
+ catch {
976
+ diagnostics.push({ severity: 'error', code: 'registration-invalid', message: `${registration.file} is invalid JSON.`, path: registration.file });
977
+ }
978
+ }
979
+ }
980
+ }
981
+ if (diagnostics.length === 0)
982
+ diagnostics.push({ severity: 'info', code: 'healthy', message: 'Workspace context graph is healthy.' });
983
+ return diagnostics;
984
+ }
985
+ export function providerContextContract(provider) {
986
+ return getProviderDefinition(provider)?.context;
987
+ }
988
+ //# sourceMappingURL=workspace-context.js.map