@jaimevalasek/aioson 1.7.0 → 1.8.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 (383) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +153 -10
  3. package/docs/en/cli-reference.md +56 -1
  4. package/docs/en/i18n.md +18 -18
  5. package/docs/en/schemas/index.json +10 -0
  6. package/docs/en/schemas/parallel-assign.schema.json +9 -0
  7. package/docs/en/schemas/parallel-doctor.schema.json +36 -0
  8. package/docs/en/schemas/parallel-guard.schema.json +63 -0
  9. package/docs/en/schemas/parallel-merge.schema.json +84 -0
  10. package/docs/en/schemas/parallel-status.schema.json +91 -1
  11. package/docs/integrations/apps-publish-marketplace.md +94 -0
  12. package/docs/pt/README.md +9 -0
  13. package/docs/pt/agentes.md +324 -3
  14. package/docs/pt/clientes-ai.md +7 -3
  15. package/docs/pt/comandos-cli.md +160 -13
  16. package/docs/pt/compress-agents.md +304 -0
  17. package/docs/pt/design-docs-governance.md +59 -0
  18. package/docs/pt/feature-archive.md +191 -0
  19. package/docs/pt/genome-3.0-spec.md +115 -4
  20. package/docs/pt/genome-distribution.md +232 -0
  21. package/docs/pt/inicio-rapido.md +1 -0
  22. package/docs/pt/motor-hardening.md +492 -0
  23. package/docs/pt/runner-system.md +113 -0
  24. package/package.json +2 -1
  25. package/src/agent-manifests.js +66 -0
  26. package/src/agents.js +27 -7
  27. package/src/autonomy-policy.js +139 -0
  28. package/src/brain-query.js +161 -0
  29. package/src/cli.js +1377 -1099
  30. package/src/commands/agents.js +102 -7
  31. package/src/commands/artifact-validate.js +33 -4
  32. package/src/commands/auth.js +272 -0
  33. package/src/commands/brain-query.js +44 -0
  34. package/src/commands/briefing.js +344 -0
  35. package/src/commands/commit-prepare.js +547 -0
  36. package/src/commands/compress-agents.js +416 -0
  37. package/src/commands/context-health.js +4 -2
  38. package/src/commands/context-trim.js +17 -11
  39. package/src/commands/design-hybrid-options.js +3 -3
  40. package/src/commands/devlog-process.js +6 -4
  41. package/src/commands/dossier.js +423 -0
  42. package/src/commands/feature-archive.js +513 -0
  43. package/src/commands/feature-close.js +123 -18
  44. package/src/commands/gate-approve.js +198 -0
  45. package/src/commands/gate-check.js +24 -5
  46. package/src/commands/genome-doctor.js +166 -9
  47. package/src/commands/git-guard.js +170 -0
  48. package/src/commands/harness.js +121 -0
  49. package/src/commands/implementation-plan.js +47 -20
  50. package/src/commands/init.js +6 -2
  51. package/src/commands/install.js +6 -2
  52. package/src/commands/live.js +497 -56
  53. package/src/commands/locale-apply.js +9 -6
  54. package/src/commands/locale-diff.js +11 -112
  55. package/src/commands/mcp-doctor.js +2 -1
  56. package/src/commands/mcp-init.js +4 -10
  57. package/src/commands/memory.js +234 -0
  58. package/src/commands/parallel-assign.js +107 -27
  59. package/src/commands/parallel-doctor.js +416 -3
  60. package/src/commands/parallel-guard.js +241 -0
  61. package/src/commands/parallel-init.js +66 -4
  62. package/src/commands/parallel-merge.js +299 -0
  63. package/src/commands/parallel-status.js +147 -3
  64. package/src/commands/preflight.js +63 -4
  65. package/src/commands/qa-init.js +10 -5
  66. package/src/commands/revision.js +235 -0
  67. package/src/commands/scaffold-complete.js +188 -0
  68. package/src/commands/security-audit.js +275 -0
  69. package/src/commands/security-scan.js +376 -0
  70. package/src/commands/self-implement-loop.js +46 -2
  71. package/src/commands/setup-context.js +11 -10
  72. package/src/commands/squad-agent-create.js +51 -9
  73. package/src/commands/squad-investigate.js +53 -0
  74. package/src/commands/squad-plan.js +33 -1
  75. package/src/commands/squad-scaffold.js +4 -3
  76. package/src/commands/squad-score.js +71 -14
  77. package/src/commands/squad-status.js +22 -1
  78. package/src/commands/squad-validate.js +93 -2
  79. package/src/commands/store-genome.js +304 -0
  80. package/src/commands/store-skill.js +247 -0
  81. package/src/commands/store-squad.js +431 -0
  82. package/src/commands/store-system.js +392 -0
  83. package/src/commands/tool-capabilities.js +63 -0
  84. package/src/commands/update.js +3 -3
  85. package/src/commands/verify-gate.js +40 -0
  86. package/src/commands/workflow-execute.js +644 -155
  87. package/src/commands/workflow-harden.js +231 -0
  88. package/src/commands/workflow-heal.js +136 -0
  89. package/src/commands/workflow-next.js +460 -22
  90. package/src/commands/workflow-status.js +328 -138
  91. package/src/commands/workspace.js +144 -0
  92. package/src/constants.js +55 -75
  93. package/src/context-memory.js +133 -4
  94. package/src/context-writer.js +2 -1
  95. package/src/context.js +32 -2
  96. package/src/doctor.js +46 -6
  97. package/src/dossier/codemap-store.js +267 -0
  98. package/src/dossier/dossier-bootstrap.js +222 -0
  99. package/src/dossier/dossier-compact.js +159 -0
  100. package/src/dossier/lock.js +128 -0
  101. package/src/dossier/revision-store.js +313 -0
  102. package/src/dossier/schema.js +155 -0
  103. package/src/dossier/store.js +400 -0
  104. package/src/execution-gateway.js +3 -0
  105. package/src/friction-scanner.js +202 -0
  106. package/src/genome-schema.js +24 -1
  107. package/src/genomes.js +33 -0
  108. package/src/handoff-contract.js +363 -0
  109. package/src/handoff-validator.js +45 -0
  110. package/src/harness/circuit-breaker.js +135 -0
  111. package/src/i18n/messages/en.js +317 -22
  112. package/src/i18n/messages/es.js +259 -18
  113. package/src/i18n/messages/fr.js +260 -18
  114. package/src/i18n/messages/pt-BR.js +313 -22
  115. package/src/install-profile.js +0 -16
  116. package/src/installer.js +70 -6
  117. package/src/lib/git-commit-guard.js +691 -0
  118. package/src/lib/security/artifact-reader.js +167 -0
  119. package/src/lib/security/exit-codes.js +51 -0
  120. package/src/lib/security/findings-writer.js +176 -0
  121. package/src/lib/security/runtime-events.js +77 -0
  122. package/src/lib/security/secrets-regex.js +115 -0
  123. package/src/lib/store/security-scan.js +173 -0
  124. package/src/lib/terminal-checkbox.js +130 -0
  125. package/src/lib/tmux-launcher.js +163 -0
  126. package/src/lib/tool-capabilities.js +102 -0
  127. package/src/locales.js +12 -8
  128. package/src/parallel-workspace.js +756 -0
  129. package/src/parser.js +8 -1
  130. package/src/path-guard.js +47 -0
  131. package/src/preflight-engine.js +237 -26
  132. package/src/self-healing.js +142 -0
  133. package/src/session-handoff.js +111 -1
  134. package/src/squad/squad-scaffold.js +183 -19
  135. package/src/test-briefing.js +226 -0
  136. package/src/updater.js +1 -1
  137. package/src/utils.js +3 -0
  138. package/src/workflow-gates.js +185 -0
  139. package/template/.aioson/agents/analyst.md +76 -130
  140. package/template/.aioson/agents/architect.md +53 -86
  141. package/template/.aioson/agents/committer.md +161 -0
  142. package/template/.aioson/agents/copywriter.md +463 -0
  143. package/template/.aioson/agents/cypher.md +252 -0
  144. package/template/.aioson/agents/dev.md +112 -600
  145. package/template/.aioson/agents/deyvin.md +33 -235
  146. package/template/.aioson/agents/discover.md +235 -0
  147. package/template/.aioson/agents/discovery-design-doc.md +17 -252
  148. package/template/.aioson/agents/genome.md +76 -26
  149. package/template/.aioson/agents/manifests/analyst.manifest.json +26 -0
  150. package/template/.aioson/agents/manifests/architect.manifest.json +23 -0
  151. package/template/.aioson/agents/manifests/committer.manifest.json +23 -0
  152. package/template/.aioson/agents/manifests/dev.manifest.json +37 -0
  153. package/template/.aioson/agents/manifests/orchestrator.manifest.json +30 -0
  154. package/template/.aioson/agents/manifests/pentester.manifest.json +39 -0
  155. package/template/.aioson/agents/manifests/pm.manifest.json +26 -0
  156. package/template/.aioson/agents/manifests/product.manifest.json +23 -0
  157. package/template/.aioson/agents/manifests/qa.manifest.json +25 -0
  158. package/template/.aioson/agents/manifests/setup.manifest.json +20 -0
  159. package/template/.aioson/agents/manifests/ux-ui.manifest.json +24 -0
  160. package/template/.aioson/agents/neo.md +10 -8
  161. package/template/.aioson/agents/orache.md +2 -6
  162. package/template/.aioson/agents/orchestrator.md +81 -182
  163. package/template/.aioson/agents/pentester.md +235 -0
  164. package/template/.aioson/agents/pm.md +40 -104
  165. package/template/.aioson/agents/product.md +99 -344
  166. package/template/.aioson/agents/profiler-enricher.md +57 -6
  167. package/template/.aioson/agents/profiler-forge.md +17 -7
  168. package/template/.aioson/agents/profiler-researcher.md +29 -6
  169. package/template/.aioson/agents/qa.md +165 -410
  170. package/template/.aioson/agents/setup.md +52 -262
  171. package/template/.aioson/agents/sheldon.md +122 -754
  172. package/template/.aioson/agents/site-forge.md +111 -1583
  173. package/template/.aioson/agents/squad.md +139 -1820
  174. package/template/.aioson/agents/tester.md +10 -0
  175. package/template/.aioson/agents/ux-ui.md +103 -645
  176. package/template/.aioson/agents/validator.md +69 -0
  177. package/template/.aioson/brains/scripts/query.js +5 -1
  178. package/template/.aioson/config/autonomy-protocol.json +43 -0
  179. package/template/.aioson/config.md +43 -15
  180. package/template/.aioson/constitution.md +36 -33
  181. package/template/.aioson/context/design-doc.md +136 -0
  182. package/template/.aioson/context/project-map.md +57 -0
  183. package/template/.aioson/design-docs/code-reuse.md +48 -0
  184. package/template/.aioson/design-docs/componentization.md +47 -0
  185. package/template/.aioson/design-docs/file-size.md +52 -0
  186. package/template/.aioson/design-docs/folder-structure.md +51 -0
  187. package/template/.aioson/design-docs/naming.md +54 -0
  188. package/template/.aioson/docs/LAYERS.md +12 -2
  189. package/template/.aioson/docs/dev/execution-discipline.md +106 -0
  190. package/template/.aioson/docs/dev/stack-conventions.md +83 -0
  191. package/template/.aioson/docs/deyvin/continuity-recovery.md +57 -0
  192. package/template/.aioson/docs/deyvin/debugging-escalation.md +30 -0
  193. package/template/.aioson/docs/deyvin/pair-execution.md +44 -0
  194. package/template/.aioson/docs/deyvin/runtime-handoffs.md +36 -0
  195. package/template/.aioson/docs/product/conversation-playbook.md +116 -0
  196. package/template/.aioson/docs/product/prd-contract.md +107 -0
  197. package/template/.aioson/docs/product/quality-lens.md +57 -0
  198. package/template/.aioson/docs/product/research-loop.md +65 -0
  199. package/template/.aioson/docs/sheldon/enrichment-paths.md +134 -0
  200. package/template/.aioson/docs/sheldon/quality-lens.md +57 -0
  201. package/template/.aioson/docs/sheldon/research-loop.md +56 -0
  202. package/template/.aioson/docs/sheldon/web-intelligence.md +75 -0
  203. package/template/.aioson/docs/site-forge-build.md +195 -0
  204. package/template/.aioson/docs/site-forge-extraction.md +135 -0
  205. package/template/.aioson/docs/site-forge-qa.md +155 -0
  206. package/template/.aioson/docs/site-forge-recon.md +434 -0
  207. package/template/.aioson/docs/site-forge-transform.md +249 -0
  208. package/template/.aioson/docs/squad/content-output.md +91 -0
  209. package/template/.aioson/docs/squad/creation-flow.md +135 -0
  210. package/template/.aioson/docs/squad/domain-classification.md +117 -0
  211. package/template/.aioson/docs/squad/genome-bindings.md +47 -0
  212. package/template/.aioson/docs/squad/package-contract.md +234 -0
  213. package/template/.aioson/docs/squad/quality-lens.md +56 -0
  214. package/template/.aioson/docs/squad/research-loop.md +59 -0
  215. package/template/.aioson/docs/squad/session-operations.md +117 -0
  216. package/template/.aioson/docs/squad/workflow-quality.md +165 -0
  217. package/template/.aioson/docs/ux-ui/accessibility-audit.md +55 -0
  218. package/template/.aioson/docs/ux-ui/audit-mode.md +86 -0
  219. package/template/.aioson/docs/ux-ui/component-map.md +35 -0
  220. package/template/.aioson/docs/ux-ui/design-execution.md +111 -0
  221. package/template/.aioson/docs/ux-ui/design-gate.md +27 -0
  222. package/template/.aioson/docs/ux-ui/research-mode.md +39 -0
  223. package/template/.aioson/docs/ux-ui/site-delivery.md +156 -0
  224. package/template/.aioson/docs/ux-ui/token-contract.md +57 -0
  225. package/template/.aioson/genomes/copywriting.md +204 -0
  226. package/template/.aioson/genomes/copywriting.meta.json +48 -0
  227. package/template/.aioson/git-guard.json +11 -0
  228. package/template/.aioson/mcp/servers.md +0 -1
  229. package/template/.aioson/rules/agent-language-policy.md +93 -0
  230. package/template/.aioson/rules/aioson-context-boundary.md +63 -0
  231. package/template/.aioson/rules/canonical-path-contract.md +47 -0
  232. package/template/.aioson/rules/data-format-convention.md +24 -86
  233. package/template/.aioson/rules/disk-first-artifacts.md +44 -0
  234. package/template/.aioson/rules/output-brevity.md +44 -0
  235. package/template/.aioson/rules/prd-section-ownership.md +49 -0
  236. package/template/.aioson/rules/security-baseline.md +139 -0
  237. package/template/.aioson/rules/spec-level-ownership.md +61 -0
  238. package/template/.aioson/rules/squad-driver-pattern.md +81 -0
  239. package/template/.aioson/schemas/squad-blueprint.schema.json +24 -0
  240. package/template/.aioson/schemas/squad-manifest.schema.json +44 -0
  241. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +2 -0
  242. package/template/.aioson/skills/marketing/references/anti-patterns.md +254 -0
  243. package/template/.aioson/skills/marketing/references/fascinations.md +192 -0
  244. package/template/.aioson/skills/marketing/references/five-acts.md +248 -0
  245. package/template/.aioson/skills/marketing/references/market-intelligence.md +198 -0
  246. package/template/.aioson/skills/marketing/references/offer-structure.md +203 -0
  247. package/template/.aioson/skills/marketing/references/one-belief.md +149 -0
  248. package/template/.aioson/skills/marketing/references/patterns.md +218 -0
  249. package/template/.aioson/skills/marketing/references/pms-research.md +193 -0
  250. package/template/.aioson/skills/marketing/vsl-craft.md +385 -0
  251. package/template/.aioson/skills/process/aioson-spec-driven/references/pm.md +30 -0
  252. package/template/.aioson/skills/process/secure-tdd/SKILL.md +97 -0
  253. package/template/.aioson/skills/process/secure-tdd/references/nextjs.md +81 -0
  254. package/template/.aioson/skills/process/secure-tdd/references/node-express.md +91 -0
  255. package/template/.aioson/skills/process/secure-tdd/references/planned-stacks.md +33 -0
  256. package/template/.aioson/skills/static/harness-validate/SKILL.md +46 -0
  257. package/template/.aioson/skills/static/landing-page-deploy.md +192 -0
  258. package/template/.aioson/skills/static/landing-page-forge.md +730 -0
  259. package/template/.aioson/skills/static/ui-ux-modern.md +1 -0
  260. package/template/.aioson/skills/static/web-research-cache.md +3 -0
  261. package/template/.aioson/tasks/squad-create.md +56 -7
  262. package/template/.aioson/tasks/squad-design.md +80 -2
  263. package/template/.aioson/tasks/squad-investigate.md +14 -1
  264. package/template/.aioson/templates/squads/digital-marketing-agency/template.json +96 -0
  265. package/template/.claude/commands/aioson/agent/committer.md +5 -0
  266. package/template/.claude/commands/aioson/agent/copywriter.md +5 -0
  267. package/template/.claude/commands/aioson/agent/cypher.md +5 -0
  268. package/template/.claude/commands/aioson/agent/pair.md +5 -0
  269. package/template/.claude/commands/aioson/agent/validator.md +5 -0
  270. package/template/.gemini/commands/aios-analyst.toml +6 -3
  271. package/template/.gemini/commands/aios-architect.toml +7 -6
  272. package/template/.gemini/commands/aios-committer.toml +7 -0
  273. package/template/.gemini/commands/aios-copywriter.toml +7 -0
  274. package/template/.gemini/commands/aios-cypher.toml +7 -0
  275. package/template/.gemini/commands/aios-dev.toml +8 -7
  276. package/template/.gemini/commands/aios-deyvin.toml +6 -5
  277. package/template/.gemini/commands/aios-discovery-design-doc.toml +6 -3
  278. package/template/.gemini/commands/aios-genome.toml +7 -0
  279. package/template/.gemini/commands/aios-neo.toml +5 -3
  280. package/template/.gemini/commands/aios-orache.toml +7 -0
  281. package/template/.gemini/commands/aios-orchestrator.toml +8 -7
  282. package/template/.gemini/commands/aios-pair.toml +6 -5
  283. package/template/.gemini/commands/aios-pm.toml +8 -7
  284. package/template/.gemini/commands/aios-product.toml +5 -3
  285. package/template/.gemini/commands/aios-qa.toml +6 -5
  286. package/template/.gemini/commands/aios-setup.toml +5 -2
  287. package/template/.gemini/commands/aios-sheldon.toml +7 -0
  288. package/template/.gemini/commands/aios-site-forge.toml +7 -0
  289. package/template/.gemini/commands/aios-squad.toml +7 -0
  290. package/template/.gemini/commands/aios-tester.toml +6 -5
  291. package/template/.gemini/commands/aios-ux-ui.toml +8 -7
  292. package/template/.gemini/commands/aios-validator.toml +7 -0
  293. package/template/AGENTS.md +12 -1
  294. package/template/CLAUDE.md +6 -1
  295. package/template/.aioson/locales/en/agents/analyst.md +0 -244
  296. package/template/.aioson/locales/en/agents/architect.md +0 -245
  297. package/template/.aioson/locales/en/agents/dev.md +0 -397
  298. package/template/.aioson/locales/en/agents/deyvin.md +0 -137
  299. package/template/.aioson/locales/en/agents/discovery-design-doc.md +0 -27
  300. package/template/.aioson/locales/en/agents/genome.md +0 -212
  301. package/template/.aioson/locales/en/agents/neo.md +0 -8
  302. package/template/.aioson/locales/en/agents/orache.md +0 -6
  303. package/template/.aioson/locales/en/agents/orchestrator.md +0 -189
  304. package/template/.aioson/locales/en/agents/pair.md +0 -5
  305. package/template/.aioson/locales/en/agents/pm.md +0 -84
  306. package/template/.aioson/locales/en/agents/product.md +0 -378
  307. package/template/.aioson/locales/en/agents/profiler-enricher.md +0 -5
  308. package/template/.aioson/locales/en/agents/profiler-forge.md +0 -5
  309. package/template/.aioson/locales/en/agents/profiler-researcher.md +0 -5
  310. package/template/.aioson/locales/en/agents/qa.md +0 -270
  311. package/template/.aioson/locales/en/agents/setup.md +0 -421
  312. package/template/.aioson/locales/en/agents/sheldon.md +0 -455
  313. package/template/.aioson/locales/en/agents/squad.md +0 -449
  314. package/template/.aioson/locales/en/agents/tester.md +0 -6
  315. package/template/.aioson/locales/en/agents/ux-ui.md +0 -668
  316. package/template/.aioson/locales/es/agents/analyst.md +0 -225
  317. package/template/.aioson/locales/es/agents/architect.md +0 -245
  318. package/template/.aioson/locales/es/agents/dev.md +0 -370
  319. package/template/.aioson/locales/es/agents/deyvin.md +0 -99
  320. package/template/.aioson/locales/es/agents/discovery-design-doc.md +0 -21
  321. package/template/.aioson/locales/es/agents/genome.md +0 -104
  322. package/template/.aioson/locales/es/agents/neo.md +0 -50
  323. package/template/.aioson/locales/es/agents/orache.md +0 -105
  324. package/template/.aioson/locales/es/agents/orchestrator.md +0 -194
  325. package/template/.aioson/locales/es/agents/pair.md +0 -7
  326. package/template/.aioson/locales/es/agents/pm.md +0 -90
  327. package/template/.aioson/locales/es/agents/product.md +0 -372
  328. package/template/.aioson/locales/es/agents/profiler-enricher.md +0 -7
  329. package/template/.aioson/locales/es/agents/profiler-forge.md +0 -7
  330. package/template/.aioson/locales/es/agents/profiler-researcher.md +0 -7
  331. package/template/.aioson/locales/es/agents/qa.md +0 -198
  332. package/template/.aioson/locales/es/agents/setup.md +0 -405
  333. package/template/.aioson/locales/es/agents/sheldon.md +0 -309
  334. package/template/.aioson/locales/es/agents/squad.md +0 -532
  335. package/template/.aioson/locales/es/agents/tester.md +0 -9
  336. package/template/.aioson/locales/es/agents/ux-ui.md +0 -212
  337. package/template/.aioson/locales/fr/agents/analyst.md +0 -225
  338. package/template/.aioson/locales/fr/agents/architect.md +0 -245
  339. package/template/.aioson/locales/fr/agents/dev.md +0 -370
  340. package/template/.aioson/locales/fr/agents/deyvin.md +0 -99
  341. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +0 -21
  342. package/template/.aioson/locales/fr/agents/genome.md +0 -104
  343. package/template/.aioson/locales/fr/agents/neo.md +0 -50
  344. package/template/.aioson/locales/fr/agents/orache.md +0 -106
  345. package/template/.aioson/locales/fr/agents/orchestrator.md +0 -194
  346. package/template/.aioson/locales/fr/agents/pair.md +0 -7
  347. package/template/.aioson/locales/fr/agents/pm.md +0 -90
  348. package/template/.aioson/locales/fr/agents/product.md +0 -372
  349. package/template/.aioson/locales/fr/agents/profiler-enricher.md +0 -7
  350. package/template/.aioson/locales/fr/agents/profiler-forge.md +0 -7
  351. package/template/.aioson/locales/fr/agents/profiler-researcher.md +0 -7
  352. package/template/.aioson/locales/fr/agents/qa.md +0 -198
  353. package/template/.aioson/locales/fr/agents/setup.md +0 -405
  354. package/template/.aioson/locales/fr/agents/sheldon.md +0 -309
  355. package/template/.aioson/locales/fr/agents/squad.md +0 -532
  356. package/template/.aioson/locales/fr/agents/tester.md +0 -9
  357. package/template/.aioson/locales/fr/agents/ux-ui.md +0 -212
  358. package/template/.aioson/locales/pt-BR/agents/analyst.md +0 -319
  359. package/template/.aioson/locales/pt-BR/agents/architect.md +0 -284
  360. package/template/.aioson/locales/pt-BR/agents/dev.md +0 -483
  361. package/template/.aioson/locales/pt-BR/agents/deyvin.md +0 -184
  362. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +0 -198
  363. package/template/.aioson/locales/pt-BR/agents/genome.md +0 -297
  364. package/template/.aioson/locales/pt-BR/agents/neo.md +0 -208
  365. package/template/.aioson/locales/pt-BR/agents/orache.md +0 -137
  366. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +0 -324
  367. package/template/.aioson/locales/pt-BR/agents/pair.md +0 -5
  368. package/template/.aioson/locales/pt-BR/agents/pm.md +0 -182
  369. package/template/.aioson/locales/pt-BR/agents/product.md +0 -466
  370. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +0 -5
  371. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +0 -5
  372. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +0 -5
  373. package/template/.aioson/locales/pt-BR/agents/qa.md +0 -300
  374. package/template/.aioson/locales/pt-BR/agents/setup.md +0 -533
  375. package/template/.aioson/locales/pt-BR/agents/sheldon.md +0 -323
  376. package/template/.aioson/locales/pt-BR/agents/squad.md +0 -1330
  377. package/template/.aioson/locales/pt-BR/agents/tester.md +0 -449
  378. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +0 -669
  379. package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
  380. package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
  381. package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
  382. package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
  383. package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
