@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,396 @@
1
+ /**
2
+ * Update Checker
3
+ *
4
+ * Checks for available updates and prompts the user to update.
5
+ * - Stable channel: Checks npm registry for newer version
6
+ * - Edge channel: Checks git remote for new commits
7
+ *
8
+ * @module src/update/checker
9
+ * @version 2024.12.0
10
+ */
11
+
12
+ import fs from 'fs/promises';
13
+ import path from 'path';
14
+ import https from 'https';
15
+ import { execSync } from 'child_process';
16
+ import { createInterface } from 'readline';
17
+ import { loadConfig, saveConfig, getChannel, getPackageRoot } from '../channel/manager.mjs';
18
+
19
+ const NPM_REGISTRY = 'https://registry.npmjs.org/aiwg';
20
+
21
+ /**
22
+ * Fetch latest version for a given npm dist-tag
23
+ * @param {string} distTag - npm dist-tag to resolve (latest, next, nightly)
24
+ * @returns {Promise<string|null>} Resolved version or null on error
25
+ */
26
+ async function fetchNpmDistTag(distTag = 'latest') {
27
+ return new Promise((resolve) => {
28
+ const request = https.get(NPM_REGISTRY, { timeout: 5000 }, (res) => {
29
+ if (res.statusCode !== 200) {
30
+ resolve(null);
31
+ return;
32
+ }
33
+
34
+ let data = '';
35
+ res.on('data', (chunk) => { data += chunk; });
36
+ res.on('end', () => {
37
+ try {
38
+ const pkg = JSON.parse(data);
39
+ resolve(pkg['dist-tags']?.[distTag] || null);
40
+ } catch {
41
+ resolve(null);
42
+ }
43
+ });
44
+ });
45
+
46
+ request.on('error', () => resolve(null));
47
+ request.on('timeout', () => {
48
+ request.destroy();
49
+ resolve(null);
50
+ });
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Fetch latest version from npm registry (stable)
56
+ * @returns {Promise<string|null>} Latest version or null on error
57
+ */
58
+ async function fetchLatestNpmVersion() {
59
+ return fetchNpmDistTag('latest');
60
+ }
61
+
62
+ /**
63
+ * Check if there are new commits in the git remote (edge channel)
64
+ * @param {string} edgePath - Path to edge installation
65
+ * @returns {Promise<boolean>} True if updates available
66
+ */
67
+ async function checkGitUpdates(edgePath) {
68
+ try {
69
+ // Fetch latest without merging
70
+ execSync('git fetch --quiet', { cwd: edgePath, timeout: 10000 });
71
+
72
+ // Check if local is behind remote
73
+ const localHash = execSync('git rev-parse HEAD', {
74
+ cwd: edgePath,
75
+ encoding: 'utf8',
76
+ }).trim();
77
+
78
+ const remoteHash = execSync('git rev-parse origin/main', {
79
+ cwd: edgePath,
80
+ encoding: 'utf8',
81
+ }).trim();
82
+
83
+ return localHash !== remoteHash;
84
+ } catch {
85
+ return false;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Compare CalVer versions
91
+ * @param {string} current - Current version (e.g., "2024.12.0")
92
+ * @param {string} latest - Latest version
93
+ * @returns {boolean} True if latest is newer
94
+ */
95
+ function isNewerVersion(current, latest) {
96
+ if (!current || !latest) return false;
97
+
98
+ const parseVersion = (v) => {
99
+ const match = v.match(/^(\d+)\.(\d+)\.(\d+)/);
100
+ if (!match) return [0, 0, 0];
101
+ return [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10)];
102
+ };
103
+
104
+ const [cy, cm, cp] = parseVersion(current);
105
+ const [ly, lm, lp] = parseVersion(latest);
106
+
107
+ if (ly > cy) return true;
108
+ if (ly === cy && lm > cm) return true;
109
+ if (ly === cy && lm === cm && lp > cp) return true;
110
+
111
+ return false;
112
+ }
113
+
114
+ /**
115
+ * Prompt user for update confirmation
116
+ * @param {string} message - Prompt message
117
+ * @returns {Promise<boolean>} True if user confirms
118
+ */
119
+ async function promptUpdate(message) {
120
+ // Skip prompt if not interactive terminal
121
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
122
+ return false;
123
+ }
124
+
125
+ const rl = createInterface({
126
+ input: process.stdin,
127
+ output: process.stdout,
128
+ });
129
+
130
+ // Hard timeout so the update prompt cannot hang the CLI. The update check
131
+ // runs as a background fire-and-forget from bin/aiwg.mjs; if the user isn't
132
+ // watching the terminal, we silently decline instead of blocking forever.
133
+ // Override via AIWG_PROMPT_TIMEOUT_MS.
134
+ const timeoutMs = (() => {
135
+ const raw = process.env['AIWG_PROMPT_TIMEOUT_MS'];
136
+ const n = raw ? parseInt(raw, 10) : NaN;
137
+ return Number.isFinite(n) && n > 0 ? n : 10_000;
138
+ })();
139
+
140
+ return new Promise((resolve) => {
141
+ let settled = false;
142
+ const timer = setTimeout(() => {
143
+ if (settled) return;
144
+ settled = true;
145
+ rl.close();
146
+ resolve(false);
147
+ }, timeoutMs);
148
+ timer.unref?.();
149
+ rl.question(`${message} [y/N]: `, (answer) => {
150
+ if (settled) return;
151
+ settled = true;
152
+ clearTimeout(timer);
153
+ rl.close();
154
+ const normalized = answer.toLowerCase().trim();
155
+ resolve(normalized === 'y' || normalized === 'yes');
156
+ });
157
+ });
158
+ }
159
+
160
+ /**
161
+ * Check for updates (background, non-blocking)
162
+ * This is called on every CLI invocation but only checks periodically
163
+ */
164
+ export async function checkForUpdates() {
165
+ const config = await loadConfig();
166
+
167
+ // Check if enough time has passed since last check
168
+ const now = Date.now();
169
+ const lastCheck = config.lastUpdateCheck || 0;
170
+ const interval = config.updateCheckInterval || 86400000; // 24 hours
171
+
172
+ if (now - lastCheck < interval) {
173
+ // Too soon to check again
174
+ return;
175
+ }
176
+
177
+ // Update last check time
178
+ config.lastUpdateCheck = now;
179
+ await saveConfig(config);
180
+
181
+ if (config.channel === 'next') {
182
+ await checkNextUpdates(config);
183
+ } else if (config.channel === 'nightly') {
184
+ await checkNightlyUpdates(config);
185
+ } else if (config.channel === 'edge') {
186
+ await checkEdgeUpdates(config);
187
+ } else {
188
+ // stable (or unrecognised — treat as stable)
189
+ await checkStableUpdates(config);
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Check for stable (npm) channel updates
195
+ */
196
+ async function checkStableUpdates(config) {
197
+ const packageRoot = getPackageRoot();
198
+ const packageJsonPath = path.join(packageRoot, 'package.json');
199
+
200
+ try {
201
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
202
+ const currentVersion = packageJson.version;
203
+ const latestVersion = await fetchLatestNpmVersion();
204
+
205
+ if (latestVersion && isNewerVersion(currentVersion, latestVersion)) {
206
+ console.log('');
207
+ console.log(`A new version of aiwg is available: ${currentVersion} → ${latestVersion}`);
208
+
209
+ const shouldUpdate = await promptUpdate('Would you like to update now?');
210
+
211
+ if (shouldUpdate) {
212
+ console.log('');
213
+ console.log('Updating aiwg...');
214
+ try {
215
+ execSync('npm install -g aiwg@latest', { stdio: 'inherit' });
216
+ console.log('Update complete! Please restart your terminal.');
217
+ } catch (error) {
218
+ console.error('Update failed. Run manually: npm install -g aiwg@latest');
219
+ }
220
+ } else {
221
+ console.log('Update skipped. Run `npm install -g aiwg@latest` when ready.');
222
+ }
223
+ console.log('');
224
+ }
225
+ } catch {
226
+ // Silently ignore errors during update check
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Check for next (alpha/beta/RC) channel updates
232
+ */
233
+ async function checkNextUpdates(config) {
234
+ const packageRoot = getPackageRoot();
235
+ const packageJsonPath = path.join(packageRoot, 'package.json');
236
+
237
+ try {
238
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
239
+ const currentVersion = packageJson.version;
240
+ const latestVersion = await fetchNpmDistTag('next');
241
+
242
+ if (!latestVersion) return;
243
+
244
+ if (currentVersion !== latestVersion) {
245
+ console.log('');
246
+ console.log(`A new next release is available: ${currentVersion} → ${latestVersion}`);
247
+
248
+ const shouldUpdate = await promptUpdate('Would you like to update now?');
249
+
250
+ if (shouldUpdate) {
251
+ console.log('');
252
+ console.log('Updating aiwg@next...');
253
+ try {
254
+ execSync('npm install -g aiwg@next', { stdio: 'inherit' });
255
+ console.log('Update complete! Please restart your terminal.');
256
+ } catch {
257
+ console.error('Update failed. Run manually: npm install -g aiwg@next');
258
+ }
259
+ } else {
260
+ console.log('Update skipped. Run `npm install -g aiwg@next` when ready.');
261
+ }
262
+ console.log('');
263
+ }
264
+ } catch {
265
+ // Silently ignore errors during update check
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Check for nightly channel updates
271
+ */
272
+ async function checkNightlyUpdates(config) {
273
+ const packageRoot = getPackageRoot();
274
+ const packageJsonPath = path.join(packageRoot, 'package.json');
275
+
276
+ try {
277
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
278
+ const currentVersion = packageJson.version;
279
+ const latestVersion = await fetchNpmDistTag('nightly');
280
+
281
+ if (!latestVersion) return;
282
+
283
+ if (currentVersion !== latestVersion) {
284
+ console.log('');
285
+ console.log(`A new nightly snapshot is available: ${currentVersion} → ${latestVersion}`);
286
+
287
+ const shouldUpdate = await promptUpdate('Would you like to update now?');
288
+
289
+ if (shouldUpdate) {
290
+ console.log('');
291
+ console.log('Updating aiwg@nightly...');
292
+ try {
293
+ execSync('npm install -g aiwg@nightly', { stdio: 'inherit' });
294
+ console.log('Update complete! Please restart your terminal.');
295
+ } catch {
296
+ console.error('Update failed. Run manually: npm install -g aiwg@nightly');
297
+ }
298
+ } else {
299
+ console.log('Update skipped. Run `npm install -g aiwg@nightly` when ready.');
300
+ }
301
+ console.log('');
302
+ }
303
+ } catch {
304
+ // Silently ignore errors during update check
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Check for edge (git) channel updates
310
+ */
311
+ async function checkEdgeUpdates(config) {
312
+ const hasUpdates = await checkGitUpdates(config.edgePath);
313
+
314
+ if (hasUpdates) {
315
+ console.log('');
316
+ console.log('New commits available in the main branch.');
317
+
318
+ const shouldUpdate = await promptUpdate('Would you like to update now?');
319
+
320
+ if (shouldUpdate) {
321
+ console.log('');
322
+ console.log('Updating edge installation...');
323
+ try {
324
+ execSync('git pull --ff-only', { cwd: config.edgePath, stdio: 'inherit' });
325
+ console.log('Update complete!');
326
+ } catch (error) {
327
+ console.error('Update failed. Run manually:');
328
+ console.error(` cd ${config.edgePath} && git pull`);
329
+ }
330
+ } else {
331
+ console.log('Update skipped. Run `aiwg -update` when ready.');
332
+ }
333
+ console.log('');
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Force an update check (called by aiwg -update)
339
+ */
340
+ export async function forceUpdateCheck() {
341
+ const config = await loadConfig();
342
+ const packageRoot = getPackageRoot();
343
+ const packageJsonPath = path.join(packageRoot, 'package.json');
344
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
345
+ const currentVersion = packageJson.version;
346
+
347
+ if (config.channel === 'next') {
348
+ console.log('Checking for updates on next channel...');
349
+ const latestVersion = await fetchNpmDistTag('next');
350
+ if (!latestVersion) {
351
+ console.log('Could not check npm registry. Try: npm install -g aiwg@next');
352
+ return;
353
+ }
354
+ if (currentVersion !== latestVersion) {
355
+ console.log(`Update available: ${currentVersion} → ${latestVersion}`);
356
+ console.log('');
357
+ console.log('Run: npm install -g aiwg@next');
358
+ } else {
359
+ console.log(`You are on the latest next release: ${currentVersion}`);
360
+ }
361
+ } else if (config.channel === 'nightly') {
362
+ console.log('Checking for updates on nightly channel...');
363
+ const latestVersion = await fetchNpmDistTag('nightly');
364
+ if (!latestVersion) {
365
+ console.log('Could not check npm registry. Try: npm install -g aiwg@nightly');
366
+ return;
367
+ }
368
+ if (currentVersion !== latestVersion) {
369
+ console.log(`Update available: ${currentVersion} → ${latestVersion}`);
370
+ console.log('');
371
+ console.log('Run: npm install -g aiwg@nightly');
372
+ } else {
373
+ console.log(`You are on the latest nightly snapshot: ${currentVersion}`);
374
+ }
375
+ } else if (config.channel === 'edge') {
376
+ const { updateEdge } = await import('../channel/manager.mjs');
377
+ await updateEdge();
378
+ } else {
379
+ // stable
380
+ console.log('Checking for updates...');
381
+ const latestVersion = await fetchLatestNpmVersion();
382
+
383
+ if (!latestVersion) {
384
+ console.log('Could not check npm registry. Try: npm install -g aiwg@latest');
385
+ return;
386
+ }
387
+
388
+ if (isNewerVersion(currentVersion, latestVersion)) {
389
+ console.log(`Update available: ${currentVersion} → ${latestVersion}`);
390
+ console.log('');
391
+ console.log('Run: npm install -g aiwg@latest');
392
+ } else {
393
+ console.log(`You are on the latest version: ${currentVersion}`);
394
+ }
395
+ }
396
+ }
@@ -0,0 +1,235 @@
1
+ /**
2
+ * AIWG Update Notifier
3
+ *
4
+ * Non-blocking update check for the AIWG CLI. Follows the
5
+ * `update-notifier` / `simple-update-notifier` pattern:
6
+ *
7
+ * 1. On CLI invocation, `scheduleBackgroundCheck()` is called from
8
+ * `bin/aiwg.mjs`. It spawns a **detached, unref()'d** child Node
9
+ * process that runs this file with `--check` and writes the result
10
+ * to `~/.aiwg/update-notifier.json`. The child exits immediately
11
+ * after writing; the parent never waits on it.
12
+ *
13
+ * 2. On the *next* invocation, `maybePrintNotice()` reads the cache
14
+ * and prints a single-line "update available" message to stderr.
15
+ * The user's current command is never delayed by a network call.
16
+ *
17
+ * The update check honours `NO_UPDATE_NOTIFIER`, `CI`, the isInteractive()
18
+ * helper, and `--no-update-check`. In all of those cases the check is
19
+ * skipped entirely.
20
+ *
21
+ * Phase 3 of the CLI Stabilization Epic (#920). Replaces the synchronous
22
+ * `checkForUpdates()` + hand-rolled prompt in `checker.mjs` that held the
23
+ * event loop open after the command completed.
24
+ *
25
+ * @module src/update/notifier
26
+ */
27
+
28
+ import https from 'https';
29
+ import path from 'path';
30
+ import os from 'os';
31
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
32
+ import { spawn } from 'child_process';
33
+ import { fileURLToPath } from 'url';
34
+
35
+ const CACHE_DIR = path.join(os.homedir(), '.aiwg');
36
+ const CACHE_FILE = path.join(CACHE_DIR, 'update-notifier.json');
37
+
38
+ /**
39
+ * Minimum time between update checks (24 hours). Checked via the
40
+ * `lastCheckAt` timestamp in the cache file.
41
+ */
42
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
43
+
44
+ /**
45
+ * Hard timeout for the npm registry HTTPS request. Keeps the spawned
46
+ * background child from lingering on slow networks.
47
+ */
48
+ const NETWORK_TIMEOUT_MS = 10_000;
49
+
50
+ /**
51
+ * Read an env var and return true iff it's set to a truthy value.
52
+ */
53
+ function envFlag(name) {
54
+ const v = process.env[name];
55
+ if (!v) return false;
56
+ return v !== '0' && v.toLowerCase() !== 'false';
57
+ }
58
+
59
+ /**
60
+ * True iff update checking is currently disabled by env / CI conventions.
61
+ */
62
+ function isDisabled() {
63
+ if (envFlag('NO_UPDATE_NOTIFIER')) return true;
64
+ if (envFlag('AIWG_NO_UPDATE_CHECK')) return true;
65
+ if (envFlag('CI')) return true;
66
+ if (envFlag('GITHUB_ACTIONS')) return true;
67
+ if (envFlag('GITLAB_CI')) return true;
68
+ // Non-interactive terminals shouldn't get a notice they can't act on.
69
+ if (!process.stdout.isTTY) return true;
70
+ return false;
71
+ }
72
+
73
+ /**
74
+ * Read the update-notifier cache. Returns null if absent or malformed.
75
+ */
76
+ function readCache() {
77
+ if (!existsSync(CACHE_FILE)) return null;
78
+ try {
79
+ return JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+
85
+ function writeCache(data) {
86
+ try {
87
+ mkdirSync(CACHE_DIR, { recursive: true });
88
+ writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2) + '\n', 'utf-8');
89
+ } catch {
90
+ // Best-effort — update-notifier failures are never fatal.
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Compare two CalVer/semver-style versions. Returns true iff `latest` is
96
+ * newer than `current`. Cheap, no full semver parsing.
97
+ */
98
+ function isNewer(current, latest) {
99
+ if (!current || !latest || current === latest) return false;
100
+ const parse = (v) => {
101
+ const match = String(v).match(/^(\d+)\.(\d+)\.(\d+)/);
102
+ if (!match) return [0, 0, 0];
103
+ return [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10)];
104
+ };
105
+ const [cy, cm, cp] = parse(current);
106
+ const [ly, lm, lp] = parse(latest);
107
+ if (ly > cy) return true;
108
+ if (ly === cy && lm > cm) return true;
109
+ if (ly === cy && lm === cm && lp > cp) return true;
110
+ return false;
111
+ }
112
+
113
+ /**
114
+ * Fetch the latest published version for the `latest` dist-tag from npm.
115
+ * Resolves to `null` on error or timeout.
116
+ */
117
+ function fetchLatestVersion() {
118
+ return new Promise((resolve) => {
119
+ const req = https.get(
120
+ 'https://registry.npmjs.org/aiwg',
121
+ { timeout: NETWORK_TIMEOUT_MS },
122
+ (res) => {
123
+ if (res.statusCode !== 200) {
124
+ resolve(null);
125
+ return;
126
+ }
127
+ let data = '';
128
+ res.on('data', (chunk) => { data += chunk; });
129
+ res.on('end', () => {
130
+ try {
131
+ const pkg = JSON.parse(data);
132
+ resolve(pkg['dist-tags']?.latest ?? null);
133
+ } catch {
134
+ resolve(null);
135
+ }
136
+ });
137
+ },
138
+ );
139
+ req.on('error', () => resolve(null));
140
+ req.on('timeout', () => {
141
+ req.destroy();
142
+ resolve(null);
143
+ });
144
+ });
145
+ }
146
+
147
+ /**
148
+ * Read current CLI version from the package.json at `packageRoot`.
149
+ */
150
+ function readCurrentVersion(packageRoot) {
151
+ try {
152
+ const pkgPath = path.join(packageRoot, 'package.json');
153
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
154
+ return pkg.version;
155
+ } catch {
156
+ return null;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Run the actual update check and write the cache file. Invoked by the
162
+ * spawned background child via `node src/update/notifier.mjs --check`.
163
+ */
164
+ async function runCheck(packageRoot) {
165
+ const currentVersion = readCurrentVersion(packageRoot);
166
+ const latestVersion = await fetchLatestVersion();
167
+ writeCache({
168
+ lastCheckAt: new Date().toISOString(),
169
+ current: currentVersion,
170
+ latest: latestVersion,
171
+ hasUpdate: !!(currentVersion && latestVersion && isNewer(currentVersion, latestVersion)),
172
+ });
173
+ }
174
+
175
+ /**
176
+ * Schedule a background update check if one hasn't run in the last
177
+ * CHECK_INTERVAL_MS. Non-blocking: spawns a detached child process and
178
+ * returns immediately. The parent must not wait on the child.
179
+ *
180
+ * Called exactly once per CLI invocation from `bin/aiwg.mjs`.
181
+ */
182
+ export function scheduleBackgroundCheck(packageRoot) {
183
+ if (isDisabled()) return;
184
+
185
+ const cache = readCache();
186
+ if (cache?.lastCheckAt) {
187
+ const age = Date.now() - new Date(cache.lastCheckAt).getTime();
188
+ if (age < CHECK_INTERVAL_MS) return; // recent enough — skip
189
+ }
190
+
191
+ try {
192
+ const entry = fileURLToPath(import.meta.url);
193
+ const child = spawn(
194
+ process.execPath,
195
+ [entry, '--check', '--package-root', packageRoot],
196
+ {
197
+ detached: true,
198
+ stdio: 'ignore',
199
+ env: { ...process.env, AIWG_UPDATE_NOTIFIER_CHILD: '1' },
200
+ },
201
+ );
202
+ // Unref so the parent can exit without waiting for the child. This is
203
+ // the crucial detail that prevents the "command hangs for 5 minutes"
204
+ // symptom we had before #918.
205
+ child.unref();
206
+ } catch {
207
+ // Spawn failures are non-fatal; the next invocation will retry.
208
+ }
209
+ }
210
+
211
+ /**
212
+ * If the cache indicates an update is available AND the current terminal
213
+ * is interactive, print a single-line notice to stderr. Never prompts.
214
+ * Safe to call unconditionally from `bin/aiwg.mjs` — gated by isDisabled().
215
+ */
216
+ export function maybePrintNotice() {
217
+ if (isDisabled()) return;
218
+ const cache = readCache();
219
+ if (!cache?.hasUpdate || !cache.current || !cache.latest) return;
220
+ // One-line, non-intrusive. Users who want to update run `aiwg update`.
221
+ const msg = `aiwg: update available ${cache.current} → ${cache.latest} (run: npm install -g aiwg)`;
222
+ process.stderr.write(`\n${msg}\n`);
223
+ }
224
+
225
+ // ── Child-process entry ────────────────────────────────────────────────
226
+
227
+ // If invoked with `--check`, act as the background-child worker.
228
+ if (process.argv.includes('--check')) {
229
+ const rootIdx = process.argv.indexOf('--package-root');
230
+ const packageRoot = rootIdx >= 0 ? process.argv[rootIdx + 1] : process.cwd();
231
+ runCheck(packageRoot).catch(() => {
232
+ // Swallow all errors — the background child must never write to stderr.
233
+ process.exit(0);
234
+ });
235
+ }