@jaimevalasek/aioson 1.5.1 → 1.7.0

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 (341) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -226
  3. package/docs/design-previews/aurora-command-ui-website.html +884 -0
  4. package/docs/design-previews/aurora-command-ui.html +682 -0
  5. package/docs/design-previews/bold-editorial-ui-website.html +658 -0
  6. package/docs/design-previews/bold-editorial-ui.html +717 -0
  7. package/docs/design-previews/clean-saas-ui-website.html +1202 -0
  8. package/docs/design-previews/clean-saas-ui.html +549 -0
  9. package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
  10. package/docs/design-previews/cognitive-core-ui.html +463 -0
  11. package/docs/design-previews/glassmorphism-ui-website.html +572 -0
  12. package/docs/design-previews/glassmorphism-ui.html +886 -0
  13. package/docs/design-previews/index.html +699 -0
  14. package/docs/design-previews/interface-design-website.html +1187 -0
  15. package/docs/design-previews/interface-design.html +513 -0
  16. package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
  17. package/docs/design-previews/neo-brutalist-ui.html +797 -0
  18. package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
  19. package/docs/design-previews/premium-command-center-ui.html +552 -0
  20. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  21. package/docs/design-previews/warm-craft-ui-website.html +684 -0
  22. package/docs/design-previews/warm-craft-ui.html +739 -0
  23. package/docs/en/cli-reference.md +20 -9
  24. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  25. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  26. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  27. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  28. package/docs/pt/README.md +10 -0
  29. package/docs/pt/agent-sharding.md +132 -0
  30. package/docs/pt/agentes.md +9 -2
  31. package/docs/pt/busca-de-contexto.md +129 -0
  32. package/docs/pt/cache-de-contexto.md +156 -0
  33. package/docs/pt/comandos-cli.md +915 -1
  34. package/docs/pt/design-hybrid-forge.md +356 -0
  35. package/docs/pt/devlog-pipeline.md +270 -0
  36. package/docs/pt/fluxo-artefatos.md +178 -0
  37. package/docs/pt/hooks-session-guard.md +454 -0
  38. package/docs/pt/inicio-rapido.md +54 -3
  39. package/docs/pt/inteligencia-adaptativa.md +324 -0
  40. package/docs/pt/monitor-de-contexto.md +158 -0
  41. package/docs/pt/recuperacao-de-sessao.md +125 -0
  42. package/docs/pt/sandbox.md +125 -0
  43. package/docs/pt/sdd-automation-scripts.md +557 -0
  44. package/docs/pt/site-forge.md +309 -0
  45. package/docs/pt/skills.md +98 -6
  46. package/docs/pt/spec-learnings-pipeline.md +265 -0
  47. package/package.json +1 -1
  48. package/src/a2a/client.js +165 -0
  49. package/src/a2a/server.js +223 -0
  50. package/src/agent-loader.js +280 -0
  51. package/src/cli.js +329 -1
  52. package/src/commands/agent-audit.js +397 -0
  53. package/src/commands/agent-export-skill.js +229 -0
  54. package/src/commands/agent-loader.js +85 -0
  55. package/src/commands/artifact-validate.js +189 -0
  56. package/src/commands/brief-gen.js +405 -0
  57. package/src/commands/brief-validate.js +65 -0
  58. package/src/commands/classify.js +256 -0
  59. package/src/commands/context-cache.js +90 -0
  60. package/src/commands/context-compact.js +49 -0
  61. package/src/commands/context-health.js +175 -0
  62. package/src/commands/context-monitor.js +163 -0
  63. package/src/commands/context-search.js +66 -0
  64. package/src/commands/context-trim.js +177 -0
  65. package/src/commands/design-hybrid-options.js +385 -0
  66. package/src/commands/detect-test-runner.js +55 -0
  67. package/src/commands/devlog-export-brains.js +27 -0
  68. package/src/commands/devlog-process.js +292 -0
  69. package/src/commands/devlog-watch.js +131 -0
  70. package/src/commands/feature-close.js +165 -0
  71. package/src/commands/gate-check.js +228 -0
  72. package/src/commands/health.js +214 -0
  73. package/src/commands/hooks-emit.js +253 -0
  74. package/src/commands/hooks-install.js +347 -0
  75. package/src/commands/init.js +54 -13
  76. package/src/commands/install.js +52 -13
  77. package/src/commands/learning-auto-promote.js +195 -0
  78. package/src/commands/learning-evolve.js +364 -0
  79. package/src/commands/learning-export.js +103 -0
  80. package/src/commands/learning-rollback.js +164 -0
  81. package/src/commands/live.js +59 -1
  82. package/src/commands/pattern-detect.js +33 -0
  83. package/src/commands/preflight-context.js +30 -0
  84. package/src/commands/preflight.js +208 -0
  85. package/src/commands/pulse-update.js +130 -0
  86. package/src/commands/recovery.js +43 -0
  87. package/src/commands/runner-daemon.js +274 -0
  88. package/src/commands/runner-plan.js +70 -0
  89. package/src/commands/runner-queue-from-plan.js +166 -0
  90. package/src/commands/runner-queue.js +189 -0
  91. package/src/commands/runner-run.js +129 -0
  92. package/src/commands/runtime.js +47 -1
  93. package/src/commands/sandbox.js +37 -0
  94. package/src/commands/self-implement-loop.js +256 -0
  95. package/src/commands/session-guard.js +218 -0
  96. package/src/commands/setup-context.js +22 -2
  97. package/src/commands/setup.js +178 -0
  98. package/src/commands/sizing.js +165 -0
  99. package/src/commands/skill.js +144 -32
  100. package/src/commands/spec-checkpoint.js +177 -0
  101. package/src/commands/spec-status.js +79 -0
  102. package/src/commands/spec-sync.js +190 -0
  103. package/src/commands/spec-tasks.js +288 -0
  104. package/src/commands/squad-autorun.js +1220 -0
  105. package/src/commands/squad-bus.js +217 -0
  106. package/src/commands/squad-card.js +149 -0
  107. package/src/commands/squad-daemon.js +134 -0
  108. package/src/commands/squad-dependency-graph.js +164 -0
  109. package/src/commands/squad-review.js +106 -0
  110. package/src/commands/squad-scaffold.js +55 -0
  111. package/src/commands/squad-tool-register.js +157 -0
  112. package/src/commands/state-save.js +122 -0
  113. package/src/commands/tool-registry-cmd.js +232 -0
  114. package/src/commands/update.js +9 -0
  115. package/src/commands/verify-gate.js +572 -0
  116. package/src/commands/workflow-execute.js +241 -0
  117. package/src/constants.js +18 -0
  118. package/src/context-cache.js +159 -0
  119. package/src/context-search.js +326 -0
  120. package/src/design-variation-catalog.js +503 -0
  121. package/src/i18n/messages/en.js +32 -2
  122. package/src/i18n/messages/es.js +30 -2
  123. package/src/i18n/messages/fr.js +30 -2
  124. package/src/i18n/messages/pt-BR.js +32 -2
  125. package/src/install-animation.js +260 -0
  126. package/src/install-profile.js +143 -0
  127. package/src/install-wizard.js +475 -0
  128. package/src/installer.js +44 -10
  129. package/src/lib/health-check.js +158 -0
  130. package/src/lib/hook-protocol.js +76 -0
  131. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  132. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  133. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  134. package/src/mcp/resources/squad-state.js +130 -0
  135. package/src/parser.js +7 -1
  136. package/src/preflight-engine.js +443 -0
  137. package/src/recovery-context-session.js +154 -0
  138. package/src/runner/cascade.js +97 -0
  139. package/src/runner/cli-launcher.js +109 -0
  140. package/src/runner/plan-importer.js +63 -0
  141. package/src/runner/queue-store.js +159 -0
  142. package/src/runtime-store.js +158 -4
  143. package/src/sandbox.js +177 -0
  144. package/src/squad/agent-teams-adapter.js +264 -0
  145. package/src/squad/brief-validator.js +350 -0
  146. package/src/squad/bus-bridge.js +140 -0
  147. package/src/squad/context-compactor.js +265 -0
  148. package/src/squad/cross-ai-synthesizer.js +250 -0
  149. package/src/squad/hooks-generator.js +196 -0
  150. package/src/squad/inter-squad-events.js +175 -0
  151. package/src/squad/intra-bus.js +345 -0
  152. package/src/squad/learning-extractor.js +213 -0
  153. package/src/squad/pattern-detector.js +365 -0
  154. package/src/squad/preflight-context.js +296 -0
  155. package/src/squad/recovery-context.js +242 -71
  156. package/src/squad/reflection.js +365 -0
  157. package/src/squad/squad-scaffold.js +177 -0
  158. package/src/squad/state-manager.js +310 -0
  159. package/src/squad/task-decomposer.js +652 -0
  160. package/src/squad/verify-gate.js +303 -0
  161. package/src/tool-executor.js +94 -0
  162. package/src/updater.js +10 -3
  163. package/src/worker-runner.js +186 -1
  164. package/template/.aioson/agents/analyst.md +119 -3
  165. package/template/.aioson/agents/architect.md +98 -0
  166. package/template/.aioson/agents/design-hybrid-forge.md +141 -0
  167. package/template/.aioson/agents/dev.md +335 -14
  168. package/template/.aioson/agents/deyvin.md +117 -2
  169. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  170. package/template/.aioson/agents/genome.md +14 -0
  171. package/template/.aioson/agents/neo.md +78 -1
  172. package/template/.aioson/agents/orache.md +50 -4
  173. package/template/.aioson/agents/orchestrator.md +197 -1
  174. package/template/.aioson/agents/pm.md +93 -0
  175. package/template/.aioson/agents/product.md +77 -4
  176. package/template/.aioson/agents/profiler-enricher.md +14 -0
  177. package/template/.aioson/agents/profiler-forge.md +14 -0
  178. package/template/.aioson/agents/profiler-researcher.md +14 -0
  179. package/template/.aioson/agents/qa.md +249 -19
  180. package/template/.aioson/agents/setup.md +144 -12
  181. package/template/.aioson/agents/sheldon.md +237 -11
  182. package/template/.aioson/agents/site-forge.md +1753 -0
  183. package/template/.aioson/agents/squad.md +162 -0
  184. package/template/.aioson/agents/tester.md +209 -0
  185. package/template/.aioson/agents/ux-ui.md +34 -1
  186. package/template/.aioson/brains/README.md +128 -0
  187. package/template/.aioson/brains/_index.json +16 -0
  188. package/template/.aioson/brains/scripts/query.js +103 -0
  189. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  190. package/template/.aioson/config.md +158 -13
  191. package/template/.aioson/constitution.md +33 -0
  192. package/template/.aioson/context/forensics/.gitkeep +0 -0
  193. package/template/.aioson/context/project-pulse.md +34 -0
  194. package/template/.aioson/context/seeds/seed-example.md +27 -0
  195. package/template/.aioson/context/user-profile.md +42 -0
  196. package/template/.aioson/docs/LAYERS.md +79 -0
  197. package/template/.aioson/docs/README.md +76 -0
  198. package/template/.aioson/docs/example-external-api-context.md +72 -0
  199. package/template/.aioson/locales/en/agents/architect.md +17 -0
  200. package/template/.aioson/locales/en/agents/dev.md +79 -13
  201. package/template/.aioson/locales/en/agents/orache.md +6 -0
  202. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  203. package/template/.aioson/locales/en/agents/product.md +50 -0
  204. package/template/.aioson/locales/en/agents/setup.md +33 -1
  205. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  206. package/template/.aioson/locales/en/agents/squad.md +14 -0
  207. package/template/.aioson/locales/en/agents/tester.md +6 -0
  208. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  209. package/template/.aioson/locales/es/agents/architect.md +19 -0
  210. package/template/.aioson/locales/es/agents/dev.md +64 -4
  211. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  212. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  213. package/template/.aioson/locales/es/agents/genome.md +2 -0
  214. package/template/.aioson/locales/es/agents/neo.md +2 -0
  215. package/template/.aioson/locales/es/agents/orache.md +2 -0
  216. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  217. package/template/.aioson/locales/es/agents/pair.md +2 -0
  218. package/template/.aioson/locales/es/agents/pm.md +2 -0
  219. package/template/.aioson/locales/es/agents/product.md +52 -0
  220. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  221. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  222. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  223. package/template/.aioson/locales/es/agents/qa.md +2 -0
  224. package/template/.aioson/locales/es/agents/setup.md +35 -1
  225. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  226. package/template/.aioson/locales/es/agents/squad.md +16 -0
  227. package/template/.aioson/locales/es/agents/tester.md +9 -0
  228. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  229. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  230. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  231. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  232. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  233. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  234. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  235. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  236. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  237. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  238. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  239. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  240. package/template/.aioson/locales/fr/agents/product.md +52 -0
  241. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  242. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  243. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  244. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  245. package/template/.aioson/locales/fr/agents/setup.md +35 -1
  246. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  247. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  248. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  249. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  250. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  251. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  252. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  253. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  254. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  255. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  256. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  257. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  258. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  259. package/template/.aioson/locales/pt-BR/agents/setup.md +134 -19
  260. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  261. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  262. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  263. package/template/.aioson/rules/README.md +69 -0
  264. package/template/.aioson/rules/data-format-convention.md +136 -0
  265. package/template/.aioson/rules/example-monetary-values.md +30 -0
  266. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  267. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
  268. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
  269. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
  270. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
  271. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
  272. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
  273. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
  274. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
  275. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
  276. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
  277. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
  278. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
  279. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
  280. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
  281. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
  282. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
  283. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
  284. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
  285. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
  286. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
  287. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
  288. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
  289. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
  290. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
  291. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  292. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  293. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  294. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  295. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  296. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  297. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  298. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +46 -0
  299. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  300. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
  301. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  302. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
  303. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
  304. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  305. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  306. package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
  307. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -0
  308. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  309. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  310. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  311. package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
  312. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
  313. package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
  314. package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
  315. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
  316. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
  317. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
  318. package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
  319. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  320. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  321. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  322. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  323. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  324. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  325. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  326. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  327. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  328. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  329. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  330. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  331. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  332. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  333. package/template/.aioson/tasks/implementation-plan.md +21 -1
  334. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  335. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  336. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  337. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  338. package/template/AGENTS.md +75 -1
  339. package/template/CLAUDE.md +31 -0
  340. package/template/OPENCODE.md +4 -0
  341. package/template/researchs/.gitkeep +0 -0
