@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,691 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { execFileSync } = require('node:child_process');
6
+
7
+ const DEFAULT_CONFIG_REL_PATH = '.aioson/git-guard.json';
8
+ const MANAGED_HOOK_MARKER = '# aioson-git-guard-hook';
9
+ const BACKUP_HOOK_GIT_PATH = 'hooks/pre-commit.aioson-backup';
10
+ const DEFAULT_POLICY = Object.freeze({
11
+ version: 1,
12
+ description: '',
13
+ allowPaths: [],
14
+ blockPaths: [],
15
+ allowExtensions: [],
16
+ blockExtensions: []
17
+ });
18
+
19
+ const BLOCKED_PATH_RULES = [
20
+ {
21
+ id: 'dependency_dir',
22
+ reason: 'dependency/vendor directory should not be committed',
23
+ test: (relPath) => /(^|\/)(node_modules|vendor)(\/|$)/i.test(relPath)
24
+ },
25
+ {
26
+ id: 'build_output',
27
+ reason: 'generated build output should not be committed',
28
+ test: (relPath) => /(^|\/)(dist|build|coverage|\.next|\.nuxt|\.svelte-kit|\.turbo|\.cache|\.parcel-cache|tmp|temp)(\/|$)/i.test(relPath)
29
+ },
30
+ {
31
+ id: 'session_artifact',
32
+ reason: 'runtime/session artifact should not be committed',
33
+ test: (relPath) => /(^|\/)(aioson-logs|output|media)(\/|$)/i.test(relPath)
34
+ },
35
+ {
36
+ id: 'aioson_backup',
37
+ reason: 'AIOSON backup artifact should not be committed',
38
+ test: (relPath) => /(^|\/)\.aioson\/backups(\/|$)/i.test(relPath)
39
+ },
40
+ {
41
+ id: 'env_file',
42
+ reason: 'environment file may contain secrets',
43
+ test: (relPath) => {
44
+ const base = path.posix.basename(relPath).toLowerCase();
45
+ if (!base.startsWith('.env')) return false;
46
+ return !['.env.example', '.env.sample', '.env.template', '.env.dist'].includes(base);
47
+ }
48
+ },
49
+ {
50
+ id: 'secret_file',
51
+ reason: 'secret or credential file should not be committed',
52
+ test: (relPath) => /\.(pem|key|p12|pfx|p8|keystore|mobileprovision|kdbx)$/i.test(relPath)
53
+ },
54
+ {
55
+ id: 'log_file',
56
+ reason: 'log/debug artifact should not be committed',
57
+ test: (relPath) => {
58
+ const base = path.posix.basename(relPath).toLowerCase();
59
+ return base === '.ds_store'
60
+ || base === 'npm-debug.log'
61
+ || base === 'yarn-error.log'
62
+ || base === 'pnpm-debug.log'
63
+ || /\.log$/i.test(base);
64
+ }
65
+ }
66
+ ];
67
+
68
+ const WARNING_PATH_RULES = [
69
+ {
70
+ id: 'backup_suffix',
71
+ reason: 'backup or temporary file staged',
72
+ test: (relPath) => /\.(bak|tmp|orig|rej|swp|swo|old|save)$/i.test(relPath)
73
+ },
74
+ {
75
+ id: 'scratch_name',
76
+ reason: 'draft/scratch-style file name staged',
77
+ test: (relPath) => {
78
+ const base = path.posix.basename(relPath);
79
+ return /(^|[._-])(draft|scratch|wip|junk|trash|temp|tmp)([._-]|$)/i.test(base);
80
+ }
81
+ },
82
+ {
83
+ id: 'local_database',
84
+ reason: 'local database or dump file staged',
85
+ test: (relPath) => /\.(sqlite|sqlite3|db|dump)$/i.test(relPath)
86
+ }
87
+ ];
88
+
89
+ const CONTENT_RULES = [
90
+ {
91
+ id: 'private_key_block',
92
+ severity: 'error',
93
+ reason: 'private key material detected',
94
+ pattern: /-----BEGIN(?: [A-Z0-9]+)? PRIVATE KEY-----/m
95
+ },
96
+ {
97
+ id: 'aws_access_key',
98
+ severity: 'error',
99
+ reason: 'AWS access key detected',
100
+ pattern: /\bAKIA[0-9A-Z]{16}\b/
101
+ },
102
+ {
103
+ id: 'github_token',
104
+ severity: 'error',
105
+ reason: 'GitHub token detected',
106
+ pattern: /\b(?:github_pat_[A-Za-z0-9_]{20,}|ghp_[A-Za-z0-9]{20,}|gho_[A-Za-z0-9]{20,}|ghu_[A-Za-z0-9]{20,}|ghs_[A-Za-z0-9]{20,}|ghr_[A-Za-z0-9]{20,})\b/
107
+ },
108
+ {
109
+ id: 'slack_token',
110
+ severity: 'error',
111
+ reason: 'Slack token detected',
112
+ pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/
113
+ },
114
+ {
115
+ id: 'google_api_key',
116
+ severity: 'error',
117
+ reason: 'Google API key detected',
118
+ pattern: /\bAIza[0-9A-Za-z\-_]{35}\b/
119
+ },
120
+ {
121
+ id: 'stripe_secret',
122
+ severity: 'error',
123
+ reason: 'Stripe secret key detected',
124
+ pattern: /\bsk_(?:live|test)_[0-9A-Za-z]{16,}\b/
125
+ },
126
+ {
127
+ id: 'openai_secret',
128
+ severity: 'error',
129
+ reason: 'OpenAI-style secret detected',
130
+ pattern: /\bsk-[A-Za-z0-9]{20,}\b/
131
+ },
132
+ {
133
+ id: 'npm_token',
134
+ severity: 'error',
135
+ reason: 'npm token detected',
136
+ pattern: /\bnpm_[A-Za-z0-9]{20,}\b/
137
+ }
138
+ ];
139
+
140
+ // Detects literal secret assignments. Quotes are required so that function
141
+ // calls (e.g. `const token = requireToken(config)`) are not flagged: only the
142
+ // value inside the matched quote pair counts toward the 8-char minimum.
143
+ const GENERIC_SECRET_ASSIGNMENT = /\b([A-Z0-9_]*(?:SECRET|TOKEN|API_KEY|ACCESS_KEY|PRIVATE_KEY|PASSWORD|PASSWD|CLIENT_SECRET)[A-Z0-9_]*)\b\s*[:=]\s*(['"`])([^'"`\n\r]{8,})\2/gi;
144
+ const PLACEHOLDER_VALUE = /^(?:example|sample|placeholder|dummy|changeme|change-me|replace[-_]?me|your[_-]?value|your[_-]?token|test|local|localhost|xxx+)$/i;
145
+
146
+ function runGit(gitRoot, args, options = {}) {
147
+ return execFileSync('git', args, {
148
+ cwd: gitRoot,
149
+ encoding: options.encoding || 'utf8',
150
+ maxBuffer: options.maxBuffer || 8 * 1024 * 1024,
151
+ stdio: ['ignore', 'pipe', 'pipe']
152
+ });
153
+ }
154
+
155
+ function normalizeRelPath(relPath) {
156
+ return String(relPath || '').replace(/\\/g, '/').replace(/^\.\//, '');
157
+ }
158
+
159
+ function resolveGitRoot(projectDir) {
160
+ return String(runGit(projectDir, ['rev-parse', '--show-toplevel'])).trim();
161
+ }
162
+
163
+ function resolveGitPath(gitRoot, gitPath) {
164
+ const resolved = String(runGit(gitRoot, ['rev-parse', '--git-path', gitPath])).trim();
165
+ return path.isAbsolute(resolved) ? resolved : path.join(gitRoot, resolved);
166
+ }
167
+
168
+ function listStagedFiles(gitRoot) {
169
+ const output = runGit(gitRoot, ['diff', '--cached', '--name-only', '--diff-filter=ACMR', '-z'], {
170
+ encoding: 'buffer'
171
+ });
172
+ return String(output)
173
+ .split('\u0000')
174
+ .map((entry) => normalizeRelPath(entry.trim()))
175
+ .filter(Boolean);
176
+ }
177
+
178
+ function readStagedBlob(gitRoot, relPath) {
179
+ return runGit(gitRoot, ['show', `:${relPath}`], {
180
+ encoding: 'buffer',
181
+ maxBuffer: 16 * 1024 * 1024
182
+ });
183
+ }
184
+
185
+ function findLineFromIndex(text, index) {
186
+ if (index == null || index < 0) return null;
187
+ return text.slice(0, index).split('\n').length;
188
+ }
189
+
190
+ function isBinaryBuffer(buffer) {
191
+ for (let i = 0; i < buffer.length; i += 1) {
192
+ if (buffer[i] === 0) return true;
193
+ }
194
+ return false;
195
+ }
196
+
197
+ function escapeRegExp(value) {
198
+ return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&');
199
+ }
200
+
201
+ function globToRegExp(pattern) {
202
+ const normalized = normalizeRelPath(pattern).replace(/^\/+/, '');
203
+ let source = '';
204
+
205
+ for (let i = 0; i < normalized.length; i += 1) {
206
+ const char = normalized[i];
207
+ const next = normalized[i + 1];
208
+
209
+ if (char === '*') {
210
+ if (next === '*') {
211
+ source += '.*';
212
+ i += 1;
213
+ } else {
214
+ source += '[^/]*';
215
+ }
216
+ continue;
217
+ }
218
+
219
+ if (char === '?') {
220
+ source += '[^/]';
221
+ continue;
222
+ }
223
+
224
+ source += escapeRegExp(char);
225
+ }
226
+
227
+ return new RegExp(`^${source}$`, 'i');
228
+ }
229
+
230
+ function matchesAnyPattern(relPath, patterns) {
231
+ return patterns.some((pattern) => globToRegExp(pattern).test(relPath));
232
+ }
233
+
234
+ function normalizeExtension(value) {
235
+ const ext = String(value || '').trim().toLowerCase();
236
+ if (!ext) return '';
237
+ return ext.startsWith('.') ? ext : `.${ext}`;
238
+ }
239
+
240
+ function matchesAnyExtension(relPath, extensions) {
241
+ const lowered = relPath.toLowerCase();
242
+ return extensions.some((ext) => lowered.endsWith(ext));
243
+ }
244
+
245
+ function validateStringArray(data, key) {
246
+ if (data[key] == null) return [];
247
+ if (!Array.isArray(data[key])) {
248
+ throw new Error(`Invalid git guard config: "${key}" must be an array of strings`);
249
+ }
250
+ return data[key].map((item, index) => {
251
+ if (typeof item !== 'string' || item.trim().length === 0) {
252
+ throw new Error(`Invalid git guard config: "${key}[${index}]" must be a non-empty string`);
253
+ }
254
+ return key.endsWith('Extensions')
255
+ ? normalizeExtension(item)
256
+ : normalizeRelPath(item).replace(/^\/+/, '');
257
+ });
258
+ }
259
+
260
+ function resolveGuardConfigPath(projectDir, candidatePath = null) {
261
+ if (!candidatePath) return path.join(projectDir, DEFAULT_CONFIG_REL_PATH);
262
+ return path.isAbsolute(candidatePath)
263
+ ? candidatePath
264
+ : path.resolve(projectDir, String(candidatePath));
265
+ }
266
+
267
+ async function loadGuardConfig(projectDir, options = {}) {
268
+ const configPath = resolveGuardConfigPath(projectDir, options.configPath || options.config);
269
+
270
+ let raw;
271
+ try {
272
+ raw = await fs.readFile(configPath, 'utf8');
273
+ } catch (error) {
274
+ if (error && error.code === 'ENOENT') {
275
+ return {
276
+ path: configPath,
277
+ loaded: false,
278
+ config: { ...DEFAULT_POLICY }
279
+ };
280
+ }
281
+ throw error;
282
+ }
283
+
284
+ let parsed;
285
+ try {
286
+ parsed = JSON.parse(raw);
287
+ } catch (error) {
288
+ throw new Error(`Invalid git guard config at ${configPath}: ${error.message}`);
289
+ }
290
+
291
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
292
+ throw new Error(`Invalid git guard config at ${configPath}: root value must be an object`);
293
+ }
294
+
295
+ const version = parsed.version == null ? 1 : Number(parsed.version);
296
+ if (!Number.isInteger(version) || version !== 1) {
297
+ throw new Error(`Invalid git guard config at ${configPath}: unsupported version "${parsed.version}"`);
298
+ }
299
+
300
+ if (parsed.description != null && typeof parsed.description !== 'string') {
301
+ throw new Error(`Invalid git guard config at ${configPath}: "description" must be a string`);
302
+ }
303
+
304
+ return {
305
+ path: configPath,
306
+ loaded: true,
307
+ config: {
308
+ version,
309
+ description: parsed.description || '',
310
+ allowPaths: validateStringArray(parsed, 'allowPaths'),
311
+ contentAllowPaths: validateStringArray(parsed, 'contentAllowPaths'),
312
+ blockPaths: validateStringArray(parsed, 'blockPaths'),
313
+ allowExtensions: validateStringArray(parsed, 'allowExtensions'),
314
+ blockExtensions: validateStringArray(parsed, 'blockExtensions')
315
+ }
316
+ };
317
+ }
318
+
319
+ function isAllowlistedPath(relPath, policy) {
320
+ return matchesAnyPattern(relPath, policy.allowPaths) || matchesAnyExtension(relPath, policy.allowExtensions);
321
+ }
322
+
323
+ function isContentAllowlistedPath(relPath, policy) {
324
+ return matchesAnyPattern(relPath, policy.contentAllowPaths || []);
325
+ }
326
+
327
+ function collectPathFindings(relPath, rules, severity) {
328
+ const findings = [];
329
+ for (const rule of rules) {
330
+ if (!rule.test(relPath)) continue;
331
+ findings.push({
332
+ type: 'path',
333
+ severity,
334
+ id: rule.id,
335
+ path: relPath,
336
+ reason: rule.reason,
337
+ line: null
338
+ });
339
+ }
340
+ return findings;
341
+ }
342
+
343
+ function collectConfiguredPathFindings(relPath, policy) {
344
+ const findings = [];
345
+
346
+ if (matchesAnyPattern(relPath, policy.blockPaths)) {
347
+ findings.push({
348
+ type: 'path',
349
+ severity: 'error',
350
+ id: 'config_block_path',
351
+ path: relPath,
352
+ reason: 'project git guard policy blocks this path',
353
+ line: null
354
+ });
355
+ }
356
+
357
+ if (matchesAnyExtension(relPath, policy.blockExtensions)) {
358
+ findings.push({
359
+ type: 'path',
360
+ severity: 'error',
361
+ id: 'config_block_extension',
362
+ path: relPath,
363
+ reason: 'project git guard policy blocks this file extension',
364
+ line: null
365
+ });
366
+ }
367
+
368
+ return findings;
369
+ }
370
+
371
+ function collectContentFindings(relPath, text) {
372
+ const findings = [];
373
+
374
+ for (const rule of CONTENT_RULES) {
375
+ const match = text.match(rule.pattern);
376
+ if (!match || match.index == null) continue;
377
+ findings.push({
378
+ type: 'content',
379
+ severity: rule.severity,
380
+ id: rule.id,
381
+ path: relPath,
382
+ reason: rule.reason,
383
+ line: findLineFromIndex(text, match.index)
384
+ });
385
+ }
386
+
387
+ let genericMatch;
388
+ GENERIC_SECRET_ASSIGNMENT.lastIndex = 0;
389
+ while ((genericMatch = GENERIC_SECRET_ASSIGNMENT.exec(text)) !== null) {
390
+ const variableName = String(genericMatch[1] || '');
391
+ const value = String(genericMatch[3] || '');
392
+ const lowered = value.toLowerCase();
393
+ if (PLACEHOLDER_VALUE.test(value)) continue;
394
+ if (/(example|sample|dummy|placeholder|changeme|localhost|local[_-]?dev)/i.test(lowered)) continue;
395
+ if (/(public|publishable)/i.test(variableName)) continue;
396
+ findings.push({
397
+ type: 'content',
398
+ severity: 'warning',
399
+ id: 'generic_secret_assignment',
400
+ path: relPath,
401
+ reason: `possible secret assignment detected for ${variableName}`,
402
+ line: findLineFromIndex(text, genericMatch.index)
403
+ });
404
+ }
405
+
406
+ return findings;
407
+ }
408
+
409
+ function buildSuggestedCommands(findings) {
410
+ const paths = [...new Set(findings.map((item) => item.path).filter(Boolean))];
411
+ if (paths.length === 0) return [];
412
+ return paths.map((relPath) => `git restore --staged -- "${relPath}"`);
413
+ }
414
+
415
+ function summarizePolicy(policyState) {
416
+ return {
417
+ path: policyState.path,
418
+ loaded: policyState.loaded,
419
+ version: policyState.config.version,
420
+ allowPathsCount: policyState.config.allowPaths.length,
421
+ blockPathsCount: policyState.config.blockPaths.length,
422
+ allowExtensionsCount: policyState.config.allowExtensions.length,
423
+ blockExtensionsCount: policyState.config.blockExtensions.length
424
+ };
425
+ }
426
+
427
+ async function inspectStagedChanges(projectDir, options = {}) {
428
+ const gitRoot = resolveGitRoot(projectDir);
429
+ const policyState = await loadGuardConfig(gitRoot, options);
430
+ const stagedFiles = listStagedFiles(gitRoot);
431
+ const allowWarnings = Boolean(options.allowWarnings);
432
+ const findings = [];
433
+ const files = [];
434
+
435
+ for (const relPath of stagedFiles) {
436
+ const allowlisted = isAllowlistedPath(relPath, policyState.config);
437
+ const fileFindings = [
438
+ ...(allowlisted ? [] : collectPathFindings(relPath, BLOCKED_PATH_RULES, 'error')),
439
+ ...(allowlisted ? [] : collectPathFindings(relPath, WARNING_PATH_RULES, 'warning')),
440
+ ...collectConfiguredPathFindings(relPath, policyState.config)
441
+ ];
442
+
443
+ let size = 0;
444
+ let binary = false;
445
+ try {
446
+ const buffer = readStagedBlob(gitRoot, relPath);
447
+ size = buffer.length;
448
+ binary = isBinaryBuffer(buffer);
449
+ if (!binary && !isContentAllowlistedPath(relPath, policyState.config)) {
450
+ const text = buffer.toString('utf8');
451
+ fileFindings.push(...collectContentFindings(relPath, text));
452
+ }
453
+ } catch (error) {
454
+ fileFindings.push({
455
+ type: 'content',
456
+ severity: 'error',
457
+ id: 'staged_read_failed',
458
+ path: relPath,
459
+ reason: `failed to inspect staged content: ${error.message}`,
460
+ line: null
461
+ });
462
+ }
463
+
464
+ findings.push(...fileFindings);
465
+ files.push({
466
+ path: relPath,
467
+ size,
468
+ binary,
469
+ allowlisted,
470
+ findings: fileFindings
471
+ });
472
+ }
473
+
474
+ const errors = findings.filter((item) => item.severity === 'error');
475
+ const warnings = findings.filter((item) => item.severity === 'warning');
476
+ const ok = stagedFiles.length > 0 && errors.length === 0 && (allowWarnings || warnings.length === 0);
477
+
478
+ return {
479
+ ok,
480
+ gitRoot,
481
+ stagedFiles,
482
+ strict: !allowWarnings,
483
+ policy: summarizePolicy(policyState),
484
+ files,
485
+ errors,
486
+ warnings,
487
+ suggestedCommands: buildSuggestedCommands([...errors, ...warnings]),
488
+ summary: {
489
+ stagedCount: stagedFiles.length,
490
+ errorCount: errors.length,
491
+ warningCount: warnings.length
492
+ }
493
+ };
494
+ }
495
+
496
+ function isManagedHook(content) {
497
+ return String(content || '').includes(MANAGED_HOOK_MARKER);
498
+ }
499
+
500
+ function buildPreCommitHookScript({ backupPath = '' } = {}) {
501
+ const backupLiteral = backupPath ? JSON.stringify(backupPath) : '""';
502
+
503
+ return `#!/bin/sh
504
+ ${MANAGED_HOOK_MARKER}
505
+ # Managed by: aioson git:guard --install-hook
506
+
507
+ set -eu
508
+
509
+ GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
510
+ HOOK_BACKUP=${backupLiteral}
511
+
512
+ run_guard() {
513
+ if command -v aioson >/dev/null 2>&1; then
514
+ aioson git:guard "$GIT_ROOT"
515
+ return $?
516
+ fi
517
+
518
+ if [ -x "$GIT_ROOT/node_modules/.bin/aioson" ]; then
519
+ "$GIT_ROOT/node_modules/.bin/aioson" git:guard "$GIT_ROOT"
520
+ return $?
521
+ fi
522
+
523
+ if [ -f "$GIT_ROOT/bin/aioson.js" ]; then
524
+ node "$GIT_ROOT/bin/aioson.js" git:guard "$GIT_ROOT"
525
+ return $?
526
+ fi
527
+
528
+ echo "AIOSON pre-commit hook blocked this commit: aioson CLI was not found." >&2
529
+ echo "Install AIOSON CLI or remove the hook with 'aioson git:guard <project> --uninstall-hook'." >&2
530
+ return 1
531
+ }
532
+
533
+ run_guard
534
+
535
+ if [ -n "$HOOK_BACKUP" ] && [ -x "$HOOK_BACKUP" ]; then
536
+ "$HOOK_BACKUP" "$@"
537
+ fi
538
+ `;
539
+ }
540
+
541
+ async function exists(filePath) {
542
+ try {
543
+ await fs.access(filePath);
544
+ return true;
545
+ } catch {
546
+ return false;
547
+ }
548
+ }
549
+
550
+ async function installPreCommitHook(projectDir, options = {}) {
551
+ const gitRoot = resolveGitRoot(projectDir);
552
+ const hookPath = resolveGitPath(gitRoot, 'hooks/pre-commit');
553
+ const backupPath = resolveGitPath(gitRoot, BACKUP_HOOK_GIT_PATH);
554
+ const dryRun = Boolean(options.dryRun || options['dry-run']);
555
+ const force = Boolean(options.force);
556
+
557
+ let existingContent = null;
558
+ try {
559
+ existingContent = await fs.readFile(hookPath, 'utf8');
560
+ } catch (error) {
561
+ if (!error || error.code !== 'ENOENT') throw error;
562
+ }
563
+
564
+ const hookExists = typeof existingContent === 'string';
565
+ const managedExistingHook = isManagedHook(existingContent);
566
+ const backupExists = await exists(backupPath);
567
+
568
+ if (hookExists && !managedExistingHook && !force) {
569
+ return {
570
+ ok: false,
571
+ error: 'hook_exists',
572
+ message: 'A non-AIOSON pre-commit hook already exists. Re-run with --force to back it up and chain it.',
573
+ gitRoot,
574
+ hookPath,
575
+ backupPath
576
+ };
577
+ }
578
+
579
+ if (hookExists && !managedExistingHook && force && backupExists) {
580
+ return {
581
+ ok: false,
582
+ error: 'hook_backup_exists',
583
+ message: 'Cannot back up the existing pre-commit hook because an AIOSON backup hook already exists.',
584
+ gitRoot,
585
+ hookPath,
586
+ backupPath
587
+ };
588
+ }
589
+
590
+ const shouldChainBackup = backupExists || (hookExists && !managedExistingHook && force);
591
+ const script = buildPreCommitHookScript({
592
+ backupPath: shouldChainBackup ? backupPath : ''
593
+ });
594
+
595
+ if (!dryRun) {
596
+ await fs.mkdir(path.dirname(hookPath), { recursive: true });
597
+ if (hookExists && !managedExistingHook && force) {
598
+ await fs.rename(hookPath, backupPath);
599
+ }
600
+ await fs.writeFile(hookPath, script, 'utf8');
601
+ await fs.chmod(hookPath, 0o755);
602
+ }
603
+
604
+ return {
605
+ ok: true,
606
+ gitRoot,
607
+ hookPath,
608
+ backupPath,
609
+ installed: !dryRun,
610
+ dryRun,
611
+ replacedExistingHook: hookExists,
612
+ backedUpExistingHook: hookExists && !managedExistingHook && force,
613
+ chainedBackupHook: shouldChainBackup
614
+ };
615
+ }
616
+
617
+ async function uninstallPreCommitHook(projectDir, options = {}) {
618
+ const gitRoot = resolveGitRoot(projectDir);
619
+ const hookPath = resolveGitPath(gitRoot, 'hooks/pre-commit');
620
+ const backupPath = resolveGitPath(gitRoot, BACKUP_HOOK_GIT_PATH);
621
+ const dryRun = Boolean(options.dryRun || options['dry-run']);
622
+
623
+ let hookContent = null;
624
+ try {
625
+ hookContent = await fs.readFile(hookPath, 'utf8');
626
+ } catch (error) {
627
+ if (!error || error.code !== 'ENOENT') throw error;
628
+ }
629
+
630
+ if (hookContent == null) {
631
+ return {
632
+ ok: true,
633
+ gitRoot,
634
+ hookPath,
635
+ backupPath,
636
+ removed: false,
637
+ restoredBackup: false,
638
+ message: 'No pre-commit hook is installed.'
639
+ };
640
+ }
641
+
642
+ if (!isManagedHook(hookContent)) {
643
+ return {
644
+ ok: false,
645
+ error: 'hook_not_managed',
646
+ message: 'The current pre-commit hook is not managed by AIOSON.',
647
+ gitRoot,
648
+ hookPath,
649
+ backupPath
650
+ };
651
+ }
652
+
653
+ const backupExists = await exists(backupPath);
654
+ if (!dryRun) {
655
+ await fs.unlink(hookPath);
656
+ if (backupExists) {
657
+ await fs.rename(backupPath, hookPath);
658
+ await fs.chmod(hookPath, 0o755);
659
+ }
660
+ }
661
+
662
+ return {
663
+ ok: true,
664
+ gitRoot,
665
+ hookPath,
666
+ backupPath,
667
+ removed: !dryRun,
668
+ restoredBackup: backupExists,
669
+ dryRun
670
+ };
671
+ }
672
+
673
+ module.exports = {
674
+ inspectStagedChanges,
675
+ resolveGitRoot,
676
+ resolveGitPath,
677
+ resolveGuardConfigPath,
678
+ loadGuardConfig,
679
+ listStagedFiles,
680
+ readStagedBlob,
681
+ normalizeRelPath,
682
+ installPreCommitHook,
683
+ uninstallPreCommitHook,
684
+ buildPreCommitHookScript,
685
+ isManagedHook,
686
+ BLOCKED_PATH_RULES,
687
+ WARNING_PATH_RULES,
688
+ DEFAULT_CONFIG_REL_PATH,
689
+ BACKUP_HOOK_GIT_PATH,
690
+ MANAGED_HOOK_MARKER
691
+ };