@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,159 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { isValidSlug } = require('./schema');
6
+
7
+ const FEATURES_SUBDIR = 'features';
8
+ const DOSSIER_FILENAME = 'dossier.md';
9
+ const HISTORY_FILENAME = 'dossier-history.md';
10
+ const MAX_ACTIVE_SIZE = 15000;
11
+ const TARGET_ACTIVE_SIZE = 10000;
12
+
13
+ // Sections whose content can be migrated once the gate they belong to is closed.
14
+ // The ordering reflects which gates close first in MEDIUM flow.
15
+ const MIGRATABLE_SECTIONS = [
16
+ 'Why',
17
+ 'What',
18
+ 'Rules & Design-Docs aplicáveis'
19
+ ];
20
+
21
+ function dossierPath(contextDir, slug) {
22
+ return path.join(contextDir, FEATURES_SUBDIR, slug, DOSSIER_FILENAME);
23
+ }
24
+
25
+ function historyPath(contextDir, slug) {
26
+ return path.join(contextDir, FEATURES_SUBDIR, slug, HISTORY_FILENAME);
27
+ }
28
+
29
+ function splitSections(raw) {
30
+ const result = [];
31
+ const lines = raw.split('\n');
32
+ let current = null;
33
+ let buf = [];
34
+ let frontmatter = null;
35
+ let inFm = false;
36
+ let fmClosed = false;
37
+ let fmBuf = [];
38
+
39
+ for (let i = 0; i < lines.length; i++) {
40
+ const line = lines[i];
41
+ if (!fmClosed) {
42
+ if (i === 0 && line === '---') { inFm = true; fmBuf.push(line); continue; }
43
+ if (inFm) {
44
+ fmBuf.push(line);
45
+ if (line === '---' && i > 0) { fmClosed = true; frontmatter = fmBuf.join('\n'); continue; }
46
+ continue;
47
+ }
48
+ fmClosed = true;
49
+ }
50
+ const m = line.match(/^##\s+(.+?)\s*$/);
51
+ if (m) {
52
+ if (current !== null) result.push({ heading: current, lines: buf });
53
+ current = m[1].trim();
54
+ buf = [];
55
+ } else {
56
+ if (current !== null) buf.push(line);
57
+ }
58
+ }
59
+ if (current !== null) result.push({ heading: current, lines: buf });
60
+ return { frontmatter, sections: result };
61
+ }
62
+
63
+ function joinSections(frontmatter, sections) {
64
+ const parts = [];
65
+ if (frontmatter) parts.push(frontmatter, '');
66
+ for (const sec of sections) {
67
+ parts.push(`## ${sec.heading}`);
68
+ parts.push(...sec.lines);
69
+ }
70
+ return parts.join('\n');
71
+ }
72
+
73
+ async function compact({ slug, contextDir, now = () => new Date(), force = false } = {}) {
74
+ if (!isValidSlug(slug)) {
75
+ const err = new Error(`invalid slug: ${JSON.stringify(slug)}`);
76
+ err.code = 'EDOSSIERSLUG';
77
+ throw err;
78
+ }
79
+
80
+ const p = dossierPath(contextDir, slug);
81
+ let raw;
82
+ try {
83
+ raw = await fs.readFile(p, 'utf8');
84
+ } catch (err) {
85
+ if (err && err.code === 'ENOENT') {
86
+ const e = new Error(`dossier not found for slug "${slug}"`);
87
+ e.code = 'EDOSSIERMISSING';
88
+ throw e;
89
+ }
90
+ throw err;
91
+ }
92
+
93
+ if (!force && Buffer.byteLength(raw, 'utf8') <= MAX_ACTIVE_SIZE) {
94
+ return { compacted: false, reason: 'size_ok', sizeBytes: Buffer.byteLength(raw, 'utf8') };
95
+ }
96
+
97
+ const { frontmatter, sections } = splitSections(raw);
98
+ const date = now().toISOString().slice(0, 10);
99
+ const hp = historyPath(contextDir, slug);
100
+
101
+ // Load or initialize history
102
+ let historyContent = '';
103
+ try {
104
+ historyContent = await fs.readFile(hp, 'utf8');
105
+ } catch {
106
+ historyContent = `# Dossier History — ${slug}\n\n`;
107
+ }
108
+
109
+ const migratedHeadings = [];
110
+ const activeSections = [];
111
+
112
+ for (const sec of sections) {
113
+ const body = sec.lines.join('\n').trim();
114
+ const isEmpty = !body || body.startsWith('_(vazio') || body.startsWith('_(empty') || body.startsWith('_(preencher');
115
+
116
+ if (MIGRATABLE_SECTIONS.includes(sec.heading) && !isEmpty) {
117
+ // Append to history (append-only, never compact again)
118
+ const anchor = sec.heading.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-');
119
+ historyContent += `\n## [Migrated from active dossier on ${date}] ${sec.heading} {#${anchor}-${date}}\n\n${body}\n`;
120
+ migratedHeadings.push(sec.heading);
121
+
122
+ // Replace in active with summary + link
123
+ activeSections.push({
124
+ heading: sec.heading,
125
+ lines: [``, `_(migrated to [dossier-history.md](dossier-history.md#${anchor}-${date}))_`, ``]
126
+ });
127
+ } else {
128
+ activeSections.push(sec);
129
+ }
130
+ }
131
+
132
+ if (migratedHeadings.length === 0) {
133
+ return { compacted: false, reason: 'nothing_migratable', sizeBytes: Buffer.byteLength(raw, 'utf8') };
134
+ }
135
+
136
+ const newRaw = joinSections(frontmatter, activeSections);
137
+ await fs.writeFile(p, newRaw, 'utf8');
138
+ // History is append-only
139
+ await fs.writeFile(hp, historyContent, 'utf8');
140
+
141
+ return {
142
+ compacted: true,
143
+ migratedSections: migratedHeadings,
144
+ activeSizeBytes: Buffer.byteLength(newRaw, 'utf8'),
145
+ historyPath: hp
146
+ };
147
+ }
148
+
149
+ async function shouldCompact({ slug, contextDir } = {}) {
150
+ const p = dossierPath(contextDir, slug);
151
+ try {
152
+ const stat = await fs.stat(p);
153
+ return stat.size > MAX_ACTIVE_SIZE;
154
+ } catch {
155
+ return false;
156
+ }
157
+ }
158
+
159
+ module.exports = { compact, shouldCompact, MAX_ACTIVE_SIZE, TARGET_ACTIVE_SIZE, dossierPath, historyPath };
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+
6
+ const LOCK_FILENAME = '.dossier.lock';
7
+ const DEFAULT_TIMEOUT_MS = 30_000;
8
+ const DEFAULT_POLL_INTERVAL_MS = 200;
9
+ const DEFAULT_STALE_TTL_MS = 60_000;
10
+
11
+ function defaultIsAlive(pid) {
12
+ if (typeof pid !== 'number' || !Number.isFinite(pid)) return false;
13
+ try {
14
+ process.kill(pid, 0);
15
+ return true;
16
+ } catch (err) {
17
+ return err && err.code === 'EPERM';
18
+ }
19
+ }
20
+
21
+ function sleep(ms) {
22
+ return new Promise((resolve) => setTimeout(resolve, ms));
23
+ }
24
+
25
+ function isStaleLock(payload, { staleTtlMs, now, isAlive }) {
26
+ if (!payload || typeof payload !== 'object') return true;
27
+ const acquiredMs = Date.parse(payload.acquired_at);
28
+ if (!Number.isFinite(acquiredMs)) return true;
29
+ if (now() - acquiredMs >= staleTtlMs) return true;
30
+ if (typeof payload.pid !== 'number' || !isAlive(payload.pid)) return true;
31
+ return false;
32
+ }
33
+
34
+ async function acquireLock(lockDir, section, opts = {}) {
35
+ if (typeof lockDir !== 'string' || !lockDir) {
36
+ throw new TypeError('acquireLock: lockDir must be a non-empty string');
37
+ }
38
+ if (typeof section !== 'string' || !section) {
39
+ throw new TypeError('acquireLock: section must be a non-empty string');
40
+ }
41
+
42
+ const {
43
+ timeoutMs = DEFAULT_TIMEOUT_MS,
44
+ pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,
45
+ staleTtlMs = DEFAULT_STALE_TTL_MS,
46
+ now = Date.now,
47
+ pid = process.pid,
48
+ isAlive = defaultIsAlive,
49
+ onWarn = (msg) => process.emitWarning(msg, 'DossierLockStale'),
50
+ sleepFn = sleep
51
+ } = opts;
52
+
53
+ const lockPath = path.join(lockDir, LOCK_FILENAME);
54
+ const start = now();
55
+
56
+ await fs.mkdir(lockDir, { recursive: true });
57
+
58
+ while (true) {
59
+ try {
60
+ const payload = {
61
+ pid,
62
+ section,
63
+ acquired_at: new Date(now()).toISOString()
64
+ };
65
+ const fh = await fs.open(lockPath, 'wx');
66
+ try {
67
+ await fh.writeFile(JSON.stringify(payload));
68
+ } finally {
69
+ await fh.close();
70
+ }
71
+
72
+ let released = false;
73
+ return async function release() {
74
+ if (released) return;
75
+ released = true;
76
+ try {
77
+ await fs.unlink(lockPath);
78
+ } catch (err) {
79
+ if (err && err.code !== 'ENOENT') throw err;
80
+ }
81
+ };
82
+ } catch (err) {
83
+ if (!err || err.code !== 'EEXIST') throw err;
84
+
85
+ let existing = null;
86
+ try {
87
+ const raw = await fs.readFile(lockPath, 'utf8');
88
+ existing = JSON.parse(raw);
89
+ } catch (_) {
90
+ existing = null;
91
+ }
92
+
93
+ if (isStaleLock(existing, { staleTtlMs, now, isAlive })) {
94
+ onWarn(
95
+ `stale dossier lockfile at ${lockPath} (pid=${existing && existing.pid != null ? existing.pid : '?'}); overriding`
96
+ );
97
+ try {
98
+ await fs.unlink(lockPath);
99
+ } catch (unlinkErr) {
100
+ if (unlinkErr && unlinkErr.code !== 'ENOENT') throw unlinkErr;
101
+ }
102
+ continue;
103
+ }
104
+
105
+ if (now() - start >= timeoutMs) {
106
+ const timeoutErr = new Error(
107
+ `timed out acquiring dossier lock at ${lockPath} after ${timeoutMs}ms`
108
+ );
109
+ timeoutErr.code = 'EDOSSIERLOCK';
110
+ timeoutErr.lockPath = lockPath;
111
+ timeoutErr.holder = existing;
112
+ throw timeoutErr;
113
+ }
114
+
115
+ await sleepFn(pollIntervalMs);
116
+ }
117
+ }
118
+ }
119
+
120
+ module.exports = {
121
+ LOCK_FILENAME,
122
+ DEFAULT_TIMEOUT_MS,
123
+ DEFAULT_POLL_INTERVAL_MS,
124
+ DEFAULT_STALE_TTL_MS,
125
+ acquireLock,
126
+ isStaleLock,
127
+ defaultIsAlive
128
+ };
@@ -0,0 +1,313 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('node:crypto');
4
+ const fs = require('node:fs/promises');
5
+ const path = require('node:path');
6
+
7
+ const { isCanonicalAgent, isValidSlug } = require('./schema');
8
+ const { shouldCompact, compact } = require('./dossier-compact');
9
+
10
+ const FEATURES_SUBDIR = 'features';
11
+ const REVISIONS_FILENAME = 'revisions.json';
12
+ const MAX_REVISION_ROUNDS = 3;
13
+
14
+ const VALID_SEVERITIES = new Set(['blocking', 'advisory']);
15
+ const VALID_STATUSES = new Set(['pending', 'approved', 'rejected', 'resolved']);
16
+
17
+ // Which workflow gate each agent "owns" (for anti-loop counter)
18
+ const GATE_BY_AGENT = {
19
+ product: 'requirements',
20
+ analyst: 'requirements',
21
+ architect: 'design',
22
+ 'ux-ui': 'design',
23
+ pm: 'plan',
24
+ dev: 'plan',
25
+ qa: 'execution'
26
+ };
27
+
28
+ function revisionsPath(contextDir, slug) {
29
+ return path.join(contextDir, FEATURES_SUBDIR, slug, REVISIONS_FILENAME);
30
+ }
31
+
32
+ function dossierPath(contextDir, slug) {
33
+ return path.join(contextDir, FEATURES_SUBDIR, slug, 'dossier.md');
34
+ }
35
+
36
+ function workflowStatePath(contextDir) {
37
+ return path.join(contextDir, 'workflow.state.json');
38
+ }
39
+
40
+ function nextRevId(existing) {
41
+ const n = existing.length + 1;
42
+ return `rev-${String(n).padStart(3, '0')}`;
43
+ }
44
+
45
+ async function readRevisions({ slug, contextDir }) {
46
+ const p = revisionsPath(contextDir, slug);
47
+ try {
48
+ const raw = await fs.readFile(p, 'utf8');
49
+ const parsed = JSON.parse(raw);
50
+ return Array.isArray(parsed) ? parsed : [];
51
+ } catch {
52
+ return [];
53
+ }
54
+ }
55
+
56
+ async function writeRevisions({ slug, contextDir, revisions }) {
57
+ const p = revisionsPath(contextDir, slug);
58
+ await fs.mkdir(path.dirname(p), { recursive: true });
59
+ await fs.writeFile(p, JSON.stringify(revisions, null, 2) + '\n', 'utf8');
60
+ }
61
+
62
+ // Replace the content of one ## section in a markdown file.
63
+ async function updateDossierSection(filePath, sectionName, newContent) {
64
+ let raw;
65
+ try {
66
+ raw = await fs.readFile(filePath, 'utf8');
67
+ } catch {
68
+ return; // dossier absent — skip silently
69
+ }
70
+
71
+ const lines = raw.split('\n');
72
+ let sectionStart = -1;
73
+ let sectionEnd = lines.length;
74
+
75
+ for (let i = 0; i < lines.length; i++) {
76
+ if (lines[i].trimEnd() === `## ${sectionName}`) {
77
+ sectionStart = i;
78
+ } else if (sectionStart !== -1 && i > sectionStart && /^## /.test(lines[i])) {
79
+ sectionEnd = i;
80
+ break;
81
+ }
82
+ }
83
+
84
+ let rebuilt;
85
+ if (sectionStart === -1) {
86
+ // Append section at end
87
+ rebuilt = raw.trimEnd() + `\n\n## ${sectionName}\n\n${newContent.trimEnd()}\n`;
88
+ } else {
89
+ const before = lines.slice(0, sectionStart + 1);
90
+ const after = lines.slice(sectionEnd);
91
+ rebuilt = [...before, '', newContent.trimEnd(), '', ...after].join('\n');
92
+ }
93
+
94
+ await fs.writeFile(filePath, rebuilt, 'utf8');
95
+ }
96
+
97
+ function buildRevisionTable(revisions) {
98
+ if (revisions.length === 0) {
99
+ return '_(sem revisões abertas)_';
100
+ }
101
+ const header = '| id | requested_by | target | severity | status |';
102
+ const divider = '|----|-------------|--------|----------|--------|';
103
+ const rows = revisions.map((r) =>
104
+ `| ${r.id} | ${r.requested_by} | ${r.target} | ${r.severity} | ${r.status} |`
105
+ );
106
+ return [header, divider, ...rows].join('\n');
107
+ }
108
+
109
+ async function readWorkflowState(contextDir) {
110
+ const p = workflowStatePath(contextDir);
111
+ try {
112
+ const raw = await fs.readFile(p, 'utf8');
113
+ return JSON.parse(raw);
114
+ } catch {
115
+ return null;
116
+ }
117
+ }
118
+
119
+ async function writeWorkflowState(contextDir, state) {
120
+ const p = workflowStatePath(contextDir);
121
+ await fs.writeFile(p, JSON.stringify(state, null, 2) + '\n', 'utf8');
122
+ }
123
+
124
+ async function open({
125
+ slug,
126
+ contextDir,
127
+ requestedBy,
128
+ target,
129
+ targetArtifact,
130
+ reason,
131
+ severity,
132
+ evidenceCodeRefs = [],
133
+ now = () => new Date()
134
+ } = {}) {
135
+ if (!isValidSlug(slug)) {
136
+ const err = new Error(`invalid slug: ${JSON.stringify(slug)}`);
137
+ err.code = 'EREVSLUG';
138
+ throw err;
139
+ }
140
+ if (!isCanonicalAgent(requestedBy)) {
141
+ const err = new Error(`requested_by must be a canonical agent id (got: ${JSON.stringify(requestedBy)})`);
142
+ err.code = 'EREVAGENT';
143
+ throw err;
144
+ }
145
+ if (!isCanonicalAgent(target)) {
146
+ const err = new Error(`target must be a canonical agent id (got: ${JSON.stringify(target)})`);
147
+ err.code = 'EREVAGENT';
148
+ throw err;
149
+ }
150
+ if (!VALID_SEVERITIES.has(severity)) {
151
+ const err = new Error(`severity must be 'blocking' or 'advisory' (got: ${JSON.stringify(severity)})`);
152
+ err.code = 'EREVSCHEMA';
153
+ throw err;
154
+ }
155
+ if (!targetArtifact || typeof targetArtifact !== 'string') {
156
+ const err = new Error('target_artifact must be a non-empty relative path');
157
+ err.code = 'EREVSCHEMA';
158
+ throw err;
159
+ }
160
+ if (!reason || typeof reason !== 'string' || !reason.trim()) {
161
+ const err = new Error('reason must be a non-empty string');
162
+ err.code = 'EREVSCHEMA';
163
+ throw err;
164
+ }
165
+
166
+ const revisions = await readRevisions({ slug, contextDir });
167
+ const id = nextRevId(revisions);
168
+ const createdAt = now().toISOString();
169
+
170
+ const revision = {
171
+ id,
172
+ status: 'pending',
173
+ requested_by: requestedBy,
174
+ target,
175
+ target_artifact: targetArtifact,
176
+ reason: reason.trim(),
177
+ severity,
178
+ evidence_code_refs: Array.isArray(evidenceCodeRefs) ? evidenceCodeRefs : [],
179
+ created_at: createdAt,
180
+ resolved_at: null,
181
+ resolution: null
182
+ };
183
+
184
+ revisions.push(revision);
185
+ await writeRevisions({ slug, contextDir, revisions });
186
+
187
+ // Update dossier ## Revision Requests
188
+ const dp = dossierPath(contextDir, slug);
189
+ await updateDossierSection(dp, 'Revision Requests', buildRevisionTable(revisions));
190
+
191
+ return revision;
192
+ }
193
+
194
+ async function list({ slug, contextDir, status } = {}) {
195
+ if (!isValidSlug(slug)) {
196
+ const err = new Error(`invalid slug: ${JSON.stringify(slug)}`);
197
+ err.code = 'EREVSLUG';
198
+ throw err;
199
+ }
200
+ const revisions = await readRevisions({ slug, contextDir });
201
+ if (status && VALID_STATUSES.has(status)) {
202
+ return revisions.filter((r) => r.status === status);
203
+ }
204
+ return revisions;
205
+ }
206
+
207
+ async function resolve({
208
+ slug,
209
+ contextDir,
210
+ revId,
211
+ action,
212
+ forceRevision = false,
213
+ now = () => new Date()
214
+ } = {}) {
215
+ if (!isValidSlug(slug)) {
216
+ const err = new Error(`invalid slug: ${JSON.stringify(slug)}`);
217
+ err.code = 'EREVSLUG';
218
+ throw err;
219
+ }
220
+ if (action !== 'approve' && action !== 'reject') {
221
+ const err = new Error(`action must be 'approve' or 'reject' (got: ${JSON.stringify(action)})`);
222
+ err.code = 'EREVSCHEMA';
223
+ throw err;
224
+ }
225
+
226
+ const revisions = await readRevisions({ slug, contextDir });
227
+ const idx = revisions.findIndex((r) => r.id === revId);
228
+ if (idx === -1) {
229
+ const err = new Error(`revision '${revId}' not found in ${slug}`);
230
+ err.code = 'EREVNOTFOUND';
231
+ throw err;
232
+ }
233
+
234
+ const rev = revisions[idx];
235
+ if (rev.status !== 'pending') {
236
+ const err = new Error(`revision '${revId}' is '${rev.status}' — only pending revisions can be resolved`);
237
+ err.code = 'EREVNOTPENDING';
238
+ throw err;
239
+ }
240
+
241
+ const resolvedAt = now().toISOString();
242
+
243
+ if (action === 'reject') {
244
+ revisions[idx] = { ...rev, status: 'rejected', resolved_at: resolvedAt, resolution: 'rejected' };
245
+ await writeRevisions({ slug, contextDir, revisions });
246
+ const dp = dossierPath(contextDir, slug);
247
+ await updateDossierSection(dp, 'Revision Requests', buildRevisionTable(revisions));
248
+ if (await shouldCompact({ slug, contextDir })) await compact({ slug, contextDir });
249
+ return { revision: revisions[idx], gateIncremented: null };
250
+ }
251
+
252
+ // approve path: check anti-loop limit
253
+ const gate = GATE_BY_AGENT[rev.target] || null;
254
+ let gateIncremented = null;
255
+ let newRounds = null;
256
+
257
+ if (gate) {
258
+ const wfState = await readWorkflowState(contextDir);
259
+ if (wfState) {
260
+ const rounds = (wfState.gate_revision_rounds || {})[gate] || 0;
261
+ if (rounds >= MAX_REVISION_ROUNDS && !forceRevision) {
262
+ const err = new Error(
263
+ `Anti-loop: gate '${gate}' already had ${rounds} revision round(s) (max ${MAX_REVISION_ROUNDS}). ` +
264
+ `Use --force-revision to override.`
265
+ );
266
+ err.code = 'EREVLOOP';
267
+ err.gate = gate;
268
+ err.rounds = rounds;
269
+ throw err;
270
+ }
271
+ newRounds = rounds + 1;
272
+ const updatedState = {
273
+ ...wfState,
274
+ gate_revision_rounds: {
275
+ ...(wfState.gate_revision_rounds || {}),
276
+ [gate]: newRounds
277
+ }
278
+ };
279
+ await writeWorkflowState(contextDir, updatedState);
280
+ gateIncremented = { gate, rounds: newRounds };
281
+ }
282
+ }
283
+
284
+ revisions[idx] = { ...rev, status: 'approved', resolved_at: resolvedAt, resolution: 'approved' };
285
+ await writeRevisions({ slug, contextDir, revisions });
286
+ const dp = dossierPath(contextDir, slug);
287
+ await updateDossierSection(dp, 'Revision Requests', buildRevisionTable(revisions));
288
+ if (await shouldCompact({ slug, contextDir })) await compact({ slug, contextDir });
289
+
290
+ return { revision: revisions[idx], gateIncremented };
291
+ }
292
+
293
+ async function getBlockingRevisions({ slug, contextDir }) {
294
+ if (!slug || !isValidSlug(slug)) return [];
295
+ const revisions = await readRevisions({ slug, contextDir });
296
+ return revisions.filter((r) => r.severity === 'blocking' && r.status === 'pending');
297
+ }
298
+
299
+ module.exports = {
300
+ VALID_SEVERITIES,
301
+ VALID_STATUSES,
302
+ GATE_BY_AGENT,
303
+ MAX_REVISION_ROUNDS,
304
+ revisionsPath,
305
+ readRevisions,
306
+ writeRevisions,
307
+ updateDossierSection,
308
+ buildRevisionTable,
309
+ open,
310
+ list,
311
+ resolve,
312
+ getBlockingRevisions
313
+ };