@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,578 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * pc-run-pod.test.cjs — suíte PRÓPRIA do motor pc-run-pod (Story SF1.2, DoD 1b).
5
+ *
6
+ * É o componente MAIS testado da fase por exigência do ADR-001: o núcleo do
7
+ * enforcement não pode ser o menos testado. Dirige o motor com `state.json` REAL
8
+ * escrito em disco entre chamadas (não mock), plantando/omitindo artefatos para
9
+ * simular o subagente. Prova o não-fake-green NO MOTOR: `done` só com verificação
10
+ * em disco passando; artefato ausente / veto violado / template não-conforme NÃO
11
+ * avançam. Cobre start/resume/next/approve/revise/abort/status + retomada topológica.
12
+ *
13
+ * Node >= 18, sem dependências externas. Exit 0/1.
14
+ */
15
+
16
+ const fs = require('node:fs');
17
+ const os = require('node:os');
18
+ const path = require('node:path');
19
+
20
+ const R = require('../pc-run-pod.cjs');
21
+ const PM = require('../pod-memory.cjs');
22
+
23
+ const FIXT = path.resolve(__dirname, '..', '__fixtures__', 'pod-run');
24
+ const WF = path.join(FIXT, 'workflows', 'wf-min.yaml');
25
+
26
+ // SF2.2: o lifecycle de memória grava em `<podRoot>/memory/`. Os casos SF1.2 usam FIXT
27
+ // como podRoot; sem isolamento isso cairia no fixture versionado. Limpamos antes e depois
28
+ // para manter o fixture limpo e os testes determinísticos — os casos novos (SF2.2) usam
29
+ // um podDir temporário isolado via `memoryPodDir`, sem tocar o repo.
30
+ function wipeFixtureMemory() {
31
+ fs.rmSync(path.join(FIXT, 'memory'), { recursive: true, force: true });
32
+ }
33
+ wipeFixtureMemory();
34
+
35
+ // --- micro-harness -------------------------------------------------------
36
+ let passed = 0;
37
+ const failures = [];
38
+ function check(cond, label) {
39
+ if (cond) { passed++; console.log(`[OK ] ${label}`); }
40
+ else { failures.push(label); console.log(`[FALHA] ${label}`); }
41
+ }
42
+ function throws(fn, label) {
43
+ let threw = false;
44
+ try { fn(); } catch (e) { threw = true; }
45
+ check(threw, label);
46
+ }
47
+
48
+ function tmpRunsRoot() {
49
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'pc-run-pod-'));
50
+ }
51
+ function start(runsRoot, runId) {
52
+ return R.startRun({
53
+ workflowPath: WF,
54
+ podRootOverride: FIXT,
55
+ pod: 'test-pod',
56
+ workflow: 'wf-min',
57
+ mode: 'interactive',
58
+ taskRef: 'canário',
59
+ runsRoot,
60
+ runId,
61
+ });
62
+ }
63
+ function plant(ctx, stepId, content) {
64
+ const rel = ctx.state.steps[stepId].artifact;
65
+ const abs = path.resolve(ctx.runDir, rel);
66
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
67
+ fs.writeFileSync(abs, content, 'utf8');
68
+ }
69
+ const BUILD_OK = '## Escopo\n## Contexto\nstatus: rascunho\n';
70
+ const BUILD_VETO_BAD = '## Escopo\n## Contexto\nstatus: final\n'; // template OK, veto falha
71
+ const BUILD_TMPL_BAD = '## Escopo\nstatus: rascunho\n'; // veto OK, template falha (sem ## Contexto)
72
+ const GATE_OK = '## Veredito\nveredito: GO\n';
73
+ const GATE_VETO_BAD = '## Veredito\nveredito: MAYBE\n';
74
+ const FINAL_OK = '## Escopo\n## Contexto\nconfianca: alta\n'; // ADR-005: veto ortogonal `confianca`
75
+
76
+ // =========================================================================
77
+ // AC2 — start grava state.json no schema exato + primeiro dispatch (AC3 brief).
78
+ // =========================================================================
79
+ (function testStartSchema() {
80
+ const rr = tmpRunsRoot();
81
+ const { ctx, result } = start(rr, '2026-07-24T18-00-00Z');
82
+ check(result.action === 'dispatch' && result.step === 'build', 'AC3 start despacha a 1a etapa (build)');
83
+
84
+ const disk = R.readState(ctx.statePath);
85
+ const topKeys = ['pod', 'workflow', 'run_id', 'mode', 'task_ref', 'steps', 'updated_at'];
86
+ check(topKeys.every((k) => k in disk), 'AC2 state.json tem todos os campos de topo do schema §B1');
87
+ check(/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z$/.test(disk.run_id), 'AC2 run_id é timestamp ISO sanitizado (padrão SPEC)');
88
+ const stepKeys = ['status', 'agent', 'artifact', 'template', 'checkpoint', 'started_at', 'verified_at'];
89
+ const okStepShape = Object.values(disk.steps).every((s) => stepKeys.every((k) => k in s));
90
+ check(okStepShape, 'AC2 cada step tem os 7 campos do schema §B1');
91
+ check(disk.steps.gate.checkpoint === 'blocking', 'AC2 checkpoint bloqueante refletido no state');
92
+ check(disk.steps.build.status === 'running' && disk.steps.gate.status === 'pending' &&
93
+ disk.steps.finalize.status === 'pending', 'AC2 só a 1a etapa fica running após start');
94
+
95
+ const brief = result.brief;
96
+ check(brief.includes(path.resolve(ctx.runDir, 'artifacts', 'build.md')), 'AC3 brief inclui path exato do artefato');
97
+ check(brief.includes(path.resolve(FIXT, 'templates', 'build-tmpl.md')), 'AC3 brief inclui path do template');
98
+ check(brief.includes('field_matches') && brief.includes('status'), 'AC3 brief inclui o veto da etapa');
99
+ check(brief.includes('≤15 linhas'), 'AC3 brief instrui retorno ≤15 linhas');
100
+ })();
101
+
102
+ // =========================================================================
103
+ // AC4a — artefato AUSENTE → done NÃO setado, próximo passo NÃO roda.
104
+ // =========================================================================
105
+ (function testNoFakeGreenAbsent() {
106
+ const rr = tmpRunsRoot();
107
+ const { ctx } = start(rr);
108
+ const res = R.advance(ctx); // build running, sem artefato plantado
109
+ check(res.action === 'blocked' && res.reason === 'verification_failed', 'AC4a artefato ausente → blocked');
110
+ check(res.failures.some((f) => /ausente/.test(f)), 'AC4a falha nomeia artefato ausente');
111
+ check(ctx.state.steps.build.status !== 'done', 'AC4a build NÃO vira done');
112
+ check(ctx.state.steps.gate.status === 'pending', 'AC4a próxima etapa (gate) NÃO roda');
113
+ })();
114
+
115
+ // =========================================================================
116
+ // AC4b — veto VIOLADO (template conforme) → done NÃO setado.
117
+ // =========================================================================
118
+ (function testNoFakeGreenVeto() {
119
+ const rr = tmpRunsRoot();
120
+ const { ctx } = start(rr);
121
+ plant(ctx, 'build', BUILD_VETO_BAD);
122
+ const res = R.advance(ctx);
123
+ check(res.action === 'blocked', 'AC4b veto violado → blocked');
124
+ check(res.failures.some((f) => /veto\.assertions/.test(f)), 'AC4b falha é do veto (não do template)');
125
+ check(!res.failures.some((f) => /seção obrigatória do template/.test(f)), 'AC4b template estava conforme (isola o veto)');
126
+ check(ctx.state.steps.build.status !== 'done' && ctx.state.steps.gate.status === 'pending', 'AC4b não avança');
127
+ })();
128
+
129
+ // =========================================================================
130
+ // AC4c — template NÃO-CONFORME (veto passaria) → done NÃO setado.
131
+ // =========================================================================
132
+ (function testNoFakeGreenTemplate() {
133
+ const rr = tmpRunsRoot();
134
+ const { ctx } = start(rr);
135
+ plant(ctx, 'build', BUILD_TMPL_BAD);
136
+ const res = R.advance(ctx);
137
+ check(res.action === 'blocked', 'AC4c template não-conforme → blocked');
138
+ check(res.failures.some((f) => /seção obrigatória do template/.test(f)), 'AC4c falha é de conformidade de template');
139
+ check(ctx.state.steps.build.status !== 'done' && ctx.state.steps.gate.status === 'pending', 'AC4c não avança');
140
+ })();
141
+
142
+ // =========================================================================
143
+ // Caminho feliz build → done → dispatch gate; verified_at gravado.
144
+ // =========================================================================
145
+ (function testHappyBuild() {
146
+ const rr = tmpRunsRoot();
147
+ const { ctx } = start(rr);
148
+ plant(ctx, 'build', BUILD_OK);
149
+ const res = R.advance(ctx);
150
+ check(ctx.state.steps.build.status === 'done', 'build verificado vira done');
151
+ check(!!ctx.state.steps.build.verified_at, 'verified_at gravado no done');
152
+ check(res.action === 'dispatch' && res.step === 'gate', 'gate liberado só após build done');
153
+ })();
154
+
155
+ // =========================================================================
156
+ // AC5 — checkpoint.blocking para o runner; approve avança até complete.
157
+ // =========================================================================
158
+ (function testCheckpointApprove() {
159
+ const rr = tmpRunsRoot();
160
+ const { ctx } = start(rr);
161
+ plant(ctx, 'build', BUILD_OK); R.advance(ctx); // gate running
162
+ plant(ctx, 'gate', GATE_OK);
163
+ const res = R.advance(ctx);
164
+ check(res.action === 'awaiting_approval' && res.step === 'gate', 'AC5 checkpoint.blocking interrompe o runner');
165
+ check(ctx.state.steps.gate.status === 'awaiting_approval' && !!ctx.state.steps.gate.verified_at, 'AC5 gate verificado, aguardando aprovação');
166
+ check(ctx.state.steps.finalize.status === 'pending', 'AC5 finalize NÃO roda sem aprovação');
167
+
168
+ const ap = R.approve(ctx);
169
+ check(ctx.state.steps.gate.status === 'done', 'AC5 approve marca gate done');
170
+ check(ap.next.action === 'dispatch' && ap.next.step === 'finalize', 'AC5 approve libera finalize');
171
+
172
+ plant(ctx, 'finalize', FINAL_OK);
173
+ const done = R.advance(ctx);
174
+ check(done.action === 'complete', 'workflow completa após última etapa verificada');
175
+ check(R.firstNonDone(ctx) === null, 'nenhum passo não-done ao completar');
176
+ })();
177
+
178
+ // =========================================================================
179
+ // AC5 — revise devolve a etapa (e o fix_cycle.to) a pending para reexecução.
180
+ // =========================================================================
181
+ (function testCheckpointRevise() {
182
+ const rr = tmpRunsRoot();
183
+ const { ctx } = start(rr);
184
+ plant(ctx, 'build', BUILD_OK); R.advance(ctx);
185
+ plant(ctx, 'gate', GATE_OK); R.advance(ctx); // awaiting_approval
186
+ const rv = R.revise(ctx);
187
+ check(rv.action === 'revised' && rv.loop_to === 'build', 'AC5 revise honra fix_cycle (loop_to=build)');
188
+ check(ctx.state.steps.gate.fix_iterations === 1, 'AC5 revise incrementa fix_iterations');
189
+ check(rv.next.action === 'dispatch' && rv.next.step === 'build', 'AC5 revise reexecuta a partir do fix_cycle.to (build)');
190
+ })();
191
+
192
+ // =========================================================================
193
+ // AC6 — resume topológico: continua do 1o não-done, não repete done.
194
+ // =========================================================================
195
+ (function testResumeTopological() {
196
+ const rr = tmpRunsRoot();
197
+ const { ctx } = start(rr);
198
+ // simula build já concluído em disco, gate/finalize pendentes
199
+ ctx.state.steps.build.status = 'done';
200
+ ctx.state.steps.build.artifact = 'artifacts/build.md';
201
+ ctx.state.steps.build.verified_at = new Date().toISOString();
202
+ ctx.state.steps.gate.status = 'pending';
203
+ R.writeState(ctx.statePath, ctx.state);
204
+
205
+ const found = R.findStateByRunId(rr, ctx.state.run_id);
206
+ check(found === ctx.statePath, 'AC6 findStateByRunId localiza o state.json pelo run-id');
207
+
208
+ const ctx2 = R.openRun({ statePath: found, workflowPath: WF, podRootOverride: FIXT });
209
+ check(R.firstNonDone(ctx2) === 'gate', 'AC6 primeiro não-done é gate (build done não repete)');
210
+ const res = R.advance(ctx2);
211
+ check(res.action === 'dispatch' && res.step === 'gate', 'AC6 resume despacha gate, não build');
212
+ check(ctx2.state.steps.build.status === 'done', 'AC6 build permanece done na retomada');
213
+ })();
214
+
215
+ // =========================================================================
216
+ // fix_cycle — max_iterations excedido → halt (não fica em loop infinito).
217
+ // =========================================================================
218
+ (function testFixCycleMax() {
219
+ const rr = tmpRunsRoot();
220
+ const { ctx } = start(rr);
221
+ function toAwaiting() {
222
+ plant(ctx, 'build', BUILD_OK); R.advance(ctx);
223
+ plant(ctx, 'gate', GATE_OK); R.advance(ctx);
224
+ }
225
+ toAwaiting(); check(R.revise(ctx).action === 'revised', 'fix_cycle iter 1 ok');
226
+ toAwaiting(); check(R.revise(ctx).action === 'revised', 'fix_cycle iter 2 ok (== max)');
227
+ toAwaiting();
228
+ const halt = R.revise(ctx);
229
+ check(halt.action === 'halt', 'fix_cycle iter 3 (> max=2) → halt');
230
+ check(ctx.state.steps.gate.status === 'failed', 'fix_cycle excedido marca a etapa failed');
231
+ })();
232
+
233
+ // =========================================================================
234
+ // abort — pendências viram failed; status resume o run.
235
+ // =========================================================================
236
+ (function testAbortStatus() {
237
+ const rr = tmpRunsRoot();
238
+ const { ctx } = start(rr);
239
+ const summ = R.statusSummary(ctx);
240
+ check(/build: running/.test(summ) && /próximo não-done/.test(summ), 'status resume o run');
241
+ R.abort(ctx);
242
+ check(ctx.state.steps.build.status === 'failed' && ctx.state.steps.gate.status === 'failed', 'abort marca pendências como failed');
243
+ })();
244
+
245
+ // =========================================================================
246
+ // Risco 4 — state.json corrompido/ inválido → HALT explícito (nunca "conserta").
247
+ // =========================================================================
248
+ (function testCorruptState() {
249
+ const rr = tmpRunsRoot();
250
+ const { ctx } = start(rr);
251
+ const p = ctx.statePath;
252
+ fs.writeFileSync(p, '{ not json', 'utf8');
253
+ throws(() => R.readState(p), 'Risco4 JSON inválido → throw (não conserta silenciosamente)');
254
+ fs.writeFileSync(p, JSON.stringify({ pod: 'x', workflow: 'y', run_id: 'z', mode: 'm', updated_at: 't' }), 'utf8');
255
+ throws(() => R.readState(p), 'Risco4 schema sem steps → throw');
256
+ fs.writeFileSync(p, JSON.stringify({
257
+ pod: 'x', workflow: 'y', run_id: 'z', mode: 'm', updated_at: 't',
258
+ steps: { a: { status: 'bogus' } },
259
+ }), 'utf8');
260
+ throws(() => R.readState(p), 'Risco4 status desconhecido → throw');
261
+ })();
262
+
263
+ // =========================================================================
264
+ // Preflight reusa o validador da SF1.1 (Risco 2): contrato inválido → não inicia.
265
+ // =========================================================================
266
+ (function testPreflightReuse() {
267
+ const bad = path.resolve(__dirname, '..', '__fixtures__', 'pod-workflow', 'invalid-cycle.yaml');
268
+ throws(() => R.loadWorkflow(bad, path.dirname(path.dirname(bad))), 'Risco2 preflight reusa validate-pod-workflow (ciclo → não inicia)');
269
+ })();
270
+
271
+ // =========================================================================
272
+ // SF1.2 finding #1 (resolvido na SF1.3) — makeRunId é único mesmo no MESMO segundo.
273
+ // Dois `start` no mesmo segundo NÃO podem colidir no path do state.json.
274
+ // =========================================================================
275
+ (function testRunIdUnique() {
276
+ const fixed = new Date('2026-07-24T18:00:00.000Z');
277
+ const a = R.makeRunId(fixed);
278
+ const b = R.makeRunId(fixed);
279
+ check(a !== b, 'finding#1 makeRunId gera ids distintos para o MESMO instante');
280
+ check(a.startsWith('2026-07-24T18-00-00Z'), 'finding#1 run-id preserva o timestamp legível da SPEC como prefixo');
281
+
282
+ // Prova de ponta: dois starts no mesmo runsRoot/pod/workflow → dois state.json distintos.
283
+ const rr = tmpRunsRoot();
284
+ const r1 = start(rr); // runId default (makeRunId)
285
+ const r2 = start(rr);
286
+ check(r1.ctx.statePath !== r2.ctx.statePath, 'finding#1 dois starts no mesmo segundo → paths de state.json distintos (sem colisão)');
287
+ })();
288
+
289
+ // =========================================================================
290
+ // SF2.2 — lifecycle de memória do pod (ADR-003 / SPEC §G1).
291
+ // Isolamento: podDir temporário via `memoryPodDir` (nunca toca o fixture/repo).
292
+ // =========================================================================
293
+
294
+ function tmpPodDir() {
295
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'pc-run-mem-'));
296
+ }
297
+ function memFile(podDir, name) {
298
+ return path.join(podDir, 'memory', name);
299
+ }
300
+ function readJsonl(podDir) {
301
+ const p = memFile(podDir, 'learnings.jsonl');
302
+ if (!fs.existsSync(p)) return [];
303
+ return fs.readFileSync(p, 'utf8').split('\n').filter((l) => l.trim()).map((l) => JSON.parse(l));
304
+ }
305
+ function startMem(runsRoot, podDir, runId) {
306
+ return R.startRun({
307
+ workflowPath: WF, podRootOverride: FIXT, pod: 'test-pod', workflow: 'wf-min',
308
+ mode: 'interactive', taskRef: 'canário', runsRoot, runId, memoryPodDir: podDir,
309
+ });
310
+ }
311
+
312
+ // AC1 — blocked/verification_failed appenda candidato estruturado (tier normal).
313
+ (function testMemAppendOnFailure() {
314
+ const rr = tmpRunsRoot();
315
+ const pd = tmpPodDir();
316
+ const { ctx } = startMem(rr, pd);
317
+ R.advance(ctx); // build running, sem artefato → blocked/verification_failed
318
+ const entries = readJsonl(pd);
319
+ check(entries.length === 1, 'AC1 verification_failed appenda exatamente 1 candidato');
320
+ const e = entries[0] || {};
321
+ check(/verification_failed/.test(e.trigger || ''), 'AC1 trigger nomeia verification_failed');
322
+ check(/etapa "build"/.test(e.trigger || ''), 'AC1 trigger identifica a etapa bloqueada');
323
+ check(e.tier === 'normal', 'AC1 entrada é tier normal (runner nunca marca critical)');
324
+ check(e.evidence && e.evidence.step === 'build' && Array.isArray(e.evidence.veto) && e.evidence.veto.length > 0,
325
+ 'AC1 evidence estruturada carrega etapa + veto violado (dos failures)');
326
+ check(/corrigir/.test(e.recommendation || ''), 'AC1 recommendation derivada dos failures');
327
+ })();
328
+
329
+ // AC2 + AC5 — complete appenda padrão-ok e dispara consolidate.
330
+ (function testMemAppendOnComplete() {
331
+ const rr = tmpRunsRoot();
332
+ const pd = tmpPodDir();
333
+ const { ctx } = startMem(rr, pd);
334
+ plant(ctx, 'build', BUILD_OK); R.advance(ctx); // gate running
335
+ plant(ctx, 'gate', GATE_OK); R.advance(ctx); // awaiting_approval
336
+ R.approve(ctx); // finalize running
337
+ plant(ctx, 'finalize', FINAL_OK);
338
+ const done = R.advance(ctx);
339
+ check(done.action === 'complete', 'AC2 run chega a complete (pré-condição)');
340
+ const entries = readJsonl(pd);
341
+ const ok = entries.find((x) => /completou sem bloqueio/.test(x.trigger || ''));
342
+ check(!!ok, 'AC2 complete appenda registro de padrão-ok');
343
+ check(ok && ok.tier === 'normal', 'AC2 padrão-ok é tier normal');
344
+ check(ok && ok.evidence && typeof ok.evidence.steps_done === 'number', 'AC2 evidence carrega steps_done');
345
+ check(fs.existsSync(memFile(pd, 'learnings.consolidated.md')), 'AC5 complete dispara consolidate (consolidado escrito)');
346
+ })();
347
+
348
+ // AC6 — K=20 appends dispara consolidate mesmo sem complete.
349
+ (function testMemConsolidateEveryK() {
350
+ const rr = tmpRunsRoot();
351
+ const pd = tmpPodDir();
352
+ const { ctx } = startMem(rr, pd); // dispatch inicial não appenda
353
+ const consPath = memFile(pd, 'learnings.consolidated.md');
354
+ for (let i = 0; i < PM.CONSOLIDATE_K - 1; i++) {
355
+ R.recordLearning(ctx, R.buildFailureLearning(ctx, `s${i}`, [`falha ${i}`]));
356
+ }
357
+ check(readJsonl(pd).length === PM.CONSOLIDATE_K - 1, 'AC6 pré-condição: 19 appends acumulados');
358
+ check(!fs.existsSync(consPath), 'AC6 consolidate NÃO disparou antes de K=20');
359
+ R.recordLearning(ctx, R.buildFailureLearning(ctx, 's19', ['falha 19'])); // 20º
360
+ check(fs.existsSync(consPath), 'AC6 20º append (K=20) dispara consolidate sem complete');
361
+ })();
362
+
363
+ // AC3 — brief injeta seção de memória só quando o consolidado tem conteúdo real.
364
+ (function testMemBriefInjection() {
365
+ const rr = tmpRunsRoot();
366
+ const pd = tmpPodDir();
367
+ const { ctx } = startMem(rr, pd);
368
+ const briefAbsent = R.buildBrief(ctx, 'build');
369
+ check(!/Memória consolidada/.test(briefAbsent), 'AC3 sem consolidado → seção de memória omitida');
370
+
371
+ // consolidado só com cabeçalho (sem heurística) → ainda omitido.
372
+ fs.mkdirSync(path.join(pd, 'memory'), { recursive: true });
373
+ fs.writeFileSync(memFile(pd, 'learnings.consolidated.md'),
374
+ '# Memória consolidada — test-pod\n\n## Heurísticas (top-N)\n\n_Nenhuma heurística consolidada ainda._\n');
375
+ check(!/Memória consolidada \(aplique/.test(R.buildBrief(ctx, 'build')), 'AC3 consolidado só-cabeçalho (vazio) → seção omitida');
376
+
377
+ // consolidado com heurística real → seção injetada com o conteúdo.
378
+ fs.writeFileSync(memFile(pd, 'learnings.consolidated.md'),
379
+ '# Memória consolidada — test-pod\n\n## Heurísticas (top-N)\n\n- **[etapa build]** valide o status antes de finalizar _(x3)_\n');
380
+ const briefWith = R.buildBrief(ctx, 'build');
381
+ check(/## Memória consolidada \(aplique estas heurísticas\)/.test(briefWith), 'AC3 consolidado com conteúdo → seção injetada');
382
+ check(/valide o status antes de finalizar/.test(briefWith), 'AC3 conteúdo real da heurística chega ao brief');
383
+ })();
384
+
385
+ // AC4 — brief NUNCA lê nem menciona o log cru learnings.jsonl (teste negativo).
386
+ (function testMemBriefNeverRaw() {
387
+ const rr = tmpRunsRoot();
388
+ const pd = tmpPodDir();
389
+ const { ctx } = startMem(rr, pd);
390
+ // gera o consolidado REAL via motor — cujo cabeçalho contém a string "learnings.jsonl".
391
+ PM.append('test-pod', {
392
+ trigger: 'etapa build', recommendation: 'valide o status antes de finalizar', tier: 'normal',
393
+ }, { podDir: pd });
394
+ PM.consolidate('test-pod', { podDir: pd });
395
+ const rawConsolidated = fs.readFileSync(memFile(pd, 'learnings.consolidated.md'), 'utf8');
396
+ check(/learnings\.jsonl/.test(rawConsolidated), 'AC4 pré-condição: o consolidado cru do motor MENCIONA learnings.jsonl no cabeçalho');
397
+
398
+ const brief = R.buildBrief(ctx, 'build');
399
+ check(/valide o status antes de finalizar/.test(brief), 'AC4 a heurística real foi injetada no brief');
400
+ check(!/learnings\.jsonl/.test(brief), 'AC4 brief NUNCA contém a string "learnings.jsonl" (cabeçalho de disclaimer descartado)');
401
+ check(!brief.includes(memFile(pd, 'learnings.jsonl')), 'AC4 brief NUNCA contém o path do log cru');
402
+ })();
403
+
404
+ // =========================================================================
405
+ // SF11.10/ADR-024 — gate de texto antes do custo: `checkpoint.skip_modes`.
406
+ // O smoke roda em `yolo` e por construção NUNCA visita um gate que o `yolo` pula;
407
+ // estes casos são o oráculo que ele não dá (DF-SF11.10-9).
408
+ // =========================================================================
409
+
410
+ const WF_SKIP = path.join(FIXT, 'workflows', 'wf-skip-modes.yaml');
411
+ const SCRIPT_OK = '## Escopo\n## Contexto\nstatus: rascunho\n';
412
+ const FINAL_GATE_OK = '## Veredito\nveredito: GO\n';
413
+
414
+ function startSkip(runsRoot, mode, podDir) {
415
+ return R.startRun({
416
+ workflowPath: WF_SKIP, podRootOverride: FIXT, pod: 'test-pod', workflow: 'wf-skip-modes',
417
+ mode, taskRef: 'canário-skip-modes', runsRoot, memoryPodDir: podDir,
418
+ });
419
+ }
420
+
421
+ // AC6 — TABELA-VERDADE de isBlocking(step, mode). A enumeração é NEGATIVA de propósito:
422
+ // o desconhecido BLOQUEIA (fail-closed). Inverter isso trocaria fail-closed por fail-open
423
+ // no único gate humano do sistema.
424
+ (function testIsBlockingTruthTable() {
425
+ const semSkip = { checkpoint: { blocking: true, criteria: 'x' } };
426
+ const comSkip = { checkpoint: { blocking: true, skip_modes: ['yolo'], criteria: 'x' } };
427
+ const naoBloq = { checkpoint: { blocking: false, criteria: 'x' } };
428
+ const semCp = { checkpoint: null };
429
+
430
+ check(R.isBlocking(semSkip, 'interactive') === true && R.isBlocking(semSkip, 'yolo') === true,
431
+ 'AC6(a) skip_modes AUSENTE ⇒ bloqueia em interactive E em yolo (retrocompat byte-idêntica)');
432
+ check(R.isBlocking(comSkip, 'interactive') === true && R.isBlocking(comSkip, 'yolo') === false,
433
+ 'AC6(b) skip_modes ["yolo"] ⇒ bloqueia em interactive, NÃO bloqueia em yolo');
434
+ check(R.isBlocking(comSkip, 'modo-que-nao-existe') === true && R.isBlocking(comSkip, undefined) === true,
435
+ 'AC6(c) modo NÃO listado (typo/undefined) ⇒ BLOQUEIA — fail-closed');
436
+ check(R.isBlocking(naoBloq, 'interactive') === false && R.isBlocking(semCp, 'interactive') === false,
437
+ 'AC6(d) blocking:false / checkpoint:null ⇒ nunca bloqueia, em modo nenhum');
438
+ check(Array.isArray(R.RUN_MODES) && R.RUN_MODES.join(',') === 'interactive,yolo',
439
+ 'AC6 conjunto fechado de ritmos vem do validador (fonte única): interactive, yolo');
440
+ })();
441
+
442
+ // AC7/AC10 (forma sintética) — em `interactive` a run PARA no gate de texto e a etapa CARA
443
+ // não é despachada. É o oposto do 1 ms medido hoje entre digest.verified_at e visuals.started_at.
444
+ (function testSkipModesInteractiveParaAntesDaEtapaCara() {
445
+ const rr = tmpRunsRoot();
446
+ const pd = tmpPodDir();
447
+ const { ctx, result } = startSkip(rr, 'interactive', pd);
448
+ check(result.action === 'dispatch' && result.step === 'script', 'SF11.10 interactive: start despacha `script`');
449
+ plant(ctx, 'script', SCRIPT_OK);
450
+ const r2 = R.advance(ctx);
451
+ check(r2.action === 'awaiting_approval' && r2.step === 'script',
452
+ 'AC10 interactive: advance PARA em awaiting_approval no gate de texto (não despacha a etapa cara)');
453
+
454
+ const disk = R.readState(ctx.statePath);
455
+ check(disk.steps.script.checkpoint === 'blocking', 'AC7 interactive: state grava checkpoint "blocking" no gate de texto');
456
+ check(disk.steps.costly.status === 'pending' && disk.steps.costly.started_at === null,
457
+ 'AC10 interactive: a etapa CARA continua pending com started_at null no instante da parada');
458
+
459
+ // `revise` sem fix_cycle devolve SÓ a própria etapa e re-despacha — zero custo na etapa cara.
460
+ const rev = R.revise(ctx);
461
+ check(rev.action === 'revised' && rev.step === 'script' && rev.next.action === 'dispatch' && rev.next.step === 'script',
462
+ 'AC10 revise no gate de texto devolve SÓ `script` a pending e re-despacha');
463
+ const afterRev = R.readState(ctx.statePath);
464
+ check(afterRev.steps.costly.status === 'pending' && afterRev.steps.costly.started_at === null &&
465
+ afterRev.steps.final.status === 'pending',
466
+ 'AC10 revise NÃO toca a etapa cara nem o gate de fechamento');
467
+
468
+ // approve libera a etapa cara; a run segue até o gate de fechamento.
469
+ plant(ctx, 'script', SCRIPT_OK);
470
+ const r3 = R.advance(ctx);
471
+ check(r3.action === 'awaiting_approval', 'AC10 re-execução do `script` volta ao mesmo gate');
472
+ const ap = R.approve(ctx);
473
+ check(ap.action === 'approved' && ap.next.action === 'dispatch' && ap.next.step === 'costly',
474
+ 'AC10 approve no gate de texto libera a etapa cara');
475
+ plant(ctx, 'costly', SCRIPT_OK);
476
+ const r4 = R.advance(ctx);
477
+ check(r4.action === 'dispatch' && r4.step === 'final', 'AC10 etapa cara roda sem regressão e despacha o fechamento');
478
+ plant(ctx, 'final', FINAL_GATE_OK);
479
+ const r5 = R.advance(ctx);
480
+ check(r5.action === 'awaiting_approval' && r5.step === 'final',
481
+ 'AC10 a run chega ao gate de FECHAMENTO como antes desta story');
482
+ })();
483
+
484
+ // AC7/AC11 — PROVA NEGATIVA: em `yolo` o gate de texto não existe, e ninguém o aprova.
485
+ (function testSkipModesYoloPulaSemAprovar() {
486
+ const rr = tmpRunsRoot();
487
+ const pd = tmpPodDir();
488
+ const { ctx, result } = startSkip(rr, 'yolo', pd);
489
+ check(result.action === 'dispatch' && result.step === 'script', 'SF11.10 yolo: start despacha `script`');
490
+
491
+ const atStart = R.readState(ctx.statePath);
492
+ check(atStart.steps.script.checkpoint === null,
493
+ 'AC7 yolo: state.json grava checkpoint null no gate pulado (a auditoria diz a verdade)');
494
+ check(atStart.steps.final.checkpoint === 'blocking',
495
+ 'AC7 yolo: o gate de FECHAMENTO segue "blocking" (sem skip_modes ⇒ bloqueia em todo modo)');
496
+
497
+ plant(ctx, 'script', SCRIPT_OK);
498
+ const r2 = R.advance(ctx);
499
+ check(r2.action === 'dispatch' && r2.step === 'costly',
500
+ 'AC11 yolo: a run atravessa o gate de texto sem parar (vai direto à etapa seguinte)');
501
+ const afterScript = R.readState(ctx.statePath);
502
+ check(afterScript.steps.script.status === 'done',
503
+ 'AC11 yolo: `script` chega a done SEM jamais passar por awaiting_approval');
504
+
505
+ plant(ctx, 'costly', SCRIPT_OK);
506
+ const r3 = R.advance(ctx);
507
+ check(r3.action === 'dispatch' && r3.step === 'final', 'AC11 yolo: etapa cara roda e despacha o fechamento');
508
+ plant(ctx, 'final', FINAL_GATE_OK);
509
+ const r4 = R.advance(ctx);
510
+ check(r4.action === 'awaiting_approval' && r4.step === 'final',
511
+ 'AC11 yolo ESTACIONA no gate de fechamento — nenhum approve foi executado pelo modo autônomo');
512
+ // Prova NEGATIVA em disco: a run não terminou; o gate de fechamento continua esperando humano.
513
+ const disk = R.readState(ctx.statePath);
514
+ check(disk.steps.final.status === 'awaiting_approval' && disk.steps.script.checkpoint === null,
515
+ 'AC11 disco: fechamento em awaiting_approval e gate de texto com checkpoint null (pular ≠ aprovar)');
516
+ })();
517
+
518
+ // AC8 — `mode` é conjunto FECHADO, validado no start, com os valores válidos na mensagem.
519
+ (function testModoForaDoConjuntoFechado() {
520
+ const rr = tmpRunsRoot();
521
+ let msg = '';
522
+ try {
523
+ R.startRun({
524
+ workflowPath: WF_SKIP, podRootOverride: FIXT, pod: 'test-pod', workflow: 'wf-skip-modes',
525
+ mode: 'YOLO', taskRef: 'canário', runsRoot: rr, memoryPodDir: tmpPodDir(),
526
+ });
527
+ } catch (e) { msg = e.message; }
528
+ check(/modo de run inválido/.test(msg) && /YOLO/.test(msg),
529
+ 'AC8 --mode fora do conjunto fechado é RECUSADO no start (não vira deadlock silencioso)');
530
+ check(/interactive/.test(msg) && /yolo/.test(msg), 'AC8 a mensagem NOMEIA os valores válidos');
531
+ })();
532
+
533
+ // AC8 — capabilityGaps enxerga chave desconhecida sob `checkpoint` (skew para frente).
534
+ (function testCapabilityGapCheckpointDesconhecido() {
535
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-skew-'));
536
+ const wf = path.join(dir, 'wf-futuro.yaml');
537
+ fs.writeFileSync(wf, [
538
+ 'state_machine:',
539
+ ' states: [init, running, complete, failed]',
540
+ ' initial: init',
541
+ ' terminal: [complete, failed]',
542
+ 'steps:',
543
+ ' - id: gate',
544
+ ' agent: pod-critic',
545
+ ' template: templates/gate-tmpl.md',
546
+ ' inputs: [brief]',
547
+ ' outputs: [verdict]',
548
+ ' depends_on: []',
549
+ ' checkpoint: { blocking: true, criteria: "x", futuro_desconhecido: 1 }',
550
+ ' veto:',
551
+ ' assertions:',
552
+ ' - { type: field_matches, field: veredito, pattern: "^(GO|NO-GO)$" }',
553
+ '',
554
+ ].join('\n'), 'utf8');
555
+
556
+ const gaps = R.capabilityGaps(wf);
557
+ check(gaps.some((g) => /checkpoint\.futuro_desconhecido/.test(g) && /não existe neste motor/.test(g)),
558
+ 'AC8 capabilityGaps NOMEIA a chave de checkpoint que este motor não conhece');
559
+
560
+ // E o preflight do runner atribui a falha à INSTALAÇÃO, não ao wf (ADR-019 DF-SF10.20-4).
561
+ let annotated = '';
562
+ try { R.loadWorkflow(wf, FIXT); } catch (e) { annotated = e.message; }
563
+ check(/ATRIBUIÇÃO/.test(annotated) && /checkpoint\.futuro_desconhecido/.test(annotated),
564
+ 'AC8 a falha do preflight vira diagnóstico de skew (instalação defasada), não acusação ao wf');
565
+ fs.rmSync(dir, { recursive: true, force: true });
566
+ })();
567
+
568
+ wipeFixtureMemory();
569
+
570
+ // --- relatório -----------------------------------------------------------
571
+ console.log(`\n${passed}/${passed + failures.length} asserções passaram.`);
572
+ if (failures.length > 0) {
573
+ console.error('\nSUÍTE pc-run-pod FALHOU:');
574
+ for (const f of failures) console.error(` - ${f}`);
575
+ process.exit(1);
576
+ }
577
+ console.log('Suíte pc-run-pod verde (motor: não-fake-green provado).');
578
+ process.exit(0);