@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,170 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * smoke-sweep.test.cjs — suíte do SWEEP DE INJEÇÃO EXAUSTIVO (Story SF3.2, Decisão
5
+ * D.G3 / G-r2-2). Prova:
6
+ * - 3a por TODA etapa + 3b por TODA assertion, com derivação POR FORMA (violação
7
+ * mais forte) sobre o fixture das 5 formas (sweep-forms) → todas BLOQUEIAM (AC1/2).
8
+ * - UNDERIVABILIDADE como REGRA GERAL fail-loud: os 4 casos do DoD 3 (field_matches
9
+ * pattern universal; json_schema_valid sem required; section_exists não-ortogonal;
10
+ * count_gte n:0) → cada um NÃO produz blocked:true silencioso, NÃO é pulado, e
11
+ * devolve underivable (exit 1) com diagnóstico de assertion degenerada (AC3).
12
+ * - Report JSON com binding {workflow, pod, spec_hash} embutido; blocked:false ⇒
13
+ * ok:false (AC4). memoryPodDir ISOLADO: sweep não appenda learning na memória de
14
+ * produção do pod (AC4, caveat SF2.4).
15
+ *
16
+ * Node >= 18. Exit 0/1.
17
+ */
18
+
19
+ const fs = require('node:fs');
20
+ const os = require('node:os');
21
+ const path = require('node:path');
22
+ const crypto = require('node:crypto');
23
+ const { runSweep, deriveViolation, findNonMatchingValue, injectAndCheckBlock, SweepUnderivable } = require('./smoke-pod-workflow.cjs');
24
+
25
+ let passed = 0;
26
+ const failures = [];
27
+ function ok(cond, label) {
28
+ if (cond) { passed++; console.log(`[OK ] ${label}`); }
29
+ else { failures.push(label); console.log(`[FALHA] ${label}`); }
30
+ }
31
+
32
+ const FORMS_DIR = path.join(__dirname, '__fixtures__', 'sweep-forms');
33
+ const FORMS_WF = path.join(FORMS_DIR, 'workflows', 'wf-forms.yaml');
34
+ const FORMS_SMOKE = path.join(FORMS_DIR, 'workflows', 'wf-forms.smoke.json');
35
+ const FORMS_SPEC = path.join(FORMS_DIR, 'specs', 'wf-forms.spec.json');
36
+ const sha256File = (p) => crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex');
37
+
38
+ // ===========================================================================
39
+ // AC1/AC2/AC4 — sweep das 5 formas: todas bloqueiam, report com binding.
40
+ // ===========================================================================
41
+ const scenario = JSON.parse(fs.readFileSync(FORMS_SMOKE, 'utf8'));
42
+ const res = runSweep({ workflowPath: FORMS_WF, podRoot: FORMS_DIR, scenario, specPath: FORMS_SPEC });
43
+
44
+ ok(res.ok === true && res.underivable === null, 'AC1/2 sweep-forms VERDE — todas as provas bloquearam, zero underivável');
45
+ ok(res.report.proofs.length === 9, `AC1/2 nº de provas = 9 (4×3a + 5×3b); obtido ${res.report.proofs.length}`);
46
+ ok(res.report.proofs.every((p) => p.blocked === true), 'AC1/2 toda prova blocked:true (nenhum vazamento)');
47
+
48
+ const forms3b = res.report.proofs.filter((p) => /^\d+:/.test(p.assertion)).map((p) => p.assertion.split(':')[1]);
49
+ for (const form of ['field_matches', 'count_gte', 'section_exists', 'file_referenced_exists', 'json_schema_valid']) {
50
+ ok(forms3b.includes(form), `AC2 3b cobre a forma "${form}"`);
51
+ }
52
+ const step3a = res.report.proofs.filter((p) => p.assertion.startsWith('__template__')).map((p) => p.step);
53
+ for (const s of ['s_field', 's_count', 's_section', 's_fileref']) {
54
+ ok(step3a.includes(s), `AC1 3a cobre a etapa "${s}" (seção obrigatória removida)`);
55
+ }
56
+
57
+ // Report com binding embutido (AC4) — spec_hash = sha256 da SPEC (não do wf).
58
+ ok(res.report.workflow === 'wf-forms' && res.report.pod === 'sweep-forms', 'AC4 report embute {workflow, pod}');
59
+ ok(res.report.spec_hash === sha256File(FORMS_SPEC), 'AC4 report.spec_hash = sha256(spec) — binding A.1 fecha o forward-compat da SF3.1');
60
+ ok(res.report.proofs.every((p) => typeof p.step === 'string' && 'assertion' in p && typeof p.blocked === 'boolean'),
61
+ 'AC4 cada prova é {step, assertion, blocked}');
62
+
63
+ // memoryPodDir ISOLADO (AC4 / caveat SF2.4): sweep NÃO cria memória no pod real.
64
+ ok(!fs.existsSync(path.join(FORMS_DIR, 'memory')),
65
+ 'AC4 sweep NÃO appendou learning sintético na memória de produção do pod (memoryPodDir isolado)');
66
+
67
+ // ===========================================================================
68
+ // AC3 — UNDERIVABILIDADE: os 4 casos do DoD 3, cada um fail-loud (não blocked:true).
69
+ // ===========================================================================
70
+ function mkPod(caseName, { templateBody, assertion, artifact }) {
71
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `pc-underiv-${caseName}-`));
72
+ fs.mkdirSync(path.join(dir, 'workflows'), { recursive: true });
73
+ fs.mkdirSync(path.join(dir, 'templates'), { recursive: true });
74
+ fs.writeFileSync(path.join(dir, 'templates', 't.md'), templateBody);
75
+ const wf = [
76
+ 'state_machine:',
77
+ ' states: [init, running, complete, failed]',
78
+ ' initial: init',
79
+ ' terminal: [complete, failed]',
80
+ 'steps:',
81
+ ' - id: s1',
82
+ ' agent: a1',
83
+ ' template: templates/t.md',
84
+ ' inputs: [x]',
85
+ ' outputs: [y]',
86
+ ' depends_on: []',
87
+ ' checkpoint: null',
88
+ ' veto:',
89
+ ' assertions:',
90
+ ` - ${JSON.stringify(assertion)}`,
91
+ '',
92
+ ].join('\n');
93
+ const wfPath = path.join(dir, 'workflows', 'wf-u.yaml');
94
+ fs.writeFileSync(wfPath, wf);
95
+ return { dir, wfPath, scenario: { target_step: 's1', artifacts: { s1: artifact } } };
96
+ }
97
+
98
+ const underivCases = [
99
+ ['field-universal', {
100
+ templateBody: '## Sec\n', assertion: { type: 'field_matches', field: 'v', pattern: '.*' },
101
+ artifact: '## Sec\nv: qualquer coisa\n', diag: /universal|sempre-true/i,
102
+ }],
103
+ ['json-no-required', {
104
+ templateBody: '', assertion: { type: 'json_schema_valid', schema: [] },
105
+ artifact: '{"a": 1}', diag: /required|degenerada|parse-error/i,
106
+ }],
107
+ ['section-nonorthogonal', {
108
+ templateBody: '## Body\n', assertion: { type: 'section_exists', section: '## Body' },
109
+ artifact: '## Body\nx\n', diag: /não-ortogonal|template/i,
110
+ }],
111
+ ['count-zero', {
112
+ templateBody: '## S\n', assertion: { type: 'count_gte', field: 'S', n: 0 },
113
+ artifact: '## S\n- a\n', diag: /degenerada|0>=0|n:0/i,
114
+ }],
115
+ ];
116
+
117
+ for (const [name, spec] of underivCases) {
118
+ const { dir, wfPath, scenario: sc } = mkPod(name, spec);
119
+ const r = runSweep({ workflowPath: wfPath, podRoot: dir, scenario: sc });
120
+ ok(r.ok === false && r.underivable != null, `AC3 [${name}] → underivável fail-loud (ok:false)`);
121
+ ok(spec.diag.test(r.underivable.reason), `AC3 [${name}] diagnóstico de assertion degenerada/não-ortogonal ("${(r.underivable.reason || '').slice(0, 60)}…")`);
122
+ // anti-fallback + anti-skip: a assertion underivável NÃO virou blocked:true silencioso.
123
+ const leaked3b = (r.report.proofs || []).some((p) => /^\d+:/.test(p.assertion) && p.blocked === true);
124
+ ok(!leaked3b, `AC3 [${name}] anti-fallback: assertion underivável NÃO produziu blocked:true silencioso nem foi pulada`);
125
+ fs.rmSync(dir, { recursive: true, force: true });
126
+ }
127
+
128
+ // ===========================================================================
129
+ // AC4 — blocked:false ⇒ ok:false (agregação fail-loud). Costura blockChecker:
130
+ // prova o CONTRATO de vazamento (a enforcement real já foi provada acima).
131
+ // ===========================================================================
132
+ const leakRes = runSweep({
133
+ workflowPath: FORMS_WF, podRoot: FORMS_DIR, scenario, specPath: FORMS_SPEC,
134
+ blockChecker: (cfg, stepId) => stepId !== 's_json', // s_json "vaza" (não bloqueia)
135
+ });
136
+ ok(leakRes.ok === false && Array.isArray(leakRes.leaked) && leakRes.leaked.length >= 1,
137
+ 'AC4 uma prova blocked:false ⇒ sweep ok:false com leaked[] populado (motor sabotado ⇒ exit 1)');
138
+ ok(leakRes.leaked.every((l) => l.step === 's_json'),
139
+ 'AC4 leaked[] nomeia exatamente a prova que vazou');
140
+
141
+ // ===========================================================================
142
+ // Unidade — findNonMatchingValue e deriveViolation (regra geral, não switch fechado).
143
+ // ===========================================================================
144
+ ok(findNonMatchingValue('.*').ok === false, 'unidade: findNonMatchingValue(".*") = universal (sem valor violador)');
145
+ ok(findNonMatchingValue('[\\s\\S]*').ok === false, 'unidade: findNonMatchingValue("[\\s\\S]*") = universal');
146
+ ok(findNonMatchingValue('^(ok|fail)$').ok === true, 'unidade: findNonMatchingValue("^(ok|fail)$") acha valor fora do pattern');
147
+ let threw = false;
148
+ try { deriveViolation({ type: 'tipo_inexistente' }, '', '', FORMS_DIR); } catch (e) { threw = e instanceof SweepUnderivable; }
149
+ ok(threw, 'unidade: forma desconhecida ⇒ SweepUnderivable (Art. IV: PARA, não inventa 6ª regra)');
150
+
151
+ // ===========================================================================
152
+ // KILL-TEST PERMANENTE (finding QA #1) — o drive ISOLA a CLASSE de bloqueio: um
153
+ // deriver que regredisse emitindo a violação da CLASSE ERRADA NÃO conta como blocked.
154
+ // s_field/veto_violation quebra o VETO (status fora do pattern); s_field/template_violation
155
+ // quebra a FORMA (sem `## Meta`). Se o expectClass não confere, blocked=false (pega o green-falso).
156
+ // ===========================================================================
157
+ // memoryPodDir ISOLADO também no kill-test (o drive é real; sem isso poluiria a memória do fixture).
158
+ const cfgKill = { workflowPath: FORMS_WF, podRoot: FORMS_DIR, pod: 'sweep-forms', workflow: 'wf-forms', scenario, memoryPodDir: fs.mkdtempSync(path.join(os.tmpdir(), 'pc-kill-mem-')) };
159
+ const vetoViol = '## Meta\nstatus: fora-do-pattern\n'; // quebra SÓ o veto (forma presente)
160
+ const tmplViol = 'status: ok\n'; // quebra SÓ a forma (## Meta ausente, veto passa)
161
+ ok(injectAndCheckBlock(cfgKill, 's_field', vetoViol, 'veto') === true, 'kill-test: violação de VETO com expectClass=veto → blocked (classe certa)');
162
+ ok(injectAndCheckBlock(cfgKill, 's_field', vetoViol, 'template') === false, 'kill-test: violação de VETO rotulada como 3a (expectClass=template) → NÃO conta como blocked (classe errada pega)');
163
+ ok(injectAndCheckBlock(cfgKill, 's_field', tmplViol, 'template') === true, 'kill-test: violação de FORMA com expectClass=template → blocked (classe certa)');
164
+ ok(injectAndCheckBlock(cfgKill, 's_field', tmplViol, 'veto') === false, 'kill-test: violação de FORMA rotulada como 3b (expectClass=veto) → NÃO conta como blocked (deriver 3b regredido é pego)');
165
+
166
+ // ===========================================================================
167
+ console.log(`\n${passed} asserções OK; ${failures.length} falha(s).`);
168
+ if (failures.length) { for (const f of failures) console.error(` ✗ ${f}`); process.exit(1); }
169
+ console.log('smoke-sweep: sweep exaustivo + underivabilidade fail-loud provados.');
170
+ process.exit(0);
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * validate-adopt.js — teste E2E do comando `power-claude adopt`.
5
+ *
6
+ * Monta um tmpdir simulando uma instalação FEITA À MÃO (sem manifest):
7
+ * - alguns arquivos idênticos ao template,
8
+ * - alguns modificados,
9
+ * - alguns ausentes,
10
+ * - um arquivo só do usuário (fora do template).
11
+ * Roda `node bin/cli.js adopt --yes` e verifica o manifest gerado, a não
12
+ * destrutividade e a composição com `update` (modificados preservados).
13
+ *
14
+ * Node >= 18, sem dependências externas.
15
+ */
16
+
17
+ const fs = require('node:fs');
18
+ const os = require('node:os');
19
+ const path = require('node:path');
20
+ const { spawnSync } = require('node:child_process');
21
+
22
+ const { walkFiles } = require('../installer/util');
23
+ const { sha256OfFile } = require('../installer/manifest');
24
+
25
+ const REPO_ROOT = path.resolve(__dirname, '..');
26
+ const CLI = path.join(REPO_ROOT, 'bin', 'cli.js');
27
+ const TEMPLATE_DIR = path.join(REPO_ROOT, 'template');
28
+
29
+ const results = [];
30
+ function check(label, ok, detail) {
31
+ results.push({ label, ok, detail });
32
+ console.log(`[${ok ? 'OK ' : 'FALHA'}] ${label}${detail ? ` — ${detail}` : ''}`);
33
+ return ok;
34
+ }
35
+
36
+ function cp(src, dest) {
37
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
38
+ fs.copyFileSync(src, dest);
39
+ }
40
+
41
+ function readManifest(tmpdir) {
42
+ try {
43
+ return JSON.parse(fs.readFileSync(path.join(tmpdir, '.power-claude', 'manifest.json'), 'utf8'));
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ function main() {
50
+ console.log('POWER CLAUDE — validate-adopt (E2E)\n');
51
+
52
+ const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'power-claude-adopt-e2e-'));
53
+ console.log(`Diretório de teste: ${tmpdir}\n`);
54
+
55
+ try {
56
+ const templateFiles = walkFiles(TEMPLATE_DIR); // rels POSIX
57
+
58
+ // Escolhe 3 arquivos-fonte estáveis para os 3 papéis do fixture.
59
+ const IDENTICAL_REL = '.claude/CLAUDE.md';
60
+ const MODIFIED_REL = 'pods/README.md';
61
+ // Ausente: um arquivo real do template que NÃO criaremos no disco.
62
+ const ABSENT_REL = '.claude/hooks/enforce-git-push-authority.cjs';
63
+ for (const [name, rel] of [
64
+ ['IDENTICAL', IDENTICAL_REL],
65
+ ['MODIFIED', MODIFIED_REL],
66
+ ['ABSENT', ABSENT_REL],
67
+ ]) {
68
+ if (!templateFiles.includes(rel)) {
69
+ check(`fixture: ${name} (${rel}) existe no template`, false, 'arquivo-âncora sumiu do template');
70
+ finish(tmpdir);
71
+ return;
72
+ }
73
+ }
74
+
75
+ // Copia TODOS os arquivos do template para o disco (instalação à mão),
76
+ // EXCETO o ABSENT_REL. Modifica o MODIFIED_REL. IDENTICAL_REL fica igual.
77
+ for (const rel of templateFiles) {
78
+ if (rel === ABSENT_REL) continue;
79
+ const src = path.join(TEMPLATE_DIR, ...rel.split('/'));
80
+ const dest = path.join(tmpdir, ...rel.split('/'));
81
+ cp(src, dest);
82
+ }
83
+ // Modifica o MODIFIED_REL (append de conteúdo do usuário).
84
+ const modifiedPath = path.join(tmpdir, ...MODIFIED_REL.split('/'));
85
+ const modifiedContent = fs.readFileSync(modifiedPath, 'utf8') + '\n<!-- edição manual do usuário -->\n';
86
+ fs.writeFileSync(modifiedPath, modifiedContent, 'utf8');
87
+ const modifiedUserHash = sha256OfFile(modifiedPath);
88
+ const templateModifiedHash = sha256OfFile(path.join(TEMPLATE_DIR, ...MODIFIED_REL.split('/')));
89
+
90
+ // Arquivo SÓ do usuário, fora do template — nunca deve ser tocado.
91
+ const USER_ONLY_REL = 'docs/minhas-notas.md';
92
+ const userOnlyPath = path.join(tmpdir, ...USER_ONLY_REL.split('/'));
93
+ const userOnlyContent = '# Notas do usuário\nconteúdo intocável\n';
94
+ fs.mkdirSync(path.dirname(userOnlyPath), { recursive: true });
95
+ fs.writeFileSync(userOnlyPath, userOnlyContent, 'utf8');
96
+ const userOnlyHash = sha256OfFile(userOnlyPath);
97
+
98
+ // Scripts do motor (ADR-007) — fora do template, vêm do pacote. Monta 3 papéis:
99
+ // idêntico = pod-memory.cjs (cópia byte-idêntica do pacote)
100
+ // modificado= watcher-audit.cjs (cópia + edição do usuário)
101
+ // ausente = forge-generate.cjs (não criado no disco)
102
+ const MOTOR_IDENTICAL = 'scripts/pod-memory.cjs';
103
+ const MOTOR_MODIFIED = 'scripts/watcher-audit.cjs';
104
+ const MOTOR_ABSENT = 'scripts/forge-generate.cjs';
105
+ cp(path.join(REPO_ROOT, ...MOTOR_IDENTICAL.split('/')), path.join(tmpdir, ...MOTOR_IDENTICAL.split('/')));
106
+ const motorModPath = path.join(tmpdir, ...MOTOR_MODIFIED.split('/'));
107
+ cp(path.join(REPO_ROOT, ...MOTOR_MODIFIED.split('/')), motorModPath);
108
+ fs.writeFileSync(motorModPath, fs.readFileSync(motorModPath, 'utf8') + '\n// edição do usuário\n', 'utf8');
109
+ const motorModUserHash = sha256OfFile(motorModPath);
110
+ const motorPkgHash = sha256OfFile(path.join(REPO_ROOT, ...MOTOR_MODIFIED.split('/')));
111
+
112
+ // Sem manifest no disco (instalação à mão).
113
+ check('fixture sem manifest antes do adopt', !fs.existsSync(path.join(tmpdir, '.power-claude', 'manifest.json')));
114
+
115
+ // 1. adopt --yes
116
+ const adopt = spawnSync(process.execPath, [CLI, 'adopt', '--yes'], {
117
+ cwd: tmpdir,
118
+ encoding: 'utf8',
119
+ timeout: 120000,
120
+ });
121
+ const ok = check('adopt --yes termina com exit 0', adopt.status === 0, `exit ${adopt.status}`);
122
+ if (!ok) {
123
+ console.error('\n--- stdout ---\n' + (adopt.stdout || ''));
124
+ console.error('\n--- stderr ---\n' + (adopt.stderr || ''));
125
+ finish(tmpdir);
126
+ return;
127
+ }
128
+
129
+ const manifest = readManifest(tmpdir);
130
+ check('.power-claude/manifest.json parseia', manifest !== null);
131
+ if (!manifest) {
132
+ finish(tmpdir);
133
+ return;
134
+ }
135
+ check('manifest tem version e installedAt', Boolean(manifest.version && manifest.installedAt));
136
+
137
+ const byPath = new Map(manifest.files.map((f) => [f.path, f]));
138
+
139
+ // Idêntico: rastreado com sha do disco (= template).
140
+ const idEntry = byPath.get(IDENTICAL_REL);
141
+ check(
142
+ 'idêntico rastreado com sha do template (sem flag)',
143
+ Boolean(idEntry) && !idEntry.origin && idEntry.sha256 === sha256OfFile(path.join(TEMPLATE_DIR, ...IDENTICAL_REL.split('/'))),
144
+ idEntry ? `origin=${idEntry.origin || 'none'}` : 'ausente'
145
+ );
146
+
147
+ // Modificado: rastreado COM flag e sha=baseline do template (faz o update preservar).
148
+ const modEntry = byPath.get(MODIFIED_REL);
149
+ check(
150
+ 'modificado rastreado com origin="modified"',
151
+ Boolean(modEntry) && modEntry.origin === 'modified',
152
+ modEntry ? `origin=${modEntry.origin}` : 'ausente'
153
+ );
154
+ check(
155
+ 'modificado usa baseline do template (sha != disco) → update preserva',
156
+ Boolean(modEntry) && modEntry.sha256 === templateModifiedHash && modEntry.sha256 !== modifiedUserHash
157
+ );
158
+
159
+ // Ausente: NÃO escrito e NÃO rastreado (declinado em --yes).
160
+ check('ausente NÃO foi escrito no disco', !fs.existsSync(path.join(tmpdir, ...ABSENT_REL.split('/'))));
161
+ check('ausente NÃO entrou no manifest (declinado em --yes)', !byPath.has(ABSENT_REL));
162
+
163
+ // Arquivo do usuário fora do template: intocado e fora do manifest.
164
+ check('arquivo só-do-usuário intocado', fs.existsSync(userOnlyPath) && sha256OfFile(userOnlyPath) === userOnlyHash);
165
+ check('arquivo só-do-usuário NÃO entrou no manifest', !byPath.has(USER_ONLY_REL));
166
+
167
+ // Não destrutivo: o modificado no disco continua com o conteúdo do usuário.
168
+ check(
169
+ 'adopt não sobrescreveu o arquivo modificado',
170
+ sha256OfFile(modifiedPath) === modifiedUserHash
171
+ );
172
+
173
+ // Scripts do motor: adopt classifica igual/modificado/ausente como o template.
174
+ const motorId = byPath.get(MOTOR_IDENTICAL);
175
+ check(
176
+ 'motor idêntico rastreado sem flag (sha do pacote)',
177
+ Boolean(motorId) && !motorId.origin && motorId.sha256 === sha256OfFile(path.join(REPO_ROOT, ...MOTOR_IDENTICAL.split('/'))),
178
+ motorId ? `origin=${motorId.origin || 'none'}` : 'ausente'
179
+ );
180
+ const motorMod = byPath.get(MOTOR_MODIFIED);
181
+ check(
182
+ 'motor modificado rastreado com origin="modified" e baseline do pacote → update preserva',
183
+ Boolean(motorMod) && motorMod.origin === 'modified' && motorMod.sha256 === motorPkgHash && motorMod.sha256 !== motorModUserHash
184
+ );
185
+ check('motor ausente NÃO entrou no manifest (declinado em --yes)', !byPath.has(MOTOR_ABSENT));
186
+ check('motor ausente NÃO foi escrito no disco', !fs.existsSync(path.join(tmpdir, ...MOTOR_ABSENT.split('/'))));
187
+
188
+ // 2. Re-adopt: detecta manifest e sai limpo sem alterar nada.
189
+ const manifestBefore = fs.readFileSync(path.join(tmpdir, '.power-claude', 'manifest.json'), 'utf8');
190
+ const readopt = spawnSync(process.execPath, [CLI, 'adopt', '--yes'], { cwd: tmpdir, encoding: 'utf8', timeout: 120000 });
191
+ check('re-adopt sai com exit 0 (manifest já existe)', readopt.status === 0, `exit ${readopt.status}`);
192
+ check('re-adopt orienta usar update', /update/.test(readopt.stdout || ''));
193
+ check(
194
+ 're-adopt não altera o manifest',
195
+ fs.readFileSync(path.join(tmpdir, '.power-claude', 'manifest.json'), 'utf8') === manifestBefore
196
+ );
197
+
198
+ // 3. Composição com update: modificado preservado; ausente instalado pelo update.
199
+ const update = spawnSync(process.execPath, [CLI, 'update', '--yes'], { cwd: tmpdir, encoding: 'utf8', timeout: 120000 });
200
+ check('update --yes após adopt termina com exit 0', update.status === 0, `exit ${update.status}`);
201
+ check(
202
+ 'update PRESERVOU o arquivo modificado pelo usuário',
203
+ sha256OfFile(modifiedPath) === modifiedUserHash
204
+ );
205
+ check(
206
+ 'update PRESERVOU o script do motor modificado (mesmo contrato do template)',
207
+ sha256OfFile(motorModPath) === motorModUserHash
208
+ );
209
+
210
+ // 4. doctor roda sobre a instalação adotada.
211
+ const doctor = spawnSync(process.execPath, [CLI, 'doctor'], { cwd: tmpdir, encoding: 'utf8', timeout: 120000 });
212
+ check('doctor executa na instalação adotada (exit 0 ou 1 determinístico)', doctor.status === 0 || doctor.status === 1, `exit ${doctor.status}`);
213
+ } finally {
214
+ finish(tmpdir);
215
+ }
216
+ }
217
+
218
+ function finish(tmpdir) {
219
+ try {
220
+ fs.rmSync(tmpdir, { recursive: true, force: true });
221
+ } catch (error) {
222
+ console.warn(`Aviso: falha ao limpar tmpdir ${tmpdir}: ${error.message}`);
223
+ }
224
+ const failed = results.filter((r) => !r.ok);
225
+ console.log(`\n${results.length - failed.length}/${results.length} checagens passaram.`);
226
+ if (failed.length > 0) {
227
+ console.error('E2E do adopt FALHOU:');
228
+ for (const f of failed) console.error(` - ${f.label}${f.detail ? ` (${f.detail})` : ''}`);
229
+ process.exit(1);
230
+ }
231
+ console.log('E2E do adopt verde.');
232
+ process.exit(0);
233
+ }
234
+
235
+ main();
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * validate-branding.js — gate de branding do POWER CLAUDE.
5
+ *
6
+ * Varre template/, bin/, installer/, README.md e docs/mecanismos/ procurando
7
+ * (case-insensitive) termos proibidos de frameworks/autores anteriores. Exit 1
8
+ * listando arquivo:linha de cada ocorrência; exit 0 = branding limpo.
9
+ *
10
+ * Escopo do gate (SF7.12): enforcement é por TOKEN de identidade (lista fechada
11
+ * abaixo) — a régua funcional-vs-gratuito de FRASES de contraste fica com
12
+ * revisão humana (heurística de frase seria frágil; decisão registrada na story).
13
+ *
14
+ * Node >= 18, sem dependências externas.
15
+ */
16
+
17
+ const fs = require('node:fs');
18
+ const path = require('node:path');
19
+
20
+ const REPO_ROOT = path.resolve(__dirname, '..');
21
+ const SCAN_TARGETS = ['template', 'bin', 'installer', 'README.md', 'docs/mecanismos'];
22
+ const FORBIDDEN_TERMS = ['aiox', 'oalanicolas', 'alan nicolas', 'pedro-valerio', 'thiago_finch'];
23
+
24
+ function isProbablyBinary(buf) {
25
+ const sample = buf.subarray(0, 8000);
26
+ return sample.includes(0);
27
+ }
28
+
29
+ function collectFiles(target) {
30
+ const full = path.join(REPO_ROOT, target);
31
+ if (!fs.existsSync(full)) return [];
32
+ const stat = fs.statSync(full);
33
+ if (stat.isFile()) return [full];
34
+ const out = [];
35
+ const stack = [full];
36
+ while (stack.length > 0) {
37
+ const dir = stack.pop();
38
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
39
+ const p = path.join(dir, entry.name);
40
+ if (entry.isDirectory()) stack.push(p);
41
+ else if (entry.isFile()) out.push(p);
42
+ }
43
+ }
44
+ return out.sort();
45
+ }
46
+
47
+ function scanFile(filePath) {
48
+ const buf = fs.readFileSync(filePath);
49
+ if (isProbablyBinary(buf)) return [];
50
+ const violations = [];
51
+ const lines = buf.toString('utf8').split(/\r?\n/);
52
+ lines.forEach((line, idx) => {
53
+ const lower = line.toLowerCase();
54
+ for (const term of FORBIDDEN_TERMS) {
55
+ if (lower.includes(term)) {
56
+ violations.push({ line: idx + 1, term, text: line.trim() });
57
+ }
58
+ }
59
+ });
60
+ return violations;
61
+ }
62
+
63
+ function main() {
64
+ let total = 0;
65
+ for (const target of SCAN_TARGETS) {
66
+ for (const filePath of collectFiles(target)) {
67
+ const rel = path.relative(REPO_ROOT, filePath);
68
+ for (const v of scanFile(filePath)) {
69
+ total++;
70
+ console.error(`${rel}:${v.line}: termo proibido "${v.term}" — ${v.text.slice(0, 100)}`);
71
+ }
72
+ }
73
+ }
74
+ if (total > 0) {
75
+ console.error(`\n${total} ocorrência(s) de branding proibido. Gate vermelho.`);
76
+ process.exit(1);
77
+ }
78
+ console.log('Branding limpo.');
79
+ process.exit(0);
80
+ }
81
+
82
+ module.exports = { FORBIDDEN_TERMS, SCAN_TARGETS };
83
+
84
+ if (require.main === module) main();
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * validate-budgets.js — gate de orçamento de ativação dos agentes de pod.
4
+ *
5
+ * Percorre pods/<pod>/agents/<agente>.md, parseia o frontmatter e valida:
6
+ * (a) budget_tokens declarado
7
+ * (b) tokens estimados (bytes/4) <= budget_tokens declarado
8
+ * (c) tokens estimados <= teto global (1500)
9
+ * (d) arquivo <= 150 linhas
10
+ *
11
+ * Exit 0 com tabela de status; exit 1 listando cada violação.
12
+ * Node >= 18, sem dependências externas.
13
+ */
14
+ 'use strict';
15
+
16
+ const fs = require('node:fs');
17
+ const path = require('node:path');
18
+
19
+ const REPO_ROOT = path.resolve(__dirname, '..');
20
+ // Diretórios a varrer: args CLI (1+) > env PODS_DIR > defaults (./pods e ./.claude/agents).
21
+ // Cada diretório pode ter layout de pods (<dir>/<pod>/agents/*.md) ou flat (<dir>/*.md).
22
+ // Ex.: `node scripts/validate-budgets.js template/pods template/.claude/agents` no repo do framework.
23
+ const argDirs = process.argv.slice(2);
24
+ const defaultDirs = [
25
+ process.env.PODS_DIR || path.join(REPO_ROOT, 'pods'),
26
+ path.join(REPO_ROOT, '.claude', 'agents'),
27
+ ];
28
+ const SCAN_DIRS = (argDirs.length ? argDirs : defaultDirs)
29
+ .map((d) => path.resolve(d))
30
+ .filter((d) => fs.existsSync(d));
31
+ const GLOBAL_TOKEN_CAP = 1500;
32
+ const MAX_LINES = 150;
33
+
34
+ function parseFrontmatter(content) {
35
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
36
+ if (!match) return null;
37
+ const fields = {};
38
+ for (const line of match[1].split(/\r?\n/)) {
39
+ const kv = line.match(/^([A-Za-z_][\w-]*):\s*(.*)$/);
40
+ if (kv) fields[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, '');
41
+ }
42
+ return fields;
43
+ }
44
+
45
+ function collectAgentFiles() {
46
+ const files = [];
47
+ for (const dir of SCAN_DIRS) {
48
+ let flat = false;
49
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
50
+ if (entry.isFile() && entry.name.endsWith('.md') && entry.name !== 'README.md') {
51
+ files.push(path.join(dir, entry.name));
52
+ flat = true;
53
+ }
54
+ }
55
+ if (flat) continue; // layout flat (ex.: .claude/agents)
56
+ for (const pod of fs.readdirSync(dir, { withFileTypes: true })) {
57
+ if (!pod.isDirectory()) continue;
58
+ const agentsDir = path.join(dir, pod.name, 'agents');
59
+ if (!fs.existsSync(agentsDir)) continue;
60
+ for (const entry of fs.readdirSync(agentsDir, { withFileTypes: true })) {
61
+ if (entry.isFile() && entry.name.endsWith('.md')) {
62
+ files.push(path.join(agentsDir, entry.name));
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return files.sort();
68
+ }
69
+
70
+ function validate(filePath) {
71
+ const content = fs.readFileSync(filePath, 'utf8');
72
+ const bytes = Buffer.byteLength(content, 'utf8');
73
+ const estTokens = Math.ceil(bytes / 4);
74
+ const lines = content.split(/\r?\n/).length;
75
+ const fm = parseFrontmatter(content);
76
+ const rel = path.relative(REPO_ROOT, filePath);
77
+ const name = (fm && fm.name) || path.basename(filePath, '.md');
78
+
79
+ const errors = [];
80
+ let budget = null;
81
+
82
+ if (!fm || !fm.budget_tokens) {
83
+ errors.push('budget_tokens nao declarado no frontmatter');
84
+ } else {
85
+ budget = Number.parseInt(fm.budget_tokens, 10);
86
+ if (!Number.isFinite(budget) || budget <= 0) {
87
+ errors.push(`budget_tokens invalido: "${fm.budget_tokens}"`);
88
+ budget = null;
89
+ } else if (estTokens > budget) {
90
+ errors.push(`excede o proprio budget: ~${estTokens} tokens > ${budget}`);
91
+ }
92
+ }
93
+ if (estTokens > GLOBAL_TOKEN_CAP) {
94
+ errors.push(`excede o teto global: ~${estTokens} tokens > ${GLOBAL_TOKEN_CAP}`);
95
+ }
96
+ if (lines > MAX_LINES) {
97
+ errors.push(`excede o limite de linhas: ${lines} > ${MAX_LINES}`);
98
+ }
99
+
100
+ return { name, rel, lines, estTokens, budget, errors };
101
+ }
102
+
103
+ function main() {
104
+ const files = collectAgentFiles();
105
+ if (files.length === 0) {
106
+ console.error(`Nenhum agente encontrado em: ${SCAN_DIRS.map((d) => path.relative(REPO_ROOT, d)).join(', ') || '(nenhum diretório existente)'}`);
107
+ process.exit(1);
108
+ }
109
+
110
+ const results = files.map(validate);
111
+ const failed = results.filter((r) => r.errors.length > 0);
112
+
113
+ const headers = ['agente', 'linhas', 'tokens est.', 'budget', 'status'];
114
+ const rows = results.map((r) => [
115
+ r.name,
116
+ String(r.lines),
117
+ String(r.estTokens),
118
+ r.budget === null ? '—' : String(r.budget),
119
+ r.errors.length === 0 ? 'OK' : 'FALHA',
120
+ ]);
121
+ const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((row) => row[i].length)));
122
+ const fmtRow = (row) => row.map((cell, i) => cell.padEnd(widths[i])).join(' | ');
123
+
124
+ console.log(fmtRow(headers));
125
+ console.log(widths.map((w) => '-'.repeat(w)).join('-|-'));
126
+ for (const row of rows) console.log(fmtRow(row));
127
+
128
+ if (failed.length > 0) {
129
+ console.error('\nVIOLACOES:');
130
+ for (const r of failed) {
131
+ for (const err of r.errors) console.error(` ${r.rel}: ${err}`);
132
+ }
133
+ console.error(`\n${failed.length} agente(s) reprovado(s) de ${results.length}.`);
134
+ process.exit(1);
135
+ }
136
+ console.log(`\n${results.length} agente(s) validado(s). Gate verde.`);
137
+ process.exit(0);
138
+ }
139
+
140
+ main();