@daniellins/power-claude 0.16.3

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.

Potentially problematic release.


This version of @daniellins/power-claude might be problematic. Click here for more details.

Files changed (467) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -0
  3. package/bin/cli.js +124 -0
  4. package/installer/__tests__/doctor-ready-oracles.test.cjs +140 -0
  5. package/installer/__tests__/merge-settings.test.cjs +330 -0
  6. package/installer/adopt.js +161 -0
  7. package/installer/copy.js +203 -0
  8. package/installer/doctor.js +266 -0
  9. package/installer/install.js +155 -0
  10. package/installer/manifest.js +102 -0
  11. package/installer/motor-scripts.js +50 -0
  12. package/installer/motor-scripts.json +39 -0
  13. package/installer/uninstall.js +99 -0
  14. package/installer/update.js +376 -0
  15. package/installer/util.js +113 -0
  16. package/installer/wizard.js +64 -0
  17. package/package.json +26 -0
  18. package/scripts/__fixtures__/anti-path-demo/agents/ap-writer.md +13 -0
  19. package/scripts/__fixtures__/anti-path-demo/templates/write-tmpl.md +7 -0
  20. package/scripts/__fixtures__/anti-path-demo/workflows/wf-ap.smoke.json +10 -0
  21. package/scripts/__fixtures__/anti-path-demo/workflows/wf-ap.yaml +25 -0
  22. package/scripts/__fixtures__/assess-tier/retrofit-leve/pod/agents/content-chief.md +1 -0
  23. package/scripts/__fixtures__/assess-tier/retrofit-leve/pod/workflows/wf-criacao-redteam.yaml +3 -0
  24. package/scripts/__fixtures__/assess-tier/retrofit-leve/pod-spec.json +13 -0
  25. package/scripts/__fixtures__/fidelity/fake-green-average-in-band.yaml +21 -0
  26. package/scripts/__fixtures__/fidelity/fake-green-average.yaml +18 -0
  27. package/scripts/__fixtures__/fidelity/fake-green-denominator.yaml +19 -0
  28. package/scripts/__fixtures__/fidelity/fake-green-missing-evidence.yaml +18 -0
  29. package/scripts/__fixtures__/fidelity/fake-green-threshold.yaml +18 -0
  30. package/scripts/__fixtures__/fidelity/fake-green-weight.yaml +18 -0
  31. package/scripts/__fixtures__/fidelity/golden.yaml +31 -0
  32. package/scripts/__fixtures__/fidelity/trindade-incoherent.yaml +15 -0
  33. package/scripts/__fixtures__/forge-canonical/pod-spec-example.json +37 -0
  34. package/scripts/__fixtures__/migrate-squad/authored/agents/offer-engineer.md +17 -0
  35. package/scripts/__fixtures__/migrate-squad/authored/knowledge/no-source.md +7 -0
  36. package/scripts/__fixtures__/migrate-squad/authored/knowledge/value-stack-method.md +8 -0
  37. package/scripts/__fixtures__/migrate-squad/authored/specs/wf-sample.smoke.json +24 -0
  38. package/scripts/__fixtures__/migrate-squad/authored/specs/wf-sample.spec.json +45 -0
  39. package/scripts/__fixtures__/migrate-squad/legacy-squad/HEADLINE.md +3 -0
  40. package/scripts/__fixtures__/migrate-squad/legacy-squad/README.md +4 -0
  41. package/scripts/__fixtures__/migrate-squad/legacy-squad/agents/hormozi-offer.md +14 -0
  42. package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/dead-redundant.md +4 -0
  43. package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/method-guide.md +6 -0
  44. package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/veto-screen.md +4 -0
  45. package/scripts/__fixtures__/migrate-squad/legacy-squad/config/config.yaml +2 -0
  46. package/scripts/__fixtures__/migrate-squad/legacy-squad/data/case-library.md +3 -0
  47. package/scripts/__fixtures__/migrate-squad/legacy-squad/scripts/validate-mvn.py +16 -0
  48. package/scripts/__fixtures__/migrate-squad/legacy-squad/sops/sop-sample.md +3 -0
  49. package/scripts/__fixtures__/migrate-squad/legacy-squad/squad-io.yaml +14 -0
  50. package/scripts/__fixtures__/migrate-squad/legacy-squad/tasks/gather-context.md +7 -0
  51. package/scripts/__fixtures__/migrate-squad/legacy-squad/templates/output-tmpl.md +5 -0
  52. package/scripts/__fixtures__/migrate-squad/legacy-squad/workflows/wf-sample.yaml +24 -0
  53. package/scripts/__fixtures__/pipeline/pipelines/pipeline-checkpoint.yaml +21 -0
  54. package/scripts/__fixtures__/pipeline/pipelines/pipeline-demo.yaml +22 -0
  55. package/scripts/__fixtures__/pipeline/pods/pipe-a/agents/maker.md +13 -0
  56. package/scripts/__fixtures__/pipeline/pods/pipe-a/memory/learnings.consolidated.md +8 -0
  57. package/scripts/__fixtures__/pipeline/pods/pipe-a/memory/learnings.jsonl +83 -0
  58. package/scripts/__fixtures__/pipeline/pods/pipe-a/templates/make-tmpl.md +8 -0
  59. package/scripts/__fixtures__/pipeline/pods/pipe-a/workflows/wf-a.yaml +16 -0
  60. package/scripts/__fixtures__/pipeline/pods/pipe-b/agents/user.md +13 -0
  61. package/scripts/__fixtures__/pipeline/pods/pipe-b/memory/learnings.consolidated.md +8 -0
  62. package/scripts/__fixtures__/pipeline/pods/pipe-b/memory/learnings.jsonl +14 -0
  63. package/scripts/__fixtures__/pipeline/pods/pipe-b/templates/use-tmpl.md +6 -0
  64. package/scripts/__fixtures__/pipeline/pods/pipe-b/workflows/wf-b.yaml +16 -0
  65. package/scripts/__fixtures__/pod-run/agents/forge-chief.md +13 -0
  66. package/scripts/__fixtures__/pod-run/agents/pod-critic.md +13 -0
  67. package/scripts/__fixtures__/pod-run/templates/build-tmpl.md +8 -0
  68. package/scripts/__fixtures__/pod-run/templates/gate-tmpl.md +6 -0
  69. package/scripts/__fixtures__/pod-run/workflows/wf-min.yaml +43 -0
  70. package/scripts/__fixtures__/pod-run/workflows/wf-skip-modes.yaml +50 -0
  71. package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-all-skippable.yaml +30 -0
  72. package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-criteria-escalar-de-bloco.yaml +40 -0
  73. package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-skip-mode-desconhecido.yaml +30 -0
  74. package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-unknown-key.yaml +29 -0
  75. package/scripts/__fixtures__/pod-workflow/invalid-cycle.yaml +26 -0
  76. package/scripts/__fixtures__/pod-workflow/invalid-fix-loop-backedge.yaml +29 -0
  77. package/scripts/__fixtures__/pod-workflow/invalid-fix-loop-forward.yaml +29 -0
  78. package/scripts/__fixtures__/pod-workflow/invalid-handoff-open.yaml +27 -0
  79. package/scripts/__fixtures__/pod-workflow/invalid-knowledge-shape.yaml +18 -0
  80. package/scripts/__fixtures__/pod-workflow/invalid-missing-agent.yaml +15 -0
  81. package/scripts/__fixtures__/pod-workflow/invalid-missing-outputs.yaml +15 -0
  82. package/scripts/__fixtures__/pod-workflow/invalid-missing-template.yaml +15 -0
  83. package/scripts/__fixtures__/pod-workflow/invalid-missing-veto.yaml +13 -0
  84. package/scripts/__fixtures__/pod-workflow/invalid-template-not-on-disk.yaml +16 -0
  85. package/scripts/__fixtures__/pod-workflow/invalid-veto-prose.yaml +17 -0
  86. package/scripts/__fixtures__/pod-workflow/knowledge/a.md +4 -0
  87. package/scripts/__fixtures__/pod-workflow/knowledge/b.md +4 -0
  88. package/scripts/__fixtures__/pod-workflow/knowledge/c.md +4 -0
  89. package/scripts/__fixtures__/pod-workflow/templates/step-tmpl.md +7 -0
  90. package/scripts/__fixtures__/pod-workflow/valid-checkpoint-skip-modes.yaml +29 -0
  91. package/scripts/__fixtures__/pod-workflow/valid-fix-loop.yaml +30 -0
  92. package/scripts/__fixtures__/pod-workflow/valid-knowledge.yaml +30 -0
  93. package/scripts/__fixtures__/pod-workflow/valid-veto-always-true.yaml +20 -0
  94. package/scripts/__fixtures__/pod-workflow/valid.yaml +27 -0
  95. package/scripts/__fixtures__/smoke-canary/agents/canary-reporter.md +13 -0
  96. package/scripts/__fixtures__/smoke-canary/agents/canary-researcher.md +13 -0
  97. package/scripts/__fixtures__/smoke-canary/agents/canary-synth.md +13 -0
  98. package/scripts/__fixtures__/smoke-canary/memory/learnings.consolidated.md +10 -0
  99. package/scripts/__fixtures__/smoke-canary/memory/learnings.jsonl +448 -0
  100. package/scripts/__fixtures__/smoke-canary/templates/report-tmpl.md +9 -0
  101. package/scripts/__fixtures__/smoke-canary/templates/research-tmpl.md +7 -0
  102. package/scripts/__fixtures__/smoke-canary/templates/synth-tmpl.md +9 -0
  103. package/scripts/__fixtures__/smoke-canary/workflows/wf-canary.smoke.json +11 -0
  104. package/scripts/__fixtures__/smoke-canary/workflows/wf-canary.yaml +53 -0
  105. package/scripts/__fixtures__/source-audit/fake-green-bronze-unsignaled.yaml +10 -0
  106. package/scripts/__fixtures__/source-audit/fake-green-counts.yaml +9 -0
  107. package/scripts/__fixtures__/source-audit/fake-green-missing-evidence.yaml +9 -0
  108. package/scripts/__fixtures__/source-audit/fake-green-unclassified.yaml +10 -0
  109. package/scripts/__fixtures__/source-audit/fake-green-verdict.yaml +10 -0
  110. package/scripts/__fixtures__/source-audit/golden-blocked.yaml +10 -0
  111. package/scripts/__fixtures__/source-audit/golden.yaml +11 -0
  112. package/scripts/__fixtures__/sweep-forms/agents/forms-count.md +13 -0
  113. package/scripts/__fixtures__/sweep-forms/agents/forms-field.md +13 -0
  114. package/scripts/__fixtures__/sweep-forms/agents/forms-fileref.md +13 -0
  115. package/scripts/__fixtures__/sweep-forms/agents/forms-json.md +13 -0
  116. package/scripts/__fixtures__/sweep-forms/agents/forms-section.md +13 -0
  117. package/scripts/__fixtures__/sweep-forms/specs/wf-forms.spec.json +5 -0
  118. package/scripts/__fixtures__/sweep-forms/templates/t_count.md +5 -0
  119. package/scripts/__fixtures__/sweep-forms/templates/t_field.md +3 -0
  120. package/scripts/__fixtures__/sweep-forms/templates/t_fileref.md +3 -0
  121. package/scripts/__fixtures__/sweep-forms/templates/t_json.md +0 -0
  122. package/scripts/__fixtures__/sweep-forms/templates/t_section.md +3 -0
  123. package/scripts/__fixtures__/sweep-forms/workflows/wf-forms.smoke.json +13 -0
  124. package/scripts/__fixtures__/sweep-forms/workflows/wf-forms.yaml +67 -0
  125. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-1-noop-state-json.fixture.md +18 -0
  126. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-2-crash-buildworkflowyaml.fixture.md +26 -0
  127. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-3-nasce-verde-skip-modes.fixture.md +29 -0
  128. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-4-guarda-sem-irmao.fixture.md +17 -0
  129. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-5a-diff-stat-sem-guarda.fixture.md +17 -0
  130. package/scripts/__fixtures__/validate-story-acs-corpus/corpus-5b-test-f-sobre-diretorio.fixture.md +20 -0
  131. package/scripts/__fixtures__/veto-checks/copy-clean.md +4 -0
  132. package/scripts/__fixtures__/veto-checks/copy-dashes.md +4 -0
  133. package/scripts/__fixtures__/veto-checks/n8n-bad.md +18 -0
  134. package/scripts/__fixtures__/veto-checks/n8n-ok.md +22 -0
  135. package/scripts/__fixtures__/veto-checks/page-bad.html +7 -0
  136. package/scripts/__fixtures__/veto-checks/phash/copy.png +0 -0
  137. package/scripts/__fixtures__/veto-checks/phash/distinct.png +0 -0
  138. package/scripts/__fixtures__/veto-checks/phash/distinct2.png +0 -0
  139. package/scripts/__fixtures__/veto-checks/phash/make-fixtures.cjs +203 -0
  140. package/scripts/__fixtures__/veto-checks/phash/ref.png +0 -0
  141. package/scripts/__fixtures__/veto-checks/slide-ok.html +15 -0
  142. package/scripts/__fixtures__/veto-checks/slide-overflow.html +14 -0
  143. package/scripts/__fixtures__/veto-checks/sweep-pod/agents/vc-checker.md +13 -0
  144. package/scripts/__fixtures__/veto-checks/sweep-pod/templates/check-tmpl.md +6 -0
  145. package/scripts/__fixtures__/veto-checks/sweep-pod/workflows/wf-vc.smoke.json +10 -0
  146. package/scripts/__fixtures__/veto-checks/sweep-pod/workflows/wf-vc.yaml +19 -0
  147. package/scripts/__fixtures__/voz-do-dono/README.md +23 -0
  148. package/scripts/__fixtures__/voz-do-dono/dono-escalar.yaml +9 -0
  149. package/scripts/__fixtures__/voz-do-dono/dono-guia.yaml +10 -0
  150. package/scripts/__fixtures__/voz-do-dono/peca-3a-pessoa.md +6 -0
  151. package/scripts/__fixtures__/voz-do-dono/peca-com-lexico-proibido.md +6 -0
  152. package/scripts/__fixtures__/voz-do-dono/peca-limpa-1a-pessoa.md +6 -0
  153. package/scripts/__tests__/derive-ready-transitions.test.cjs +269 -0
  154. package/scripts/__tests__/enforce-cycle-authority.test.cjs +869 -0
  155. package/scripts/__tests__/enforce-git-push-authority.test.cjs +701 -0
  156. package/scripts/__tests__/enforce-ready-oracles.test.cjs +745 -0
  157. package/scripts/__tests__/motor-scripts.test.cjs +339 -0
  158. package/scripts/__tests__/pc-run-pod-counter.test.cjs +58 -0
  159. package/scripts/__tests__/pc-run-pod.test.cjs +578 -0
  160. package/scripts/__tests__/validate-pod-workflow.test.cjs +90 -0
  161. package/scripts/__tests__/validate-story-acs.test.cjs +607 -0
  162. package/scripts/anti-path.test.cjs +163 -0
  163. package/scripts/arena.cjs +514 -0
  164. package/scripts/arena.test.cjs +213 -0
  165. package/scripts/brief-leitura-obrigatoria.test.cjs +364 -0
  166. package/scripts/consolidate-knowledge-runner.test.cjs +249 -0
  167. package/scripts/default-funcional.test.cjs +153 -0
  168. package/scripts/derive-ready-transitions.cjs +325 -0
  169. package/scripts/forge-additive.test.cjs +158 -0
  170. package/scripts/forge-assess-tier.cjs +205 -0
  171. package/scripts/forge-assess-tier.test.cjs +114 -0
  172. package/scripts/forge-canonical.test.cjs +624 -0
  173. package/scripts/forge-generate.cjs +1303 -0
  174. package/scripts/forge-harden-learning.cjs +921 -0
  175. package/scripts/forge-harden-learning.test.cjs +242 -0
  176. package/scripts/forge-ingest-memory.cjs +136 -0
  177. package/scripts/forge-upgrade-pod.cjs +368 -0
  178. package/scripts/forge.test.cjs +609 -0
  179. package/scripts/harden-knowledge.test.cjs +612 -0
  180. package/scripts/harness-g5-lite.cjs +243 -0
  181. package/scripts/harness-g5-lite.test.cjs +134 -0
  182. package/scripts/hn-carousel-contrato-entrada.test.cjs +96 -0
  183. package/scripts/migrate-squad-orchestration.test.cjs +146 -0
  184. package/scripts/migration-manifest-sf3.2.test.cjs +382 -0
  185. package/scripts/migration-manifest-sf3.3.test.cjs +170 -0
  186. package/scripts/migration-manifest-sf5.5.test.cjs +189 -0
  187. package/scripts/migration-manifest.cjs +1146 -0
  188. package/scripts/migration-manifest.test.cjs +186 -0
  189. package/scripts/npm-scope-invocation.test.cjs +194 -0
  190. package/scripts/owner-layer.cjs +442 -0
  191. package/scripts/owner-layer.test.cjs +358 -0
  192. package/scripts/pc-run-pipeline.cjs +289 -0
  193. package/scripts/pc-run-pipeline.test.cjs +256 -0
  194. package/scripts/pc-run-pod-countgte.test.cjs +66 -0
  195. package/scripts/pc-run-pod.cjs +1355 -0
  196. package/scripts/phash-gate.test.cjs +433 -0
  197. package/scripts/pod-export-compile.cjs +487 -0
  198. package/scripts/pod-export-compile.test.cjs +312 -0
  199. package/scripts/pod-export-executor.cjs +678 -0
  200. package/scripts/pod-export-executor.test.cjs +1341 -0
  201. package/scripts/pod-export-hardening.test.cjs +531 -0
  202. package/scripts/pod-export-postprocess.cjs +427 -0
  203. package/scripts/pod-export-postprocess.test.cjs +558 -0
  204. package/scripts/pod-export-queue-race.test.cjs +865 -0
  205. package/scripts/pod-export-release.cjs +473 -0
  206. package/scripts/pod-export-release.test.cjs +267 -0
  207. package/scripts/pod-export-service.cjs +1297 -0
  208. package/scripts/pod-export-service.test.cjs +489 -0
  209. package/scripts/pod-export-tools.cjs +470 -0
  210. package/scripts/pod-export-ui.cjs +805 -0
  211. package/scripts/pod-export-ui.test.cjs +301 -0
  212. package/scripts/pod-memory-budget.test.cjs +309 -0
  213. package/scripts/pod-memory-note.cjs +357 -0
  214. package/scripts/pod-memory-note.test.cjs +452 -0
  215. package/scripts/pod-memory.cjs +1252 -0
  216. package/scripts/pod-memory.test.cjs +951 -0
  217. package/scripts/render-png.test.cjs +307 -0
  218. package/scripts/smoke-isolation.test.cjs +100 -0
  219. package/scripts/smoke-pod-workflow.cjs +755 -0
  220. package/scripts/smoke-sweep.test.cjs +170 -0
  221. package/scripts/validate-adopt.js +235 -0
  222. package/scripts/validate-branding.js +84 -0
  223. package/scripts/validate-budgets.js +140 -0
  224. package/scripts/validate-fidelity-output.cjs +267 -0
  225. package/scripts/validate-fidelity-output.test.cjs +101 -0
  226. package/scripts/validate-install.js +230 -0
  227. package/scripts/validate-no-clone.cjs +220 -0
  228. package/scripts/validate-no-clone.test.cjs +77 -0
  229. package/scripts/validate-pipeline.cjs +145 -0
  230. package/scripts/validate-pod-workflow.cjs +878 -0
  231. package/scripts/validate-source-audit.cjs +170 -0
  232. package/scripts/validate-source-audit.test.cjs +90 -0
  233. package/scripts/validate-story-acs.cjs +862 -0
  234. package/scripts/validate-update-scope-motor.js +421 -0
  235. package/scripts/veto-checks/html-valid.cjs +92 -0
  236. package/scripts/veto-checks/lexical-check.cjs +62 -0
  237. package/scripts/veto-checks/phash-gate.cjs +589 -0
  238. package/scripts/veto-checks/render-gate.cjs +165 -0
  239. package/scripts/veto-checks/render-png.cjs +358 -0
  240. package/scripts/veto-checks.test.cjs +219 -0
  241. package/scripts/watcher-audit.cjs +178 -0
  242. package/template/.claude/CLAUDE.md +103 -0
  243. package/template/.claude/agents/pc-analyst.md +100 -0
  244. package/template/.claude/agents/pc-architect.md +32 -0
  245. package/template/.claude/agents/pc-dev.md +27 -0
  246. package/template/.claude/agents/pc-devops.md +45 -0
  247. package/template/.claude/agents/pc-planner.md +32 -0
  248. package/template/.claude/agents/pc-po.md +25 -0
  249. package/template/.claude/agents/pc-qa.md +25 -0
  250. package/template/.claude/commands/power/academy.md +9 -0
  251. package/template/.claude/commands/power/automation.md +9 -0
  252. package/template/.claude/commands/power/content-carousel.md +267 -0
  253. package/template/.claude/commands/power/content.md +9 -0
  254. package/template/.claude/commands/power/dev.md +9 -0
  255. package/template/.claude/commands/power/forge.md +224 -0
  256. package/template/.claude/commands/power/hormozi.md +221 -0
  257. package/template/.claude/commands/power/modo.md +57 -0
  258. package/template/.claude/hooks/README.md +114 -0
  259. package/template/.claude/hooks/context-budget.cjs +64 -0
  260. package/template/.claude/hooks/enforce-cycle-authority.cjs +457 -0
  261. package/template/.claude/hooks/enforce-git-push-authority.cjs +925 -0
  262. package/template/.claude/hooks/enforce-ready-oracles.cjs +502 -0
  263. package/template/.claude/rules/authority.md +76 -0
  264. package/template/.claude/rules/curadoria-de-conhecimento.md +30 -0
  265. package/template/.claude/rules/model-matrix.md +34 -0
  266. package/template/.claude/rules/orchestration.md +133 -0
  267. package/template/.claude/settings.json +50 -0
  268. package/template/.claude/skills/pc-apply-qa-fixes/SKILL.md +108 -0
  269. package/template/.claude/skills/pc-apply-qa-fixes/references/fix-loop.md +40 -0
  270. package/template/.claude/skills/pc-apply-qa-fixes/references/fix-request-template.md +70 -0
  271. package/template/.claude/skills/pc-arena/SKILL.md +96 -0
  272. package/template/.claude/skills/pc-close-story/SKILL.md +105 -0
  273. package/template/.claude/skills/pc-commit/SKILL.md +108 -0
  274. package/template/.claude/skills/pc-develop-story/SKILL.md +116 -0
  275. package/template/.claude/skills/pc-full-cycle/SKILL.md +150 -0
  276. package/template/.claude/skills/pc-pipeline/SKILL.md +63 -0
  277. package/template/.claude/skills/pc-pipeline/references/gate-templates.md +46 -0
  278. package/template/.claude/skills/pc-review-story/SKILL.md +129 -0
  279. package/template/.claude/skills/pc-review-story/references/false-positive-detection.md +50 -0
  280. package/template/.claude/skills/pc-review-story/references/nfr-assess.md +47 -0
  281. package/template/.claude/skills/pc-review-story/references/risk-profile.md +75 -0
  282. package/template/.claude/skills/pc-review-story/references/security-checklist.md +69 -0
  283. package/template/.claude/skills/pc-review-story/references/test-design.md +37 -0
  284. package/template/.claude/skills/pc-review-story/references/trace-requirements.md +46 -0
  285. package/template/.claude/skills/pc-run-pod/SKILL.md +123 -0
  286. package/template/.claude/skills/pc-validate-story/SKILL.md +114 -0
  287. package/template/.claude/skills/pc-wave/SKILL.md +133 -0
  288. package/template/.env.example +10 -0
  289. package/template/knowledge/analyst/brainstorming.md +40 -0
  290. package/template/knowledge/analyst/brief-skeleton.md +32 -0
  291. package/template/knowledge/analyst/competitor-skeleton.md +39 -0
  292. package/template/knowledge/analyst/elicitation-menu.md +49 -0
  293. package/template/knowledge/analyst/market-research-skeleton.md +36 -0
  294. package/template/knowledge/analyst/research-prompt-structure.md +48 -0
  295. package/template/knowledge/analyst/roi-skeleton.md +51 -0
  296. package/template/knowledge/voice-dna/README.md +99 -0
  297. package/template/knowledge/voice-dna/voice-dna.example.yaml +157 -0
  298. package/template/pods/README.md +64 -0
  299. package/template/pods/academy/README.md +37 -0
  300. package/template/pods/academy/agents/academy-chief.md +27 -0
  301. package/template/pods/academy/examples/palestra.example.md +142 -0
  302. package/template/pods/academy/pod-spec.json +44 -0
  303. package/template/pods/academy/templates/materiais-tmpl.md +17 -0
  304. package/template/pods/academy/templates/revisao-didatica-tmpl.md +20 -0
  305. package/template/pods/academy/workflows/wf-materiais-revisao.yaml +30 -0
  306. package/template/pods/authority-content/README.md +43 -0
  307. package/template/pods/authority-content/agents/content-chief.md +28 -0
  308. package/template/pods/authority-content/pod-spec.json +45 -0
  309. package/template/pods/authority-content/templates/criacao-na-voz-tmpl.md +17 -0
  310. package/template/pods/authority-content/templates/red-team-factual-tmpl.md +23 -0
  311. package/template/pods/authority-content/workflows/wf-criacao-redteam.yaml +30 -0
  312. package/template/pods/automation/README.md +37 -0
  313. package/template/pods/automation/agents/langgraph-architect.md +30 -0
  314. package/template/pods/automation/agents/n8n-architect.md +30 -0
  315. package/template/pods/automation/examples/README.md +46 -0
  316. package/template/pods/automation/examples/n8n-content-radar.example.json +380 -0
  317. package/template/pods/automation/knowledge/langgraph-patterns.md +126 -0
  318. package/template/pods/automation/knowledge/n8n-patterns.md +131 -0
  319. package/template/pods/automation/memory/README.md +16 -0
  320. package/template/pods/automation/memory/learnings.consolidated.md +8 -0
  321. package/template/pods/automation/memory/learnings.jsonl +0 -0
  322. package/template/pods/automation/pod-spec.json +109 -0
  323. package/template/pods/automation/specs/wf-langgraph-build.spec.json +107 -0
  324. package/template/pods/automation/squad-io.yaml +28 -0
  325. package/template/pods/automation/templates/lg-build-tmpl.md +17 -0
  326. package/template/pods/automation/templates/lg-design-tmpl.md +23 -0
  327. package/template/pods/automation/templates/lg-discover-tmpl.md +20 -0
  328. package/template/pods/automation/templates/lg-handoff-tmpl.md +20 -0
  329. package/template/pods/automation/templates/lg-test-tmpl.md +20 -0
  330. package/template/pods/automation/templates/n8n-build-tmpl.md +14 -0
  331. package/template/pods/automation/templates/n8n-design-tmpl.md +23 -0
  332. package/template/pods/automation/templates/n8n-discover-tmpl.md +20 -0
  333. package/template/pods/automation/templates/n8n-handoff-tmpl.md +20 -0
  334. package/template/pods/automation/templates/n8n-test-tmpl.md +20 -0
  335. package/template/pods/automation/workflows/wf-langgraph-build.smoke.json +11 -0
  336. package/template/pods/automation/workflows/wf-langgraph-build.yaml +64 -0
  337. package/template/pods/automation/workflows/wf-n8n-build.smoke.json +11 -0
  338. package/template/pods/automation/workflows/wf-n8n-build.yaml +65 -0
  339. package/template/pods/content-carousel/README.md +91 -0
  340. package/template/pods/content-carousel/agents/carousel-builder.md +28 -0
  341. package/template/pods/content-carousel/agents/carousel-visual.md +24 -0
  342. package/template/pods/content-carousel/agents/hn-curator.md +74 -0
  343. package/template/pods/content-carousel/config/heuristic-watcher-rubric.yaml +59 -0
  344. package/template/pods/content-carousel/knowledge/aquisicao-ancora.md +443 -0
  345. package/template/pods/content-carousel/knowledge/cta-brief.md +25 -0
  346. package/template/pods/content-carousel/knowledge/dono.example.yaml +45 -0
  347. package/template/pods/content-carousel/knowledge/identidade-visual-mascote.md +62 -0
  348. package/template/pods/content-carousel/knowledge/image-generation.md +62 -0
  349. package/template/pods/content-carousel/knowledge/selecao-de-ancora.md +60 -0
  350. package/template/pods/content-carousel/knowledge/slides-html.md +56 -0
  351. package/template/pods/content-carousel/memory/README.md +18 -0
  352. package/template/pods/content-carousel/memory/learnings.consolidated.md +6 -0
  353. package/template/pods/content-carousel/memory/learnings.jsonl +0 -0
  354. package/template/pods/content-carousel/pod-spec.json +100 -0
  355. package/template/pods/content-carousel/squad-io.yaml +10 -0
  356. package/template/pods/content-carousel/templates/assembly-tmpl.md +23 -0
  357. package/template/pods/content-carousel/templates/digest-tmpl.md +29 -0
  358. package/template/pods/content-carousel/templates/visuals-tmpl.md +20 -0
  359. package/template/pods/content-carousel/workflows/wf-content-carousel.smoke.json +23 -0
  360. package/template/pods/content-carousel/workflows/wf-content-carousel.yaml +80 -0
  361. package/template/pods/dev-ia/README.md +45 -0
  362. package/template/pods/dev-ia/agents/db-architect.md +33 -0
  363. package/template/pods/dev-ia/agents/ux-architect.md +29 -0
  364. package/template/pods/dev-ia/knowledge/db/migration-protocol.md +95 -0
  365. package/template/pods/dev-ia/knowledge/db/rls-patterns.md +101 -0
  366. package/template/pods/dev-ia/knowledge/db/schema-review-checklist.md +76 -0
  367. package/template/pods/dev-ia/memory/README.md +16 -0
  368. package/template/pods/dev-ia/memory/learnings.consolidated.md +8 -0
  369. package/template/pods/dev-ia/memory/learnings.jsonl +0 -0
  370. package/template/pods/dev-ia/pod-spec.json +34 -0
  371. package/template/pods/dev-ia/templates/schema-review-tmpl.md +23 -0
  372. package/template/pods/dev-ia/templates/ux-flow-review-tmpl.md +23 -0
  373. package/template/pods/dev-ia/tools/db-ops/backup-manager.sh +321 -0
  374. package/template/pods/dev-ia/tools/db-ops/best-practices-auditor.sh +534 -0
  375. package/template/pods/dev-ia/tools/db-ops/bootstrap-runner.sh +255 -0
  376. package/template/pods/dev-ia/tools/db-ops/data-loader.sh +616 -0
  377. package/template/pods/dev-ia/tools/db-ops/detect-database.sh +113 -0
  378. package/template/pods/dev-ia/tools/db-ops/explain-analyzer.sh +285 -0
  379. package/template/pods/dev-ia/tools/db-ops/health-checker.sh +323 -0
  380. package/template/pods/dev-ia/tools/db-ops/migration-runner.sh +308 -0
  381. package/template/pods/dev-ia/tools/db-ops/postgresql-schema-loader.sh +334 -0
  382. package/template/pods/dev-ia/tools/db-ops/query-runner.sh +171 -0
  383. package/template/pods/dev-ia/tools/db-ops/rls-policy-installer.sh +480 -0
  384. package/template/pods/dev-ia/tools/db-ops/rls-test-suite.sh +172 -0
  385. package/template/pods/dev-ia/tools/db-ops/schema-context-loader.sh +176 -0
  386. package/template/pods/hormozi-method/README.md +52 -0
  387. package/template/pods/hormozi-method/agents/acquisition-strategist.md +33 -0
  388. package/template/pods/hormozi-method/agents/conversion-copywriter.md +34 -0
  389. package/template/pods/hormozi-method/agents/monetization-architect.md +35 -0
  390. package/template/pods/hormozi-method/agents/offer-engineer.md +37 -0
  391. package/template/pods/hormozi-method/knowledge/core-four-leads.md +51 -0
  392. package/template/pods/hormozi-method/knowledge/grand-slam-offer.md +66 -0
  393. package/template/pods/hormozi-method/knowledge/growth-decision.md +38 -0
  394. package/template/pods/hormozi-method/knowledge/hooks-and-ads.md +56 -0
  395. package/template/pods/hormozi-method/knowledge/launch-email.md +31 -0
  396. package/template/pods/hormozi-method/knowledge/money-model.md +46 -0
  397. package/template/pods/hormozi-method/knowledge/opportunity-screening.md +44 -0
  398. package/template/pods/hormozi-method/knowledge/pages.md +25 -0
  399. package/template/pods/hormozi-method/knowledge/pos-lancamento-leads.md +56 -0
  400. package/template/pods/hormozi-method/knowledge/pricing.md +36 -0
  401. package/template/pods/hormozi-method/knowledge/retention-ltv.md +37 -0
  402. package/template/pods/hormozi-method/knowledge/scale-roadmap.md +35 -0
  403. package/template/pods/hormozi-method/knowledge/swipefiles-curados.md +44 -0
  404. package/template/pods/hormozi-method/knowledge/value-equation-diagnostic.md +77 -0
  405. package/template/pods/hormozi-method/memory/README.md +16 -0
  406. package/template/pods/hormozi-method/memory/learnings.consolidated.md +6 -0
  407. package/template/pods/hormozi-method/memory/learnings.jsonl +0 -0
  408. package/template/pods/hormozi-method/pod-spec.json +50 -0
  409. package/template/pods/hormozi-method/specs/wf-full-launch-sequence.spec.json +149 -0
  410. package/template/pods/hormozi-method/specs/wf-lead-magnet-pipeline.spec.json +125 -0
  411. package/template/pods/hormozi-method/specs/wf-money-model-design.spec.json +117 -0
  412. package/template/pods/hormozi-method/specs/wf-paid-ads-campaign.spec.json +132 -0
  413. package/template/pods/hormozi-method/specs/wf-scaling-diagnostic.spec.json +121 -0
  414. package/template/pods/hormozi-method/squad-io.yaml +43 -0
  415. package/template/pods/hormozi-method/templates/conversion-copywriter-tmpl.md +20 -0
  416. package/template/pods/hormozi-method/templates/launch-execucao-tmpl.md +17 -0
  417. package/template/pods/hormozi-method/templates/launch-fechamento-tmpl.md +17 -0
  418. package/template/pods/hormozi-method/templates/launch-pos-tmpl.md +17 -0
  419. package/template/pods/hormozi-method/templates/launch-preparacao-tmpl.md +17 -0
  420. package/template/pods/hormozi-method/templates/lm-copy-tmpl.md +17 -0
  421. package/template/pods/hormozi-method/templates/lm-distribuicao-tmpl.md +18 -0
  422. package/template/pods/hormozi-method/templates/lm-estrategia-tmpl.md +17 -0
  423. package/template/pods/hormozi-method/templates/mm-arquitetura-tmpl.md +18 -0
  424. package/template/pods/hormozi-method/templates/mm-copy-tmpl.md +17 -0
  425. package/template/pods/hormozi-method/templates/mm-diagnostico-tmpl.md +14 -0
  426. package/template/pods/hormozi-method/templates/monetization-architect-tmpl.md +17 -0
  427. package/template/pods/hormozi-method/templates/offer-engineer-tmpl.md +20 -0
  428. package/template/pods/hormozi-method/templates/paid-criativos-tmpl.md +19 -0
  429. package/template/pods/hormozi-method/templates/paid-fundacao-tmpl.md +17 -0
  430. package/template/pods/hormozi-method/templates/paid-teste-escala-tmpl.md +17 -0
  431. package/template/pods/hormozi-method/templates/scaling-diagnostico-tmpl.md +17 -0
  432. package/template/pods/hormozi-method/templates/scaling-priorizacao-tmpl.md +17 -0
  433. package/template/pods/hormozi-method/templates/scaling-roadmap-tmpl.md +17 -0
  434. package/template/pods/hormozi-method/workflows/wf-full-launch-sequence.smoke.json +12 -0
  435. package/template/pods/hormozi-method/workflows/wf-full-launch-sequence.yaml +56 -0
  436. package/template/pods/hormozi-method/workflows/wf-grand-slam-offer.smoke.json +11 -0
  437. package/template/pods/hormozi-method/workflows/wf-grand-slam-offer.yaml +45 -0
  438. package/template/pods/hormozi-method/workflows/wf-lead-magnet-pipeline.smoke.json +9 -0
  439. package/template/pods/hormozi-method/workflows/wf-lead-magnet-pipeline.yaml +45 -0
  440. package/template/pods/hormozi-method/workflows/wf-money-model-design.smoke.json +11 -0
  441. package/template/pods/hormozi-method/workflows/wf-money-model-design.yaml +45 -0
  442. package/template/pods/hormozi-method/workflows/wf-paid-ads-campaign.smoke.json +9 -0
  443. package/template/pods/hormozi-method/workflows/wf-paid-ads-campaign.yaml +46 -0
  444. package/template/pods/hormozi-method/workflows/wf-scaling-diagnostic.smoke.json +11 -0
  445. package/template/pods/hormozi-method/workflows/wf-scaling-diagnostic.yaml +44 -0
  446. package/template/pods/squad-forge/README.md +53 -0
  447. package/template/pods/squad-forge/agents/forge-chief.md +31 -0
  448. package/template/pods/squad-forge/agents/mind-extractor.md +29 -0
  449. package/template/pods/squad-forge/agents/pod-critic.md +26 -0
  450. package/template/pods/squad-forge/config/heuristic-watcher-rubric.yaml +74 -0
  451. package/template/pods/squad-forge/knowledge/fidelity-rubric.yaml +176 -0
  452. package/template/pods/squad-forge/knowledge/g6-memory-check.md +17 -0
  453. package/template/pods/squad-forge/knowledge/memory-ingest.md +16 -0
  454. package/template/pods/squad-forge/knowledge/source-audit-rubric.yaml +60 -0
  455. package/template/pods/squad-forge/memory/README.md +16 -0
  456. package/template/pods/squad-forge/memory/learnings.consolidated.md +8 -0
  457. package/template/pods/squad-forge/memory/learnings.jsonl +0 -0
  458. package/template/pods/squad-forge/pod-spec.json +166 -0
  459. package/template/pods/squad-forge/squad-io.yaml +13 -0
  460. package/template/pods/squad-forge/tasks/pipeline.md +158 -0
  461. package/template/pods/squad-forge/templates/discovery-tmpl.md +40 -0
  462. package/template/pods/squad-forge/templates/generation-tmpl.md +18 -0
  463. package/template/pods/squad-forge/templates/red-team-tmpl.md +17 -0
  464. package/template/pods/squad-forge/templates/register-tmpl.md +17 -0
  465. package/template/pods/squad-forge/templates/workflow-tmpl.yaml +101 -0
  466. package/template/pods/squad-forge/workflows/wf-forge.smoke.json +12 -0
  467. package/template/pods/squad-forge/workflows/wf-forge.yaml +60 -0