@@ -0,0 +1,392 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { exists, ensureDir } = require('../utils');
6
+ const { readConfig } = require('./config');
7
+ const { readWorkspace, findProjectRoot } = require('./workspace');
8
+
9
+ const DEFAULT_BASE_URL = 'https://aioson.com';
10
+ const SYSTEM_PACKAGES_DIR = '.aioson/system-packages';
11
+ const BACKUPS_DIR = '.aioson/.backups';
12
+
13
+ // Extensions allowed in a system package (Vite React source tree)
14
+ const SYSTEM_ALLOWED_EXTS = new Set([
15
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
16
+ '.json', '.jsonc',
17
+ '.css', '.scss', '.sass', '.less',
18
+ '.html',
19
+ '.svg', '.ico',
20
+ '.md', '.txt',
21
+ '.sql',
22
+ '.env', '.env.example', '.env.template',
23
+ '.yaml', '.yml',
24
+ '.toml',
25
+ '.gitignore',
26
+ ]);
27
+
28
+ // Dirs/files to skip when collecting sources
29
+ const SKIP_DIRS = new Set([
30
+ 'node_modules', '.git', 'dist', 'build', '.turbo', '.next',
31
+ '.cache', 'coverage', '.nyc_output', 'out',
32
+ // AIOSON tooling — não faz parte do código-fonte do sistema
33
+ '.aioson', '.claude', '.gemini', '.codex', 'researchs',
34
+ ]);
35
+
36
+ const SKIP_FILES = new Set([
37
+ 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
38
+ 'bun.lockb',
39
+ ]);
40
+
41
+ const MAX_FILE_BYTES = 512 * 1024; // 512 KB per file
42
+ const MAX_PACKAGE_BYTES = 20 * 1024 * 1024; // 20 MB total
43
+
44
+ /**
45
+ * Parseia lista de emails autorizados a partir de:
46
+ * 1. Flag CLI --invite="email1,email2,email3" (string com separadores , ; espaço quebra)
47
+ * 2. Fallback: campo `authorized_emails` no system.json (array ou string)
48
+ * Devolve array dedup, lowercase, trimmed, validado (contém @).
49
+ */
50
+ function parseInviteEmails(cliInvite, manifestEmails) {
51
+ const raw = cliInvite ?? manifestEmails;
52
+ if (!raw) return [];
53
+ let parts;
54
+ if (Array.isArray(raw)) {
55
+ parts = raw.map(String);
56
+ } else {
57
+ parts = String(raw).split(/[,;\s\n]+/);
58
+ }
59
+ return Array.from(new Set(
60
+ parts.map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0 && s.includes('@'))
61
+ ));
62
+ }
63
+
64
+ function resolveBaseUrl(config) {
65
+ return String(config.aiosonBaseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
66
+ }
67
+
68
+ function requireToken(config, t) {
69
+ const token = config.aiosonToken;
70
+ if (!token) throw new Error(t('store.error_not_authenticated'));
71
+ return token;
72
+ }
73
+
74
+ async function storePost(url, payload, token) {
75
+ const response = await fetch(url, {
76
+ method: 'POST',
77
+ headers: {
78
+ authorization: `Bearer ${token}`,
79
+ 'content-type': 'application/json',
80
+ accept: 'application/json',
81
+ },
82
+ body: JSON.stringify(payload),
83
+ signal: AbortSignal.timeout(120000),
84
+ });
85
+
86
+ const text = await response.text();
87
+ let parsed = null;
88
+ try { parsed = JSON.parse(text); } catch { /* */ }
89
+
90
+ if (!response.ok) {
91
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
92
+ throw new Error(`HTTP ${response.status}: ${detail}`);
93
+ }
94
+
95
+ return parsed;
96
+ }
97
+
98
+ async function storeGet(url, token) {
99
+ const response = await fetch(url, {
100
+ headers: { authorization: `Bearer ${token}`, accept: 'application/json' },
101
+ signal: AbortSignal.timeout(15000),
102
+ });
103
+ const text = await response.text();
104
+ let parsed = null;
105
+ try { parsed = JSON.parse(text); } catch { /* */ }
106
+ if (!response.ok) {
107
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
108
+ throw new Error(`HTTP ${response.status}: ${detail}`);
109
+ }
110
+ return parsed;
111
+ }
112
+
113
+ /**
114
+ * Collect all eligible source files under `dir`.
115
+ * Returns { relativePath: content } — only text files with allowed extensions.
116
+ */
117
+ async function collectSystemFiles(dir) {
118
+ const files = {};
119
+ let totalBytes = 0;
120
+ const errors = [];
121
+
122
+ async function walk(current, rel) {
123
+ const entries = await fs.readdir(current, { withFileTypes: true });
124
+ for (const entry of entries) {
125
+ if (SKIP_DIRS.has(entry.name)) continue;
126
+ if (SKIP_FILES.has(entry.name)) continue;
127
+
128
+ const fullPath = path.join(current, entry.name);
129
+ const relPath = rel ? `${rel}/${entry.name}` : entry.name;
130
+
131
+ if (entry.isDirectory()) {
132
+ await walk(fullPath, relPath);
133
+ continue;
134
+ }
135
+
136
+ const ext = entry.name.includes('.')
137
+ ? `.${entry.name.split('.').pop().toLowerCase()}`
138
+ : '';
139
+
140
+ // Allow dotfiles with no extension (like .gitignore) that match skip list check
141
+ if (!SYSTEM_ALLOWED_EXTS.has(ext) && ext !== '') continue;
142
+
143
+ try {
144
+ const stat = await fs.stat(fullPath);
145
+ if (stat.size > MAX_FILE_BYTES) {
146
+ errors.push(`File too large (skipped): "${relPath}" (${(stat.size / 1024).toFixed(0)} KB)`);
147
+ continue;
148
+ }
149
+ totalBytes += stat.size;
150
+ if (totalBytes > MAX_PACKAGE_BYTES) {
151
+ errors.push(`Package exceeds ${MAX_PACKAGE_BYTES / 1024 / 1024} MB limit — stop collecting.`);
152
+ return;
153
+ }
154
+ const content = await fs.readFile(fullPath, 'utf8');
155
+ files[relPath] = content;
156
+ } catch {
157
+ // binary or unreadable — skip silently
158
+ }
159
+ }
160
+ }
161
+
162
+ await walk(dir, '');
163
+ return { files, totalBytes, errors };
164
+ }
165
+
166
+ /**
167
+ * Parse and validate system.json.
168
+ * Returns the parsed manifest or throws.
169
+ */
170
+ async function readSystemJson(dir, t) {
171
+ const manifestPath = path.join(dir, 'system.json');
172
+ if (!(await exists(manifestPath))) {
173
+ throw new Error(t('system.error_no_manifest', { path: manifestPath }));
174
+ }
175
+ let manifest;
176
+ try {
177
+ manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
178
+ } catch {
179
+ throw new Error(t('system.error_invalid_manifest'));
180
+ }
181
+ if (!manifest.slug) throw new Error(t('system.error_manifest_missing_slug'));
182
+ if (!manifest.version) throw new Error(t('system.error_manifest_missing_version'));
183
+ if (!manifest.name) throw new Error(t('system.error_manifest_missing_name'));
184
+ return manifest;
185
+ }
186
+
187
+ // ── system:package ──────────────────────────────────────────────────────────
188
+
189
+ async function runSystemPackage({ args, options, logger, t }) {
190
+ const dir = path.resolve(process.cwd(), args[0] || '.');
191
+
192
+ logger.log(t('system.package_reading_manifest'));
193
+ const manifest = await readSystemJson(dir, t);
194
+ logger.log(t('system.package_manifest_ok', { slug: manifest.slug, version: manifest.version, name: manifest.name }));
195
+
196
+ logger.log(t('system.package_collecting_files'));
197
+ const { files, totalBytes, errors } = await collectSystemFiles(dir);
198
+
199
+ if (errors.length > 0) {
200
+ for (const e of errors) logger.log(` [WARN] ${e}`);
201
+ }
202
+
203
+ const fileCount = Object.keys(files).length;
204
+ logger.log(t('system.package_files_found', { count: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
205
+
206
+ if (!files['system.json']) {
207
+ throw new Error(t('system.error_no_manifest', { path: path.join(dir, 'system.json') }));
208
+ }
209
+
210
+ if (options['dry-run']) {
211
+ logger.log(t('system.package_dry_run', { slug: manifest.slug, version: manifest.version }));
212
+ for (const f of Object.keys(files).sort()) logger.log(` ${f}`);
213
+ return { ok: true, dryRun: true, manifest, fileCount, totalBytes };
214
+ }
215
+
216
+ // Save package descriptor locally
217
+ const projectDir = await findProjectRoot(dir);
218
+ const pkgDir = path.join(projectDir, SYSTEM_PACKAGES_DIR, manifest.slug);
219
+ await ensureDir(pkgDir);
220
+
221
+ const pkgFile = path.join(pkgDir, `${manifest.slug}-${manifest.version}.json`);
222
+ await fs.writeFile(pkgFile, JSON.stringify({ manifest, files }, null, 2), 'utf8');
223
+
224
+ logger.log(t('system.package_saved', { path: pkgFile }));
225
+ return { ok: true, manifest, fileCount, totalBytes, path: pkgFile };
226
+ }
227
+
228
+ // ── system:publish ──────────────────────────────────────────────────────────
229
+
230
+ async function runSystemPublish({ args, options, logger, t }) {
231
+ const config = await readConfig();
232
+ const token = requireToken(config, t);
233
+ const dir = path.resolve(process.cwd(), args[0] || '.');
234
+
235
+ logger.log(t('system.publish_reading_manifest'));
236
+ const manifest = await readSystemJson(dir, t);
237
+ logger.log(t('system.package_manifest_ok', { slug: manifest.slug, version: manifest.version, name: manifest.name }));
238
+
239
+ logger.log(t('system.package_collecting_files'));
240
+ const { files, totalBytes, errors } = await collectSystemFiles(dir);
241
+
242
+ if (errors.length > 0) {
243
+ for (const e of errors) logger.log(` [WARN] ${e}`);
244
+ }
245
+
246
+ const fileCount = Object.keys(files).length;
247
+ logger.log(t('system.package_files_found', { count: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
248
+
249
+ // Basic integrity checks
250
+ if (!files['system.json']) {
251
+ throw new Error(t('system.error_no_manifest', { path: path.join(dir, 'system.json') }));
252
+ }
253
+ if (!files['package.json']) {
254
+ throw new Error(t('system.error_missing_package_json'));
255
+ }
256
+
257
+ const visibility = options.private ? 'private' : 'public';
258
+ const paid = Boolean(options.paid);
259
+ const ws = await readWorkspace(dir);
260
+
261
+ // Lista de emails autorizados a instalar quando visibility=private.
262
+ // Aceita via --invite="email1,email2" OU campo `authorized_emails` no
263
+ // manifest (system.json). Sem efeito quando visibility !== private.
264
+ const authorizedEmails = parseInviteEmails(options.invite, manifest.authorized_emails);
265
+
266
+ if (options['dry-run']) {
267
+ logger.log(t('system.publish_dry_run', { slug: manifest.slug, version: manifest.version, visibility }));
268
+ return { ok: true, dryRun: true, manifest, fileCount, totalBytes, visibility, authorizedEmails };
269
+ }
270
+
271
+ logger.log(t('system.publish_sending'));
272
+ const baseUrl = resolveBaseUrl(config);
273
+ const response = await storePost(`${baseUrl}/api/store/systems/publish`, {
274
+ kind: 'aioson.store.system',
275
+ slug: manifest.slug,
276
+ version: manifest.version,
277
+ files,
278
+ manifest,
279
+ visibility,
280
+ paid,
281
+ authorizedEmails,
282
+ workspaceSlug: ws?.slug || null,
283
+ }, token);
284
+
285
+ logger.log(t('system.publish_done', { slug: manifest.slug, url: `${baseUrl}/store/systems/${manifest.slug}` }));
286
+ logger.log(t('system.publish_summary', { files: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
287
+ return { ok: true, manifest, fileCount, totalBytes, visibility, paid, response };
288
+ }
289
+
290
+ // ── system:list ─────────────────────────────────────────────────────────────
291
+
292
+ async function runSystemList({ args, options, logger, t }) {
293
+ if (options.remote) {
294
+ const config = await readConfig();
295
+ const token = requireToken(config, t);
296
+ const baseUrl = resolveBaseUrl(config);
297
+ logger.log(t('list_remote_fetching', { type: 'systems' }));
298
+ const response = await storeGet(`${baseUrl}/api/store/systems`, token);
299
+ const systems = response.systems || [];
300
+ if (systems.length === 0) {
301
+ logger.log(t('system.list_remote_empty'));
302
+ } else {
303
+ logger.log(t('system.list_remote_header', { count: systems.length }));
304
+ for (const s of systems) {
305
+ logger.log(t('system.list_remote_item', { slug: s.slug, name: s.name || s.slug, version: s.version || '?', visibility: s.visibility || '?' }));
306
+ }
307
+ }
308
+ return { ok: true, systems, remote: true };
309
+ }
310
+
311
+ // Local: list cached system packages
312
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
313
+ const pkgsDir = path.join(projectDir, SYSTEM_PACKAGES_DIR);
314
+
315
+ if (!(await exists(pkgsDir))) {
316
+ logger.log(t('system.list_local_empty'));
317
+ return { ok: true, systems: [] };
318
+ }
319
+
320
+ const entries = await fs.readdir(pkgsDir, { withFileTypes: true });
321
+ const systems = entries
322
+ .filter(e => e.isDirectory())
323
+ .map(e => ({ slug: e.name }));
324
+
325
+ if (systems.length === 0) {
326
+ logger.log(t('system.list_local_empty'));
327
+ } else {
328
+ logger.log(t('system.list_local_header', { count: systems.length }));
329
+ for (const s of systems) {
330
+ logger.log(t('system.list_local_item', { slug: s.slug }));
331
+ }
332
+ }
333
+
334
+ return { ok: true, systems };
335
+ }
336
+
337
+ // ── system:install (developer use — downloads source from store) ─────────────
338
+
339
+ async function runSystemInstall({ args, options, logger, t }) {
340
+ const config = await readConfig();
341
+ const token = requireToken(config, t);
342
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
343
+ const baseUrl = resolveBaseUrl(config);
344
+
345
+ const ref = String(options.slug || options.code || args[1] || '').trim();
346
+ if (!ref) throw new Error(t('store.error_missing_code_or_slug'));
347
+
348
+ logger.log(t('system.install_fetching', { ref }));
349
+
350
+ const response = await storePost(`${baseUrl}/api/store/systems/install`, {
351
+ ref,
352
+ workspaceSlug: (await readWorkspace(projectDir))?.slug || null,
353
+ }, token);
354
+
355
+ const slug = response.manifest?.slug || response.slug;
356
+ if (!slug || !response.files) throw new Error(t('store.error_invalid_response'));
357
+
358
+ const version = response.manifest?.version || '?';
359
+ const publisher = response.publisher || 'unknown';
360
+ logger.log(t('store.install_preview_header', { slug, version, publisher }));
361
+
362
+ if (options.inspect) {
363
+ logger.log(t('store.install_inspect_files', { count: Object.keys(response.files).length }));
364
+ for (const f of Object.keys(response.files).sort()) logger.log(` ${f}`);
365
+ logger.log(t('store.install_inspect_hint'));
366
+ return { ok: true, slug, inspect: true, files: Object.keys(response.files) };
367
+ }
368
+
369
+ const pkgDir = path.join(projectDir, SYSTEM_PACKAGES_DIR, slug);
370
+
371
+ if ((await exists(pkgDir)) && !options.force) {
372
+ const backupDir = path.join(projectDir, BACKUPS_DIR, `system-packages/${slug}`);
373
+ logger.log(t('store.install_backing_up', { path: backupDir }));
374
+ await fs.rm(backupDir, { recursive: true, force: true });
375
+ await fs.cp(pkgDir, backupDir, { recursive: true });
376
+ await fs.rm(pkgDir, { recursive: true, force: true });
377
+ }
378
+
379
+ // Write files
380
+ logger.log(t('system.install_writing'));
381
+ for (const [relPath, content] of Object.entries(response.files)) {
382
+ if (typeof content !== 'string') continue;
383
+ const destPath = path.join(pkgDir, relPath);
384
+ await ensureDir(path.dirname(destPath));
385
+ await fs.writeFile(destPath, content, 'utf8');
386
+ }
387
+
388
+ logger.log(t('system.install_done', { slug, path: pkgDir }));
389
+ return { ok: true, slug, path: pkgDir, manifest: response.manifest };
390
+ }
391
+
392
+ module.exports = { runSystemPackage, runSystemPublish, runSystemList, runSystemInstall };
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+
3
+ const { TOOL_CAPS, getToolCapabilities, listSupportedTools } = require('../lib/tool-capabilities');
4
+
5
+ // Expose the per-tool capability map (resume support, install command, etc.)
6
+ // so external clients (AIOSON Play, IDE extensions) can drive UI without
7
+ // hard-coding their own copy of this lookup.
8
+ //
9
+ // Usage:
10
+ // aioson tool:capabilities --json
11
+ // aioson tool:capabilities --tool=claude --json
12
+ async function runToolCapabilities({ args: _args, options = {}, logger, t: _t }) {
13
+ const tool = options.tool ? String(options.tool).trim() : null;
14
+
15
+ let payload;
16
+ if (tool) {
17
+ const caps = getToolCapabilities(tool);
18
+ if (!caps) {
19
+ const supported = listSupportedTools();
20
+ throw new Error(`tool_unknown:${tool} (supported: ${supported.join(', ')})`);
21
+ }
22
+ payload = { tool: tool.toLowerCase(), capabilities: caps };
23
+ } else {
24
+ payload = {
25
+ tools: TOOL_CAPS,
26
+ schema_version: 1,
27
+ };
28
+ }
29
+
30
+ if (options.json) {
31
+ logger.log(JSON.stringify(payload, null, 2));
32
+ return { ok: true, payload };
33
+ }
34
+
35
+ // Human-readable fallback
36
+ if (tool) {
37
+ const caps = payload.capabilities;
38
+ logger.log(`Tool: ${payload.tool}`);
39
+ logger.log(` binary: ${caps.binary}`);
40
+ logger.log(` install_command: ${caps.install_command}`);
41
+ logger.log(` supports_resume: ${caps.supports_resume}`);
42
+ if (caps.supports_resume) {
43
+ logger.log(` resume_last: ${(caps.resume_last || []).join(' ')}`);
44
+ logger.log(` supports_session_id: ${caps.supports_session_id}`);
45
+ if (caps.supports_session_id) {
46
+ logger.log(` resume_session_id: ${(caps.resume_session_id || []).join(' ')}`);
47
+ }
48
+ logger.log(` supports_session_picker: ${caps.supports_session_picker}`);
49
+ if (caps.supports_session_picker) {
50
+ logger.log(` session_picker: ${(caps.session_picker || []).join(' ')}`);
51
+ }
52
+ }
53
+ } else {
54
+ logger.log(`Supported tools: ${listSupportedTools().join(', ')}`);
55
+ logger.log(`Run with --tool=<name> for details, or --json for the full map.`);
56
+ }
57
+
58
+ return { ok: true, payload };
59
+ }
60
+
61
+ module.exports = {
62
+ runToolCapabilities,
63
+ };
@@ -3,7 +3,7 @@
3
3
  const path = require('node:path');
4
4
  const { detectFramework } = require('../detector');
5
5
  const { updateInstallation } = require('../updater');
6
- const { validateProjectContextFile } = require('../context');
6
+ const { validateProjectContextFile, getInteractionLanguage } = require('../context');
7
7
  const { applyAgentLocale } = require('../locales');
8
8
 
9
9
  async function runUpdate({ args, options, logger, t }) {
@@ -28,8 +28,8 @@ async function runUpdate({ args, options, logger, t }) {
28
28
  const context = await validateProjectContextFile(targetDir);
29
29
  const language =
30
30
  requestedLanguage ||
31
- (context.parsed && context.data && context.data.conversation_language
32
- ? context.data.conversation_language
31
+ (context.parsed && context.data
32
+ ? getInteractionLanguage(context.data, '')
33
33
  : null) ||
34
34
  (result.savedProfile && result.savedProfile.locale
35
35
  ? result.savedProfile.locale
@@ -454,6 +454,35 @@ async function runVerifyGate({ args, options = {}, logger }) {
454
454
  // ── Parse spec requirements ───────────────────────────────────────────────
455
455
  const requirements = parseSpecRequirements(specContent);
456
456
 
457
+ // ── Harness Integration ───────────────────────────────────────────────────
458
+ let contractCriteria = [];
459
+ if (options.contract) {
460
+ try {
461
+ const contractContent = await fs.readFile(path.resolve(targetDir, options.contract), 'utf8');
462
+ const contract = JSON.parse(contractContent);
463
+ if (contract.criteria && Array.isArray(contract.criteria)) {
464
+ contractCriteria = contract.criteria;
465
+ for (const c of contract.criteria) {
466
+ let mapped = false;
467
+ // Map assertion to deterministic check if possible
468
+ // Pattern mapping: if assertion looks like "path/to/file.js", add to required files
469
+ if (c.assertion.includes('/') && !c.assertion.includes(' ')) {
470
+ requirements.required_files.push(c.assertion.trim());
471
+ mapped = true;
472
+ }
473
+
474
+ // Only add to acceptance criteria for reporting if not deterministically mapped
475
+ // This prevents "Unchecked criterion" issues for things already checked via files/patterns
476
+ if (!mapped) {
477
+ requirements.acceptance_criteria.push({ text: `[Harness ${c.id}] ${c.description}`, checked: false });
478
+ }
479
+ }
480
+ }
481
+ } catch (err) {
482
+ logger.warn(`[VerifyGate] Falha ao ler contrato: ${err.message}`);
483
+ }
484
+ }
485
+
457
486
  // ── Collect artifact files ────────────────────────────────────────────────
458
487
  const allFiles = await collectFiles(artifactPath);
459
488
 
@@ -499,6 +528,16 @@ async function runVerifyGate({ args, options = {}, logger }) {
499
528
  const relOut = path.relative(targetDir, outPath);
500
529
 
501
530
  if (options.json) {
531
+ // Map issues/passes back to contract IDs if possible
532
+ const criteriaResults = contractCriteria.map(c => {
533
+ const passed = !allIssues.some(i => i.includes(c.id) || i.includes(c.assertion));
534
+ return {
535
+ id: c.id,
536
+ passed,
537
+ reason: passed ? null : allIssues.find(i => i.includes(c.id) || i.includes(c.assertion))
538
+ };
539
+ });
540
+
502
541
  return {
503
542
  ok: verdict === 'PASS' || verdict === 'PASS_WITH_NOTES',
504
543
  verdict,
@@ -509,6 +548,7 @@ async function runVerifyGate({ args, options = {}, logger }) {
509
548
  issues: allIssues,
510
549
  notes: allNotes,
511
550
  passes: allPasses,
551
+ criteria_results: criteriaResults,
512
552
  requirements: {
513
553
  required_files: requirements.required_files.length,
514
554
  acceptance_criteria: requirements.acceptance_criteria.length,