@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,243 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * harness-g5-lite.cjs — HARNESS DE PARIDADE G5-LITE (Story SF3.2, item h; ADR-006
5
+ * Decisão 2). Empacota, como FUNÇÃO/COMANDO reusável, o nível LITE de paridade que
6
+ * SF3.4 (piloto) vai invocar sobre `wf-money-model-design` sem reinventar sob pressão.
7
+ *
8
+ * LITE corta SÓ a repetição estatística — nunca a prova de bloqueio (integral nos dois
9
+ * níveis). Três etapas, todas obrigatórias:
10
+ * (1) VALIDADOR ESTÁTICO + smoke `--sweep` COMPLETO (idêntico ao FULL: prova integral
11
+ * de que ESTE dado trava o caminho errado).
12
+ * (2) G5(a) reduzido: N=2 runs — conformidade 100% + DAG monotônico em AMBAS; SEM
13
+ * estatística de variância (invariante do motor, provado na âncora).
14
+ * (3) G5(b): 1 par lado-a-lado (2ª run do pod vs 1 run do squad, mesma tarefa) —
15
+ * completude ≥ squad E conformidade ≥ squad são BLOQUEANTES; custo REGISTRADO
16
+ * sem critério de bloqueio (única dimensão dispensada, Daniel 2026-07-24).
17
+ *
18
+ * PROTOCOLO DE LEGADO INEXECUTÁVEL (M-r2-3): quando `waiver` está presente, a completude
19
+ * passa a ser comparada contra os artefatos DECLARADOS do legado (não contra uma run do
20
+ * squad que não existe) — o waiver pressupõe tentativa real registrada (validada pelo
21
+ * `migration-manifest.cjs waiver-set`, não aqui).
22
+ *
23
+ * ASSINATURA (para SF3.4 herdar sem arqueologia de código):
24
+ * runG5Lite({
25
+ * workflowPath, // abs: <pod>/workflows/wf-<id>.yaml
26
+ * podRoot, // abs: raiz do pod
27
+ * specPath, // abs: spec (spec_hash binding no sweep) — opcional
28
+ * scenarioPath, // abs: default <wf>.smoke.json
29
+ * squadArtifacts, // string[]: artefatos do lado SQUAD (par lado-a-lado)
30
+ * artifactMapPath, // abs: mapa artefato-a-artefato (yaml|json) — via para pods
31
+ * // CONSOLIDADOS vs squad GRANULAR (design §D/M1); ver artifactMap
32
+ * artifactMap, // [] inline: {squad_artifact, pod_output, section?, evidence?}
33
+ * // OU dispensa registrada: {squad_artifact, disposition:'dispensed',
34
+ * // approved_by, evidence} — sai de missing SÓ com approved_by
35
+ * squadConformance, // 0..1: conformidade do lado squad (default 1)
36
+ * waiver, // { declared_artifacts:[] } | null — compara completude
37
+ * // contra DECLARADOS quando o par squad não completa
38
+ * }) -> {
39
+ * static:{ok,failures[]}, sweep:{ok,proofs,spec_hash,reason?},
40
+ * runs:[{run,conformance,monotonic,complete}], // N=2
41
+ * pair:{podArtifacts[],squadArtifacts[],missing[],completeness_ok,conformance_ok,blocked,
42
+ * basis, map_path, mapped, unmapped[], dispensed[], sections_verified, warning},
43
+ * cost:{runs,steps,note}, // registrado, SEM bloqueio
44
+ * blocked, ok
45
+ * }
46
+ *
47
+ * COMPLETUDE POR TABELA (design §D/M1): com --artifact-map, cada artefato do squad
48
+ * precisa de ENTRADA no mapa cujo pod_output existe nos outputs do wf e cuja `section`
49
+ * (se declarada) EXISTE no artefato em disco da run 2 — mapping falso não passa. Sem
50
+ * mapa, completude estrita por identidade de nome (com aviso).
51
+ *
52
+ * Node >= 18. CLI exit 0 = ok && !blocked; 1 caso contrário.
53
+ */
54
+
55
+ const fs = require('node:fs');
56
+ const os = require('node:os');
57
+ const path = require('node:path');
58
+
59
+ const smoke = require('./smoke-pod-workflow.cjs');
60
+ const { parseYaml, validateWorkflow, podRootFor } = require('./validate-pod-workflow.cjs');
61
+
62
+ const N_RUNS = 2; // G5(a) reduzido: 2 runs (invariante do motor, sem variância estatística).
63
+
64
+ /** Métricas de conformidade/monotonia de UMA run já dirigida. */
65
+ function runMetrics(run) {
66
+ const steps = Object.values(run.disk.steps);
67
+ const done = steps.filter((s) => s.status === 'done').length;
68
+ const conformance = steps.length ? done / steps.length : 0;
69
+ const complete = run.final.action === 'complete';
70
+ // DAG monotônico: cada etapa concluída DEPOIS de suas dependências (a ordem em que o
71
+ // runner despachou == ordem topológica; run completa ⇒ nenhuma etapa fora de ordem).
72
+ const monotonic = complete && conformance === 1;
73
+ return { conformance, monotonic, complete };
74
+ }
75
+
76
+ /** Dirige UMA run do pod. Com `retain`, NÃO limpa (o caller inspeciona os artefatos
77
+ * em disco para verificar seções mapeadas) e devolve {run, memoryPodDir, cleanup}. */
78
+ function driveConformRun(cfg, retain) {
79
+ const memoryPodDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-g5lite-mem-'));
80
+ const run = smoke.driveRun({ ...cfg, inject: null, memoryPodDir });
81
+ const cleanup = () => {
82
+ try { fs.rmSync(run.runsRoot, { recursive: true, force: true }); } catch { /* best-effort */ }
83
+ try { fs.rmSync(memoryPodDir, { recursive: true, force: true }); } catch { /* best-effort */ }
84
+ };
85
+ if (retain) return { ...runMetrics(run), run, cleanup };
86
+ cleanup();
87
+ return runMetrics(run);
88
+ }
89
+
90
+ /** Carrega o mapa de artefatos (yaml|json): lista de {squad_artifact, pod_output, section?, evidence?}. */
91
+ function loadArtifactMap(p) {
92
+ const raw = fs.readFileSync(p, 'utf8');
93
+ let parsed;
94
+ try { parsed = JSON.parse(raw); } catch { parsed = parseYaml(raw); }
95
+ const entries = Array.isArray(parsed) ? parsed
96
+ : (parsed && Array.isArray(parsed.entries) ? parsed.entries
97
+ : (parsed && Array.isArray(parsed.map) ? parsed.map : null));
98
+ if (!entries) throw new Error(`artifact-map inválido (${p}): esperado lista de entradas ou {entries|map:[…]}`);
99
+ return entries;
100
+ }
101
+
102
+ /** Seção existe no artefato (heading trim-igual OU token presente) — mapping falso não passa. */
103
+ function sectionInText(text, section) {
104
+ const want = String(section).trim();
105
+ return text.split(/\r?\n/).some((l) => l.trim() === want) || text.includes(want);
106
+ }
107
+
108
+ function runG5Lite(opts) {
109
+ const workflowPath = path.resolve(opts.workflowPath);
110
+ const podRoot = opts.podRoot ? path.resolve(opts.podRoot) : podRootFor(workflowPath);
111
+ const scenarioPath = opts.scenarioPath ? path.resolve(opts.scenarioPath) : workflowPath.replace(/\.ya?ml$/, '.smoke.json');
112
+ const specPath = opts.specPath ? path.resolve(opts.specPath) : null;
113
+ const doc = parseYaml(fs.readFileSync(workflowPath, 'utf8'));
114
+ const pod = path.basename(podRoot);
115
+ const workflow = path.basename(workflowPath).replace(/\.ya?ml$/, '');
116
+ const scenario = JSON.parse(fs.readFileSync(scenarioPath, 'utf8'));
117
+ const cfg = { workflowPath, podRoot, pod, workflow, scenario };
118
+
119
+ // ---- (1) ESTÁTICO + SWEEP COMPLETO ---------------------------------------
120
+ const staticRes = { ok: true, failures: [] };
121
+ try { validateWorkflow(workflowPath, podRoot); }
122
+ catch (e) { staticRes.ok = false; staticRes.failures.push(e.message); }
123
+ const sweepRaw = smoke.runSweep({ workflowPath, podRoot, scenario, specPath });
124
+ const sweep = {
125
+ ok: sweepRaw.ok && !sweepRaw.underivable,
126
+ proofs: sweepRaw.report.proofs.length,
127
+ spec_hash: sweepRaw.report.spec_hash,
128
+ reason: sweepRaw.underivable ? sweepRaw.underivable.reason
129
+ : (sweepRaw.leaked && sweepRaw.leaked.length ? `vazou: ${sweepRaw.leaked.map((l) => `${l.step}/${l.assertion}`).join(', ')}` : null),
130
+ };
131
+
132
+ // ---- (2) N=2 RUNS: conformidade 100% + DAG monotônico em AMBAS -----------
133
+ // Run 1 descartável; run 2 RETIDA (é o lado "pod" do par — seus artefatos em disco
134
+ // são a fonte da verificação de CONTEÚDO das seções mapeadas).
135
+ const runs = [{ run: 1, ...driveConformRun(cfg) }];
136
+ const r2 = driveConformRun(cfg, true);
137
+ runs.push({ run: 2, conformance: r2.conformance, monotonic: r2.monotonic, complete: r2.complete });
138
+ const runsOk = runs.every((r) => r.conformance === 1 && r.monotonic);
139
+
140
+ // Texto em disco de cada output do wf (via a run 2 retida) — para verificar seções.
141
+ const outputText = {};
142
+ for (const s of doc.steps) {
143
+ const rel = r2.run.disk.steps[s.id] && r2.run.disk.steps[s.id].artifact;
144
+ const text = (rel && fs.existsSync(path.resolve(r2.run.ctx.runDir, rel)))
145
+ ? fs.readFileSync(path.resolve(r2.run.ctx.runDir, rel), 'utf8') : '';
146
+ for (const o of (Array.isArray(s.outputs) ? s.outputs : [])) outputText[o] = text;
147
+ }
148
+ r2.cleanup();
149
+
150
+ // ---- (3) 1 PAR LADO-A-LADO: completude ≥ squad (por TABELA) E conformidade ≥ squad ----
151
+ const podArtifacts = [...new Set(doc.steps.flatMap((s) => Array.isArray(s.outputs) ? s.outputs : []))].sort();
152
+ const basis = opts.waiver ? 'declared' : 'squad-run'; // M-r2-3: waiver ⇒ compara contra declarados.
153
+ const squadArtifacts = [...new Set(
154
+ (opts.waiver && Array.isArray(opts.waiver.declared_artifacts)) ? opts.waiver.declared_artifacts
155
+ : (opts.squadArtifacts || []),
156
+ )].sort();
157
+ const podConformance = runsOk ? 1 : (runs[runs.length - 1] || {}).conformance || 0;
158
+ const squadConformance = typeof opts.squadConformance === 'number' ? opts.squadConformance : 1;
159
+
160
+ // Completude POR TABELA artefato-a-artefato (design §D / M1): pod consolidado (3
161
+ // artefatos) vs squad granular (21) NÃO é identidade ingênua de nome — cada artefato
162
+ // do squad precisa de ENTRADA no mapa, com pod_output existente e (se `section`) a
163
+ // seção presente NO ARTEFATO em disco da run 2 (mapping falso não passa).
164
+ let missing = [];
165
+ const unmapped = [];
166
+ const dispensed = [];
167
+ let sections_verified = 0;
168
+ let warning = null;
169
+ const mapEntries = opts.artifactMap || (opts.artifactMapPath ? loadArtifactMap(path.resolve(opts.artifactMapPath)) : null);
170
+ const map_path = opts.artifactMapPath ? path.resolve(opts.artifactMapPath) : null;
171
+ if (mapEntries && squadArtifacts.length) {
172
+ for (const sa of squadArtifacts) {
173
+ const e = mapEntries.find((m) => m && m.squad_artifact === sa);
174
+ if (!e) { unmapped.push(sa); missing.push(sa); continue; } // sem entrada → missing
175
+ // DISPENSA registrada (decisão do Daniel): entregável fora do design (ex.: loop de
176
+ // USO pós-entrega) sai de missing SÓ com approved_by — dispensa não-registrada NÃO
177
+ // vale (bloqueia). Auditável em pair.dispensed[].
178
+ if (e.disposition === 'dispensed') {
179
+ if (!e.approved_by) { missing.push(sa); continue; } // dispensa sem aprovação → bloqueia
180
+ dispensed.push({ squad_artifact: sa, approved_by: e.approved_by, evidence: e.evidence || null });
181
+ continue;
182
+ }
183
+ if (!podArtifacts.includes(e.pod_output)) { missing.push(sa); continue; } // pod_output inexistente
184
+ if (e.section) {
185
+ if (!sectionInText(outputText[e.pod_output] || '', e.section)) { missing.push(sa); continue; } // anti-fake-mapping
186
+ sections_verified++;
187
+ }
188
+ }
189
+ } else {
190
+ // Sem --artifact-map: comportamento ESTRITO atual (identidade de nome) mantido.
191
+ missing = squadArtifacts.filter((a) => !podArtifacts.includes(a));
192
+ if (squadArtifacts.length) warning = 'sem --artifact-map: completude por identidade de nome (estrito); use a tabela artefato-a-artefato para pods consolidados vs squad granular';
193
+ }
194
+ const mapped = squadArtifacts.length - unmapped.length;
195
+ const completeness_ok = missing.length === 0;
196
+ const conformance_ok = podConformance >= squadConformance;
197
+ const pairBlocked = !completeness_ok || !conformance_ok;
198
+ const pair = { podArtifacts, squadArtifacts, missing, completeness_ok, conformance_ok, blocked: pairBlocked, basis, map_path, mapped, unmapped, dispensed, sections_verified, warning };
199
+
200
+ // ---- CUSTO: registrado, SEM critério de bloqueio (Daniel 2026-07-24) -----
201
+ const cost = { runs: N_RUNS + 1, steps: doc.steps.length * (N_RUNS + 1), note: 'registrado sem critério de bloqueio (única dimensão dispensada)' };
202
+
203
+ const blocked = !staticRes.ok || !sweep.ok || !runsOk || pairBlocked;
204
+ return { static: staticRes, sweep, runs, pair, cost, blocked, ok: !blocked };
205
+ }
206
+
207
+ // ---------------------------------------------------------------------------
208
+ // CLI.
209
+ // ---------------------------------------------------------------------------
210
+ function argVal(args, flag) { const i = args.indexOf(flag); return i >= 0 ? args[i + 1] : null; }
211
+ function argAll(args, flag) { const out = []; for (let i = 0; i < args.length; i++) if (args[i] === flag) out.push(args[i + 1]); return out; }
212
+
213
+ function main() {
214
+ const args = process.argv.slice(2);
215
+ const workflowPath = args[0];
216
+ if (!workflowPath || workflowPath.startsWith('--')) {
217
+ console.error('Uso: node scripts/harness-g5-lite.cjs <wf.yaml> [--pod-root <dir>] [--spec <spec>] [--squad-artifact <a> ...] [--artifact-map <path>] [--squad-conformance <0..1>] [--report <out.json>]');
218
+ process.exit(2);
219
+ }
220
+ const res = runG5Lite({
221
+ workflowPath,
222
+ podRoot: argVal(args, '--pod-root'),
223
+ specPath: argVal(args, '--spec'),
224
+ scenarioPath: argVal(args, '--scenario'),
225
+ squadArtifacts: argAll(args, '--squad-artifact'),
226
+ artifactMapPath: argVal(args, '--artifact-map'),
227
+ squadConformance: args.includes('--squad-conformance') ? Number(argVal(args, '--squad-conformance')) : undefined,
228
+ });
229
+ const reportPath = argVal(args, '--report');
230
+ if (reportPath) fs.writeFileSync(reportPath, JSON.stringify(res, null, 2));
231
+ console.log(`# G5-LITE — ${path.basename(workflowPath)}`);
232
+ console.log(`(1) estático=${res.static.ok ? 'OK' : 'FALHA'} · sweep=${res.sweep.ok ? `OK (${res.sweep.proofs} provas)` : 'FALHA'}${res.sweep.reason ? ' — ' + res.sweep.reason : ''}`);
233
+ console.log(`(2) N=${res.runs.length} runs — conformidade/monotonia: ${res.runs.map((r) => `run${r.run}=${(r.conformance * 100).toFixed(0)}%${r.monotonic ? '↑' : '✗'}`).join(', ')}`);
234
+ const mapNote = (res.pair.map_path || res.pair.dispensed.length) ? ` [tabela: ${res.pair.mapped}/${res.pair.squadArtifacts.length} mapeados, ${res.pair.sections_verified} seç. verif.${res.pair.dispensed.length ? ', dispensed=' + res.pair.dispensed.map((d) => d.squad_artifact).join(',') : ''}${res.pair.unmapped.length ? ', unmapped=' + res.pair.unmapped.join(',') : ''}]` : (res.pair.warning ? ' [identidade de nome — sem --artifact-map]' : '');
235
+ console.log(`(3) par [${res.pair.basis}] completude${res.pair.completeness_ok ? '≥' : '<'}squad conformidade${res.pair.conformance_ok ? '≥' : '<'}squad${res.pair.missing.length ? ' faltando=' + res.pair.missing.join(',') : ''}${mapNote} (BLOQUEANTE)`);
236
+ console.log(`custo: ${res.cost.runs} runs / ${res.cost.steps} etapas — ${res.cost.note}`);
237
+ console.log(res.ok ? '\nG5-LITE VERDE — paridade LITE satisfeita (prova de bloqueio integral, repetição estatística cortada).' : '\nG5-LITE BLOQUEADO.');
238
+ process.exit(res.ok ? 0 : 1);
239
+ }
240
+
241
+ if (require.main === module) main();
242
+
243
+ module.exports = { runG5Lite, N_RUNS, loadArtifactMap, sectionInText };
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * harness-g5-lite.test.cjs — suíte do HARNESS G5-LITE (Story SF3.2, AC8; ADR-006
5
+ * Decisão 2). Prova as 3 etapas + os bloqueios:
6
+ * (1) estático + sweep completo; (2) N=2 runs 100%/monotônico sem variância;
7
+ * (3) par lado-a-lado: completude≥squad E conformidade≥squad BLOQUEANTES, custo
8
+ * registrado SEM bloqueio; waiver ⇒ completude comparada contra DECLARADOS (M-r2-3).
9
+ *
10
+ * Node >= 18.
11
+ */
12
+
13
+ const fs = require('node:fs');
14
+ const os = require('node:os');
15
+ const path = require('node:path');
16
+ const { runG5Lite, N_RUNS } = require('./harness-g5-lite.cjs');
17
+
18
+ let passed = 0;
19
+ const failures = [];
20
+ function ok(cond, label) {
21
+ if (cond) { passed++; console.log(`[OK ] ${label}`); }
22
+ else { failures.push(label); console.log(`[FALHA] ${label}`); }
23
+ }
24
+
25
+ const FORMS = path.join(__dirname, '__fixtures__', 'sweep-forms');
26
+ const WF = path.join(FORMS, 'workflows', 'wf-forms.yaml');
27
+ const SPEC = path.join(FORMS, 'specs', 'wf-forms.spec.json');
28
+ const base = { workflowPath: WF, podRoot: FORMS, specPath: SPEC };
29
+
30
+ // --- Caminho verde: par cuja completude ⊆ pod, conformidade squad ≤ pod ---
31
+ const green = runG5Lite({ ...base, squadArtifacts: ['a_field', 'a_count'], squadConformance: 1 });
32
+ ok(green.ok === true && green.blocked === false, 'AC8 G5-LITE VERDE quando estático+sweep+2 runs+par passam');
33
+ ok(green.static.ok === true, 'AC8 (1) validador estático OK');
34
+ ok(green.sweep.ok === true && green.sweep.proofs === 9, 'AC8 (1) sweep COMPLETO (9 provas) — idêntico ao FULL');
35
+ ok(green.runs.length === N_RUNS && N_RUNS === 2, 'AC8 (2) N=2 runs (sem variância estatística)');
36
+ ok(green.runs.every((r) => r.conformance === 1 && r.monotonic), 'AC8 (2) conformidade 100% + DAG monotônico em AMBAS');
37
+ ok(green.pair.completeness_ok && green.pair.conformance_ok && green.pair.blocked === false, 'AC8 (3) par: completude≥squad E conformidade≥squad');
38
+ ok(green.cost && typeof green.cost.runs === 'number' && !('blocked' in green.cost), 'AC8 (3) custo REGISTRADO sem critério de bloqueio');
39
+
40
+ // --- BLOQUEIO por completude < squad (squad produziu artefato que o pod não tem) ---
41
+ const lessComplete = runG5Lite({ ...base, squadArtifacts: ['a_field', 'a_EXCLUSIVO_DO_SQUAD'], squadConformance: 1 });
42
+ ok(lessComplete.ok === false && lessComplete.pair.blocked === true, 'AC8 (3) completude < squad → BLOQUEIA');
43
+ ok(lessComplete.pair.missing.includes('a_EXCLUSIVO_DO_SQUAD'), 'AC8 (3) nomeia o artefato faltante (completude é BLOQUEANTE)');
44
+
45
+ // --- BLOQUEIO por conformidade < squad ---
46
+ const lessConform = runG5Lite({ ...base, squadArtifacts: ['a_field'], squadConformance: 1.5 });
47
+ ok(lessConform.ok === false && lessConform.pair.conformance_ok === false, 'AC8 (3) conformidade < squad → BLOQUEIA (conformidade é BLOQUEANTE)');
48
+
49
+ // --- WAIVER (M-r2-3): completude comparada contra os DECLARADOS do legado ---
50
+ const wv = runG5Lite({ ...base, waiver: { declared_artifacts: ['a_field', 'a_json'] } });
51
+ ok(wv.pair.basis === 'declared', 'AC8/M-r2-3 waiver presente ⇒ base de completude = artefatos DECLARADOS (não run do squad)');
52
+ ok(wv.ok === true && wv.pair.completeness_ok, 'AC8/M-r2-3 waiver: completude ⊇ declarados ⇒ passa');
53
+ const wvBlock = runG5Lite({ ...base, waiver: { declared_artifacts: ['a_field', 'a_DECLARADO_AUSENTE'] } });
54
+ ok(wvBlock.ok === false && wvBlock.pair.missing.includes('a_DECLARADO_AUSENTE'),
55
+ 'AC8/M-r2-3 waiver: declarado não coberto pelo pod → BLOQUEIA');
56
+
57
+ // ===========================================================================
58
+ // COMPLETUDE POR TABELA artefato-a-artefato (design §D/M1) — pod CONSOLIDADO (poucos
59
+ // outputs) vs squad GRANULAR: identidade ingênua de nome reprova sempre; o mapa resolve.
60
+ // wf-forms run2 em disco: a_field⇐"## Meta\nstatus: ok", a_count⇐"## Value Stack\n…\n## Notas".
61
+ // ===========================================================================
62
+ // (a) mapa COMPLETO + seções REAIS (verificadas em disco) → pass; sections_verified conta.
63
+ const mapOk = runG5Lite({ ...base,
64
+ squadArtifacts: ['sq-oferta', 'sq-preco', 'sq-stack'],
65
+ artifactMap: [
66
+ { squad_artifact: 'sq-oferta', pod_output: 'a_field', section: '## Meta', evidence: 'phase authoring' },
67
+ { squad_artifact: 'sq-preco', pod_output: 'a_count', section: '## Value Stack' },
68
+ { squad_artifact: 'sq-stack', pod_output: 'a_count', section: '## Notas' },
69
+ ] });
70
+ ok(mapOk.ok === true && mapOk.pair.completeness_ok, 'TABELA mapa completo + seções reais em disco → completude OK (consolidado vs granular resolvido)');
71
+ ok(mapOk.pair.mapped === 3 && mapOk.pair.sections_verified === 3 && mapOk.pair.unmapped.length === 0,
72
+ 'TABELA report auditável: mapped=3, sections_verified=3, unmapped=[]');
73
+
74
+ // (b) 1 squad artifact SEM entrada no mapa → missing (bloqueia); unmapped[] o nomeia.
75
+ const mapGap = runG5Lite({ ...base,
76
+ squadArtifacts: ['sq-oferta', 'sq-orfao'],
77
+ artifactMap: [{ squad_artifact: 'sq-oferta', pod_output: 'a_field' }] });
78
+ ok(mapGap.ok === false && mapGap.pair.missing.includes('sq-orfao') && mapGap.pair.unmapped.includes('sq-orfao'),
79
+ 'TABELA squad artifact SEM entrada no mapa → missing/unmapped (BLOQUEIA)');
80
+
81
+ // (c) mapa apontando seção INEXISTENTE → blocked (anti-fake-mapping: conteúdo em disco).
82
+ const mapFake = runG5Lite({ ...base,
83
+ squadArtifacts: ['sq-oferta'],
84
+ artifactMap: [{ squad_artifact: 'sq-oferta', pod_output: 'a_field', section: '## SECAO_QUE_NAO_EXISTE' }] });
85
+ ok(mapFake.ok === false && mapFake.pair.missing.includes('sq-oferta'),
86
+ 'TABELA anti-fake-mapping: seção declarada inexistente no artefato de disco → BLOQUEIA');
87
+
88
+ // (c2) mapa apontando pod_output inexistente no wf → blocked.
89
+ const mapBadOut = runG5Lite({ ...base,
90
+ squadArtifacts: ['sq-x'],
91
+ artifactMap: [{ squad_artifact: 'sq-x', pod_output: 'a_INEXISTENTE' }] });
92
+ ok(mapBadOut.ok === false && mapBadOut.pair.missing.includes('sq-x'),
93
+ 'TABELA pod_output inexistente nos outputs do wf → BLOQUEIA');
94
+
95
+ // (d) SEM --artifact-map com squadArtifacts → comportamento estrito atual + aviso.
96
+ const strict = runG5Lite({ ...base, squadArtifacts: ['a_field'] });
97
+ ok(strict.ok === true && strict.pair.map_path === null && /artifact-map/.test(strict.pair.warning || ''),
98
+ 'SEM mapa: completude estrita por identidade de nome mantida, com aviso apontando a tabela');
99
+
100
+ // (f) DISPENSA registrada (decisão do Daniel): disposition:dispensed COM approved_by →
101
+ // sai de missing, entra em pair.dispensed[] auditável; SEM approved_by → blocked.
102
+ const disp = runG5Lite({ ...base,
103
+ squadArtifacts: ['sq-oferta', 'sq-die-framework'],
104
+ artifactMap: [
105
+ { squad_artifact: 'sq-oferta', pod_output: 'a_field', section: '## Meta' },
106
+ { squad_artifact: 'sq-die-framework', disposition: 'dispensed', approved_by: 'Alexa Exemplo (2026-07-25)', evidence: 'entregável do loop de uso pós-entrega, fora do design' },
107
+ ] });
108
+ ok(disp.ok === true && disp.pair.completeness_ok, 'DISPENSA com approved_by → sai de missing (completude OK)');
109
+ // SF12.1/AC8: a asserção conferia o NOME dentro de `approved_by`. O valor virou a identidade
110
+ // fictícia canônica do repo (`scripts/owner-layer.cjs` → FICTIONAL_IDENTITY); o slot continua
111
+ // sendo mecanismo, só o valor é que era personalização.
112
+ ok(disp.pair.dispensed.length === 1 && disp.pair.dispensed[0].squad_artifact === 'sq-die-framework' && /Alexa Exemplo/.test(disp.pair.dispensed[0].approved_by) && disp.pair.dispensed[0].evidence,
113
+ 'DISPENSA registrada em pair.dispensed[] auditável (squad_artifact/approved_by/evidence)');
114
+ ok(!disp.pair.missing.includes('sq-die-framework'), 'DISPENSA aprovada NÃO consta em missing');
115
+
116
+ const dispNoApprove = runG5Lite({ ...base,
117
+ squadArtifacts: ['sq-die-framework'],
118
+ artifactMap: [{ squad_artifact: 'sq-die-framework', disposition: 'dispensed', evidence: 'sem aprovação' }] });
119
+ ok(dispNoApprove.ok === false && dispNoApprove.pair.missing.includes('sq-die-framework') && dispNoApprove.pair.dispensed.length === 0,
120
+ 'DISPENSA SEM approved_by → BLOQUEIA (dispensa não-registrada não vale)');
121
+
122
+ // (e) --artifact-map via ARQUIVO (loadArtifactMap + JSON) → pass.
123
+ const mdir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-map-'));
124
+ const mapFile = path.join(mdir, 'map.json');
125
+ fs.writeFileSync(mapFile, JSON.stringify([{ squad_artifact: 'sq1', pod_output: 'a_json' }]));
126
+ const fromFile = runG5Lite({ ...base, squadArtifacts: ['sq1'], artifactMapPath: mapFile });
127
+ ok(fromFile.ok === true && fromFile.pair.map_path === mapFile && fromFile.pair.mapped === 1,
128
+ 'TABELA --artifact-map via arquivo (loadArtifactMap json) → mapeia e passa');
129
+ fs.rmSync(mdir, { recursive: true, force: true });
130
+
131
+ console.log(`\n${passed} asserções OK; ${failures.length} falha(s).`);
132
+ if (failures.length) { for (const f of failures) console.error(` ✗ ${f}`); process.exit(1); }
133
+ console.log('harness-g5-lite: 3 etapas + bloqueios de par + waiver provados (invocável, reusável por SF3.4).');
134
+ process.exit(0);
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * hn-carousel-contrato-entrada.test.cjs — tabela-verdade do pattern do veto
5
+ * `field_matches contrato_entrada` do pod `hn-carousel`, depois que a Story SF11.7
6
+ * (ADR-026 `DF-SF11.7-8`, oráculo 1) alargou o conjunto de pares implementados de
7
+ * `^(ancora:hn)$` para `^(ancora:hn|roteiro:proprio)$`.
8
+ *
9
+ * POR QUE ESTE TESTE EXISTE, e o que ele NÃO é (honestidade obrigatória):
10
+ * o sidecar do smoke do pod planta UM único digest conforme, com `ancora:hn`. Com o
11
+ * pattern alargado, o smoke continua provando (i) que `ancora:hn` passa e (ii) que valor
12
+ * fora do conjunto bloqueia — mas ele JAMAIS exercita positivamente o caminho `roteiro`
13
+ * (`ADR-026 DF-SF11.7-8`, ponto cego declarado). Este teste é o oráculo determinístico
14
+ * que fecha essa metade; o outro é a run real na instalação, que a story registra.
15
+ * Ele NÃO prova proveniência (o campo é auto-atestado pelo agente — ADR-015) e NÃO prova
16
+ * fidelidade ao roteiro (não há veto de máquina sobre isso, `DF-SF11.7-4`).
17
+ *
18
+ * DUPLICAÇÃO DECLARADA: o valor LITERAL do pattern vive no `wf` da instalação
19
+ * (`second-brain/pods/hn-carousel/workflows/wf-hn-carousel.yaml`), que não é arquivo
20
+ * deste repo. Aqui ele é REPETIDO de propósito, para o teste ser determinístico e sem
21
+ * fixture de pod (`DF-SF11.7-8`). Se os dois divergirem, este teste continua verde e
22
+ * mente: a guarda contra isso é a INVARIANTE DE MANUTENÇÃO escrita no `_sources` da
23
+ * própria assertion + a matriz §0.3 do knowledge, auditadas pelo `*review`.
24
+ *
25
+ * Node >= 18. Exit 0/1.
26
+ */
27
+
28
+ const path = require('node:path');
29
+ const { evalVeto } = require('./pc-run-pod.cjs');
30
+
31
+ // Espelho do pattern do `wf` (ver DUPLICAÇÃO DECLARADA acima).
32
+ const PATTERN = '^(ancora:hn|roteiro:proprio)$';
33
+ const ASSERTION = { type: 'field_matches', field: 'contrato_entrada', pattern: PATTERN };
34
+
35
+ const roots = { podRoot: __dirname, runDir: __dirname };
36
+ const evalOn = (artifactText) =>
37
+ evalVeto(ASSERTION, artifactText, path.join(__dirname, 'digest.md'), roots);
38
+
39
+ // Artefato mínimo no formato real do fecho do digest (campo fora dos headings, ADR-005 A).
40
+ const digest = (contratoLine) =>
41
+ ['## Noticia', 'texto', '', '## Angulos para Slides', '- a', '', 'confianca: alta']
42
+ .concat(contratoLine === null ? [] : [contratoLine])
43
+ .join('\n') + '\n';
44
+
45
+ let passed = 0;
46
+ const failures = [];
47
+ function ok(cond, label) {
48
+ if (cond) { passed++; console.log(`[OK ] ${label}`); }
49
+ else { failures.push(label); console.log(`[FALHA] ${label}`); }
50
+ }
51
+
52
+ // --- Tabela-verdade do DF-SF11.7-8 (5 casos, binária) ---
53
+ ok(evalOn(digest('contrato_entrada: ancora:hn')).ok === true,
54
+ '`ancora:hn` → PASSA (M1 preservado: o alargamento é superset por construção)');
55
+
56
+ ok(evalOn(digest('contrato_entrada: roteiro:proprio')).ok === true,
57
+ '`roteiro:proprio` → PASSA (par implementado pela §1b, Story SF11.7)');
58
+
59
+ ok(evalOn(digest('contrato_entrada: roteiro:outro')).ok === false,
60
+ '`roteiro:outro` → BLOQUEIA (modo implementado, fonte que não existe)');
61
+
62
+ ok(evalOn(digest('contrato_entrada: ancora:x')).ok === false,
63
+ '`ancora:x` → BLOQUEIA (fonte fora do conjunto implementado)');
64
+
65
+ ok(evalOn(digest(null)).ok === false,
66
+ 'campo AUSENTE → BLOQUEIA (fail-closed: sem declaração de entrada não há artefato válido)');
67
+
68
+ // --- Guardas de borda: o alargamento não pode ter virado pattern frouxo ---
69
+ ok(evalOn(digest('contrato_entrada: ancora:hn|roteiro:proprio')).ok === false,
70
+ 'valor com o próprio `|` literal → BLOQUEIA (a alternância é do regex, não do campo)');
71
+
72
+ ok(evalOn(digest('contrato_entrada: xancora:hn')).ok === false,
73
+ 'prefixo espúrio → BLOQUEIA (âncoras ^ e $ intactas)');
74
+
75
+ ok(evalOn(digest('contrato_entrada: roteiro:proprio ')).ok === true,
76
+ 'espaço à direita → PASSA (extractField apara a borda; comportamento pré-existente do motor)');
77
+
78
+ // --- AC-B4 item 3 (ADR-026 Emenda 3, DF-SF11.7-26): VIOLABILIDADE do pattern alargado ---
79
+ // A guarda SF10.18 protege "a assertion que você alargou continua VIOLÁVEL". O instrumento que o
80
+ // harness usa para isso é `findNonMatchingValue` — usado aqui DIRETAMENTE (não um proxy), sem tocar
81
+ // uma linha de `smoke-pod-workflow.cjs`. O `--sweep` deste pod está vermelho por defeito de OUTRA
82
+ // etapa (o `command_check` de MEDIDA de `visuals`, que por design nunca bloqueia); isso não diz nada
83
+ // sobre esta assertion, e é exatamente a distinção que esta asserção mantém viva.
84
+ const { findNonMatchingValue } = require('./smoke-pod-workflow.cjs');
85
+ const violador = findNonMatchingValue(PATTERN);
86
+ ok(violador.ok === true && evalOn(digest(`contrato_entrada: ${violador.value}`)).ok === false,
87
+ `pattern alargado continua VIOLÁVEL — findNonMatchingValue derivou ${violador.value === '' ? '<string vazia>' : `"${violador.value}"`} e o veto BLOQUEIA (não virou pattern universal)`);
88
+
89
+ ok(evalOn(digest('contrato_entrada: valor-que-nenhum-modo-declara')).ok === false,
90
+ 'valor arbitrário fora do conjunto → BLOQUEIA (2ª evidência de não-universalidade)');
91
+
92
+ console.log(`\n${passed}/${passed + failures.length} asserções da tabela-verdade de \`contrato_entrada\` passaram.`);
93
+ if (failures.length) {
94
+ console.error('FALHAS:\n - ' + failures.join('\n - '));
95
+ process.exit(1);
96
+ }
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /**
4
+ * migrate-squad-orchestration.test.cjs — smoke de ORQUESTRAÇÃO F0→F3 fim-a-fim
5
+ * sobre o squad de fixture (Story SF3.3, Testing) + ACs estáticos.
6
+ * Prova que o comando ENCADEIA os motores existentes (migration-manifest +
7
+ * forge-generate --additive + validate-no-clone) nas fases — sem execução de LLM
8
+ * (isso é SF3.4). NÃO-fake-green: artefatos reais em disco.
9
+ * Cobre:
10
+ * AC3 spec AUTORADA: redutível→veto.assertions c/ _sources; aritmético→checkpoint
11
+ * (nunca veto); tarefa-canário + .smoke.json na mesma etapa.
12
+ * AC4 forge-generate --additive + tierOverride invocado no loop (reuso SF3.1).
13
+ * AC6 pod-critic.md G6 tem a dimensão anti-persona (item 12) — leitura do arquivo.
14
+ * AC7 ZERO ingestão automática de memória no código do comando.
15
+ * AC8 ZERO `git rm`/deleção no código do comando; F3 só PROPÕE ao Daniel.
16
+ * E2E F0→F1→F2(spec/gen/lint)→F3(coverage) encadeado uma vez.
17
+ *
18
+ * Node >= 18. Exit 0/1.
19
+ */
20
+
21
+ const fs = require('node:fs');
22
+ const os = require('node:os');
23
+ const path = require('node:path');
24
+
25
+ const m = require('./migration-manifest.cjs');
26
+ const g = require('./forge-generate.cjs');
27
+ const clone = require('./validate-no-clone.cjs');
28
+
29
+ const ROOT = path.join(__dirname, '..');
30
+ const FIX = path.join(__dirname, '__fixtures__', 'migrate-squad');
31
+ const LEGACY = path.join(FIX, 'legacy-squad');
32
+ const AUTH = path.join(FIX, 'authored');
33
+
34
+ let passed = 0;
35
+ const failures = [];
36
+ function ok(cond, label) {
37
+ if (cond) { passed++; console.log(`[OK ] ${label}`); }
38
+ else { failures.push(label); console.log(`[FALHA] ${label}`); }
39
+ }
40
+ function tmp(n) { return fs.mkdtempSync(path.join(os.tmpdir(), `mig-${n}-`)); }
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // AC3 — spec AUTORADA com o mapeamento veto/checkpoint por machine-redutibilidade.
44
+ // ---------------------------------------------------------------------------
45
+ {
46
+ const spec = JSON.parse(fs.readFileSync(path.join(AUTH, 'specs', 'wf-sample.spec.json'), 'utf8'));
47
+ ok(Array.isArray(spec._sources) && spec._sources.some((s) => s.includes('wf-sample.yaml')), 'AC3 spec cita o legado em _sources (ADR-005, nunca parse automático)');
48
+ const intake = spec.agents.find((a) => a.step === 'mm-intake');
49
+ const redu = intake.veto.find((v) => v.type === 'count_gte');
50
+ ok(redu && redu._sources, 'AC3 veto_condition machine-redutível (count_gte) → veto.assertions COM _sources');
51
+ const build = spec.agents.find((a) => a.step === 'mm-build');
52
+ ok(build.checkpoint && build.checkpoint.blocking && /LTV:CAC/.test(build.checkpoint.criteria), 'AC3 condição aritmética (LTV:CAC≥3) → checkpoint.blocking');
53
+ const allVeto = JSON.stringify(spec.agents.map((a) => a.veto || []));
54
+ ok(!/LTV|CAC/.test(allVeto), 'AC3 aritmético NUNCA vira veto.assertion (fronteira ADR-002)');
55
+ const smokePath = path.join(AUTH, 'specs', 'wf-sample.smoke.json');
56
+ const smoke = JSON.parse(fs.readFileSync(smokePath, 'utf8'));
57
+ ok(smoke._authored_with === 'specs/wf-sample.spec.json' && smoke.happy_path['mm-intake'], 'AC3 tarefa-canário + .smoke.json AUTORADOS na mesma etapa que a spec');
58
+ }
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // E2E F0→F1→F2(gen/lint)→F3 encadeado + AC4 (forge-generate --additive+tierOverride).
62
+ // ---------------------------------------------------------------------------
63
+ {
64
+ const dir = tmp('e2e');
65
+ const mf = path.join(dir, 'MIGRATION-hormozi.yaml');
66
+ const pod = path.join(dir, 'pod');
67
+ const specPath = path.join(AUTH, 'specs', 'wf-sample.spec.json');
68
+ const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
69
+
70
+ // F0
71
+ const inv = m.cmdInit(mf, { squad: 'hormozi', squadDir: LEGACY, now: 'T0' });
72
+ ok(inv.inventory.families.length === 10, 'E2E F0 inventário das 10 famílias');
73
+
74
+ // F1: triagem + aprovação (PARA no Daniel; sem ela F2 não abre).
75
+ m.cmdTriageSet(mf, { workflow: 'wf-sample', disposition: 'migrate', purpose: 'wf-sample.yaml:1', overlap: '', basis: 'julgamento', now: 'T' });
76
+ m.cmdTriageApprove(mf, { workflow: 'wf-sample', approvedBy: 'daniel', now: 'T' });
77
+
78
+ // F2b: pod PRÉ-EXISTENTE (aditivo preserva). Gera base, depois --additive.
79
+ // SF12.4a/ADR-030 Bloco O — pod PRÉ-EXISTENTE (bootstrap do fixture) — 'derived'.
80
+ g.generatePod({ pod: 'hormozi-method-fixture', workflowId: 'existing', agents: [{ name: 'legacy-keeper', output: 'kept' }] }, pod, { tierOverride: 'STANDARD/COMPLEX', specOrigin: 'derived' });
81
+ const baseWf = path.join(pod, 'workflows', 'wf-existing.yaml');
82
+ ok(fs.existsSync(baseWf), 'E2E base pod gerado (workflow pré-existente)');
83
+
84
+ // F2a: open-line (só após aprovação).
85
+ m.cmdOpenLine(mf, { workflow: 'wf-sample', spec: specPath, podDir: pod, pod: 'hormozi-method-fixture', owns: ['workflows/wf-sample.yaml', 'agents/mm-intake.md', 'agents/offer-engineer.md'], now: 'T' });
86
+
87
+ // F2b: geração ADITIVA + tierOverride agregado (reuso SF3.1; AC4).
88
+ // SF12.4a/ADR-030 Bloco O (AC48/AC50b) — F2b É o call site real de `*migrate-squad`:
89
+ // 'authored' (mesmo com --additive) — Frente 5 passa por aqui, tem que seguir com gate.
90
+ const CANON_REFUSED_MSQ = { nao_se_aplica: true, razao: 'fixture E2E de *migrate-squad não modela ritmo/entrada/entregável', respondido_por: 'migrate-squad-orchestration.test.cjs' };
91
+ g.generatePod({ ...spec, ritmo: CANON_REFUSED_MSQ, contrato_entrada: CANON_REFUSED_MSQ, entregavel: CANON_REFUSED_MSQ }, pod, { additive: true, tierOverride: 'STANDARD/COMPLEX', owns: ['workflows/wf-sample.yaml', 'agents/mm-intake.md', 'agents/offer-engineer.md'], specOrigin: 'authored' });
92
+ ok(fs.existsSync(path.join(pod, 'workflows', 'wf-sample.yaml')), 'AC4 forge-generate --additive gerou wf-sample.yaml (novo)');
93
+ ok(fs.existsSync(baseWf), 'AC4 modo aditivo PRESERVOU o workflow pré-existente');
94
+ const wfGen = fs.readFileSync(path.join(pod, 'workflows', 'wf-sample.yaml'), 'utf8');
95
+ ok(/count_gte/.test(wfGen) && /Value Stack/.test(wfGen), 'AC4 veto redutível da spec propagado ao wf-*.yaml gerado');
96
+
97
+ // F2d: lint regra 3 sobre os artefatos autorados do pod → limpo; legado → reprova.
98
+ const cleanAgent = clone.run([path.join(AUTH, 'agents', 'offer-engineer.md'), '--squad-source', LEGACY]);
99
+ ok(cleanAgent.violations.length === 0, 'F2d validate-no-clone limpo no agente capability-based autorado');
100
+ const dirtyAgent = clone.run([path.join(LEGACY, 'agents', 'hormozi-offer.md'), '--squad-source', LEGACY]);
101
+ ok(dirtyAgent.violations.length > 0, 'F2d validate-no-clone reprova o agente legado (lint wired ao loop)');
102
+
103
+ // F3: coverage (diff squad×manifest). Sem endereçar tudo, há resíduo → gate barra.
104
+ const cov = m.cmdCoverage(mf, { squadDir: LEGACY });
105
+ ok(cov.total > 0 && !cov.clean, 'AC8/F3 coverage computa diff squad×manifest (resíduo barra fechamento até endereçar tudo)');
106
+ }
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // AC6 — pod-critic.md G6 estendido com a dimensão anti-persona (leitura do arquivo).
110
+ // ---------------------------------------------------------------------------
111
+ {
112
+ const pc = fs.readFileSync(path.join(ROOT, 'template', 'pods', 'squad-forge', 'agents', 'pod-critic.md'), 'utf8');
113
+ ok(/\(12\)\s*\*\*anti-persona/.test(pc), 'AC6 pod-critic G6 contém o item (12) anti-persona');
114
+ ok(/tabela 16→N do manifest/.test(pc), 'AC6 dimensão usa o par exato da tabela 16→N do manifest (B.5)');
115
+ ok(/dos 7 falhando/.test(pc), 'AC6 contador do gate atualizado (6→7 com o item (13) anti-autoatestado, SF7.11)');
116
+ const budgets = fs.statSync(path.join(ROOT, 'template', 'pods', 'squad-forge', 'agents', 'pod-critic.md')).size;
117
+ ok(Math.ceil(budgets / 4) <= 1200, 'AC6 pod-critic dentro do budget (≤1200 tokens) após a extensão');
118
+ }
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // AC7 — ZERO ingestão automática de memória no código do comando.
122
+ // ---------------------------------------------------------------------------
123
+ {
124
+ const mmCode = fs.readFileSync(path.join(ROOT, 'scripts', 'migration-manifest.cjs'), 'utf8');
125
+ ok(!/forge-ingest-memory/.test(mmCode), 'AC7 migration-manifest.cjs NUNCA chama forge-ingest-memory (zero automação)');
126
+ const pipeline = fs.readFileSync(path.join(ROOT, 'template', 'pods', 'squad-forge', 'tasks', 'pipeline.md'), 'utf8');
127
+ ok(/NUNCA ingeridos automaticamente/.test(pipeline), 'AC7 pipeline F0-F3 declara learnings como candidatos (nunca ingestão automática)');
128
+ // forge-chief: ingest só na linha *ingest-memory, não na de *migrate-squad.
129
+ const fc = fs.readFileSync(path.join(ROOT, 'template', 'pods', 'squad-forge', 'agents', 'forge-chief.md'), 'utf8');
130
+ const migrateLine = fc.split('\n').find((l) => l.includes('*migrate-squad'));
131
+ ok(migrateLine && !/forge-ingest-memory/.test(migrateLine), 'AC7 a linha *migrate-squad NÃO invoca ingestão de memória');
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // AC8 — ZERO `git rm`/deleção no código do comando; F3 só PROPÕE ao Daniel.
136
+ // ---------------------------------------------------------------------------
137
+ {
138
+ const mmCode = fs.readFileSync(path.join(ROOT, 'scripts', 'migration-manifest.cjs'), 'utf8');
139
+ ok(!/git\s+rm|rmSync|unlinkSync|rmdirSync/.test(mmCode), 'AC8 migration-manifest.cjs não executa git rm nem deleção de arquivos do squad');
140
+ const pipeline = fs.readFileSync(path.join(ROOT, 'template', 'pods', 'squad-forge', 'tasks', 'pipeline.md'), 'utf8');
141
+ ok(/nunca deleta.*git rm.*pc-devops/is.test(pipeline), 'AC8 pipeline F3: comando nunca deleta — proposta ao Daniel, git rm é exclusivo do pc-devops');
142
+ }
143
+
144
+ console.log(`\n${passed} verificações OK, ${failures.length} falha(s).`);
145
+ if (failures.length) { for (const f of failures) console.error(` - ${f}`); process.exit(1); }
146
+ process.exit(0);