@@ -9,11 +9,13 @@ const { applyAgentLocale } = require('../locales');
9
9
  async function runUpdate({ args, options, logger, t }) {
10
10
  const targetDir = path.resolve(process.cwd(), args[0] || '.');
11
11
  const dryRun = Boolean(options['dry-run']);
12
+ const all = Boolean(options.all);
12
13
  const requestedLanguage = options.lang || options.language;
13
14
 
14
15
  const detection = await detectFramework(targetDir);
15
16
  const result = await updateInstallation(targetDir, {
16
17
  dryRun,
18
+ all,
17
19
  frameworkDetection: detection.framework
18
20
  });
19
21
 
@@ -28,6 +30,9 @@ async function runUpdate({ args, options, logger, t }) {
28
30
  requestedLanguage ||
29
31
  (context.parsed && context.data && context.data.conversation_language
30
32
  ? context.data.conversation_language
33
+ : null) ||
34
+ (result.savedProfile && result.savedProfile.locale
35
+ ? result.savedProfile.locale
31
36
  : 'en');
32
37
  localeSync = await applyAgentLocale(targetDir, language, { dryRun });
33
38
  }
@@ -35,6 +40,10 @@ async function runUpdate({ args, options, logger, t }) {
35
40
  logger.log(t('update.done_at', { targetDir }));
36
41
  logger.log(t('update.files_updated', { count: result.copied.length }));
37
42
  logger.log(t('update.backups_created', { count: result.backedUp.length }));
43
+ if (!dryRun) {
44
+ logger.log('');
45
+ logger.log(t('update.reconfigure_hint'));
46
+ }
38
47
  if (localeSync) {
39
48
  if (dryRun) {
40
49
  logger.log(t('locale_apply.dry_run_applied', { locale: localeSync.locale }));
@@ -0,0 +1,572 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson verify:gate — Fresh-eyes verification pass on a deliverable
5
+ *
6
+ * Spawns a verification pass using only the spec and the artifact (file or
7
+ * directory). No conversation history is carried in — this catches bugs the
8
+ * generating agent cannot see due to context bias.
9
+ *
10
+ * Verdict outputs:
11
+ * PASS — artifact satisfies all spec requirements
12
+ * PASS_WITH_NOTES — passes but has minor issues worth flagging
13
+ * FAIL_WITH_ISSUES — one or more requirements not met (list provided)
14
+ * BLOCKED — cannot evaluate (missing spec, unreadable artifact, etc.)
15
+ *
16
+ * What it checks (deterministic, no LLM):
17
+ * - Required file existence (from spec "Files to write" or "Output files")
18
+ * - Forbidden patterns (patterns listed under "Constraints" or "Must not")
19
+ * - Required patterns (patterns listed under "Must contain" or "Done criteria")
20
+ * - File size sanity (files > 0 bytes, no obviously truncated outputs)
21
+ * - Acceptance criteria checkboxes presence (reports unchecked items)
22
+ *
23
+ * Usage:
24
+ * aioson verify:gate . --spec=.aioson/context/spec.md --artifact=src/
25
+ * aioson verify:gate . --spec=briefs/phase-2.md --artifact=src/api/
26
+ * aioson verify:gate . --spec=briefs/phase-2.md --artifact=src/api/ --out=verify-phase-2.md
27
+ * aioson verify:gate . --spec=briefs/phase-2.md --artifact=src/foo.ts --strict
28
+ * aioson verify:gate . --json
29
+ */
30
+
31
+ const fs = require('node:fs/promises');
32
+ const path = require('node:path');
33
+
34
+ // ─── Spec parser ──────────────────────────────────────────────────────────────
35
+
36
+ /**
37
+ * Extract structured verification requirements from a spec/brief markdown.
38
+ * Looks for:
39
+ * - "Done criteria" / "Acceptance criteria" sections → required checkboxes
40
+ * - "Files to write" / "Output files" → required file paths
41
+ * - "Must contain" / "Required patterns" → regex patterns to match
42
+ * - "Hard constraints" / "Must not" → forbidden patterns
43
+ */
44
+ function parseSpecRequirements(content) {
45
+ const lines = content.split(/\r?\n/);
46
+ const requirements = {
47
+ required_files: [],
48
+ required_patterns: [],
49
+ forbidden_patterns: [],
50
+ acceptance_criteria: [],
51
+ raw_sections: {}
52
+ };
53
+
54
+ let currentSection = null;
55
+
56
+ const SECTION_MAP = {
57
+ 'done criteria': 'done',
58
+ 'acceptance criteria': 'done',
59
+ 'files to write': 'output_files',
60
+ 'files to create': 'output_files',
61
+ 'output files': 'output_files',
62
+ 'must contain': 'required_patterns',
63
+ 'required patterns': 'required_patterns',
64
+ 'hard constraints': 'forbidden',
65
+ 'must not': 'forbidden',
66
+ 'constraints': 'forbidden',
67
+ 'out of scope': 'out_of_scope'
68
+ };
69
+
70
+ const headingRe = /^(#{1,4})\s+(.+)$/;
71
+ let sectionLevel = 0;
72
+
73
+ for (const line of lines) {
74
+ const headingMatch = line.match(headingRe);
75
+ if (headingMatch) {
76
+ const level = headingMatch[1].length;
77
+ const title = headingMatch[2].trim().toLowerCase();
78
+
79
+ // Check if this heading exits the current section
80
+ if (currentSection && level <= sectionLevel) {
81
+ currentSection = null;
82
+ }
83
+
84
+ // Check if this heading starts a tracked section
85
+ for (const [keyword, sectionType] of Object.entries(SECTION_MAP)) {
86
+ if (title.includes(keyword)) {
87
+ currentSection = sectionType;
88
+ sectionLevel = level;
89
+ if (!requirements.raw_sections[sectionType]) {
90
+ requirements.raw_sections[sectionType] = [];
91
+ }
92
+ break;
93
+ }
94
+ }
95
+ continue;
96
+ }
97
+
98
+ if (!currentSection) continue;
99
+
100
+ // Parse bullet items
101
+ const bulletMatch = line.match(/^[-*]\s+(.+)$/);
102
+ const checkboxMatch = line.match(/^[-*]\s+\[([ x])\]\s+(.+)$/i);
103
+ const item = checkboxMatch ? checkboxMatch[2].trim() : (bulletMatch ? bulletMatch[1].trim() : null);
104
+
105
+ if (!item) continue;
106
+
107
+ if (requirements.raw_sections[currentSection]) {
108
+ requirements.raw_sections[currentSection].push(item);
109
+ }
110
+
111
+ switch (currentSection) {
112
+ case 'done': {
113
+ const checked = checkboxMatch ? checkboxMatch[1].trim().toLowerCase() === 'x' : false;
114
+ requirements.acceptance_criteria.push({ text: item, checked });
115
+
116
+ // Extract file paths from criteria (pattern: `path/to/file`)
117
+ const fileMatch = item.match(/`([^`]+\.[a-z]{1,6})`/g);
118
+ if (fileMatch) {
119
+ for (const m of fileMatch) {
120
+ const fp = m.replace(/`/g, '').trim();
121
+ if (!fp.includes(' ') && fp.includes('/')) {
122
+ requirements.required_files.push(fp);
123
+ }
124
+ }
125
+ }
126
+ break;
127
+ }
128
+ case 'output_files': {
129
+ // Extract paths from items like "`src/foo.ts` — description"
130
+ const fpMatch = item.match(/`([^`]+)`/);
131
+ if (fpMatch) {
132
+ requirements.required_files.push(fpMatch[1].trim());
133
+ } else if (!item.includes(' ') || item.startsWith('src/') || item.startsWith('./')) {
134
+ requirements.required_files.push(item.split(' ')[0].trim());
135
+ }
136
+ break;
137
+ }
138
+ case 'required_patterns': {
139
+ requirements.required_patterns.push(item);
140
+ break;
141
+ }
142
+ case 'forbidden': {
143
+ // Only add as forbidden pattern if it looks like a code or file reference
144
+ const fpMatch2 = item.match(/`([^`]+)`/);
145
+ if (fpMatch2) {
146
+ requirements.forbidden_patterns.push(fpMatch2[1].trim());
147
+ }
148
+ break;
149
+ }
150
+ }
151
+ }
152
+
153
+ // Deduplicate
154
+ requirements.required_files = [...new Set(requirements.required_files)];
155
+ requirements.required_patterns = [...new Set(requirements.required_patterns)];
156
+ requirements.forbidden_patterns = [...new Set(requirements.forbidden_patterns)];
157
+
158
+ return requirements;
159
+ }
160
+
161
+ // ─── Artifact scanner ─────────────────────────────────────────────────────────
162
+
163
+ async function collectFiles(artifactPath, maxFiles = 200) {
164
+ const collected = [];
165
+
166
+ async function walk(p) {
167
+ if (collected.length >= maxFiles) return;
168
+ let stat;
169
+ try {
170
+ stat = await fs.stat(p);
171
+ } catch {
172
+ return;
173
+ }
174
+
175
+ if (stat.isFile()) {
176
+ collected.push(p);
177
+ } else if (stat.isDirectory()) {
178
+ let entries;
179
+ try {
180
+ entries = await fs.readdir(p, { withFileTypes: true });
181
+ } catch {
182
+ return;
183
+ }
184
+ for (const entry of entries) {
185
+ if (entry.name.startsWith('.')) continue; // skip dot files
186
+ await walk(path.join(p, entry.name));
187
+ }
188
+ }
189
+ }
190
+
191
+ await walk(artifactPath);
192
+ return collected;
193
+ }
194
+
195
+ async function readFileSafe(filePath, maxBytes = 50000) {
196
+ try {
197
+ const buf = Buffer.alloc(maxBytes);
198
+ const fh = await fs.open(filePath, 'r');
199
+ const { bytesRead } = await fh.read(buf, 0, maxBytes, 0);
200
+ await fh.close();
201
+ return buf.slice(0, bytesRead).toString('utf8');
202
+ } catch {
203
+ return null;
204
+ }
205
+ }
206
+
207
+ // ─── Checks ───────────────────────────────────────────────────────────────────
208
+
209
+ async function checkRequiredFiles(requirements, artifactBase, allFiles, targetDir) {
210
+ const issues = [];
211
+ const passes = [];
212
+
213
+ for (const requiredPath of requirements.required_files) {
214
+ // Try relative to artifact base first, then targetDir
215
+ const candidates = [
216
+ path.resolve(artifactBase, requiredPath),
217
+ path.resolve(targetDir, requiredPath)
218
+ ];
219
+
220
+ let found = false;
221
+ for (const c of candidates) {
222
+ if (allFiles.includes(c)) {
223
+ found = true;
224
+ break;
225
+ }
226
+ // Also try if the file appears anywhere in allFiles by basename
227
+ const basename = path.basename(requiredPath);
228
+ if (allFiles.some((f) => path.basename(f) === basename && f.includes(path.dirname(requiredPath)))) {
229
+ found = true;
230
+ break;
231
+ }
232
+ }
233
+
234
+ if (found) {
235
+ passes.push(`Required file exists: \`${requiredPath}\``);
236
+ } else {
237
+ issues.push(`Missing required file: \`${requiredPath}\``);
238
+ }
239
+ }
240
+
241
+ return { issues, passes };
242
+ }
243
+
244
+ async function checkFileContents(requirements, allFiles, targetDir) {
245
+ const issues = [];
246
+ const passes = [];
247
+ const notes = [];
248
+
249
+ // Check for empty files
250
+ for (const filePath of allFiles) {
251
+ try {
252
+ const stat = await fs.stat(filePath);
253
+ if (stat.size === 0) {
254
+ notes.push(`Empty file: \`${path.relative(targetDir, filePath)}\``);
255
+ }
256
+ } catch { /* ignore */ }
257
+ }
258
+
259
+ // Check required patterns across all artifact files
260
+ if (requirements.required_patterns.length > 0) {
261
+ const allContent = [];
262
+ for (const filePath of allFiles.slice(0, 30)) { // limit to first 30 files
263
+ const content = await readFileSafe(filePath);
264
+ if (content) allContent.push({ path: filePath, content });
265
+ }
266
+
267
+ for (const pattern of requirements.required_patterns) {
268
+ const found = allContent.some(({ content }) => content.includes(pattern));
269
+ if (found) {
270
+ passes.push(`Required pattern found: \`${pattern}\``);
271
+ } else {
272
+ issues.push(`Required pattern not found in artifact: \`${pattern}\``);
273
+ }
274
+ }
275
+ }
276
+
277
+ // Check forbidden patterns
278
+ if (requirements.forbidden_patterns.length > 0) {
279
+ const allContent = [];
280
+ for (const filePath of allFiles.slice(0, 30)) {
281
+ const content = await readFileSafe(filePath);
282
+ if (content) allContent.push({ path: path.relative(targetDir, filePath), content });
283
+ }
284
+
285
+ for (const pattern of requirements.forbidden_patterns) {
286
+ const found = allContent.find(({ content }) => content.includes(pattern));
287
+ if (found) {
288
+ issues.push(`Forbidden pattern found in \`${found.path}\`: \`${pattern}\``);
289
+ } else {
290
+ passes.push(`Forbidden pattern absent: \`${pattern}\``);
291
+ }
292
+ }
293
+ }
294
+
295
+ return { issues, passes, notes };
296
+ }
297
+
298
+ function checkAcceptanceCriteria(requirements) {
299
+ const unchecked = requirements.acceptance_criteria.filter((c) => !c.checked);
300
+ const checked = requirements.acceptance_criteria.filter((c) => c.checked);
301
+
302
+ const issues = [];
303
+ const passes = [];
304
+ const notes = [];
305
+
306
+ for (const c of checked) {
307
+ passes.push(`Criterion checked: ${c.text}`);
308
+ }
309
+ for (const c of unchecked) {
310
+ // Only warn if criteria look like real requirements (not placeholder text)
311
+ if (c.text.includes('Fill in') || c.text.includes('Example')) {
312
+ notes.push(`Placeholder criterion (not checked): ${c.text}`);
313
+ } else {
314
+ issues.push(`Unchecked criterion: ${c.text}`);
315
+ }
316
+ }
317
+
318
+ return { issues, passes, notes };
319
+ }
320
+
321
+ // ─── Report builder ───────────────────────────────────────────────────────────
322
+
323
+ function buildReport({ verdict, specPath, artifactPath, projectDir, issues, passes, notes, fileCount, requirements }) {
324
+ const relSpec = path.relative(projectDir, specPath);
325
+ const relArtifact = path.relative(projectDir, artifactPath);
326
+ const now = new Date().toISOString();
327
+
328
+ const lines = [
329
+ '---',
330
+ `generated_at : ${now}`,
331
+ `spec : ${relSpec}`,
332
+ `artifact : ${relArtifact}`,
333
+ `verdict : ${verdict}`,
334
+ `files_scanned: ${fileCount}`,
335
+ '---',
336
+ '',
337
+ `# Verify Gate — ${verdict}`,
338
+ '',
339
+ `**Spec:** \`${relSpec}\``,
340
+ `**Artifact:** \`${relArtifact}\``,
341
+ `**Files scanned:** ${fileCount}`,
342
+ ''
343
+ ];
344
+
345
+ if (issues.length > 0) {
346
+ lines.push('## Issues');
347
+ for (const issue of issues) lines.push(`- ❌ ${issue}`);
348
+ lines.push('');
349
+ }
350
+
351
+ if (notes.length > 0) {
352
+ lines.push('## Notes');
353
+ for (const note of notes) lines.push(`- ⚠ ${note}`);
354
+ lines.push('');
355
+ }
356
+
357
+ if (passes.length > 0) {
358
+ lines.push('## Passed checks');
359
+ for (const p of passes) lines.push(`- ✓ ${p}`);
360
+ lines.push('');
361
+ }
362
+
363
+ if (requirements.required_files.length === 0 &&
364
+ requirements.acceptance_criteria.length === 0 &&
365
+ requirements.required_patterns.length === 0) {
366
+ lines.push('## Coverage warning');
367
+ lines.push('');
368
+ lines.push('No verifiable requirements were extracted from the spec.');
369
+ lines.push('The spec may not contain "Done criteria", "Files to write", or "Must contain" sections.');
370
+ lines.push('Add structured sections to the spec to enable meaningful verification.');
371
+ lines.push('');
372
+ }
373
+
374
+ return lines.join('\n');
375
+ }
376
+
377
+ // ─── Verdict logic ────────────────────────────────────────────────────────────
378
+
379
+ function determineVerdict(issues, notes, strict) {
380
+ if (issues.length > 0) return 'FAIL_WITH_ISSUES';
381
+ if (notes.length > 0 && strict) return 'FAIL_WITH_ISSUES';
382
+ if (notes.length > 0) return 'PASS_WITH_NOTES';
383
+ return 'PASS';
384
+ }
385
+
386
+ // ─── Main command ─────────────────────────────────────────────────────────────
387
+
388
+ async function runVerifyGate({ args, options = {}, logger }) {
389
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
390
+ const strict = Boolean(options.strict);
391
+
392
+ // ── Locate spec ──────────────────────────────────────────────────────────
393
+ let specPath;
394
+ if (options.spec) {
395
+ specPath = path.resolve(targetDir, options.spec);
396
+ } else {
397
+ // Auto-discover: prefer brief files, then spec.md
398
+ const candidates = [
399
+ path.join(targetDir, '.aioson', 'context', 'spec.md'),
400
+ path.join(targetDir, 'docs', 'spec.md'),
401
+ path.join(targetDir, 'SPEC.md')
402
+ ];
403
+ for (const c of candidates) {
404
+ try {
405
+ await fs.access(c);
406
+ specPath = c;
407
+ break;
408
+ } catch { /* continue */ }
409
+ }
410
+ }
411
+
412
+ if (!specPath) {
413
+ const msg = 'No spec file found. Use --spec=<path> to specify one.';
414
+ if (options.json) return { ok: false, verdict: 'BLOCKED', error: msg };
415
+ logger.error(msg);
416
+ return { ok: false, verdict: 'BLOCKED' };
417
+ }
418
+
419
+ const specContent = await (async () => {
420
+ try { return await fs.readFile(specPath, 'utf8'); } catch { return null; }
421
+ })();
422
+
423
+ if (!specContent) {
424
+ const msg = `Cannot read spec file: ${path.relative(targetDir, specPath)}`;
425
+ if (options.json) return { ok: false, verdict: 'BLOCKED', error: msg };
426
+ logger.error(msg);
427
+ return { ok: false, verdict: 'BLOCKED' };
428
+ }
429
+
430
+ // ── Locate artifact ──────────────────────────────────────────────────────
431
+ let artifactPath;
432
+ if (options.artifact) {
433
+ artifactPath = path.resolve(targetDir, options.artifact);
434
+ } else {
435
+ // Default to src/ if it exists
436
+ const srcDir = path.join(targetDir, 'src');
437
+ try {
438
+ await fs.access(srcDir);
439
+ artifactPath = srcDir;
440
+ } catch {
441
+ artifactPath = targetDir;
442
+ }
443
+ }
444
+
445
+ try {
446
+ await fs.access(artifactPath);
447
+ } catch {
448
+ const msg = `Artifact path not found: ${path.relative(targetDir, artifactPath)}`;
449
+ if (options.json) return { ok: false, verdict: 'BLOCKED', error: msg };
450
+ logger.error(msg);
451
+ return { ok: false, verdict: 'BLOCKED' };
452
+ }
453
+
454
+ // ── Parse spec requirements ───────────────────────────────────────────────
455
+ const requirements = parseSpecRequirements(specContent);
456
+
457
+ // ── Collect artifact files ────────────────────────────────────────────────
458
+ const allFiles = await collectFiles(artifactPath);
459
+
460
+ // ── Run checks ────────────────────────────────────────────────────────────
461
+ const [fileCheck, contentCheck] = await Promise.all([
462
+ checkRequiredFiles(requirements, artifactPath, allFiles, targetDir),
463
+ checkFileContents(requirements, allFiles, targetDir)
464
+ ]);
465
+ const criteriaCheck = checkAcceptanceCriteria(requirements);
466
+
467
+ const allIssues = [...fileCheck.issues, ...contentCheck.issues, ...criteriaCheck.issues];
468
+ const allPasses = [...fileCheck.passes, ...contentCheck.passes, ...criteriaCheck.passes];
469
+ const allNotes = [...contentCheck.notes, ...criteriaCheck.notes];
470
+
471
+ const verdict = determineVerdict(allIssues, allNotes, strict);
472
+
473
+ // ── Build report ─────────────────────────────────────────────────────────
474
+ const report = buildReport({
475
+ verdict,
476
+ specPath,
477
+ artifactPath,
478
+ projectDir: targetDir,
479
+ issues: allIssues,
480
+ passes: allPasses,
481
+ notes: allNotes,
482
+ fileCount: allFiles.length,
483
+ requirements
484
+ });
485
+
486
+ // ── Write output ──────────────────────────────────────────────────────────
487
+ let outPath;
488
+ if (options.out) {
489
+ outPath = path.resolve(targetDir, options.out);
490
+ } else {
491
+ const slug = path.basename(specPath, '.md').replace(/[^a-z0-9-]/gi, '-').toLowerCase();
492
+ const outDir = path.join(targetDir, '.aioson', 'context');
493
+ outPath = path.join(outDir, `verify-gate-${slug}.md`);
494
+ }
495
+
496
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
497
+ await fs.writeFile(outPath, report, 'utf8');
498
+
499
+ const relOut = path.relative(targetDir, outPath);
500
+
501
+ if (options.json) {
502
+ return {
503
+ ok: verdict === 'PASS' || verdict === 'PASS_WITH_NOTES',
504
+ verdict,
505
+ spec: path.relative(targetDir, specPath),
506
+ artifact: path.relative(targetDir, artifactPath),
507
+ report_path: relOut,
508
+ files_scanned: allFiles.length,
509
+ issues: allIssues,
510
+ notes: allNotes,
511
+ passes: allPasses,
512
+ requirements: {
513
+ required_files: requirements.required_files.length,
514
+ acceptance_criteria: requirements.acceptance_criteria.length,
515
+ required_patterns: requirements.required_patterns.length,
516
+ forbidden_patterns: requirements.forbidden_patterns.length
517
+ }
518
+ };
519
+ }
520
+
521
+ // Console output
522
+ const VERDICT_ICON = {
523
+ PASS: '✓',
524
+ PASS_WITH_NOTES: '⚠',
525
+ FAIL_WITH_ISSUES: '✗',
526
+ BLOCKED: '?'
527
+ };
528
+
529
+ logger.log('Verify Gate');
530
+ logger.log('─'.repeat(60));
531
+ logger.log(`Spec : ${path.relative(targetDir, specPath)}`);
532
+ logger.log(`Artifact : ${path.relative(targetDir, artifactPath)}`);
533
+ logger.log(`Files : ${allFiles.length}`);
534
+ logger.log('');
535
+
536
+ logger.log(`Verdict : ${VERDICT_ICON[verdict]} ${verdict}`);
537
+ logger.log('');
538
+
539
+ if (allIssues.length > 0) {
540
+ logger.log('Issues:');
541
+ for (const issue of allIssues) logger.log(` ✗ ${issue}`);
542
+ logger.log('');
543
+ }
544
+
545
+ if (allNotes.length > 0) {
546
+ logger.log('Notes:');
547
+ for (const note of allNotes) logger.log(` ⚠ ${note}`);
548
+ logger.log('');
549
+ }
550
+
551
+ if (allPasses.length > 0) {
552
+ logger.log(`Passed: ${allPasses.length} check${allPasses.length !== 1 ? 's' : ''}`);
553
+ logger.log('');
554
+ }
555
+
556
+ if (requirements.required_files.length === 0 &&
557
+ requirements.acceptance_criteria.length === 0 &&
558
+ requirements.required_patterns.length === 0) {
559
+ logger.log('⚠ No verifiable requirements extracted from spec.');
560
+ logger.log(' Add "Done criteria", "Files to write", or "Must contain" sections to enable checks.');
561
+ logger.log('');
562
+ }
563
+
564
+ logger.log(`Report : ${relOut}`);
565
+
566
+ return {
567
+ ok: verdict === 'PASS' || verdict === 'PASS_WITH_NOTES',
568
+ verdict
569
+ };
570
+ }
571
+
572
+ module.exports = { runVerifyGate };