@@ -0,0 +1,607 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * validate-story-acs.test.cjs — suíte real do validador de ACs (Story
6
+ * SF13.1, `ADR-031`). Roda os 47 ACs da story, incluindo os 6 fixtures do
7
+ * Bloco E (comportamentais, não mockados) e o controle negativo do AC-32b.
8
+ *
9
+ * DESVIO DOCUMENTADO (Dev Agent Record da story tem os detalhes completos):
10
+ * os fixtures literais de `AC-14` e `AC-25` usam `test -f package.json`
11
+ * SEM `[Guarda]` como prova/placeholder — mas essa é EXATAMENTE a forma que
12
+ * `AC-32b` rotula, na própria story, como *"óbvio nasce-verde"* (linha 446),
13
+ * e que `AC-5`/Contexto(b) exigem que o validador REPROVE quando referenciada
14
+ * como `[Guarda] (prova: AC-M)` sem pareamento válido. Um validador que
15
+ * deixasse "test -f package.json" sem guarda passar como `ok` (a leitura
16
+ * literal de AC-14/AC-25) reabriria a MESMA classe de defeito que a story
17
+ * inteira existe para fechar — e contradiria AC-5, AC-13, AC-19, AC-22 e o
18
+ * próprio AC-32b. Implementei a regra normativa (Contexto (b), `ADR-031`
19
+ * Decisão 1) e, nestes 2 casos, testo o comportamento CORRETO em vez do
20
+ * literal — reportado como achado, não corrigido silenciosamente na story
21
+ * (fora da minha autoridade de edição nesta rodada).
22
+ */
23
+
24
+ const fs = require('node:fs');
25
+ const os = require('node:os');
26
+ const path = require('node:path');
27
+
28
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
29
+ const MODULE_PATH = path.join(REPO_ROOT, 'scripts', 'validate-story-acs.cjs');
30
+ const FIXTURES_DIR = path.join(REPO_ROOT, 'scripts', '__fixtures__', 'validate-story-acs-corpus');
31
+
32
+ let failures = 0;
33
+ function assert(ok, msg, extra) {
34
+ if (ok) {
35
+ console.log(`[OK ] ${msg}`);
36
+ } else {
37
+ console.error(`[FALHA] ${msg}${extra !== undefined ? ' :: ' + JSON.stringify(extra) : ''}`);
38
+ failures++;
39
+ }
40
+ }
41
+
42
+ function freshModule() {
43
+ delete require.cache[require.resolve(MODULE_PATH)];
44
+ return require(MODULE_PATH);
45
+ }
46
+
47
+ const f = (lines) => lines.join('\n');
48
+
49
+ function run() {
50
+ process.chdir(REPO_ROOT);
51
+ const m = freshModule();
52
+
53
+ // ---------------------------------------------------------------------
54
+ // Bloco A — Convenção e produtor
55
+ // ---------------------------------------------------------------------
56
+ {
57
+ const r = m.wouldBeRefused === undefined ? null : true;
58
+ assert(fs.existsSync(path.join(REPO_ROOT, 'docs', 'mecanismos', 'validador-de-acs-do-ciclo.md')), 'AC-1: doc de mecanismo existe');
59
+ }
60
+ {
61
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'template', '.claude', 'agents', 'pc-planner.md'), 'utf8');
62
+ assert(/oraculo|oráculo/i.test(c), 'AC-2: pc-planner.md instrui emissão da fence oraculo');
63
+ }
64
+
65
+ // ---------------------------------------------------------------------
66
+ // Bloco B — Parsing
67
+ // ---------------------------------------------------------------------
68
+ {
69
+ const c = f(['exemplo fora da secao:', '```oraculo', 'test -f nada', '```', '', '## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'test -f package.json', '```']);
70
+ const r = m.parseAcs(c);
71
+ assert(r.length === 1 && r[0].id === 'AC-X', 'AC-3: parseAcs restrito à seção, sem fence aninhado', r);
72
+ }
73
+ {
74
+ // Achado do QA (gate `sf13.1-validador-de-acs`, finding 1a): o marcador
75
+ // com anotação entre colchetes (`**AC-N [novo, ...].**`) é o estilo
76
+ // PREDOMINANTE já convencionado no projeto — 32 dos 43 cabeçalhos reais
77
+ // desta própria story usam essa forma ou prosa adicional dentro do
78
+ // negrito. `parseAcs` tem de casar as 3 formas.
79
+ const c = f(['## Acceptance Criteria', '', '**AC-1 [novo, B4].** descricao simples', '```oraculo', 'test -f package.json', '```', '', '**AC-2. Corpus 1 — titulo com prosa dentro do negrito.** descricao', '```oraculo', 'test -f package.json', '```']);
80
+ const r = m.parseAcs(c);
81
+ assert(r.length === 2 && r[0].id === 'AC-1' && r[1].id === 'AC-2', 'AC-3b [novo, achado do QA]: parseAcs casa anotação entre colchetes E prosa dentro do negrito', r);
82
+ }
83
+ {
84
+ // Achado do QA (finding 1b): fence-aware — string de fixture embutida
85
+ // (contendo `**AC-A.**`/```oraculo``` como DADO literal, não marcador
86
+ // real) dentro do PRÓPRIO oráculo de um AC não pode virar um AC novo
87
+ // nem truncar o comando real. Reproduz a forma exata do AC-14/AC-5 desta
88
+ // story (fixture com aspas simples aninhadas via `'\''`).
89
+ const c = f(['## Acceptance Criteria', '', "**AC-Y.** constroi fixture em memoria", '```oraculo', `node -e 'const f=(l)=>l.join("\\\\n");const c=f(["## Acceptance Criteria","","**AC-A.** irmao","` + '```' + `oraculo","test -f package.json","` + '```' + `"]);console.log(1)'`, '```']);
90
+ const r = m.parseAcs(c);
91
+ const hasFakeAc = r.find((x) => x.id === 'AC-A');
92
+ assert(r.length === 1 && r[0].id === 'AC-Y' && !hasFakeAc && /console\.log\(1\)/.test(r[0].oracleCmd || ''), 'AC-3c [novo, achado do QA]: fence-aware — marcador embutido em oráculo não vira AC novo, comando não trunca', r);
93
+ }
94
+ {
95
+ // Achado do QA: `'\''` (idioma bash — fecha aspa, aspa literal
96
+ // escapada, reabre aspa) precisa tokenizar como UM caractere de aspa
97
+ // literal inserido no meio da string, não como um backslash espúrio —
98
+ // reproduz o defeito real medido em AC-10c contra a story.
99
+ // Monta literalmente: node -e 'console.log('\''hi'\'')'
100
+ const Q = "'";
101
+ const IDIOM = Q + '\\' + Q + Q; // os 4 chars '\''
102
+ const idiomCmd = 'node -e ' + Q + "console.log(" + IDIOM + 'hi' + IDIOM + ')' + Q;
103
+ const rIdiom = m.runOracle(idiomCmd, { cwd: process.cwd(), timeoutMs: 5000 });
104
+ assert(rIdiom.refused !== true && rIdiom.exitCode === 0 && rIdiom.stdout.trim() === 'hi', "AC-10g [novo, achado do QA]: idioma bash '\\'' tokeniza como aspa literal, não como backslash espúrio", rIdiom);
105
+
106
+ const rSanity = m.runOracle("node -e 'const x=1;console.log(x)'", { cwd: process.cwd(), timeoutMs: 5000 });
107
+ assert(rSanity.refused !== true && rSanity.exitCode === 0 && rSanity.stdout.trim() === '1', 'AC-10h [novo, achado do QA]: sanidade de aspa simples simples continua íntegra após o fix de backslash', rSanity);
108
+ }
109
+ {
110
+ // PROVA NA ROTA REAL (gate `sf13.1-validador-de-acs`, ação sugerida do
111
+ // finding 1): o CLI contra a PRÓPRIA story tem de reconhecer os 47 ACs
112
+ // reais, com ids reais — não 22 fantasmas. Este é o teste que teria
113
+ // pego o FAIL antes do QA.
114
+ const story = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'stories', 'sf13.1.story.md'), 'utf8');
115
+ const acsReal = m.parseAcs(story);
116
+ const idsCorrompidos = acsReal.filter((a) => a.id === 'AC-X' || a.id === 'AC-A' || a.id === 'AC-B' || a.id === 'AC-Z');
117
+ assert(acsReal.length === 47 && idsCorrompidos.length === 0, `ROTA REAL [novo, achado do QA]: parseAcs(sf13.1.story.md).length === 47 (obtido: ${acsReal.length}), zero ids fantasma`, acsReal.map((a) => a.id));
118
+ const r = m.validateStory(story, { cwd: process.cwd() });
119
+ assert(r.total === 47, `ROTA REAL: validateStory(sf13.1.story.md).total === 47 (obtido: ${r.total})`, r);
120
+ }
121
+ {
122
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '[Guarda] (prova: AC-Z)', '```oraculo', 'test -f package.json', '```']);
123
+ const r = m.validateStory(c, { cwd: process.cwd() });
124
+ const hit = r.reprovados.find((x) => x.id === 'AC-X' && /prova nomeada n(a|ã)o existe/i.test(x.motivo));
125
+ assert(!!hit, 'AC-4: prova nomeada inexistente reprova', r);
126
+ }
127
+ {
128
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '[Guarda] (prova: AC-A) texto livre depois nao quebra o parser', '```oraculo', 'test -f package.json', '```', '', '**AC-A.** irmao', '```oraculo', 'test -f package.json', '```']);
129
+ const r = m.parseAcs(c);
130
+ const ac = r.find((x) => x.id === 'AC-X');
131
+ assert(!!(ac && ac.guarda && ac.guarda.forma === 'prova' && ac.guarda.provaId === 'AC-A'), 'AC-4b: parser aceita prosa após o grupo reconhecido', ac);
132
+ }
133
+ {
134
+ const c = f(['## Acceptance Criteria', '', '**AC-A.** guarda', '```oraculo', 'test -f package.json', '```', '', '**AC-B.** alvo', '[Guarda] (prova: AC-A)', '```oraculo', 'test -f package.json', '```']);
135
+ const r = m.validateStory(c, { cwd: process.cwd() });
136
+ const hit = r.reprovados.find((x) => x.id === 'AC-B' && /cadeia guarda/i.test(x.motivo));
137
+ assert(!!hit, 'AC-5: cadeia guarda→guarda proibida', r);
138
+ }
139
+ {
140
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '[Guarda] (banana)', '```oraculo', 'test -f package.json', '```']);
141
+ const r = m.validateStory(c, { cwd: process.cwd() });
142
+ const hit = r.reprovados.find((x) => x.id === 'AC-X' && /forma.*n(a|ã)o reconhecida/i.test(x.motivo));
143
+ assert(!!hit, 'AC-5b: forma de guarda não reconhecida ⇒ REPROVA (destino pinado)', r);
144
+ }
145
+ {
146
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '[Guarda] (sem irmao - ausencia declarada)', '```oraculo', '# espera: stdout-nao-vazio', 'test -f package.json', '```']);
147
+ const r = m.validateStory(c, { cwd: process.cwd() });
148
+ const hit = r.reprovados.find((x) => x.id === 'AC-X' && /forma 2|ausencia|ausência/i.test(x.motivo));
149
+ assert(!!hit, 'AC-6: forma "sem irmão" exige asserção de ausência', r);
150
+ }
151
+ {
152
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '[Guarda] (citacao de fato pre-existente, nao prova de trabalho)', '```oraculo', 'test -f package.json', '```']);
153
+ const r = m.validateStory(c, { cwd: process.cwd() });
154
+ const inCit = r.citacoes && r.citacoes.find((x) => x.id === 'AC-X');
155
+ const notInOk = !r.ok.find((x) => x.id === 'AC-X');
156
+ assert(!!(inCit && notInOk), 'AC-6b: citação vai para `citacoes`, nunca `ok`', r);
157
+ }
158
+ {
159
+ const c = '## Acceptance Criteria\n\nSem nenhum AC com bloco.';
160
+ const r = m.validateStory(c, { cwd: process.cwd() });
161
+ assert(r.naoDeterminados && r.naoDeterminados.length === 1, 'AC-7: arquivo sem nenhum oráculo — relatório fala', r);
162
+ }
163
+
164
+ // ---------------------------------------------------------------------
165
+ // Bloco C — Execução sem shell
166
+ // ---------------------------------------------------------------------
167
+ {
168
+ const r = m.runOracle('test -f package.json', { cwd: process.cwd(), timeoutMs: 5000 });
169
+ assert(r.exitCode === 0 && typeof r.stdout === 'string' && typeof r.durationMs === 'number', 'AC-8: runOracle via execFile-família', r);
170
+ }
171
+ {
172
+ const r = m.runOracle('awk BEGIN{print 1}', { cwd: process.cwd(), timeoutMs: 5000 });
173
+ assert(r.refused === true && /n(a|ã)o consegui determinar/i.test(r.refusalReason || ''), 'AC-9: cabeçalho fora da allow-list recusa falada', r);
174
+ }
175
+ {
176
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'awk BEGIN{print 1}', '```']);
177
+ const r = m.validateStory(c, { cwd: process.cwd() });
178
+ const hit = r.naoDeterminados.find((x) => x.id === 'AC-X');
179
+ const clean = !r.ok.find((x) => x.id === 'AC-X') && !r.reprovados.find((x) => x.id === 'AC-X') && !r.alertas.find((x) => x.id === 'AC-X');
180
+ assert(!!(hit && clean), 'AC-9b: recusa/timeout ⇒ naoDeterminados no relatório agregado', r);
181
+ }
182
+ {
183
+ const r = m.runOracle('grep -c a package.json | wc -l', { cwd: process.cwd(), timeoutMs: 5000 });
184
+ assert(r.refused === true, 'AC-10: metacaractere fora de aspas ⇒ recusa', r);
185
+ }
186
+ {
187
+ const r = m.runOracle('grep -c "a\\|b" package.json', { cwd: process.cwd(), timeoutMs: 5000 });
188
+ const ran = r.refused !== true && r.exitCode === 0 && typeof r.stdout === 'string' && r.stdout.trim().length > 0;
189
+ assert(ran, 'AC-10b: metacaractere dentro de aspas duplas roda de fato', r);
190
+ }
191
+ {
192
+ const r = m.runOracle("node -e 'console.log(1)'", { cwd: process.cwd(), timeoutMs: 5000 });
193
+ const ran = r.refused !== true && r.exitCode === 0 && r.stdout.trim() === '1';
194
+ assert(ran, 'AC-10c: aspa simples (forma dominante) roda de fato', r);
195
+ }
196
+ {
197
+ // AC-10d ENDURECIDO (gate `sf13.1-validador-de-acs`, findings 1/2): a
198
+ // asserção original (`refusals.length === 0`) é satisfazível por um
199
+ // array CORROMPIDO (parseAcs cortando cabeçalhos errado) tão facilmente
200
+ // quanto por um array correto — 0 recusas sobre 22 fantasmas também é
201
+ // 0. Isso é vacuidade na camada do PARSER, a mesma classe que a regra
202
+ // de convergência existe para impedir, só que um nível abaixo de onde
203
+ // ela mirava. Fecho: cruzar `parseAcs().length` com uma contagem
204
+ // INDEPENDENTE de cabeçalhos reais (`**AC-<id>` em início de linha,
205
+ // fora de fence — mesma definição normativa, mas sem reusar
206
+ // `parseAcs`/`AC_HEADER_RE` internamente: contada aqui por regex
207
+ // própria e comparada ao número publicado pela própria story, 47).
208
+ const story = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'stories', 'sf13.1.story.md'), 'utf8');
209
+ const acs = m.parseAcs(story);
210
+ const refusals = acs.filter((a) => a.oracleCmd && m.wouldBeRefused(a.oracleCmd).refused);
211
+ const section = m.extractAcSection(story);
212
+ const fencedRanges = [];
213
+ {
214
+ const fre = /^```[^\n]*\n[\s\S]*?^```[ \t]*$/gm;
215
+ let fm;
216
+ while ((fm = fre.exec(section))) fencedRanges.push([fm.index, fm.index + fm[0].length]);
217
+ }
218
+ const headerRe = /^\*\*(AC-[A-Za-z0-9]+)\b/gm;
219
+ let hm;
220
+ let independentCount = 0;
221
+ while ((hm = headerRe.exec(section))) {
222
+ const insideFence = fencedRanges.some(([s2, e2]) => hm.index >= s2 && hm.index < e2);
223
+ if (!insideFence) independentCount += 1;
224
+ }
225
+ const noVacuidade = acs.length === independentCount && acs.length === 47;
226
+ assert(refusals.length === 0 && noVacuidade, `AC-10d: anti-vacuidade PURA — parseAcs().length (${acs.length}) === contagem independente (${independentCount}) === 47 publicado na story, E zero recusas`, { refusals, parsedCount: acs.length, independentCount });
227
+ }
228
+ {
229
+ const a = m.wouldBeRefused('awk BEGIN{print 1}');
230
+ const b = m.wouldBeRefused('grep -c a package.json | wc -l');
231
+ assert(a.refused === true && b.refused === true, 'AC-10e: wouldBeRefused — controle negativo (as 2 causas)', [a, b]);
232
+ }
233
+ {
234
+ const cmd1 = 'awk BEGIN{print 1}';
235
+ const cmd2 = 'test -f package.json';
236
+ const wA = m.wouldBeRefused(cmd1).refused;
237
+ const wB = m.wouldBeRefused(cmd2).refused;
238
+ const rA = m.runOracle(cmd1, { cwd: process.cwd(), timeoutMs: 5000 }).refused;
239
+ const rB = m.runOracle(cmd2, { cwd: process.cwd(), timeoutMs: 5000 }).refused;
240
+ assert(wA === true && rA === true && wB !== true && rB !== true, 'AC-10f: runOracle delega a wouldBeRefused (fonte única)', [wA, rA, wB, rB]);
241
+ }
242
+ {
243
+ const r = m.runOracle('git push origin main', { cwd: process.cwd(), timeoutMs: 5000 });
244
+ assert(r.refused === true, 'AC-11: sub-allow-list de git recusa push/commit/checkout/reset', r);
245
+ }
246
+ {
247
+ const r = m.runOracle('node -e "setInterval(function(){},1000)"', { cwd: process.cwd(), timeoutMs: 200 });
248
+ assert(r.timedOut === true, 'AC-12: timeout mata o processo filho', r);
249
+ }
250
+ {
251
+ const prevDepth = process.env.VSA_DEPTH;
252
+ process.env.VSA_DEPTH = '1';
253
+ const m2 = freshModule();
254
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'test -f package.json', '```']);
255
+ const r = m2.validateStory(c, { cwd: process.cwd() });
256
+ const hit = r.naoDeterminados.find((x) => x.id === 'AC-X' && x.causa === 'reentrancia');
257
+ assert(!!hit, 'AC-12b: guarda de reentrância — metade CONSUMIDORA', r);
258
+ if (prevDepth === undefined) delete process.env.VSA_DEPTH; else process.env.VSA_DEPTH = prevDepth;
259
+ freshModule();
260
+ }
261
+ {
262
+ const r = m.runOracle('node -e "console.log(process.env.VSA_DEPTH)"', { cwd: process.cwd(), timeoutMs: 5000 });
263
+ assert(r.stdout.trim() === '1', 'AC-12c: guarda de reentrância — metade PRODUTORA (env propagado)', r);
264
+ }
265
+
266
+ // ---------------------------------------------------------------------
267
+ // Bloco D — Classificação
268
+ // ---------------------------------------------------------------------
269
+ {
270
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', '# espera: stdout == 0', 'grep -c zzz-termo-inexistente-xyz package.json', '```']);
271
+ const r = m.validateStory(c, { cwd: process.cwd() });
272
+ const hit = r.reprovados.find((x) => x.id === 'AC-X' && /nasce verde/i.test(x.motivo));
273
+ assert(!!hit, 'AC-13: nasce verde é a asserção declarada, não o exit code', r);
274
+ }
275
+ {
276
+ // DESVIO DOCUMENTADO (ver cabeçalho do arquivo): o AC-14 literal da story
277
+ // usa AC-A = `test -f package.json` SEM guarda como "prova" — que é
278
+ // exatamente o padrão que AC-5/AC-32b definem como nasce-verde óbvio.
279
+ // Testo o comportamento CORRETO (cadeia bloqueada) em vez do literal.
280
+ const c = f(['## Acceptance Criteria', '', '**AC-A.** irmao', '```oraculo', 'test -f package.json', '```', '', '**AC-X.** d', '[Guarda] (prova: AC-A)', '```oraculo', '# espera: stdout == 0', 'grep -c zzz-termo-inexistente-xyz package.json', '```']);
281
+ const r = m.validateStory(c, { cwd: process.cwd() });
282
+ const acA = r.reprovados.find((x) => x.id === 'AC-A' && /nasce verde/i.test(x.motivo));
283
+ const acX = r.reprovados.find((x) => x.id === 'AC-X' && /cadeia guarda/i.test(x.motivo));
284
+ assert(!!(acA && acX), 'AC-14 [DESVIO — ver cabeçalho]: prova apontando para alvo também nasce-verde é bloqueada, consistente com AC-5/AC-32b', r);
285
+ }
286
+ {
287
+ const s1 = 'node:internal/modules/cjs/loader:1573\n throw err;\nError: Cannot find module x\n at Module._resolveFilename (node:internal/modules/cjs/loader:1569:15)\n at a (node:internal/modules/cjs/loader:1123:27)\n at b (node:internal/modules/cjs/loader:1147:10)\n at c (node:internal/modules/cjs/loader:1174:12)\n at d (node:internal/modules/cjs/loader:1346:5)\n at e (node:internal/modules/cjs/loader:261:19)\n at f (node:internal/main/run_main_module:33:47) {\n code: "MODULE_NOT_FOUND"\n}';
288
+ const r1 = m.isCrash({ exitCode: 1, stderr: s1 });
289
+ const s2 = "TypeError: Cannot read properties of undefined (reading X)\n at Object.buildWorkflowYaml (scripts/forge-generate.cjs:398:9)";
290
+ const r2 = m.isCrash({ exitCode: 1, stderr: s2 });
291
+ assert(r1.crash === false && r2.crash === true, 'AC-15: precedência normativa de isCrash', [r1, r2]);
292
+ }
293
+ {
294
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'grep -c zzz-termo-inexistente-xyz package.json', '```']);
295
+ const r = m.validateStory(c, { cwd: process.cwd() });
296
+ const hit = r.alertas.find((x) => x.id === 'AC-X' && /no-op/i.test(x.motivo));
297
+ assert(!!hit, 'AC-16: padrão de contagem ingênua ⇒ ALERTA no-op', r);
298
+ }
299
+ {
300
+ const a = m.evaluateAssertion({ exitCode: 1, stdout: '', stderr: '' }, { type: 'exit!=0' });
301
+ const b = m.evaluateAssertion({ exitCode: 0, stdout: '', stderr: '' }, { type: 'exit!=0' });
302
+ const c = m.evaluateAssertion({ exitCode: 0, stdout: 'x', stderr: '' }, { type: 'stdout-nao-vazio' });
303
+ const d = m.evaluateAssertion({ exitCode: 0, stdout: '', stderr: '' }, { type: 'stdout-nao-vazio' });
304
+ assert(a === true && b === false && c === true && d === false, 'AC-16b: as 5 formas de # espera — controle positivo e negativo', [a, b, c, d]);
305
+ }
306
+ {
307
+ const c = f(['## Status', '', 'InReview', '', '## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'test -f package.json', '```']);
308
+ const r = m.validateStory(c, { cwd: process.cwd() });
309
+ const hit = r.naoDeterminados.find((x) => x.id === 'AC-X' && x.causa === 'nasce-verde-pos-trabalho');
310
+ assert(!!hit, 'AC-16c: nasce verde é classe datada — InReview suspende', r);
311
+ }
312
+ {
313
+ const c = f(['## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', '# espera: stdout-vazia', 'test -f package.json', '```']);
314
+ const r = m.validateStory(c, { cwd: process.cwd() });
315
+ const hit = r.naoDeterminados.find((x) => x.id === 'AC-X' && x.causa === 'assercao-desconhecida');
316
+ const notOk = !r.ok.find((x) => x.id === 'AC-X');
317
+ assert(!!(hit && notOk), 'AC-16e: typo em # espera NUNCA cai no default exit0', r);
318
+ }
319
+ {
320
+ const c = f(['## Status', '', 'InReview', '', '## Acceptance Criteria', '', '**AC-X.** d', '```oraculo', 'node -e "null.x"', '```']);
321
+ const r = m.validateStory(c, { cwd: process.cwd() });
322
+ const hit = r.reprovados.find((x) => x.id === 'AC-X' && /comando quebrado/i.test(x.motivo));
323
+ assert(!!hit, 'AC-16d: gate por CLASSE — crash continua REPROVA em InReview', r);
324
+ }
325
+
326
+ // ---------------------------------------------------------------------
327
+ // Bloco E — Meta-prova: 5 corpus reais, comportamentais
328
+ // ---------------------------------------------------------------------
329
+ {
330
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-1-noop-state-json.fixture.md'), 'utf8');
331
+ const r = m.validateStory(c, { cwd: process.cwd() });
332
+ const hit = r.alertas.find((x) => /no-op/i.test(x.motivo));
333
+ assert(!!hit, 'AC-17: Corpus 1 (sf12.4b, no-op) — rodado de verdade', r);
334
+ }
335
+ {
336
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-2-crash-buildworkflowyaml.fixture.md'), 'utf8');
337
+ const r = m.validateStory(c, { cwd: process.cwd() });
338
+ const hit = r.reprovados.find((x) => /comando quebrado/i.test(x.motivo) && /TypeError/i.test(x.motivo));
339
+ assert(!!hit, 'AC-18: Corpus 2 (sf12.5a, crash) — TypeError real citado', r);
340
+ }
341
+ {
342
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-3-nasce-verde-skip-modes.fixture.md'), 'utf8');
343
+ const r = m.validateStory(c, { cwd: process.cwd() });
344
+ const hit = r.reprovados.find((x) => x.id === 'AC-3a' && /nasce verde/i.test(x.motivo));
345
+ assert(!!hit, 'AC-19: Corpus 3a (sem guarda) — REPROVA nasce verde', r);
346
+ }
347
+ {
348
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-3-nasce-verde-skip-modes.fixture.md'), 'utf8');
349
+ const r = m.validateStory(c, { cwd: process.cwd() });
350
+ const bad = r.reprovados.find((x) => x.id === 'AC-3b');
351
+ assert(!bad, 'AC-20: Corpus 3b (com guarda) — NÃO reprova', r);
352
+ }
353
+ {
354
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-4-guarda-sem-irmao.fixture.md'), 'utf8');
355
+ const r = m.validateStory(c, { cwd: process.cwd() });
356
+ const bad = r.reprovados.find((x) => x.id === 'AC-4');
357
+ assert(!bad, 'AC-21: Corpus 4 (guarda sem irmão possível) — NÃO reprova', r);
358
+ }
359
+ {
360
+ const c = fs.readFileSync(path.join(FIXTURES_DIR, 'corpus-5a-diff-stat-sem-guarda.fixture.md'), 'utf8');
361
+ const r = m.validateStory(c, { cwd: process.cwd() });
362
+ const hit = r.reprovados.find((x) => x.id === 'AC-5a' && /nasce verde/i.test(x.motivo));
363
+ assert(!!hit, 'AC-22: Corpus 5a (git diff --stat sob exit-code puro) — REPROVA', r);
364
+ }
365
+ {
366
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'mecanismos', 'validador-de-acs-do-ciclo.md'), 'utf8');
367
+ assert(/Corpus 5b/.test(c), 'AC-23: fronteira Corpus 5b declarada no doc de mecanismo', null);
368
+ }
369
+ {
370
+ let n = 0;
371
+ try {
372
+ n = fs.readdirSync(FIXTURES_DIR).filter((x) => x.endsWith('.fixture.md')).length;
373
+ } catch (e) { n = 0; }
374
+ assert(n === 6, 'AC-24: os 6 arquivos de fixture existem', n);
375
+ }
376
+
377
+ // ---------------------------------------------------------------------
378
+ // Bloco F — Relatório, CLI, integração com o PO
379
+ // ---------------------------------------------------------------------
380
+ {
381
+ // DESVIO DOCUMENTADO (ver cabeçalho do arquivo): AC-25 usa AC-A = `test
382
+ // -f package.json` SEM guarda esperando `ok` — mesmo padrão do AC-14,
383
+ // contradiz AC-5/AC-32b. Testo a categoria ALERTA (que não depende do
384
+ // caso conflitante) e confirmo que a AC nasce-verde é corretamente
385
+ // reprovada (não silenciada) — total conta as 2 entradas roteadas.
386
+ const c = f(['## Acceptance Criteria', '', '**AC-A.** ok', '```oraculo', 'test -f package.json', '```', '', '**AC-B.** alerta', '```oraculo', 'grep -c zzz-termo-inexistente-xyz package.json', '```']);
387
+ const r = m.validateStory(c, { cwd: process.cwd() });
388
+ const alOk = r.alertas.find((x) => x.id === 'AC-B');
389
+ const acAReprovado = r.reprovados.find((x) => x.id === 'AC-A' && /nasce verde/i.test(x.motivo));
390
+ assert(!!(alOk && acAReprovado && r.total === 2), 'AC-25 [DESVIO — ver cabeçalho]: relatório agregado com total/ok/reprovados/alertas corretos', r);
391
+ }
392
+ {
393
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'vsa-'));
394
+ // `test -f package.json` sem guarda seria nasce-verde (mesma classe do
395
+ // desvio AC-14/AC-25 — ver cabeçalho do arquivo); aqui a asserção
396
+ // precisa ser genuinamente FALSA hoje para cair em `ok` sem ambiguidade.
397
+ const bodyOk = f(['## Acceptance Criteria', '', '**AC-A.** ok', '```oraculo', 'test -f arquivo-que-nao-existe-vsa-fixture.txt', '```']);
398
+ const bodyAlerta = f(['## Acceptance Criteria', '', '**AC-B.** alerta', '```oraculo', 'grep -c zzz-termo-inexistente-xyz package.json', '```']);
399
+ fs.writeFileSync(path.join(dir, 'a.story.md'), bodyOk);
400
+ fs.writeFileSync(path.join(dir, 'b.story.md'), bodyAlerta);
401
+ const r = m.validateStoryBatch(dir, { cwd: process.cwd() });
402
+ // Positivo: 2 arquivos DIFERENTES agregados de fato (não só a contagem
403
+ // de arquivos) — 1 ok de a.story.md + 1 alerta de b.story.md somados.
404
+ const agregouOk = r.ok.find((x) => x.id === 'AC-A');
405
+ const agregouAlerta = r.alertas.find((x) => x.id === 'AC-B');
406
+ assert(r.files === 2 && r.total === 2 && !!agregouOk && !!agregouAlerta, 'AC-26: validateStoryBatch agrega ok+alertas de 2 arquivos DIFERENTES (não só files===2)', r);
407
+ }
408
+ {
409
+ // AC-26 CONTROLE NEGATIVO (finding 4 do gate — regra de convergência:
410
+ // validateStoryBatch só tinha caso positivo). Diretório real, sem
411
+ // NENHUM `*.story.md` — glob vazio não pode virar exceção nem contar
412
+ // como se tivesse processado algo.
413
+ const emptyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vsa-empty-'));
414
+ fs.writeFileSync(path.join(emptyDir, 'nota.txt'), 'não é story');
415
+ const r = m.validateStoryBatch(emptyDir, { cwd: process.cwd() });
416
+ assert(r.files === 0 && r.total === 0 && r.ok.length === 0 && r.reprovados.length === 0, 'AC-26 [controle negativo]: diretório sem *.story.md — files=0, sem exceção', r);
417
+ }
418
+ {
419
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'template', '.claude', 'skills', 'pc-validate-story', 'SKILL.md'), 'utf8');
420
+ const i = c.indexOf('ACs testaveis e rastreaveis');
421
+ const i2 = c.indexOf('ACs testáveis e rastreáveis');
422
+ const idx = i >= 0 ? i : i2;
423
+ const near = idx >= 0 ? c.slice(idx, idx + 600) : '';
424
+ assert(idx >= 0 && near.indexOf('validate-story-acs') >= 0, 'AC-27: SKILL.md ancora a instrução no item 3', null);
425
+ }
426
+ {
427
+ const r = m.runOracle('node scripts/validate-story-acs.cjs /caminho/que/nao/existe.story.md', { cwd: process.cwd(), timeoutMs: 5000 });
428
+ const noRawTrace = !/at Object\.|at Module\._compile|node:internal/.test(r.stderr || '');
429
+ assert(r.exitCode !== 0 && noRawTrace, 'AC-28: CLI sobre arquivo inexistente — erro limpo, sem stack cru', r);
430
+ }
431
+
432
+ // ---------------------------------------------------------------------
433
+ // Bloco G — Guardas gerais / auto-referência com controle negativo
434
+ // ---------------------------------------------------------------------
435
+ {
436
+ // SF12.6/ADR-030 Bloco C/D: `scripts/forge-generate.cjs` deixou de ser "motor congelado"
437
+ // — é o GERADOR de pods (`*new`/`*upgrade-pod`/`*migrate-squad`/`*harden-learning`), que
438
+ // evolui a cada story da linha ADR-030 (SF12.4a/SF12.4b/SF12.5a/SF12.5b/SF12.6...). Um
439
+ // AC permanente que exige "eternamente intocado" quebraria toda story futura que o toque
440
+ // legitimamente — retirado do escopo desta checagem; DF2-1 (zero linha de motor) segue
441
+ // provado para os 2 scripts de RUNTIME (pc-run-pod.cjs/validate-pod-workflow.cjs), que são
442
+ // os que a decisão original (SF11.11) de fato cobria.
443
+ const r = m.runOracle('git diff --stat -- scripts/pc-run-pod.cjs scripts/validate-pod-workflow.cjs', { cwd: process.cwd(), timeoutMs: 5000 });
444
+ assert(r.refused !== true && r.stdout.trim() === '', 'AC-29: motor de runtime intocado (DF2-1) — git diff --stat vazio (pc-run-pod.cjs/validate-pod-workflow.cjs; forge-generate.cjs evolui por story, SF12.6)', r);
445
+ }
446
+ {
447
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8');
448
+ assert(/validate-story-acs/.test(c), 'AC-30: package.json referencia validate-story-acs no scripts.test', null);
449
+ }
450
+ {
451
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'mecanismos', 'validador-de-acs-do-ciclo.md'), 'utf8');
452
+ assert(/vocabulario|vocabulário/i.test(c), 'AC-31: fronteiras declaradas (vocabulário + Corpus 5b) no doc', null);
453
+ }
454
+ {
455
+ const mutant = f(['## Acceptance Criteria', '', '**AC-M.** mutante', '```oraculo', 'test -f package.json', '```']);
456
+ const rm = m.validateStory(mutant, { cwd: process.cwd() });
457
+ const mutantCaught = rm.reprovados.find((x) => x.id === 'AC-M' && /nasce verde/i.test(x.motivo));
458
+ assert(!!mutantCaught, 'AC-32b: controle negativo — mutante nasce-verde é REPROVADO', rm);
459
+ }
460
+
461
+ // ---------------------------------------------------------------------
462
+ // Story SF13.7 — `parseGuarda` distingue CITAÇÃO (code span / fence) de USO
463
+ // real. Cada caso vem PAREADO: o que NÃO deve ser reconhecido junto com o
464
+ // que DEVE — um fix que simplesmente parasse de reconhecer `[Guarda]`
465
+ // zeraria os falsos positivos e cegaria o instrumento, e é exatamente isso
466
+ // que os controles positivos abaixo impedem de passar.
467
+ // ---------------------------------------------------------------------
468
+ {
469
+ // --- Controle NEGATIVO: citação entre crases não é uso (AC-1) ---
470
+ const body = [
471
+ 'descricao cita `[Guarda] (prova: AC-CITADO)` como exemplo, mas o guarda real eh outro:',
472
+ '[Guarda] (sem irmao - ausencia declarada)',
473
+ '```oraculo',
474
+ '# espera: stdout-vazio',
475
+ 'test -f arquivo-que-nao-existe-xyz123',
476
+ '```',
477
+ ].join('\n');
478
+ const g = m.parseGuarda(body);
479
+ assert(
480
+ !!g && g.forma === 'sem-irmao',
481
+ 'SF13.7/AC-1: citação em code span é ignorada e vence o uso REAL da linha seguinte',
482
+ g,
483
+ );
484
+ }
485
+ {
486
+ // --- Controle POSITIVO pareado: uso real SEM citação segue reconhecido ---
487
+ const body = ['descricao real do AC.', '[Guarda] (prova: AC-A)', '```oraculo', 'test -f package.json', '```'].join('\n');
488
+ const g = m.parseGuarda(body);
489
+ assert(
490
+ !!g && g.forma === 'prova' && g.provaId === 'AC-A',
491
+ 'SF13.7/AC-2: controle positivo — `[Guarda] (prova: AC-A)` sem citação continua reconhecido',
492
+ g,
493
+ );
494
+ }
495
+ {
496
+ // --- Controle POSITIVO das outras 2 formas (o fix não cega a família) ---
497
+ const semIrmao = m.parseGuarda('d\n[Guarda] (sem irmão — ausência declarada)\n');
498
+ const citacao = m.parseGuarda('d\n[Guarda] (citação de fato pré-existente, não prova de trabalho)\n');
499
+ const desconhecida = m.parseGuarda('d\n[Guarda] (banana)\n');
500
+ assert(
501
+ semIrmao && semIrmao.forma === 'sem-irmao'
502
+ && citacao && citacao.forma === 'citacao'
503
+ && desconhecida && desconhecida.forma === 'desconhecida',
504
+ 'SF13.7/AC-2b: as 3 formas + a não reconhecida continuam classificadas quando o uso é real',
505
+ { semIrmao, citacao, desconhecida },
506
+ );
507
+ }
508
+ {
509
+ // --- SF13.9/M5: o caso que a restrição de "mesma linha" de
510
+ // `computeInlineCodeRanges` de fato protege. Fixture e asserção exatas
511
+ // do gate `sf13.7-conserto-do-instrumento.yaml`
512
+ // (`finding_4_julgamento.teste_que_mata_M5`), executadas pelo QA nas
513
+ // duas direções: COM a restrição dá `AC-A`; SEM ela dá `null`.
514
+ // Existe porque `AC-29` de `sf13.1` — o caso que o comentário do fonte
515
+ // citava — NÃO exercita a restrição: sob M5 ele continua `sem-irmao` e
516
+ // nenhum AC ficava vermelho, então o mutante sobrevivia. ---
517
+ const body = [
518
+ 'prosa com crase orfa ` aberta aqui',
519
+ '[Guarda] (prova: AC-A)',
520
+ 'mais prosa com ` outra crase',
521
+ '```oraculo',
522
+ 'test -f package.json',
523
+ '```',
524
+ ].join('\n');
525
+ const g = m.parseGuarda(body);
526
+ assert(
527
+ !!g && g.forma === 'prova' && g.provaId === 'AC-A',
528
+ 'SF13.9/M5: crase órfã não pareia ATRAVÉS de linhas — o guarda REAL entre as duas continua reconhecido (AC-A)',
529
+ g,
530
+ );
531
+ }
532
+ {
533
+ // --- Citação DENTRO de fence (fixture literal em ```oraculo) não é uso ---
534
+ const body = ['descricao sem guarda propria.', '```oraculo', 'node -e \'const c="[Guarda] (prova: AC-Z)";\'', '```'].join('\n');
535
+ assert(
536
+ m.parseGuarda(body) === null,
537
+ 'SF13.7/AC-1b: `[Guarda]` como dado literal dentro da fence do oráculo não é etiqueta aplicada',
538
+ m.parseGuarda(body),
539
+ );
540
+ }
541
+ {
542
+ // --- Precedência: escolhe a ocorrência REAL, não a primeira TEXTUAL ---
543
+ const body = ['cita `[Guarda] (prova: AC-CITADO)` na prosa', '[Guarda] (prova: AC-REAL)', '```oraculo', 'test -f package.json', '```'].join('\n');
544
+ const g = m.parseGuarda(body);
545
+ assert(
546
+ !!g && g.provaId === 'AC-REAL',
547
+ 'SF13.7/AC-1c: citação e uso com textos DIFERENTES — vence o uso real, não o 1º match textual',
548
+ g,
549
+ );
550
+ }
551
+ {
552
+ // --- Regressão no corpus REAL: AC-29 de sf13.1 (citação e uso idênticos,
553
+ // em linhas consecutivas) continua classificado `sem-irmao` (AC-3) ---
554
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'stories', 'sf13.1.story.md'), 'utf8');
555
+ const ac29 = m.parseAcs(c).find((a) => a.id === 'AC-29');
556
+ assert(
557
+ !!ac29 && !!ac29.guarda && ac29.guarda.forma === 'sem-irmao',
558
+ 'SF13.7/AC-3: corpus real — AC-29 de sf13.1 (citação + uso idênticos) mantém `sem-irmao`',
559
+ ac29 && ac29.guarda,
560
+ );
561
+ }
562
+ {
563
+ // --- Corpus real, contabilidade COMPLETA (não amostra): a única guarda
564
+ // REAL de sf13.1 é a do AC-29; as outras 8 eram citação em code span.
565
+ // É o que prova que o fix não removeu nenhum verdadeiro positivo. ---
566
+ const c = fs.readFileSync(path.join(REPO_ROOT, 'docs', 'stories', 'sf13.1.story.md'), 'utf8');
567
+ const comGuarda = m.parseAcs(c).filter((a) => a.guarda).map((a) => a.id);
568
+ assert(
569
+ comGuarda.length === 1 && comGuarda[0] === 'AC-29',
570
+ 'SF13.7/AC-4: corpus real sf13.1 — exatamente 1 guarda real reconhecida (AC-29)',
571
+ comGuarda,
572
+ );
573
+ }
574
+ {
575
+ // --- Campos que o HOOK consome não mudam com o fix (fundamento do
576
+ // gatilho `pc-architect` NÃO ATIVO, AC-6): `parseGuarda` só altera
577
+ // `.guarda`, nunca `hasOraculo`/`oracleCmd`/`oracleEmpty`/`espera`. ---
578
+ const c = f([
579
+ '## Acceptance Criteria',
580
+ '',
581
+ '**AC-X.** cita `[Guarda] (prova: AC-CITADO)` na prosa',
582
+ '```oraculo',
583
+ '# espera: stdout == OK',
584
+ 'test -f package.json',
585
+ '```',
586
+ ]);
587
+ const ac = m.parseAcs(c).find((a) => a.id === 'AC-X');
588
+ assert(
589
+ !!ac && ac.hasOraculo === true && ac.oracleCmd === 'test -f package.json'
590
+ && ac.oracleEmpty === false && !!ac.espera && ac.espera.type === 'stdout==',
591
+ 'SF13.7/AC-6: campos consumidos pelo hook (hasOraculo/oracleCmd/oracleEmpty/espera) intactos',
592
+ ac,
593
+ );
594
+ }
595
+
596
+ // ---------------------------------------------------------------------
597
+ // Sumário
598
+ // ---------------------------------------------------------------------
599
+ if (failures > 0) {
600
+ console.error(`\n${failures} asserção(ões) falharam.`);
601
+ process.exitCode = 1;
602
+ } else {
603
+ console.log('\nTodas as asserções passaram.');
604
+ }
605
+ }
606
+
607
+ run();