@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,165 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * render-gate.cjs — veto BLESSED (forma command_check, ADR-011). RENDERIZA o HTML do
5
+ * artefato em headless Chrome e detecta OVERFLOW de layout (conteúdo que estoura a
6
+ * viewport ou uma caixa) — o defeito de campo (a): 2 interfaces quebradas na R5 passaram
7
+ * por todo veto textual; "o braço que fazia render+inspeção peça a peça não quebrou".
8
+ *
9
+ * ZERO-DEP npm (ADR-011 Decisão 3): usa o binário de sistema headless Chrome via
10
+ * execFileSync (nunca uma lib npm). DEPENDÊNCIA AUSENTE = FAIL-LOUD (exit 3, mensagem
11
+ * acionável), NUNCA skip-silencioso — um veto que pula quando a ferramenta falta é
12
+ * green-fake (o artefato embarca não-verificado com o run parecendo limpo).
13
+ *
14
+ * MECANISMO: injeta (numa CÓPIA temporária, sem mutar o artefato) um <script> de medição
15
+ * que marca `document.documentElement[data-render-gate] = OVERFLOW|OK` conforme
16
+ * scrollWidth/scrollHeight excedam a viewport ou uma caixa sem overflow rolável; roda
17
+ * `chrome --headless --dump-dom` e lê o marcador do DOM renderizado.
18
+ *
19
+ * LIMITES HONESTOS (documentados — ADR-011 Decisão 3, render-gate portável só onde há
20
+ * headless browser): detecta OVERFLOW/CORTE por métrica de scroll; NÃO detecta colisão
21
+ * visual por z-index/sobreposição de cor, contraste, nem estética. Viewport é parâmetro
22
+ * (--width/--height; default 1080×1350, retrato Instagram). Onde não há Chrome, BLOQUEIA
23
+ * com mensagem (nunca falso-verde). Direção FAIL-CLOSED por design (na dúvida, bloqueia).
24
+ * CONTEÚDO DEVE SER PINADO À MOLDURA: o artefato precisa fixar `html,body{width:W;height:H}`
25
+ * casando a viewport (--width/--height); um elemento de largura EXATAMENTE igual à viewport
26
+ * num body NÃO-pinado toca a borda e é reportado como overflow de borda (falso-positivo de
27
+ * borda, fail-closed) — os slides de pod já são autorados pinados à moldura, então não ocorre
28
+ * no uso pretendido (MINOR-1 do gate SF7.2).
29
+ *
30
+ * Uso: node scripts/veto-checks/render-gate.cjs <artefato.html> [--width N] [--height N]
31
+ * Exit 0 = sem overflow; exit 1 = overflow detectado (bloqueia); exit 2 = uso;
32
+ * exit 3 = Chrome ausente (fail-loud) ou falha ao renderizar.
33
+ */
34
+
35
+ const fs = require('node:fs');
36
+ const os = require('node:os');
37
+ const path = require('node:path');
38
+ const { execFileSync } = require('node:child_process');
39
+
40
+ const CHROME_CANDIDATES = [
41
+ 'google-chrome-stable', 'google-chrome', 'chromium', 'chromium-browser', 'chrome',
42
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
43
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
44
+ ];
45
+
46
+ /** Testa se um candidato é um Chrome utilizável. */
47
+ function usable(cand) {
48
+ try {
49
+ if (cand.includes('/')) return fs.existsSync(cand) ? cand : null; // caminho absoluto
50
+ execFileSync(cand, ['--version'], { stdio: 'ignore', timeout: 8000 }); // nome no PATH
51
+ return cand;
52
+ } catch { return null; }
53
+ }
54
+
55
+ /**
56
+ * Resolve um binário de Chrome utilizável, ou null (→ fail-loud no chamador).
57
+ * Se CHROME_BIN está SETADO, é honrado ESTRITAMENTE: inválido → null (fail-loud), SEM
58
+ * fallback silencioso para outro navegador (um veto que troca de ferramenta por baixo dos
59
+ * panos seria green-fake). Sem CHROME_BIN, varre os candidatos conhecidos.
60
+ */
61
+ function probeChrome() {
62
+ if (process.env.CHROME_BIN) return usable(process.env.CHROME_BIN);
63
+ for (const cand of CHROME_CANDIDATES) {
64
+ const u = usable(cand);
65
+ if (u) return u;
66
+ }
67
+ return null;
68
+ }
69
+
70
+ // Medição VIEWPORT-INDEPENDENTE: compara cada elemento (body + descendentes) com a PRÓPRIA
71
+ // caixa (scrollWidth/Height vs clientWidth/Height). NÃO usa documentElement.clientHeight, que
72
+ // em headless retorna a viewport interna (menor que --window-size por causa do cromo da
73
+ // janela) e geraria falso-positivo. Um filho que estoura a caixa de overflow:hidden do pai
74
+ // aparece como scroll no PAI — é o corte real que queremos pegar.
75
+ const MEASURE_SCRIPT = `
76
+ <script>(function(){
77
+ function overflowing(){
78
+ // TOL=8px: ignora ruído de métricas de texto (line-height apertado faz scrollHeight
79
+ // exceder clientHeight por ~1-4px sem corte real). Os defeitos de campo (interface
80
+ // quebrada, caixa estourando a moldura) são GROSSEIROS (centenas de px). LIMITE HONESTO:
81
+ // este gate pega corte GROSSEIRO, não descender clipado por sub-pixel.
82
+ var TOL=8, root=document.body;
83
+ if (!root) return false;
84
+ var els=[root].concat([].slice.call(root.querySelectorAll('*')));
85
+ for (var i=0;i<els.length;i++){
86
+ var e=els[i], cs=getComputedStyle(e);
87
+ if (cs.display==='none' || cs.visibility==='hidden') continue;
88
+ var scrollable=/auto|scroll/.test((cs.overflow||'')+(cs.overflowX||'')+(cs.overflowY||''));
89
+ if (!scrollable && (e.scrollWidth>e.clientWidth+TOL || e.scrollHeight>e.clientHeight+TOL)) return true;
90
+ }
91
+ return false;
92
+ }
93
+ try { document.documentElement.setAttribute('data-render-gate', overflowing()?'OVERFLOW':'OK'); }
94
+ catch(err){ document.documentElement.setAttribute('data-render-gate','ERROR'); }
95
+ })();</script>`;
96
+
97
+ /** Decide o veredito a partir do DOM renderizado (dump-dom). Pura, testável. */
98
+ function decideFromDom(domHtml) {
99
+ const m = domHtml.match(/data-render-gate="([^"]*)"/);
100
+ if (!m) return { ok: false, verdict: 'no-marker', reason: 'marcador de medição ausente no DOM renderizado (script não executou?)' };
101
+ if (m[1] === 'OK') return { ok: true, verdict: 'OK' };
102
+ if (m[1] === 'OVERFLOW') return { ok: false, verdict: 'OVERFLOW', reason: 'conteúdo estoura a viewport ou uma caixa não-rolável (overflow/corte)' };
103
+ return { ok: false, verdict: m[1], reason: `medição retornou "${m[1]}"` };
104
+ }
105
+
106
+ function renderDom(chromeBin, htmlPath, width, height) {
107
+ return execFileSync(chromeBin, [
108
+ '--headless=new', '--disable-gpu', '--no-sandbox', '--hide-scrollbars',
109
+ `--window-size=${width},${height}`, '--virtual-time-budget=4000',
110
+ '--dump-dom', `file://${htmlPath}`,
111
+ ], { encoding: 'utf8', timeout: 30000, stdio: ['ignore', 'pipe', 'ignore'] });
112
+ }
113
+
114
+ function parseArgs(argv) {
115
+ const o = { width: 1080, height: 1350 };
116
+ for (let i = 0; i < argv.length; i++) {
117
+ if (argv[i] === '--width') o.width = Number.parseInt(argv[++i], 10);
118
+ else if (argv[i] === '--height') o.height = Number.parseInt(argv[++i], 10);
119
+ }
120
+ return o;
121
+ }
122
+
123
+ function main() {
124
+ const artifact = process.argv[2];
125
+ if (!artifact || !fs.existsSync(artifact)) {
126
+ console.error(`render-gate: artefato não encontrado: ${artifact}`);
127
+ process.exit(2);
128
+ }
129
+ const { width, height } = parseArgs(process.argv.slice(3));
130
+
131
+ const chromeBin = probeChrome();
132
+ if (!chromeBin) {
133
+ console.error('render-gate BLOQUEOU (fail-loud): headless Chrome não encontrado. ' +
134
+ 'Defina CHROME_BIN ou instale google-chrome/chromium. Não é possível verificar a ' +
135
+ 'renderização — BLOQUEANDO em vez de pular (skip = green-fake).');
136
+ process.exit(3);
137
+ }
138
+
139
+ // Cópia temporária com o script de medição anexado (não muta o artefato; scripts não
140
+ // afetam o layout, então a medição reflete o render real).
141
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-render-gate-'));
142
+ const tmpHtml = path.join(tmpDir, 'measured.html');
143
+ let dom;
144
+ try {
145
+ fs.writeFileSync(tmpHtml, fs.readFileSync(artifact, 'utf8') + MEASURE_SCRIPT, 'utf8');
146
+ dom = renderDom(chromeBin, tmpHtml, width, height);
147
+ } catch (e) {
148
+ console.error(`render-gate BLOQUEOU (fail-loud): falha ao renderizar em ${chromeBin}: ${e.message}`);
149
+ process.exit(3);
150
+ } finally {
151
+ try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch { /* best-effort */ }
152
+ }
153
+
154
+ const r = decideFromDom(dom);
155
+ if (r.ok) {
156
+ console.log(`render-gate OK: sem overflow em ${width}×${height} (${chromeBin.split('/').pop()}).`);
157
+ process.exit(0);
158
+ }
159
+ console.error(`render-gate BLOQUEOU: ${r.reason} (veredito ${r.verdict}).`);
160
+ process.exit(r.verdict === 'no-marker' ? 3 : 1);
161
+ }
162
+
163
+ if (require.main === module) main();
164
+
165
+ module.exports = { probeChrome, decideFromDom, parseArgs, CHROME_CANDIDATES };
@@ -0,0 +1,358 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * render-png.cjs — veto BLESSED (forma command_check, ADR-011) que PRODUZ o entregável de
5
+ * publicacao e o VERIFICA por maquina, ANTES do checkpoint humano da etapa.
6
+ *
7
+ * Story SF11.11 / ADR-025 (`DF-SF11.11-1`..`-4`). O problema que ele resolve: o pod entregava
8
+ * HTML e o dono publicava PNG renderizado a mao, fora do caminho governado — logo ele aprovava
9
+ * uma coisa e publicava outra. Como `verifyStep` (onde os vetos rodam) e chamado por
10
+ * `advance()` ANTES de `isBlocking`/`awaiting_approval`, declarar a renderizacao aqui faz os
11
+ * PNGs existirem, medidos e aprovados por maquina, no instante em que o humano e convocado —
12
+ * em QUALQUER modo (`verifyStep`/`evalVeto` nao leem `mode`), sem uma linha de motor.
13
+ *
14
+ * GENERICO POR CONTRATO (ADR-025 `DF-SF11.11-1`): nenhum nome de pod, de peca ou de dominio
15
+ * mora aqui. Tudo que e especifico do pod vem por argumento LITERAL do `wf` (ADR-011 proibe
16
+ * interpolacao): quantos arquivos, que dimensao, de onde e para onde.
17
+ *
18
+ * ZERO-DEP npm (ADR-011 Decisao 3): headless Chrome de sistema via execFileSync. DEPENDENCIA
19
+ * AUSENTE = FAIL-LOUD (exit 3), NUNCA skip-silencioso. NAO EXISTE escape hatch: nenhuma flag,
20
+ * nenhuma env var e nenhum ramo de codigo faz este script sair 0 sem ter renderizado e medido
21
+ * as `--expect` pecas (decisao do dono, 2026-08-03: uma rodada sem Chrome NAO FECHA, nem
22
+ * entregando HTML — a alternativa reintroduziria a degradacao silenciosa que a SF11.4b
23
+ * eliminou). `probeChrome` e REUSADO de `render-gate.cjs` (mesma recusa de fallback silencioso
24
+ * quando CHROME_BIN esta setado e invalido) — este script nao reimplementa a sonda.
25
+ *
26
+ * O QUE ELE PROVA: que existem EXATAMENTE `--expect` arquivos `.html` no dir declarado, que o
27
+ * Chrome conseguiu renderizar cada um, e que cada PNG gerado tem `--width`x`--height` EXATOS,
28
+ * lidos do IHDR do proprio arquivo (`readUInt32BE(16)`/`readUInt32BE(20)`), comparados com
29
+ * `===`. Igualdade de inteiros: sem tolerancia, sem `+/-`, sem limiar calibravel (ADR-018
30
+ * `DF4-5` — o oraculo e o formato de publicacao declarado no `wf`, nao uma amostragem).
31
+ *
32
+ * O QUE ELE NAO PROVA (dito antes que alguem descubra): que a peca esta bonita, que o texto
33
+ * coube, que o contraste presta ou que o encaixe copy x canvas ficou bom. Isso e JULGAMENTO
34
+ * HUMANO no checkpoint (fronteira ADR-002), agora com a evidencia certa na mao. Overflow de
35
+ * layout tem script proprio (`render-gate.cjs`) e NAO entra aqui (ADR-025 `DF-SF11.11-13`,
36
+ * divida 1).
37
+ *
38
+ * LIMITE HONESTO DA CHECAGEM DE DIMENSAO (MEDIDO na implementacao da SF11.11, corrigindo o que
39
+ * o ADR-025 supunha): a dimensao do PNG e ditada pelo `--window-size` do Chrome, NAO pelo CSS
40
+ * do documento. Medido: um HTML pinado a 1080x2000 e outro a 900x700, renderizados com
41
+ * `--window-size=1080,1350`, produzem os DOIS um PNG 1080x1350. Logo esta checagem NAO e um
42
+ * veto sobre o CONTEUDO do HTML — e uma POS-CONDICAO SOBRE O RENDERIZADOR: ela pega o
43
+ * renderizador que desobedece a moldura (escala de tela dobrada/HiDPI, PNG truncado ou
44
+ * corrompido, binario que sai 0 escrevendo outra coisa — a classe de green-fake que o
45
+ * chromium-snap produziu na VPS, achado 1 do provisionamento). Isso continua valendo a pena e
46
+ * continua sendo igualdade binaria sem limiar; o que NAO se pode afirmar e que "HTML com altura
47
+ * errada bloqueia aqui". Quem pega defeito de encaixe no canvas e o olho humano no checkpoint,
48
+ * e (divida 1) o `render-gate.cjs`.
49
+ *
50
+ * Uso (o motor passa o artefato da etapa como argv[2] — invariante runDir/artifacts/<step>.md):
51
+ * node scripts/veto-checks/render-png.cjs <artefato.md> \
52
+ * --html-dir <rel> --out-dir <rel> --width N --height N --expect N
53
+ *
54
+ * Exit 0 = `--expect` PNGs gerados, todos na dimensao exata.
55
+ * Exit 1 = VETO DE CONTEUDO: contagem de HTML != --expect, ou dimensao medida != pedida.
56
+ * Exit 2 = wiring/uso invalido: artefato inexistente, argumento ausente/invalido, dir
57
+ * resolvendo FORA do runDir, dir de HTML inexistente.
58
+ * Exit 3 = FAIL-LOUD de dependencia: Chrome ausente/invalido, ou falha ao renderizar/escrever.
59
+ * Qualquer exit != 0 vira `no()` no `evalVeto` => etapa BLOQUEADA => o checkpoint nao acontece.
60
+ */
61
+
62
+ const fs = require('node:fs');
63
+ const path = require('node:path');
64
+ const crypto = require('node:crypto');
65
+ const { execFileSync } = require('node:child_process');
66
+
67
+ // Reuso, nao extensao (Dev Notes da SF11.11): `render-gate.cjs` recebe UM html e mede overflow;
68
+ // este recebe o artefato da etapa e produz o entregavel. O que e comum e a SONDA de Chrome, e
69
+ // ela existe uma unica vez — duplicar seria arriscar duas doutrinas de fail-loud divergindo.
70
+ const { probeChrome } = require('./render-gate.cjs');
71
+
72
+ const BLOCK_BEGIN = '<!-- pc:entregavel-png:inicio -->';
73
+ const BLOCK_END = '<!-- pc:entregavel-png:fim -->';
74
+
75
+ const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
76
+
77
+ /** Erro de USO/WIRING (exit 2). Separado do fail-loud de dependencia (exit 3) por classe. */
78
+ class UsageError extends Error {}
79
+
80
+ // ---------------------------------------------------------------------------
81
+ // Funcoes puras (testaveis sem Chrome e sem disco).
82
+ // ---------------------------------------------------------------------------
83
+
84
+ /**
85
+ * Le a dimensao do IHDR de um buffer PNG. NAO usa heuristica: exige a assinatura PNG de 8 bytes
86
+ * e le os dois uint32 big-endian do IHDR. Buffer que nao e PNG => { ok:false } (nunca um palpite).
87
+ */
88
+ function readPngDimensions(buf) {
89
+ if (!Buffer.isBuffer(buf) || buf.length < 24) {
90
+ return { ok: false, reason: 'arquivo com menos de 24 bytes — nao ha IHDR para ler' };
91
+ }
92
+ if (!buf.subarray(0, 8).equals(PNG_SIGNATURE)) {
93
+ return { ok: false, reason: 'assinatura PNG ausente (os 8 primeiros bytes nao sao 89 50 4E 47 0D 0A 1A 0A)' };
94
+ }
95
+ if (buf.subarray(12, 16).toString('latin1') !== 'IHDR') {
96
+ return { ok: false, reason: 'primeiro chunk nao e IHDR — PNG malformado' };
97
+ }
98
+ return { ok: true, width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) };
99
+ }
100
+
101
+ /**
102
+ * Veredito de dimensao: IGUALDADE DE INTEIROS, os dois lados. Nenhuma tolerancia, nenhum
103
+ * `Math.abs`, nenhum `>=`/`<=` — 1 pixel de diferenca BLOQUEIA (ADR-018 `DF4-5`).
104
+ */
105
+ function dimensionMatches(measured, width, height) {
106
+ return measured.width === width && measured.height === height;
107
+ }
108
+
109
+ /**
110
+ * Veredito de cardinalidade: igualdade EXATA contra o conjunto declarado no `wf`. Nao e limiar
111
+ * (`--min`): pacote incompleto nao e pacote, e pacote com peca a mais tambem nao.
112
+ */
113
+ function countMatches(found, expect) {
114
+ return found === expect;
115
+ }
116
+
117
+ /** Parse dos args LITERAIS. Argumento ausente/invalido => UsageError (exit 2), nunca default. */
118
+ function parseArgs(argv) {
119
+ const o = { htmlDir: null, outDir: null, width: null, height: null, expect: null };
120
+ const int = (raw, flag) => {
121
+ const n = Number.parseInt(raw, 10);
122
+ if (!Number.isInteger(n) || n <= 0 || String(n) !== String(raw)) {
123
+ throw new UsageError(`${flag} exige um inteiro positivo (recebido: ${JSON.stringify(raw)})`);
124
+ }
125
+ return n;
126
+ };
127
+ for (let i = 0; i < argv.length; i++) {
128
+ switch (argv[i]) {
129
+ case '--html-dir': o.htmlDir = argv[++i]; break;
130
+ case '--out-dir': o.outDir = argv[++i]; break;
131
+ case '--width': o.width = int(argv[++i], '--width'); break;
132
+ case '--height': o.height = int(argv[++i], '--height'); break;
133
+ case '--expect': o.expect = int(argv[++i], '--expect'); break;
134
+ default:
135
+ throw new UsageError(`argumento desconhecido: ${JSON.stringify(argv[i])}`);
136
+ }
137
+ }
138
+ for (const [k, flag] of [['htmlDir', '--html-dir'], ['outDir', '--out-dir'], ['width', '--width'], ['height', '--height'], ['expect', '--expect']]) {
139
+ if (o[k] === null || o[k] === undefined) throw new UsageError(`argumento obrigatorio ausente: ${flag}`);
140
+ }
141
+ return o;
142
+ }
143
+
144
+ /**
145
+ * Resolve um dir de arg LITERAL relativo ao dir do artefato, exigindo contencao no runDir.
146
+ * Mesmo molde de `phash-gate.cjs:474-482` — um `wf` nao pode fazer este script ler/escrever
147
+ * fora do run que o invocou.
148
+ */
149
+ function resolveWithin(runDir, artDir, rel, label) {
150
+ const abs = path.resolve(artDir, rel);
151
+ const root = path.resolve(runDir);
152
+ if (abs !== root && !abs.startsWith(root + path.sep)) {
153
+ throw new UsageError(`${label} "${rel}" resolve FORA do runDir (${abs}) — recusado`);
154
+ }
155
+ return abs;
156
+ }
157
+
158
+ /** Lista os `.html` do dir (nao-recursivo), em ordem estavel por nome. */
159
+ function listHtml(dir) {
160
+ return fs.readdirSync(dir, { withFileTypes: true })
161
+ .filter((e) => e.isFile() && /\.html?$/i.test(e.name))
162
+ .map((e) => e.name)
163
+ .sort((a, b) => a.localeCompare(b, 'en'));
164
+ }
165
+
166
+ /** Bloco delimitado, humano-legivel e grep-avel, gravado no artefato da etapa. */
167
+ function renderBlock({ rows, width, height, outRel, chromeLabel, failures }) {
168
+ // ATENCAO: o bloco e escrito DENTRO do artefato da etapa, que continua sendo lido por outros
169
+ // vetos na mesma verificacao e nas retentativas. Nada aqui pode introduzir um caractere que
170
+ // outro veto do mesmo `wf` bane (ex.: travessao em/en-dash sob `lexical-check`), nem um
171
+ // heading que colida com a conformidade de template. Ha teste para isso.
172
+ const L = [BLOCK_BEGIN, '', '## Entregavel de publicacao (PNG): verificado por maquina', ''];
173
+ L.push(`Gerado e medido por \`render-png.cjs\` ANTES do checkpoint desta etapa (ADR-025). Dimensao exigida: ${width}x${height};`);
174
+ L.push(`destino: \`${outRel}\`; renderizador: ${chromeLabel}.`);
175
+ L.push('');
176
+ L.push('| Peca (PNG) | Dimensao medida (IHDR) | sha256 | Veredito |');
177
+ L.push('|---|---|---|---|');
178
+ for (const r of rows) {
179
+ const dim = r.measured.ok ? `${r.measured.width}x${r.measured.height}` : `ILEGIVEL (${r.measured.reason})`;
180
+ L.push(`| ${r.png} | ${dim} | ${r.sha256 || '-'} | ${r.verdict} |`);
181
+ }
182
+ L.push('');
183
+ if (failures.length > 0) {
184
+ L.push('### BLOQUEIO');
185
+ L.push('');
186
+ for (const f of failures) L.push(`- ${f}`);
187
+ L.push('');
188
+ }
189
+ L.push('### O que este bloco garante, e o que NAO garante (declarado, nao omitido)');
190
+ L.push('');
191
+ L.push(`- GARANTE: existem exatamente as pecas listadas, o Chrome renderizou cada uma, e a dimensao de cada PNG foi lida do IHDR`);
192
+ L.push(' do proprio arquivo e comparada por IGUALDADE de inteiros com o formato declarado no `wf`. Sem tolerancia, sem limiar.');
193
+ L.push('- NAO GARANTE: que a peca esteja bonita, que o texto tenha cabido, que o contraste preste ou que o encaixe copy x canvas');
194
+ L.push(' esteja bom. Isso e JULGAMENTO HUMANO no checkpoint (fronteira ADR-002). Overflow de layout tem script proprio');
195
+ L.push(' (`render-gate.cjs`) e NAO roda aqui.');
196
+ L.push('', BLOCK_END);
197
+ return L.join('\n');
198
+ }
199
+
200
+ /** Insere/SUBSTITUI o bloco no texto do artefato (idempotente entre retentativas da etapa). */
201
+ function upsertBlock(text, block) {
202
+ const b = text.indexOf(BLOCK_BEGIN);
203
+ const e = text.indexOf(BLOCK_END);
204
+ if (b >= 0 && e > b) return `${text.slice(0, b)}${block}${text.slice(e + BLOCK_END.length)}`;
205
+ return `${text.replace(/\s*$/, '')}\n\n${block}\n`;
206
+ }
207
+
208
+ /** Nome do PNG derivado do HTML (mesmo stem, extensao trocada). */
209
+ function pngNameFor(htmlName) {
210
+ return htmlName.replace(/\.html?$/i, '.png');
211
+ }
212
+
213
+ // ---------------------------------------------------------------------------
214
+ // Render (unico ponto que toca processo externo).
215
+ // ---------------------------------------------------------------------------
216
+
217
+ /**
218
+ * Renderiza UM html em PNG. Argumentos identicos aos medidos no `*assess` da SF11.11, cujo
219
+ * resultado foi byte-a-byte identico ao render manual de referencia (sha256 bf4e809d...9d01).
220
+ */
221
+ function renderOne(chromeBin, htmlAbs, pngAbs, width, height, timeoutMs) {
222
+ execFileSync(chromeBin, [
223
+ '--headless=new', '--disable-gpu', '--no-sandbox', '--hide-scrollbars',
224
+ '--force-device-scale-factor=1', `--window-size=${width},${height}`,
225
+ '--virtual-time-budget=4000', `--screenshot=${pngAbs}`, `file://${htmlAbs}`,
226
+ ], { encoding: 'utf8', timeout: timeoutMs, stdio: ['ignore', 'ignore', 'pipe'] });
227
+ }
228
+
229
+ const RENDER_TIMEOUT_MS = 60000;
230
+
231
+ function main() {
232
+ const artifact = process.argv[2];
233
+ if (!artifact || artifact.startsWith('--') || !fs.existsSync(artifact)) {
234
+ console.error(`render-png: artefato nao encontrado: ${artifact} (uso: render-png.cjs <artefato.md> ` +
235
+ '--html-dir <rel> --out-dir <rel> --width N --height N --expect N)');
236
+ process.exit(2);
237
+ }
238
+
239
+ let opts; let htmlAbsDir; let outAbsDir; let runDir;
240
+ try {
241
+ opts = parseArgs(process.argv.slice(3));
242
+ const artDir = path.dirname(path.resolve(artifact));
243
+ runDir = path.dirname(artDir); // invariante runDir/artifacts/<step>.md
244
+ htmlAbsDir = resolveWithin(runDir, artDir, opts.htmlDir, '--html-dir');
245
+ outAbsDir = resolveWithin(runDir, artDir, opts.outDir, '--out-dir');
246
+ if (!fs.existsSync(htmlAbsDir) || !fs.statSync(htmlAbsDir).isDirectory()) {
247
+ throw new UsageError(`--html-dir "${opts.htmlDir}" nao existe ou nao e diretorio (${htmlAbsDir})`);
248
+ }
249
+ } catch (e) {
250
+ if (e instanceof UsageError) {
251
+ console.error(`render-png: ${e.message}`);
252
+ process.exit(2);
253
+ }
254
+ throw e;
255
+ }
256
+
257
+ const { width, height, expect } = opts;
258
+
259
+ // ── (1) CARDINALIDADE — igualdade exata, antes de gastar Chrome.
260
+ let htmlFiles;
261
+ try {
262
+ htmlFiles = listHtml(htmlAbsDir);
263
+ } catch (e) {
264
+ console.error(`render-png: falha ao listar --html-dir (${htmlAbsDir}): ${e.message}`);
265
+ process.exit(2);
266
+ }
267
+ if (!countMatches(htmlFiles.length, expect)) {
268
+ console.error(`render-png BLOQUEOU: esperado EXATAMENTE ${expect} arquivo(s) .html em ${path.relative(runDir, htmlAbsDir) || '.'}, ` +
269
+ `encontrado(s) ${htmlFiles.length}${htmlFiles.length ? ` [${htmlFiles.join(', ')}]` : ''}. ` +
270
+ 'Pacote incompleto (ou com peca a mais) nao e pacote — nada foi renderizado.');
271
+ process.exit(1);
272
+ }
273
+
274
+ // ── (2) CHROME — fail-loud, sem fallback e sem escape hatch.
275
+ const chromeBin = probeChrome();
276
+ if (!chromeBin) {
277
+ console.error('render-png BLOQUEOU (fail-loud): headless Chrome nao encontrado. Instale google-chrome/chromium ' +
278
+ 'ou defina CHROME_BIN apontando para um binario valido. NAO existe modo degradado: sem render nao ha entregavel ' +
279
+ 'de publicacao, e entregar HTML no lugar seria aprovar um proxy do que se publica (ADR-025 DF-SF11.11-4).');
280
+ process.exit(3);
281
+ }
282
+
283
+ // ── (3) RENDER + MEDIDA. Falha de render = exit 3 (dependencia/ferramenta); dimensao errada
284
+ // = exit 1 (veto de conteudo). As classes nao se misturam: a causa fica legivel no run.
285
+ try {
286
+ fs.mkdirSync(outAbsDir, { recursive: true });
287
+ } catch (e) {
288
+ console.error(`render-png BLOQUEOU (fail-loud): nao foi possivel criar --out-dir (${outAbsDir}): ${e.message}`);
289
+ process.exit(3);
290
+ }
291
+
292
+ const rows = [];
293
+ const dimFailures = [];
294
+ for (const htmlName of htmlFiles) {
295
+ const htmlAbs = path.join(htmlAbsDir, htmlName);
296
+ const pngName = pngNameFor(htmlName);
297
+ const pngAbs = path.join(outAbsDir, pngName);
298
+ try {
299
+ fs.rmSync(pngAbs, { force: true }); // nunca medir o PNG da tentativa anterior
300
+ renderOne(chromeBin, htmlAbs, pngAbs, width, height, RENDER_TIMEOUT_MS);
301
+ } catch (e) {
302
+ const err = `${(e.stderr || '').toString().trim().split('\n').pop() || e.message}`;
303
+ console.error(`render-png BLOQUEOU (fail-loud): falha ao renderizar "${htmlName}" em ${chromeBin}: ${err}`);
304
+ process.exit(3);
305
+ }
306
+ if (!fs.existsSync(pngAbs)) {
307
+ console.error(`render-png BLOQUEOU (fail-loud): o Chrome saiu sem erro mas NAO escreveu o PNG de "${htmlName}" ` +
308
+ `(esperado em ${pngAbs}). Sem arquivo nao ha entregavel — bloqueando em vez de seguir.`);
309
+ process.exit(3);
310
+ }
311
+ const buf = fs.readFileSync(pngAbs);
312
+ const measured = readPngDimensions(buf);
313
+ if (!measured.ok) {
314
+ console.error(`render-png BLOQUEOU (fail-loud): "${pngName}" nao e um PNG legivel: ${measured.reason}.`);
315
+ process.exit(3);
316
+ }
317
+ const sha256 = crypto.createHash('sha256').update(buf).digest('hex');
318
+ const okDim = dimensionMatches(measured, width, height);
319
+ if (!okDim) {
320
+ dimFailures.push(`${pngName}: medido ${measured.width}x${measured.height}, exigido ${width}x${height} (origem: ${htmlName})`);
321
+ }
322
+ rows.push({ html: htmlName, png: pngName, measured, sha256, verdict: okDim ? 'OK' : 'DIMENSAO ERRADA' });
323
+ }
324
+
325
+ // ── (4) RASTRO no artefato (upsert idempotente), gravado tanto no verde quanto no bloqueio
326
+ // por dimensao: quem for consertar precisa ver o numero medido, nao so a mensagem do run.
327
+ const outRel = path.relative(runDir, outAbsDir) || '.';
328
+ const block = renderBlock({
329
+ rows, width, height, outRel,
330
+ chromeLabel: chromeBin.split('/').pop(),
331
+ failures: dimFailures,
332
+ });
333
+ try {
334
+ const raw = fs.readFileSync(path.resolve(artifact), 'utf8');
335
+ fs.writeFileSync(path.resolve(artifact), upsertBlock(raw, block), 'utf8');
336
+ } catch (e) {
337
+ console.error(`render-png: AVISO — gravacao do bloco no artefato falhou: ${e.message} ` +
338
+ '(o veredito abaixo NAO depende desta escrita)');
339
+ }
340
+
341
+ if (dimFailures.length > 0) {
342
+ console.error(`render-png BLOQUEOU: ${dimFailures.length} peca(s) fora de ${width}x${height} — ${dimFailures.join(' | ')}. ` +
343
+ 'Dimensao e igualdade de inteiros lida do IHDR do PNG gerado: nao ha tolerancia a ajustar.');
344
+ process.exit(1);
345
+ }
346
+
347
+ console.log(`render-png OK: ${rows.length} PNG(s) gerados em ${outRel}, todos ${width}x${height} por IHDR ` +
348
+ `(${rows.map((r) => `${r.png}=${r.sha256.slice(0, 12)}`).join(', ')}). Renderizador: ${chromeBin.split('/').pop()}.`);
349
+ process.exit(0);
350
+ }
351
+
352
+ if (require.main === module) main();
353
+
354
+ module.exports = {
355
+ readPngDimensions, dimensionMatches, countMatches, parseArgs, resolveWithin,
356
+ listHtml, renderBlock, upsertBlock, pngNameFor, UsageError,
357
+ BLOCK_BEGIN, BLOCK_END, PNG_SIGNATURE,
358
+ };