@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.
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/bin/cli.js +124 -0
- package/installer/__tests__/doctor-ready-oracles.test.cjs +140 -0
- package/installer/__tests__/merge-settings.test.cjs +330 -0
- package/installer/adopt.js +161 -0
- package/installer/copy.js +203 -0
- package/installer/doctor.js +266 -0
- package/installer/install.js +155 -0
- package/installer/manifest.js +102 -0
- package/installer/motor-scripts.js +50 -0
- package/installer/motor-scripts.json +39 -0
- package/installer/uninstall.js +99 -0
- package/installer/update.js +376 -0
- package/installer/util.js +113 -0
- package/installer/wizard.js +64 -0
- package/package.json +26 -0
- package/scripts/__fixtures__/anti-path-demo/agents/ap-writer.md +13 -0
- package/scripts/__fixtures__/anti-path-demo/templates/write-tmpl.md +7 -0
- package/scripts/__fixtures__/anti-path-demo/workflows/wf-ap.smoke.json +10 -0
- package/scripts/__fixtures__/anti-path-demo/workflows/wf-ap.yaml +25 -0
- package/scripts/__fixtures__/assess-tier/retrofit-leve/pod/agents/content-chief.md +1 -0
- package/scripts/__fixtures__/assess-tier/retrofit-leve/pod/workflows/wf-criacao-redteam.yaml +3 -0
- package/scripts/__fixtures__/assess-tier/retrofit-leve/pod-spec.json +13 -0
- package/scripts/__fixtures__/fidelity/fake-green-average-in-band.yaml +21 -0
- package/scripts/__fixtures__/fidelity/fake-green-average.yaml +18 -0
- package/scripts/__fixtures__/fidelity/fake-green-denominator.yaml +19 -0
- package/scripts/__fixtures__/fidelity/fake-green-missing-evidence.yaml +18 -0
- package/scripts/__fixtures__/fidelity/fake-green-threshold.yaml +18 -0
- package/scripts/__fixtures__/fidelity/fake-green-weight.yaml +18 -0
- package/scripts/__fixtures__/fidelity/golden.yaml +31 -0
- package/scripts/__fixtures__/fidelity/trindade-incoherent.yaml +15 -0
- package/scripts/__fixtures__/forge-canonical/pod-spec-example.json +37 -0
- package/scripts/__fixtures__/migrate-squad/authored/agents/offer-engineer.md +17 -0
- package/scripts/__fixtures__/migrate-squad/authored/knowledge/no-source.md +7 -0
- package/scripts/__fixtures__/migrate-squad/authored/knowledge/value-stack-method.md +8 -0
- package/scripts/__fixtures__/migrate-squad/authored/specs/wf-sample.smoke.json +24 -0
- package/scripts/__fixtures__/migrate-squad/authored/specs/wf-sample.spec.json +45 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/HEADLINE.md +3 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/README.md +4 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/agents/hormozi-offer.md +14 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/dead-redundant.md +4 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/method-guide.md +6 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/checklists/veto-screen.md +4 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/config/config.yaml +2 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/data/case-library.md +3 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/scripts/validate-mvn.py +16 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/sops/sop-sample.md +3 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/squad-io.yaml +14 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/tasks/gather-context.md +7 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/templates/output-tmpl.md +5 -0
- package/scripts/__fixtures__/migrate-squad/legacy-squad/workflows/wf-sample.yaml +24 -0
- package/scripts/__fixtures__/pipeline/pipelines/pipeline-checkpoint.yaml +21 -0
- package/scripts/__fixtures__/pipeline/pipelines/pipeline-demo.yaml +22 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-a/agents/maker.md +13 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-a/memory/learnings.consolidated.md +8 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-a/memory/learnings.jsonl +83 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-a/templates/make-tmpl.md +8 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-a/workflows/wf-a.yaml +16 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-b/agents/user.md +13 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-b/memory/learnings.consolidated.md +8 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-b/memory/learnings.jsonl +14 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-b/templates/use-tmpl.md +6 -0
- package/scripts/__fixtures__/pipeline/pods/pipe-b/workflows/wf-b.yaml +16 -0
- package/scripts/__fixtures__/pod-run/agents/forge-chief.md +13 -0
- package/scripts/__fixtures__/pod-run/agents/pod-critic.md +13 -0
- package/scripts/__fixtures__/pod-run/templates/build-tmpl.md +8 -0
- package/scripts/__fixtures__/pod-run/templates/gate-tmpl.md +6 -0
- package/scripts/__fixtures__/pod-run/workflows/wf-min.yaml +43 -0
- package/scripts/__fixtures__/pod-run/workflows/wf-skip-modes.yaml +50 -0
- package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-all-skippable.yaml +30 -0
- package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-criteria-escalar-de-bloco.yaml +40 -0
- package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-skip-mode-desconhecido.yaml +30 -0
- package/scripts/__fixtures__/pod-workflow/invalid-checkpoint-unknown-key.yaml +29 -0
- package/scripts/__fixtures__/pod-workflow/invalid-cycle.yaml +26 -0
- package/scripts/__fixtures__/pod-workflow/invalid-fix-loop-backedge.yaml +29 -0
- package/scripts/__fixtures__/pod-workflow/invalid-fix-loop-forward.yaml +29 -0
- package/scripts/__fixtures__/pod-workflow/invalid-handoff-open.yaml +27 -0
- package/scripts/__fixtures__/pod-workflow/invalid-knowledge-shape.yaml +18 -0
- package/scripts/__fixtures__/pod-workflow/invalid-missing-agent.yaml +15 -0
- package/scripts/__fixtures__/pod-workflow/invalid-missing-outputs.yaml +15 -0
- package/scripts/__fixtures__/pod-workflow/invalid-missing-template.yaml +15 -0
- package/scripts/__fixtures__/pod-workflow/invalid-missing-veto.yaml +13 -0
- package/scripts/__fixtures__/pod-workflow/invalid-template-not-on-disk.yaml +16 -0
- package/scripts/__fixtures__/pod-workflow/invalid-veto-prose.yaml +17 -0
- package/scripts/__fixtures__/pod-workflow/knowledge/a.md +4 -0
- package/scripts/__fixtures__/pod-workflow/knowledge/b.md +4 -0
- package/scripts/__fixtures__/pod-workflow/knowledge/c.md +4 -0
- package/scripts/__fixtures__/pod-workflow/templates/step-tmpl.md +7 -0
- package/scripts/__fixtures__/pod-workflow/valid-checkpoint-skip-modes.yaml +29 -0
- package/scripts/__fixtures__/pod-workflow/valid-fix-loop.yaml +30 -0
- package/scripts/__fixtures__/pod-workflow/valid-knowledge.yaml +30 -0
- package/scripts/__fixtures__/pod-workflow/valid-veto-always-true.yaml +20 -0
- package/scripts/__fixtures__/pod-workflow/valid.yaml +27 -0
- package/scripts/__fixtures__/smoke-canary/agents/canary-reporter.md +13 -0
- package/scripts/__fixtures__/smoke-canary/agents/canary-researcher.md +13 -0
- package/scripts/__fixtures__/smoke-canary/agents/canary-synth.md +13 -0
- package/scripts/__fixtures__/smoke-canary/memory/learnings.consolidated.md +10 -0
- package/scripts/__fixtures__/smoke-canary/memory/learnings.jsonl +448 -0
- package/scripts/__fixtures__/smoke-canary/templates/report-tmpl.md +9 -0
- package/scripts/__fixtures__/smoke-canary/templates/research-tmpl.md +7 -0
- package/scripts/__fixtures__/smoke-canary/templates/synth-tmpl.md +9 -0
- package/scripts/__fixtures__/smoke-canary/workflows/wf-canary.smoke.json +11 -0
- package/scripts/__fixtures__/smoke-canary/workflows/wf-canary.yaml +53 -0
- package/scripts/__fixtures__/source-audit/fake-green-bronze-unsignaled.yaml +10 -0
- package/scripts/__fixtures__/source-audit/fake-green-counts.yaml +9 -0
- package/scripts/__fixtures__/source-audit/fake-green-missing-evidence.yaml +9 -0
- package/scripts/__fixtures__/source-audit/fake-green-unclassified.yaml +10 -0
- package/scripts/__fixtures__/source-audit/fake-green-verdict.yaml +10 -0
- package/scripts/__fixtures__/source-audit/golden-blocked.yaml +10 -0
- package/scripts/__fixtures__/source-audit/golden.yaml +11 -0
- package/scripts/__fixtures__/sweep-forms/agents/forms-count.md +13 -0
- package/scripts/__fixtures__/sweep-forms/agents/forms-field.md +13 -0
- package/scripts/__fixtures__/sweep-forms/agents/forms-fileref.md +13 -0
- package/scripts/__fixtures__/sweep-forms/agents/forms-json.md +13 -0
- package/scripts/__fixtures__/sweep-forms/agents/forms-section.md +13 -0
- package/scripts/__fixtures__/sweep-forms/specs/wf-forms.spec.json +5 -0
- package/scripts/__fixtures__/sweep-forms/templates/t_count.md +5 -0
- package/scripts/__fixtures__/sweep-forms/templates/t_field.md +3 -0
- package/scripts/__fixtures__/sweep-forms/templates/t_fileref.md +3 -0
- package/scripts/__fixtures__/sweep-forms/templates/t_json.md +0 -0
- package/scripts/__fixtures__/sweep-forms/templates/t_section.md +3 -0
- package/scripts/__fixtures__/sweep-forms/workflows/wf-forms.smoke.json +13 -0
- package/scripts/__fixtures__/sweep-forms/workflows/wf-forms.yaml +67 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-1-noop-state-json.fixture.md +18 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-2-crash-buildworkflowyaml.fixture.md +26 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-3-nasce-verde-skip-modes.fixture.md +29 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-4-guarda-sem-irmao.fixture.md +17 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-5a-diff-stat-sem-guarda.fixture.md +17 -0
- package/scripts/__fixtures__/validate-story-acs-corpus/corpus-5b-test-f-sobre-diretorio.fixture.md +20 -0
- package/scripts/__fixtures__/veto-checks/copy-clean.md +4 -0
- package/scripts/__fixtures__/veto-checks/copy-dashes.md +4 -0
- package/scripts/__fixtures__/veto-checks/n8n-bad.md +18 -0
- package/scripts/__fixtures__/veto-checks/n8n-ok.md +22 -0
- package/scripts/__fixtures__/veto-checks/page-bad.html +7 -0
- package/scripts/__fixtures__/veto-checks/phash/copy.png +0 -0
- package/scripts/__fixtures__/veto-checks/phash/distinct.png +0 -0
- package/scripts/__fixtures__/veto-checks/phash/distinct2.png +0 -0
- package/scripts/__fixtures__/veto-checks/phash/make-fixtures.cjs +203 -0
- package/scripts/__fixtures__/veto-checks/phash/ref.png +0 -0
- package/scripts/__fixtures__/veto-checks/slide-ok.html +15 -0
- package/scripts/__fixtures__/veto-checks/slide-overflow.html +14 -0
- package/scripts/__fixtures__/veto-checks/sweep-pod/agents/vc-checker.md +13 -0
- package/scripts/__fixtures__/veto-checks/sweep-pod/templates/check-tmpl.md +6 -0
- package/scripts/__fixtures__/veto-checks/sweep-pod/workflows/wf-vc.smoke.json +10 -0
- package/scripts/__fixtures__/veto-checks/sweep-pod/workflows/wf-vc.yaml +19 -0
- package/scripts/__fixtures__/voz-do-dono/README.md +23 -0
- package/scripts/__fixtures__/voz-do-dono/dono-escalar.yaml +9 -0
- package/scripts/__fixtures__/voz-do-dono/dono-guia.yaml +10 -0
- package/scripts/__fixtures__/voz-do-dono/peca-3a-pessoa.md +6 -0
- package/scripts/__fixtures__/voz-do-dono/peca-com-lexico-proibido.md +6 -0
- package/scripts/__fixtures__/voz-do-dono/peca-limpa-1a-pessoa.md +6 -0
- package/scripts/__tests__/derive-ready-transitions.test.cjs +269 -0
- package/scripts/__tests__/enforce-cycle-authority.test.cjs +869 -0
- package/scripts/__tests__/enforce-git-push-authority.test.cjs +701 -0
- package/scripts/__tests__/enforce-ready-oracles.test.cjs +745 -0
- package/scripts/__tests__/motor-scripts.test.cjs +339 -0
- package/scripts/__tests__/pc-run-pod-counter.test.cjs +58 -0
- package/scripts/__tests__/pc-run-pod.test.cjs +578 -0
- package/scripts/__tests__/validate-pod-workflow.test.cjs +90 -0
- package/scripts/__tests__/validate-story-acs.test.cjs +607 -0
- package/scripts/anti-path.test.cjs +163 -0
- package/scripts/arena.cjs +514 -0
- package/scripts/arena.test.cjs +213 -0
- package/scripts/brief-leitura-obrigatoria.test.cjs +364 -0
- package/scripts/consolidate-knowledge-runner.test.cjs +249 -0
- package/scripts/default-funcional.test.cjs +153 -0
- package/scripts/derive-ready-transitions.cjs +325 -0
- package/scripts/forge-additive.test.cjs +158 -0
- package/scripts/forge-assess-tier.cjs +205 -0
- package/scripts/forge-assess-tier.test.cjs +114 -0
- package/scripts/forge-canonical.test.cjs +624 -0
- package/scripts/forge-generate.cjs +1303 -0
- package/scripts/forge-harden-learning.cjs +921 -0
- package/scripts/forge-harden-learning.test.cjs +242 -0
- package/scripts/forge-ingest-memory.cjs +136 -0
- package/scripts/forge-upgrade-pod.cjs +368 -0
- package/scripts/forge.test.cjs +609 -0
- package/scripts/harden-knowledge.test.cjs +612 -0
- package/scripts/harness-g5-lite.cjs +243 -0
- package/scripts/harness-g5-lite.test.cjs +134 -0
- package/scripts/hn-carousel-contrato-entrada.test.cjs +96 -0
- package/scripts/migrate-squad-orchestration.test.cjs +146 -0
- package/scripts/migration-manifest-sf3.2.test.cjs +382 -0
- package/scripts/migration-manifest-sf3.3.test.cjs +170 -0
- package/scripts/migration-manifest-sf5.5.test.cjs +189 -0
- package/scripts/migration-manifest.cjs +1146 -0
- package/scripts/migration-manifest.test.cjs +186 -0
- package/scripts/npm-scope-invocation.test.cjs +194 -0
- package/scripts/owner-layer.cjs +442 -0
- package/scripts/owner-layer.test.cjs +358 -0
- package/scripts/pc-run-pipeline.cjs +289 -0
- package/scripts/pc-run-pipeline.test.cjs +256 -0
- package/scripts/pc-run-pod-countgte.test.cjs +66 -0
- package/scripts/pc-run-pod.cjs +1355 -0
- package/scripts/phash-gate.test.cjs +433 -0
- package/scripts/pod-export-compile.cjs +487 -0
- package/scripts/pod-export-compile.test.cjs +312 -0
- package/scripts/pod-export-executor.cjs +678 -0
- package/scripts/pod-export-executor.test.cjs +1341 -0
- package/scripts/pod-export-hardening.test.cjs +531 -0
- package/scripts/pod-export-postprocess.cjs +427 -0
- package/scripts/pod-export-postprocess.test.cjs +558 -0
- package/scripts/pod-export-queue-race.test.cjs +865 -0
- package/scripts/pod-export-release.cjs +473 -0
- package/scripts/pod-export-release.test.cjs +267 -0
- package/scripts/pod-export-service.cjs +1297 -0
- package/scripts/pod-export-service.test.cjs +489 -0
- package/scripts/pod-export-tools.cjs +470 -0
- package/scripts/pod-export-ui.cjs +805 -0
- package/scripts/pod-export-ui.test.cjs +301 -0
- package/scripts/pod-memory-budget.test.cjs +309 -0
- package/scripts/pod-memory-note.cjs +357 -0
- package/scripts/pod-memory-note.test.cjs +452 -0
- package/scripts/pod-memory.cjs +1252 -0
- package/scripts/pod-memory.test.cjs +951 -0
- package/scripts/render-png.test.cjs +307 -0
- package/scripts/smoke-isolation.test.cjs +100 -0
- package/scripts/smoke-pod-workflow.cjs +755 -0
- package/scripts/smoke-sweep.test.cjs +170 -0
- package/scripts/validate-adopt.js +235 -0
- package/scripts/validate-branding.js +84 -0
- package/scripts/validate-budgets.js +140 -0
- package/scripts/validate-fidelity-output.cjs +267 -0
- package/scripts/validate-fidelity-output.test.cjs +101 -0
- package/scripts/validate-install.js +230 -0
- package/scripts/validate-no-clone.cjs +220 -0
- package/scripts/validate-no-clone.test.cjs +77 -0
- package/scripts/validate-pipeline.cjs +145 -0
- package/scripts/validate-pod-workflow.cjs +878 -0
- package/scripts/validate-source-audit.cjs +170 -0
- package/scripts/validate-source-audit.test.cjs +90 -0
- package/scripts/validate-story-acs.cjs +862 -0
- package/scripts/validate-update-scope-motor.js +421 -0
- package/scripts/veto-checks/html-valid.cjs +92 -0
- package/scripts/veto-checks/lexical-check.cjs +62 -0
- package/scripts/veto-checks/phash-gate.cjs +589 -0
- package/scripts/veto-checks/render-gate.cjs +165 -0
- package/scripts/veto-checks/render-png.cjs +358 -0
- package/scripts/veto-checks.test.cjs +219 -0
- package/scripts/watcher-audit.cjs +178 -0
- package/template/.claude/CLAUDE.md +103 -0
- package/template/.claude/agents/pc-analyst.md +100 -0
- package/template/.claude/agents/pc-architect.md +32 -0
- package/template/.claude/agents/pc-dev.md +27 -0
- package/template/.claude/agents/pc-devops.md +45 -0
- package/template/.claude/agents/pc-planner.md +32 -0
- package/template/.claude/agents/pc-po.md +25 -0
- package/template/.claude/agents/pc-qa.md +25 -0
- package/template/.claude/commands/power/academy.md +9 -0
- package/template/.claude/commands/power/automation.md +9 -0
- package/template/.claude/commands/power/content-carousel.md +267 -0
- package/template/.claude/commands/power/content.md +9 -0
- package/template/.claude/commands/power/dev.md +9 -0
- package/template/.claude/commands/power/forge.md +224 -0
- package/template/.claude/commands/power/hormozi.md +221 -0
- package/template/.claude/commands/power/modo.md +57 -0
- package/template/.claude/hooks/README.md +114 -0
- package/template/.claude/hooks/context-budget.cjs +64 -0
- package/template/.claude/hooks/enforce-cycle-authority.cjs +457 -0
- package/template/.claude/hooks/enforce-git-push-authority.cjs +925 -0
- package/template/.claude/hooks/enforce-ready-oracles.cjs +502 -0
- package/template/.claude/rules/authority.md +76 -0
- package/template/.claude/rules/curadoria-de-conhecimento.md +30 -0
- package/template/.claude/rules/model-matrix.md +34 -0
- package/template/.claude/rules/orchestration.md +133 -0
- package/template/.claude/settings.json +50 -0
- package/template/.claude/skills/pc-apply-qa-fixes/SKILL.md +108 -0
- package/template/.claude/skills/pc-apply-qa-fixes/references/fix-loop.md +40 -0
- package/template/.claude/skills/pc-apply-qa-fixes/references/fix-request-template.md +70 -0
- package/template/.claude/skills/pc-arena/SKILL.md +96 -0
- package/template/.claude/skills/pc-close-story/SKILL.md +105 -0
- package/template/.claude/skills/pc-commit/SKILL.md +108 -0
- package/template/.claude/skills/pc-develop-story/SKILL.md +116 -0
- package/template/.claude/skills/pc-full-cycle/SKILL.md +150 -0
- package/template/.claude/skills/pc-pipeline/SKILL.md +63 -0
- package/template/.claude/skills/pc-pipeline/references/gate-templates.md +46 -0
- package/template/.claude/skills/pc-review-story/SKILL.md +129 -0
- package/template/.claude/skills/pc-review-story/references/false-positive-detection.md +50 -0
- package/template/.claude/skills/pc-review-story/references/nfr-assess.md +47 -0
- package/template/.claude/skills/pc-review-story/references/risk-profile.md +75 -0
- package/template/.claude/skills/pc-review-story/references/security-checklist.md +69 -0
- package/template/.claude/skills/pc-review-story/references/test-design.md +37 -0
- package/template/.claude/skills/pc-review-story/references/trace-requirements.md +46 -0
- package/template/.claude/skills/pc-run-pod/SKILL.md +123 -0
- package/template/.claude/skills/pc-validate-story/SKILL.md +114 -0
- package/template/.claude/skills/pc-wave/SKILL.md +133 -0
- package/template/.env.example +10 -0
- package/template/knowledge/analyst/brainstorming.md +40 -0
- package/template/knowledge/analyst/brief-skeleton.md +32 -0
- package/template/knowledge/analyst/competitor-skeleton.md +39 -0
- package/template/knowledge/analyst/elicitation-menu.md +49 -0
- package/template/knowledge/analyst/market-research-skeleton.md +36 -0
- package/template/knowledge/analyst/research-prompt-structure.md +48 -0
- package/template/knowledge/analyst/roi-skeleton.md +51 -0
- package/template/knowledge/voice-dna/README.md +99 -0
- package/template/knowledge/voice-dna/voice-dna.example.yaml +157 -0
- package/template/pods/README.md +64 -0
- package/template/pods/academy/README.md +37 -0
- package/template/pods/academy/agents/academy-chief.md +27 -0
- package/template/pods/academy/examples/palestra.example.md +142 -0
- package/template/pods/academy/pod-spec.json +44 -0
- package/template/pods/academy/templates/materiais-tmpl.md +17 -0
- package/template/pods/academy/templates/revisao-didatica-tmpl.md +20 -0
- package/template/pods/academy/workflows/wf-materiais-revisao.yaml +30 -0
- package/template/pods/authority-content/README.md +43 -0
- package/template/pods/authority-content/agents/content-chief.md +28 -0
- package/template/pods/authority-content/pod-spec.json +45 -0
- package/template/pods/authority-content/templates/criacao-na-voz-tmpl.md +17 -0
- package/template/pods/authority-content/templates/red-team-factual-tmpl.md +23 -0
- package/template/pods/authority-content/workflows/wf-criacao-redteam.yaml +30 -0
- package/template/pods/automation/README.md +37 -0
- package/template/pods/automation/agents/langgraph-architect.md +30 -0
- package/template/pods/automation/agents/n8n-architect.md +30 -0
- package/template/pods/automation/examples/README.md +46 -0
- package/template/pods/automation/examples/n8n-content-radar.example.json +380 -0
- package/template/pods/automation/knowledge/langgraph-patterns.md +126 -0
- package/template/pods/automation/knowledge/n8n-patterns.md +131 -0
- package/template/pods/automation/memory/README.md +16 -0
- package/template/pods/automation/memory/learnings.consolidated.md +8 -0
- package/template/pods/automation/memory/learnings.jsonl +0 -0
- package/template/pods/automation/pod-spec.json +109 -0
- package/template/pods/automation/specs/wf-langgraph-build.spec.json +107 -0
- package/template/pods/automation/squad-io.yaml +28 -0
- package/template/pods/automation/templates/lg-build-tmpl.md +17 -0
- package/template/pods/automation/templates/lg-design-tmpl.md +23 -0
- package/template/pods/automation/templates/lg-discover-tmpl.md +20 -0
- package/template/pods/automation/templates/lg-handoff-tmpl.md +20 -0
- package/template/pods/automation/templates/lg-test-tmpl.md +20 -0
- package/template/pods/automation/templates/n8n-build-tmpl.md +14 -0
- package/template/pods/automation/templates/n8n-design-tmpl.md +23 -0
- package/template/pods/automation/templates/n8n-discover-tmpl.md +20 -0
- package/template/pods/automation/templates/n8n-handoff-tmpl.md +20 -0
- package/template/pods/automation/templates/n8n-test-tmpl.md +20 -0
- package/template/pods/automation/workflows/wf-langgraph-build.smoke.json +11 -0
- package/template/pods/automation/workflows/wf-langgraph-build.yaml +64 -0
- package/template/pods/automation/workflows/wf-n8n-build.smoke.json +11 -0
- package/template/pods/automation/workflows/wf-n8n-build.yaml +65 -0
- package/template/pods/content-carousel/README.md +91 -0
- package/template/pods/content-carousel/agents/carousel-builder.md +28 -0
- package/template/pods/content-carousel/agents/carousel-visual.md +24 -0
- package/template/pods/content-carousel/agents/hn-curator.md +74 -0
- package/template/pods/content-carousel/config/heuristic-watcher-rubric.yaml +59 -0
- package/template/pods/content-carousel/knowledge/aquisicao-ancora.md +443 -0
- package/template/pods/content-carousel/knowledge/cta-brief.md +25 -0
- package/template/pods/content-carousel/knowledge/dono.example.yaml +45 -0
- package/template/pods/content-carousel/knowledge/identidade-visual-mascote.md +62 -0
- package/template/pods/content-carousel/knowledge/image-generation.md +62 -0
- package/template/pods/content-carousel/knowledge/selecao-de-ancora.md +60 -0
- package/template/pods/content-carousel/knowledge/slides-html.md +56 -0
- package/template/pods/content-carousel/memory/README.md +18 -0
- package/template/pods/content-carousel/memory/learnings.consolidated.md +6 -0
- package/template/pods/content-carousel/memory/learnings.jsonl +0 -0
- package/template/pods/content-carousel/pod-spec.json +100 -0
- package/template/pods/content-carousel/squad-io.yaml +10 -0
- package/template/pods/content-carousel/templates/assembly-tmpl.md +23 -0
- package/template/pods/content-carousel/templates/digest-tmpl.md +29 -0
- package/template/pods/content-carousel/templates/visuals-tmpl.md +20 -0
- package/template/pods/content-carousel/workflows/wf-content-carousel.smoke.json +23 -0
- package/template/pods/content-carousel/workflows/wf-content-carousel.yaml +80 -0
- package/template/pods/dev-ia/README.md +45 -0
- package/template/pods/dev-ia/agents/db-architect.md +33 -0
- package/template/pods/dev-ia/agents/ux-architect.md +29 -0
- package/template/pods/dev-ia/knowledge/db/migration-protocol.md +95 -0
- package/template/pods/dev-ia/knowledge/db/rls-patterns.md +101 -0
- package/template/pods/dev-ia/knowledge/db/schema-review-checklist.md +76 -0
- package/template/pods/dev-ia/memory/README.md +16 -0
- package/template/pods/dev-ia/memory/learnings.consolidated.md +8 -0
- package/template/pods/dev-ia/memory/learnings.jsonl +0 -0
- package/template/pods/dev-ia/pod-spec.json +34 -0
- package/template/pods/dev-ia/templates/schema-review-tmpl.md +23 -0
- package/template/pods/dev-ia/templates/ux-flow-review-tmpl.md +23 -0
- package/template/pods/dev-ia/tools/db-ops/backup-manager.sh +321 -0
- package/template/pods/dev-ia/tools/db-ops/best-practices-auditor.sh +534 -0
- package/template/pods/dev-ia/tools/db-ops/bootstrap-runner.sh +255 -0
- package/template/pods/dev-ia/tools/db-ops/data-loader.sh +616 -0
- package/template/pods/dev-ia/tools/db-ops/detect-database.sh +113 -0
- package/template/pods/dev-ia/tools/db-ops/explain-analyzer.sh +285 -0
- package/template/pods/dev-ia/tools/db-ops/health-checker.sh +323 -0
- package/template/pods/dev-ia/tools/db-ops/migration-runner.sh +308 -0
- package/template/pods/dev-ia/tools/db-ops/postgresql-schema-loader.sh +334 -0
- package/template/pods/dev-ia/tools/db-ops/query-runner.sh +171 -0
- package/template/pods/dev-ia/tools/db-ops/rls-policy-installer.sh +480 -0
- package/template/pods/dev-ia/tools/db-ops/rls-test-suite.sh +172 -0
- package/template/pods/dev-ia/tools/db-ops/schema-context-loader.sh +176 -0
- package/template/pods/hormozi-method/README.md +52 -0
- package/template/pods/hormozi-method/agents/acquisition-strategist.md +33 -0
- package/template/pods/hormozi-method/agents/conversion-copywriter.md +34 -0
- package/template/pods/hormozi-method/agents/monetization-architect.md +35 -0
- package/template/pods/hormozi-method/agents/offer-engineer.md +37 -0
- package/template/pods/hormozi-method/knowledge/core-four-leads.md +51 -0
- package/template/pods/hormozi-method/knowledge/grand-slam-offer.md +66 -0
- package/template/pods/hormozi-method/knowledge/growth-decision.md +38 -0
- package/template/pods/hormozi-method/knowledge/hooks-and-ads.md +56 -0
- package/template/pods/hormozi-method/knowledge/launch-email.md +31 -0
- package/template/pods/hormozi-method/knowledge/money-model.md +46 -0
- package/template/pods/hormozi-method/knowledge/opportunity-screening.md +44 -0
- package/template/pods/hormozi-method/knowledge/pages.md +25 -0
- package/template/pods/hormozi-method/knowledge/pos-lancamento-leads.md +56 -0
- package/template/pods/hormozi-method/knowledge/pricing.md +36 -0
- package/template/pods/hormozi-method/knowledge/retention-ltv.md +37 -0
- package/template/pods/hormozi-method/knowledge/scale-roadmap.md +35 -0
- package/template/pods/hormozi-method/knowledge/swipefiles-curados.md +44 -0
- package/template/pods/hormozi-method/knowledge/value-equation-diagnostic.md +77 -0
- package/template/pods/hormozi-method/memory/README.md +16 -0
- package/template/pods/hormozi-method/memory/learnings.consolidated.md +6 -0
- package/template/pods/hormozi-method/memory/learnings.jsonl +0 -0
- package/template/pods/hormozi-method/pod-spec.json +50 -0
- package/template/pods/hormozi-method/specs/wf-full-launch-sequence.spec.json +149 -0
- package/template/pods/hormozi-method/specs/wf-lead-magnet-pipeline.spec.json +125 -0
- package/template/pods/hormozi-method/specs/wf-money-model-design.spec.json +117 -0
- package/template/pods/hormozi-method/specs/wf-paid-ads-campaign.spec.json +132 -0
- package/template/pods/hormozi-method/specs/wf-scaling-diagnostic.spec.json +121 -0
- package/template/pods/hormozi-method/squad-io.yaml +43 -0
- package/template/pods/hormozi-method/templates/conversion-copywriter-tmpl.md +20 -0
- package/template/pods/hormozi-method/templates/launch-execucao-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/launch-fechamento-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/launch-pos-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/launch-preparacao-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/lm-copy-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/lm-distribuicao-tmpl.md +18 -0
- package/template/pods/hormozi-method/templates/lm-estrategia-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/mm-arquitetura-tmpl.md +18 -0
- package/template/pods/hormozi-method/templates/mm-copy-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/mm-diagnostico-tmpl.md +14 -0
- package/template/pods/hormozi-method/templates/monetization-architect-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/offer-engineer-tmpl.md +20 -0
- package/template/pods/hormozi-method/templates/paid-criativos-tmpl.md +19 -0
- package/template/pods/hormozi-method/templates/paid-fundacao-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/paid-teste-escala-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/scaling-diagnostico-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/scaling-priorizacao-tmpl.md +17 -0
- package/template/pods/hormozi-method/templates/scaling-roadmap-tmpl.md +17 -0
- package/template/pods/hormozi-method/workflows/wf-full-launch-sequence.smoke.json +12 -0
- package/template/pods/hormozi-method/workflows/wf-full-launch-sequence.yaml +56 -0
- package/template/pods/hormozi-method/workflows/wf-grand-slam-offer.smoke.json +11 -0
- package/template/pods/hormozi-method/workflows/wf-grand-slam-offer.yaml +45 -0
- package/template/pods/hormozi-method/workflows/wf-lead-magnet-pipeline.smoke.json +9 -0
- package/template/pods/hormozi-method/workflows/wf-lead-magnet-pipeline.yaml +45 -0
- package/template/pods/hormozi-method/workflows/wf-money-model-design.smoke.json +11 -0
- package/template/pods/hormozi-method/workflows/wf-money-model-design.yaml +45 -0
- package/template/pods/hormozi-method/workflows/wf-paid-ads-campaign.smoke.json +9 -0
- package/template/pods/hormozi-method/workflows/wf-paid-ads-campaign.yaml +46 -0
- package/template/pods/hormozi-method/workflows/wf-scaling-diagnostic.smoke.json +11 -0
- package/template/pods/hormozi-method/workflows/wf-scaling-diagnostic.yaml +44 -0
- package/template/pods/squad-forge/README.md +53 -0
- package/template/pods/squad-forge/agents/forge-chief.md +31 -0
- package/template/pods/squad-forge/agents/mind-extractor.md +29 -0
- package/template/pods/squad-forge/agents/pod-critic.md +26 -0
- package/template/pods/squad-forge/config/heuristic-watcher-rubric.yaml +74 -0
- package/template/pods/squad-forge/knowledge/fidelity-rubric.yaml +176 -0
- package/template/pods/squad-forge/knowledge/g6-memory-check.md +17 -0
- package/template/pods/squad-forge/knowledge/memory-ingest.md +16 -0
- package/template/pods/squad-forge/knowledge/source-audit-rubric.yaml +60 -0
- package/template/pods/squad-forge/memory/README.md +16 -0
- package/template/pods/squad-forge/memory/learnings.consolidated.md +8 -0
- package/template/pods/squad-forge/memory/learnings.jsonl +0 -0
- package/template/pods/squad-forge/pod-spec.json +166 -0
- package/template/pods/squad-forge/squad-io.yaml +13 -0
- package/template/pods/squad-forge/tasks/pipeline.md +158 -0
- package/template/pods/squad-forge/templates/discovery-tmpl.md +40 -0
- package/template/pods/squad-forge/templates/generation-tmpl.md +18 -0
- package/template/pods/squad-forge/templates/red-team-tmpl.md +17 -0
- package/template/pods/squad-forge/templates/register-tmpl.md +17 -0
- package/template/pods/squad-forge/templates/workflow-tmpl.yaml +101 -0
- package/template/pods/squad-forge/workflows/wf-forge.smoke.json +12 -0
- package/template/pods/squad-forge/workflows/wf-forge.yaml +60 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* make-fixtures.cjs — GERADOR determinístico dos PNGs de fixture do veto `phash-gate.cjs`
|
|
5
|
+
* (Story SF10.8). NÃO é script de produção (vive sob __fixtures__/, excluído do manifesto
|
|
6
|
+
* ADR-007): existe para que a calibração do limiar seja AUDITÁVEL e REPRODUZÍVEL — o QA
|
|
7
|
+
* regenera, altera a agressividade da "cópia" e re-mede a margem sem depender de binários
|
|
8
|
+
* opacos comitados no repo.
|
|
9
|
+
*
|
|
10
|
+
* ZERO-DEP: encoder PNG (RGB8, filtro 0) escrito à mão sobre `node:zlib` — nenhuma lib npm.
|
|
11
|
+
* PRNG determinístico (LCG com semente fixa) ⇒ os bytes gerados são idênticos a cada rodada.
|
|
12
|
+
*
|
|
13
|
+
* Uso: node scripts/__fixtures__/veto-checks/phash/make-fixtures.cjs [dir-de-saida]
|
|
14
|
+
*
|
|
15
|
+
* Saída (o "cenário" de calibração):
|
|
16
|
+
* ref.png — a REFERÊNCIA (papel da referência Pinterest do run)
|
|
17
|
+
* copy.png — CÓPIA ADVERSARIAL da referência: crop 4% + reescala + rotação de canal
|
|
18
|
+
* (recolor) + brilho + ruído. Um observador razoável diz "é a mesma imagem".
|
|
19
|
+
* DEVE ser VETADA.
|
|
20
|
+
* distinct.png — peça LEGÍTIMA de composição/paleta próprias. DEVE PASSAR.
|
|
21
|
+
* distinct2.png — 2ª peça legítima (o par capa+CTA do veredito POR-IMAGEM).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('node:fs');
|
|
25
|
+
const path = require('node:path');
|
|
26
|
+
const zlib = require('node:zlib');
|
|
27
|
+
|
|
28
|
+
const W = 512;
|
|
29
|
+
const H = 640;
|
|
30
|
+
|
|
31
|
+
// --- PNG (RGB8, sem filtro) --------------------------------------------------
|
|
32
|
+
const CRC_TABLE = (() => {
|
|
33
|
+
const t = new Int32Array(256);
|
|
34
|
+
for (let n = 0; n < 256; n++) {
|
|
35
|
+
let c = n;
|
|
36
|
+
for (let k = 0; k < 8; k++) c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1);
|
|
37
|
+
t[n] = c;
|
|
38
|
+
}
|
|
39
|
+
return t;
|
|
40
|
+
})();
|
|
41
|
+
function crc32(buf) {
|
|
42
|
+
let c = 0xFFFFFFFF;
|
|
43
|
+
for (let i = 0; i < buf.length; i++) c = CRC_TABLE[(c ^ buf[i]) & 0xFF] ^ (c >>> 8);
|
|
44
|
+
return (c ^ 0xFFFFFFFF) >>> 0;
|
|
45
|
+
}
|
|
46
|
+
function chunk(type, data) {
|
|
47
|
+
const len = Buffer.alloc(4); len.writeUInt32BE(data.length, 0);
|
|
48
|
+
const td = Buffer.concat([Buffer.from(type, 'ascii'), data]);
|
|
49
|
+
const crc = Buffer.alloc(4); crc.writeUInt32BE(crc32(td), 0);
|
|
50
|
+
return Buffer.concat([len, td, crc]);
|
|
51
|
+
}
|
|
52
|
+
/** Codifica pixels RGB (Uint8Array de W*H*3) em PNG. */
|
|
53
|
+
function encodePng(px, w, h) {
|
|
54
|
+
const raw = Buffer.alloc(h * (1 + w * 3));
|
|
55
|
+
for (let y = 0; y < h; y++) {
|
|
56
|
+
raw[y * (1 + w * 3)] = 0; // filtro None
|
|
57
|
+
px.copy
|
|
58
|
+
? px.copy(raw, y * (1 + w * 3) + 1, y * w * 3, (y + 1) * w * 3)
|
|
59
|
+
: Buffer.from(px.subarray(y * w * 3, (y + 1) * w * 3)).copy(raw, y * (1 + w * 3) + 1);
|
|
60
|
+
}
|
|
61
|
+
const ihdr = Buffer.alloc(13);
|
|
62
|
+
ihdr.writeUInt32BE(w, 0); ihdr.writeUInt32BE(h, 4);
|
|
63
|
+
ihdr[8] = 8; ihdr[9] = 2; ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0; // 8bit, truecolor
|
|
64
|
+
return Buffer.concat([
|
|
65
|
+
Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
|
|
66
|
+
chunk('IHDR', ihdr),
|
|
67
|
+
chunk('IDAT', zlib.deflateSync(raw, { level: 9 })),
|
|
68
|
+
chunk('IEND', Buffer.alloc(0)),
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- desenho ----------------------------------------------------------------
|
|
73
|
+
function canvas(w, h) { return Buffer.alloc(w * h * 3); }
|
|
74
|
+
const clamp = (v) => (v < 0 ? 0 : v > 255 ? 255 : v | 0);
|
|
75
|
+
function setPx(buf, w, x, y, r, g, b) {
|
|
76
|
+
const i = (y * w + x) * 3;
|
|
77
|
+
buf[i] = clamp(r); buf[i + 1] = clamp(g); buf[i + 2] = clamp(b);
|
|
78
|
+
}
|
|
79
|
+
function rect(buf, w, x0, y0, x1, y1, c) {
|
|
80
|
+
for (let y = Math.max(0, y0); y < Math.min(H, y1); y++) {
|
|
81
|
+
for (let x = Math.max(0, x0); x < Math.min(w, x1); x++) setPx(buf, w, x, y, c[0], c[1], c[2]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function disc(buf, w, cx, cy, r, c) {
|
|
85
|
+
for (let y = Math.max(0, cy - r); y < Math.min(H, cy + r); y++) {
|
|
86
|
+
for (let x = Math.max(0, cx - r); x < Math.min(w, cx + r); x++) {
|
|
87
|
+
const dx = x - cx; const dy = y - cy;
|
|
88
|
+
if (dx * dx + dy * dy <= r * r) setPx(buf, w, x, y, c[0], c[1], c[2]);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function tri(buf, w, x0, y0, size, c) { // triângulo retângulo (cateto = size)
|
|
93
|
+
for (let y = 0; y < size; y++) {
|
|
94
|
+
for (let x = 0; x < size - y; x++) setPx(buf, w, x0 + x, y0 + y, c[0], c[1], c[2]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** PRNG determinístico (LCG) — fixtures byte-idênticas a cada geração. */
|
|
99
|
+
function lcg(seed) {
|
|
100
|
+
let s = seed >>> 0;
|
|
101
|
+
return () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** REFERÊNCIA: gradiente escuro + disco claro + barras + triângulo (composição forte). */
|
|
105
|
+
function drawRef() {
|
|
106
|
+
const buf = canvas(W, H);
|
|
107
|
+
for (let y = 0; y < H; y++) {
|
|
108
|
+
for (let x = 0; x < W; x++) {
|
|
109
|
+
const t = y / H;
|
|
110
|
+
setPx(buf, W, x, y, 20 + 60 * t + (x / W) * 30, 24 + 20 * t, 70 + 120 * (1 - t));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
disc(buf, W, 150, 170, 105, [240, 214, 120]);
|
|
114
|
+
rect(buf, W, 40, 330, 470, 366, [250, 250, 250]);
|
|
115
|
+
rect(buf, W, 40, 392, 330, 424, [250, 250, 250]);
|
|
116
|
+
rect(buf, W, 40, 450, 400, 478, [180, 180, 190]);
|
|
117
|
+
tri(buf, W, 300, 500, 170, [230, 90, 60]);
|
|
118
|
+
return buf;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** PEÇA LEGÍTIMA 1: fundo claro, composição e paleta próprias. */
|
|
122
|
+
function drawDistinct() {
|
|
123
|
+
const buf = canvas(W, H);
|
|
124
|
+
for (let y = 0; y < H; y++) {
|
|
125
|
+
for (let x = 0; x < W; x++) {
|
|
126
|
+
const t = x / W;
|
|
127
|
+
setPx(buf, W, x, y, 235 - 40 * t, 238 - 20 * (y / H), 228 - 60 * t);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
rect(buf, W, 0, 0, W, 96, [18, 92, 76]);
|
|
131
|
+
disc(buf, W, 400, 520, 90, [24, 40, 120]);
|
|
132
|
+
rect(buf, W, 60, 180, 200, 470, [200, 60, 90]);
|
|
133
|
+
rect(buf, W, 230, 240, 300, 400, [40, 40, 40]);
|
|
134
|
+
return buf;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** PEÇA LEGÍTIMA 2: outra composição (o par capa+CTA do veredito por-imagem). */
|
|
138
|
+
function drawDistinct2() {
|
|
139
|
+
const buf = canvas(W, H);
|
|
140
|
+
for (let y = 0; y < H; y++) {
|
|
141
|
+
for (let x = 0; x < W; x++) {
|
|
142
|
+
const d = Math.abs(x - W / 2) / (W / 2);
|
|
143
|
+
setPx(buf, W, x, y, 40 + 120 * d, 130 - 60 * d, 60 + 30 * (y / H));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
rect(buf, W, 0, 240, W, 300, [255, 255, 255]);
|
|
147
|
+
rect(buf, W, 0, 340, W, 372, [255, 255, 255]);
|
|
148
|
+
disc(buf, W, 256, 560, 70, [10, 10, 10]);
|
|
149
|
+
return buf;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* CÓPIA ADVERSARIAL da referência (o ataque que o veto TEM de pegar):
|
|
154
|
+
* crop de 4% em cada borda + reescala de volta (nearest) + rotação leve de canais (recolor)
|
|
155
|
+
* + ganho de brilho + ruído determinístico. Nenhum byte em comum; a MESMA imagem aos olhos.
|
|
156
|
+
*/
|
|
157
|
+
function drawCopy(ref) {
|
|
158
|
+
const out = canvas(W, H);
|
|
159
|
+
const rnd = lcg(20260731);
|
|
160
|
+
const mx = Math.round(W * 0.04);
|
|
161
|
+
const my = Math.round(H * 0.04);
|
|
162
|
+
const cw = W - 2 * mx;
|
|
163
|
+
const ch = H - 2 * my;
|
|
164
|
+
// Ruído em BLOCOS 8×8 (artefato de compressão, não chuvisco por pixel): igualmente eficaz
|
|
165
|
+
// contra igualdade de bytes e MUITO mais compressível — o PNG de fixture fica leve.
|
|
166
|
+
const nb = new Float32Array(Math.ceil(W / 8) * Math.ceil(H / 8));
|
|
167
|
+
for (let i = 0; i < nb.length; i++) nb[i] = (rnd() - 0.5) * 10;
|
|
168
|
+
for (let y = 0; y < H; y++) {
|
|
169
|
+
const sy = my + Math.min(ch - 1, Math.floor((y / H) * ch));
|
|
170
|
+
for (let x = 0; x < W; x++) {
|
|
171
|
+
const sx = mx + Math.min(cw - 1, Math.floor((x / W) * cw));
|
|
172
|
+
const i = (sy * W + sx) * 3;
|
|
173
|
+
const n = nb[(y >> 3) * Math.ceil(W / 8) + (x >> 3)];
|
|
174
|
+
// recolor: mistura leve entre canais + brilho (preserva a estrutura luminante)
|
|
175
|
+
const r = ref[i] * 0.92 + ref[i + 2] * 0.08 + 10 + n;
|
|
176
|
+
const g = ref[i + 1] * 0.94 + ref[i] * 0.06 + 8 + n;
|
|
177
|
+
const b = ref[i + 2] * 0.90 + ref[i + 1] * 0.10 + 12 + n;
|
|
178
|
+
setPx(out, W, x, y, r, g, b);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function main() {
|
|
185
|
+
const outDir = process.argv[2] ? path.resolve(process.argv[2]) : __dirname;
|
|
186
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
187
|
+
const ref = drawRef();
|
|
188
|
+
const files = {
|
|
189
|
+
'ref.png': ref,
|
|
190
|
+
'copy.png': drawCopy(ref),
|
|
191
|
+
'distinct.png': drawDistinct(),
|
|
192
|
+
'distinct2.png': drawDistinct2(),
|
|
193
|
+
};
|
|
194
|
+
for (const [name, px] of Object.entries(files)) {
|
|
195
|
+
const p = path.join(outDir, name);
|
|
196
|
+
fs.writeFileSync(p, encodePng(px, W, H));
|
|
197
|
+
console.log(`escrito: ${p} (${fs.statSync(p).size}B)`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (require.main === module) main();
|
|
202
|
+
|
|
203
|
+
module.exports = { encodePng, drawRef, drawCopy, drawDistinct, drawDistinct2, W, H };
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>Slide 1</title>
|
|
3
|
+
<style>
|
|
4
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
5
|
+
html,body{width:1080px;height:1350px;overflow:hidden;font-family:Arial,Helvetica,sans-serif}
|
|
6
|
+
.slide{width:1080px;height:1350px;padding:80px;background:#0b1e3a;color:#fff;display:flex;flex-direction:column;justify-content:center}
|
|
7
|
+
h1{font-size:88px;line-height:1.2;margin-bottom:40px}
|
|
8
|
+
p{font-size:44px;line-height:1.35;max-width:900px}
|
|
9
|
+
</style></head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="slide">
|
|
12
|
+
<h1>Notícia do dia</h1>
|
|
13
|
+
<p>Resumo que cabe folgado na moldura de 1080 por 1350, sem estourar nenhuma caixa.</p>
|
|
14
|
+
</div>
|
|
15
|
+
</body></html>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>Slide quebrado</title>
|
|
3
|
+
<style>
|
|
4
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
5
|
+
html,body{width:1080px;height:1350px;overflow:hidden;font-family:Arial,Helvetica,sans-serif}
|
|
6
|
+
.slide{width:1080px;height:1350px;padding:80px;background:#0b1e3a;color:#fff}
|
|
7
|
+
/* DEFEITO REAL da R5: título numa única linha sem quebra, 2400px de largura → corta na moldura de 1080. */
|
|
8
|
+
h1{font-size:120px;white-space:nowrap;width:2400px}
|
|
9
|
+
</style></head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="slide">
|
|
12
|
+
<h1>Manchete longa demais que não quebra de linha e estoura a largura</h1>
|
|
13
|
+
</div>
|
|
14
|
+
</body></html>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vc-checker
|
|
3
|
+
description: "Agente de FIXTURE da etapa \"check\" de sweep-pod. Existe para satisfazer a leitura obrigatória da etapa (SF11.2/ADR-021 DF-SF11.2-4): agente declarado no wf tem de existir em disco."
|
|
4
|
+
model: sonnet
|
|
5
|
+
budget_tokens: 200
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# vc-checker — agente de fixture (etapa "check")
|
|
9
|
+
|
|
10
|
+
Fixture de teste, não é agente de produção. O conteúdo é irrelevante para as provas
|
|
11
|
+
que usam este pod; o que importa é que o arquivo EXISTA, porque desde a Story SF11.2
|
|
12
|
+
o runner resolve e verifica `agents/<step.agent>.md` antes de despachar a etapa, e o
|
|
13
|
+
validador estático checa a mesma existência (paridade com `pod-export-compile.cjs:214`).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Sidecar do wf-vc (SF7.2). 'artifacts' = conforme por etapa (passa template E veto). 'violations' = fixture de violação por etapa para o command_check (conforme ao template, mas o script blessed bloqueia). Sem 'violations[check]' o sweep é UNDERIVÁVEL fail-loud (ADR-011 Decisão 4).",
|
|
3
|
+
"target_step": "check",
|
|
4
|
+
"artifacts": {
|
|
5
|
+
"check": "## Body\n\nTexto limpo, sem travessao, passa no lexical-check.\n"
|
|
6
|
+
},
|
|
7
|
+
"violations": {
|
|
8
|
+
"check": "## Body\n\nTexto com travessao — aqui — que o lexical-check bloqueia.\n"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# wf-vc — workflow-fixture do SWEEP de command_check (Story SF7.2/ADR-011 Decisão 4).
|
|
2
|
+
# NÃO é pod de produção. Existe só para provar que o sweep bloqueia por uma fixture de
|
|
3
|
+
# violação DECLARADA no sidecar (scenario.violations), e que a ausência dessa fixture é
|
|
4
|
+
# UNDERIVÁVEL fail-loud. O veto é command_check lexical-check (blessed, Node puro).
|
|
5
|
+
state_machine:
|
|
6
|
+
states: [init, running, complete, failed]
|
|
7
|
+
initial: init
|
|
8
|
+
terminal: [complete, failed]
|
|
9
|
+
steps:
|
|
10
|
+
- id: check
|
|
11
|
+
agent: vc-checker
|
|
12
|
+
template: templates/check-tmpl.md
|
|
13
|
+
inputs: [pedido]
|
|
14
|
+
outputs: [artefato]
|
|
15
|
+
depends_on: []
|
|
16
|
+
checkpoint: null
|
|
17
|
+
veto:
|
|
18
|
+
assertions:
|
|
19
|
+
- { type: command_check, command: "lexical-check.cjs", args: ["--max", "0"] }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Fixtures — guarda de voz do dono (SF7.9 / ADR-013)
|
|
2
|
+
|
|
3
|
+
Provas reproduzíveis da checagem híbrida (veto léxico de máquina + checkpoint de julgamento)
|
|
4
|
+
e da retrocompat do `dono.yaml`.
|
|
5
|
+
|
|
6
|
+
## Arquivos
|
|
7
|
+
|
|
8
|
+
- `dono-guia.yaml` — bloco `voz:` ESTRUTURADO (forma nova, ADR-013 Decisão 2). O veto do
|
|
9
|
+
workflow deriva os args de `voz.lexico_proibido` em tempo de AUTORIA (args literais,
|
|
10
|
+
ADR-011).
|
|
11
|
+
- `dono-escalar.yaml` — forma ESCALAR antiga (`voz: "primeira pessoa"`), que permanece
|
|
12
|
+
VÁLIDA: nenhum script do motor parseia `dono.yaml` (dado de instância consumido pelo
|
|
13
|
+
AGENTE; a golden rule interpreta o escalar como `voz.pessoa: "primeira"` + defaults e
|
|
14
|
+
oferece upgrade). Retrocompat é por indiferença de máquina + prosa do agente.
|
|
15
|
+
- `peca-com-lexico-proibido.md` — peça VIOLANDO o léxico do guia (contém em-dash). O
|
|
16
|
+
blessed real bloqueia:
|
|
17
|
+
`node scripts/veto-checks/lexical-check.cjs scripts/__fixtures__/voz-do-dono/peca-com-lexico-proibido.md --max 0 --pattern "[—–]"` → exit 1.
|
|
18
|
+
- `peca-limpa-1a-pessoa.md` — peça conforme (1ª pessoa, sem tokens banidos) → exit 0.
|
|
19
|
+
- `peca-3a-pessoa.md` — o DEFEITO REAL da R2 do benchmark: cita o dono em 3ª pessoa como
|
|
20
|
+
fonte externa, SEM nenhum token do léxico proibido. O `lexical-check.cjs` dá exit 0
|
|
21
|
+
(a máquina NÃO pega — e não deve tentar por regex, ADR-013 Decisão 3/Risco 2): quem pega é
|
|
22
|
+
a cláusula de voz do CHECKPOINT (julgamento humano) em `wf-content-carousel.yaml`.
|
|
23
|
+
Este fixture é a prova de que a 3ª pessoa NÃO virou regex.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Fixture — dono.yaml na forma ESCALAR antiga (pré-ADR-013). Continua VÁLIDO (retrocompat):
|
|
2
|
+
# o agente interpreta `voz` escalar como `voz.pessoa: "primeira"` com defaults e oferece o
|
|
3
|
+
# upgrade na ativação; nenhum script do motor parseia este arquivo. Dono FICTÍCIO.
|
|
4
|
+
dono:
|
|
5
|
+
nome: "Alexa Exemplo"
|
|
6
|
+
handle: "@alexa.exemplo"
|
|
7
|
+
autoridade: "Automação para pequenos negócios, testada em campo"
|
|
8
|
+
voz: "primeira pessoa"
|
|
9
|
+
acao_padrao_cta: "seguir"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Fixture — dono.yaml com o bloco `voz:` estruturado (ADR-013 Decisão 2). Dono FICTÍCIO.
|
|
2
|
+
dono:
|
|
3
|
+
nome: "Alexa Exemplo"
|
|
4
|
+
handle: "@alexa.exemplo"
|
|
5
|
+
autoridade: "Automação para pequenos negócios, testada em campo"
|
|
6
|
+
acao_padrao_cta: "seguir"
|
|
7
|
+
voz:
|
|
8
|
+
pessoa: "primeira"
|
|
9
|
+
lexico_proibido: ["—", "–"]
|
|
10
|
+
tom: "direto, técnico sem jargão, sem hype"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Slide de exemplo (fixture do DEFEITO R2: 3ª pessoa, SEM token proibido)
|
|
2
|
+
|
|
3
|
+
Como explica Alexa Exemplo, referência em automação para pequenos negócios, a ferramenta
|
|
4
|
+
resolve o problema quando bem configurada. Para Alexa, o segredo é começar pequeno.
|
|
5
|
+
|
|
6
|
+
confianca: alta
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* derive-ready-transitions.test.cjs — meta-prova do instrumento offline que
|
|
5
|
+
* deriva do git a contagem de `D-Dono-2` (i) (`ADR-035`, D7; story `SF13.8`).
|
|
6
|
+
*
|
|
7
|
+
* `ADR-035` D7 exige, no MÍNIMO, quatro elementos — e diz por quê: *"sem (b) e
|
|
8
|
+
* (d), o teste fica verde para um instrumento que conta zero"*. Um detector
|
|
9
|
+
* cuja classe alvo nunca é provada alcançável passa igual quebrado e correto
|
|
10
|
+
* (`calibrar-detector-exige-corpus-externo`). Os quatro estão aqui:
|
|
11
|
+
*
|
|
12
|
+
* (a) CORPUS REAL — a derivação roda sobre o histórico DESTE repositório,
|
|
13
|
+
* pinado num sha imutável (`force-push` é `deny` para todos os agentes,
|
|
14
|
+
* `authority.md`), e exige a âncora estável `6b948efa`/`sf13.1.story.md`
|
|
15
|
+
* com o veredito `ask` em `P8`.
|
|
16
|
+
* (b) CONTROLE POSITIVO — repositório git sintético e descartável, com uma
|
|
17
|
+
* transição `Draft`→`Ready` conhecida, num diretório de stories
|
|
18
|
+
* NÃO-padrão (o argumento `--stories-dir` é exercitado de verdade, não
|
|
19
|
+
* só declarado na assinatura).
|
|
20
|
+
* (c) CONTROLE NEGATIVO — commit que toca a story SEM mudar `## Status` não
|
|
21
|
+
* é contado. Sem ele, um instrumento que contasse "toda escrita" também
|
|
22
|
+
* ficaria verde em (b).
|
|
23
|
+
* (d) FALSO NEGATIVO ASSERTADO — story que NASCE `Ready` não é contada.
|
|
24
|
+
* É limitação conhecida e declarada (`ADR-035` M7/dívida 1), no mesmo
|
|
25
|
+
* padrão do `~~Ready~~` de `enforce-ready-oracles.test.cjs:595`:
|
|
26
|
+
* escrever a limitação em prosa não impede que ela vire outra coisa em
|
|
27
|
+
* silêncio — assertá-la trava o comportamento no valor que foi aceito.
|
|
28
|
+
*
|
|
29
|
+
* Mais três guardas que decorrem das decisões do ADR e não têm outro dono:
|
|
30
|
+
* D4 (`exit 0` sempre), D2 (fonte única — nenhum predicado reimplementado) e
|
|
31
|
+
* a Segurança (`git` por `execFileSync` com array, nunca shell).
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const fs = require('node:fs');
|
|
35
|
+
const os = require('node:os');
|
|
36
|
+
const path = require('node:path');
|
|
37
|
+
const { execFileSync, spawnSync } = require('node:child_process');
|
|
38
|
+
|
|
39
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
40
|
+
const SCRIPT = path.join(REPO_ROOT, 'scripts', 'derive-ready-transitions.cjs');
|
|
41
|
+
|
|
42
|
+
// Sha pinado: o commit mais recente entre as 70 transições do corpus real.
|
|
43
|
+
// Pinar é o que impede o teste de ficar RED meses depois por trabalho legítimo
|
|
44
|
+
// do ciclo (a contagem só cresce a cada `Draft`→`Ready` novo).
|
|
45
|
+
const REV_PINADO = '6ef33f90';
|
|
46
|
+
const MARCO_V1 = 'd6ae744'; // commit em que a v1 do hook passou a existir em `template/`
|
|
47
|
+
const ANCORA_SHA = '6b948efa';
|
|
48
|
+
const ANCORA_ARQUIVO = 'sf13.1.story.md';
|
|
49
|
+
|
|
50
|
+
let failures = 0;
|
|
51
|
+
function assert(ok, msg) {
|
|
52
|
+
if (ok) {
|
|
53
|
+
console.log(`[OK ] ${msg}`);
|
|
54
|
+
} else {
|
|
55
|
+
console.error(`[FALHA] ${msg}`);
|
|
56
|
+
failures += 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function rodar(args) {
|
|
61
|
+
const r = spawnSync(process.execPath, [SCRIPT].concat(args), {
|
|
62
|
+
encoding: 'utf8',
|
|
63
|
+
cwd: REPO_ROOT,
|
|
64
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
65
|
+
});
|
|
66
|
+
return { status: r.status, stdout: r.stdout || '', stderr: r.stderr || '' };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function campo(saida, nome) {
|
|
70
|
+
const linha = saida.split('\n').find((l) => l.includes(`${nome}=`));
|
|
71
|
+
if (!linha) return null;
|
|
72
|
+
const depois = linha.slice(linha.indexOf(`${nome}=`) + nome.length + 1);
|
|
73
|
+
const m = /^\d+/.test(depois) ? depois.match(/^\d+/) : null;
|
|
74
|
+
return m ? m[0] : null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Repositório git sintético e descartável. Criado por teste, nunca reusado:
|
|
78
|
+
// estado compartilhado entre controles faria um controle mascarar o outro.
|
|
79
|
+
function repoSintetico(prefixo) {
|
|
80
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefixo));
|
|
81
|
+
const git = (args) => execFileSync('git', args, { cwd: dir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
82
|
+
git(['init', '-q']);
|
|
83
|
+
git(['config', 'user.email', 'teste@exemplo.invalid']);
|
|
84
|
+
git(['config', 'user.name', 'teste']);
|
|
85
|
+
fs.mkdirSync(path.join(dir, 'stories-sinteticas'));
|
|
86
|
+
return {
|
|
87
|
+
dir,
|
|
88
|
+
escrever(nome, conteudo, mensagem) {
|
|
89
|
+
fs.writeFileSync(path.join(dir, 'stories-sinteticas', nome), conteudo);
|
|
90
|
+
git(['add', '.']);
|
|
91
|
+
git(['commit', '-q', '-m', mensagem]);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// (a) Corpus real — o histórico deste repositório, pinado
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
function testCorpusReal() {
|
|
101
|
+
console.log('\n--- D7a: corpus real (histórico deste repositório, sha pinado) ---');
|
|
102
|
+
|
|
103
|
+
const r = rodar(['.', '--rev', REV_PINADO, '--since', MARCO_V1]);
|
|
104
|
+
assert(r.status === 0, `D7a: exit 0 sobre o corpus real (status=${r.status})`);
|
|
105
|
+
|
|
106
|
+
assert(campo(r.stdout, 'total') === '70', `D7a: total=70 transições draft→ready até ${REV_PINADO} (medido: ${campo(r.stdout, 'total')})`);
|
|
107
|
+
|
|
108
|
+
// `desde` é a leitura RESTRITA de `D-Dono-2` (i) — "com a v1". O número é 14,
|
|
109
|
+
// por ancestralidade `d6ae744..6ef33f90`. A tabela M3 do `ADR-035` publicou
|
|
110
|
+
// `17` na 1ª versão e foi CORRIGIDA para 14 (a causa era filtro por
|
|
111
|
+
// granularidade de DIA, que inclui 3 transições anteriores às 15:29:56 em que
|
|
112
|
+
// a v1 nasceu). Leitura superada, não repetir: quem vir 17 aqui está
|
|
113
|
+
// copiando a versão superada, não medindo.
|
|
114
|
+
assert(campo(r.stdout, 'desde') === '14', `D7a: desde=14 no recorte ${MARCO_V1}..${REV_PINADO} (medido: ${campo(r.stdout, 'desde')})`);
|
|
115
|
+
|
|
116
|
+
const listaTemAncora = r.stdout.split('\n').some((l) => l.includes(ANCORA_SHA) && l.includes(ANCORA_ARQUIVO));
|
|
117
|
+
assert(listaTemAncora, `D7a: a âncora ${ANCORA_SHA} (${ANCORA_ARQUIVO}) aparece na lista auditável — cada transição é conferível uma a uma, não é total agregado`);
|
|
118
|
+
|
|
119
|
+
// Replay do veredito da v1 (D2/D3): o hook é PURO, logo o veredito é função
|
|
120
|
+
// total do conteúdo resultante, e o conteúdo resultante é o que o git guarda.
|
|
121
|
+
assert(campo(r.stdout, 'ask') === '1' && campo(r.stdout, 'silencio') === '69', `D7a: replay da v1 sobre as 70 dá ask=1 silencio=69 (medido: ask=${campo(r.stdout, 'ask')} silencio=${campo(r.stdout, 'silencio')})`);
|
|
122
|
+
|
|
123
|
+
const linhaAsk = r.stdout.split('\n').find((l) => l.startsWith('ASK'));
|
|
124
|
+
assert(
|
|
125
|
+
!!linhaAsk && linhaAsk.includes(ANCORA_SHA) && linhaAsk.includes(ANCORA_ARQUIVO) && linhaAsk.includes('P8'),
|
|
126
|
+
`D7a: a única emissão é a já nomeada em ADR-032 (consequência 5): ${ANCORA_SHA}/${ANCORA_ARQUIVO}, predicado P8 (linha: ${linhaAsk || '<ausente>'})`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// (b) Controle positivo — alcançabilidade da classe
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
function testControlePositivo() {
|
|
135
|
+
console.log('\n--- D7b: controle positivo (repo git sintético, --stories-dir não-padrão) ---');
|
|
136
|
+
|
|
137
|
+
const repo = repoSintetico('derive-positivo-');
|
|
138
|
+
repo.escrever('z.story.md', '## Status\n\nDraft\n', 'nasce Draft');
|
|
139
|
+
repo.escrever('z.story.md', '## Status\n\nReady\n', 'Draft -> Ready');
|
|
140
|
+
|
|
141
|
+
const r = rodar([repo.dir, '--stories-dir', 'stories-sinteticas']);
|
|
142
|
+
assert(r.status === 0, `D7b: exit 0 no repo sintético (status=${r.status})`);
|
|
143
|
+
assert(campo(r.stdout, 'total') === '1', `D7b/controle positivo: a transição conhecida É contada — total=1 (medido: ${campo(r.stdout, 'total')})`);
|
|
144
|
+
assert(
|
|
145
|
+
r.stdout.includes('stories-dir=stories-sinteticas') && r.stdout.includes('stories-sinteticas/z.story.md'),
|
|
146
|
+
'D7b: `--stories-dir` é EXERCITADO de verdade (diretório não-padrão), não só declarado na assinatura',
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// (c) Controle negativo — o instrumento não conta "toda escrita"
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
function testControleNegativo() {
|
|
155
|
+
console.log('\n--- D7c: controle negativo (commit toca a story sem mudar o status) ---');
|
|
156
|
+
|
|
157
|
+
const repo = repoSintetico('derive-negativo-');
|
|
158
|
+
repo.escrever('z.story.md', '## Status\n\nDraft\n', 'nasce Draft');
|
|
159
|
+
repo.escrever('z.story.md', '## Status\n\nReady\n\n## Acceptance Criteria\n', 'Draft -> Ready');
|
|
160
|
+
repo.escrever('z.story.md', '## Status\n\nReady\n\n## Acceptance Criteria\n\nAC-1 novo\n', 'toca a story sem mudar Status');
|
|
161
|
+
|
|
162
|
+
const r = rodar([repo.dir, '--stories-dir', 'stories-sinteticas']);
|
|
163
|
+
assert(r.status === 0, `D7c: exit 0 no repo sintético (status=${r.status})`);
|
|
164
|
+
assert(campo(r.stdout, 'total') === '1', `D7c/controle negativo: Ready→Ready NÃO conta — total continua 1, não sobe para 2 (medido: ${campo(r.stdout, 'total')})`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// (d) Falso negativo DECLARADO — assertado, não só escrito em prosa
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
function testFalsoNegativoDeclarado() {
|
|
172
|
+
console.log('\n--- D7d: falso negativo <ausente>->ready, assertado ---');
|
|
173
|
+
|
|
174
|
+
const repo = repoSintetico('derive-falso-neg-');
|
|
175
|
+
repo.escrever('nasce-ready.story.md', '## Status\n\nReady\n', 'nasce em Ready, sem Draft anterior');
|
|
176
|
+
|
|
177
|
+
const r = rodar([repo.dir, '--stories-dir', 'stories-sinteticas']);
|
|
178
|
+
assert(r.status === 0, `D7d: exit 0 no repo sintético (status=${r.status})`);
|
|
179
|
+
assert(
|
|
180
|
+
campo(r.stdout, 'total') === '0',
|
|
181
|
+
`D7d: story que NASCE Ready não é contada — total=0. LIMITAÇÃO CONHECIDA e aceita (ADR-035 M7/dívida 1): a classe <ausente>->ready tem teto de 20 em 90 (22%) no framework, e a perda sempre SUBTRAI, nunca infla a contagem que autorizaria um deny. Se este número virar 1, alguém ampliou a detecção — o que pode ser bom, mas é decisão do dono, não efeito colateral (medido: ${campo(r.stdout, 'total')})`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
// D4 — o instrumento NUNCA é trava
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
|
|
189
|
+
function testNuncaTrava() {
|
|
190
|
+
console.log('\n--- D4: exit 0 sempre, com diagnóstico (nunca silêncio, nunca crash) ---');
|
|
191
|
+
|
|
192
|
+
const inexistente = path.join(os.tmpdir(), 'derive-alvo-que-nao-existe-4c1f9a');
|
|
193
|
+
const r = rodar([inexistente]);
|
|
194
|
+
assert(r.status === 0, `D4: repositório-alvo inexistente ⇒ exit 0 (status=${r.status})`);
|
|
195
|
+
assert(/DIAGNOSTICO/.test(r.stdout), 'D4: a falha é DECLARADA no stdout — nem silêncio (indistinguível de "zero transições") nem exceção não tratada');
|
|
196
|
+
|
|
197
|
+
const semGit = fs.mkdtempSync(path.join(os.tmpdir(), 'derive-sem-git-'));
|
|
198
|
+
const r2 = rodar([semGit]);
|
|
199
|
+
assert(r2.status === 0 && /DIAGNOSTICO/.test(r2.stdout), `D4: diretório que existe mas não é repo git ⇒ exit 0 + diagnóstico (status=${r2.status})`);
|
|
200
|
+
|
|
201
|
+
const r3 = rodar(['.', '--rev']);
|
|
202
|
+
assert(r3.status === 0 && /DIAGNOSTICO/.test(r3.stdout), `D4: opção sem valor ⇒ exit 0 + diagnóstico (status=${r3.status})`);
|
|
203
|
+
|
|
204
|
+
const r4 = rodar(['.', '--rev', 'ref-que-nao-existe-4c1f9a', '--stories-dir', 'docs/stories']);
|
|
205
|
+
assert(r4.status === 0 && /DIAGNOSTICO/.test(r4.stdout), `D4: rev irresolvível ⇒ exit 0 + diagnóstico (status=${r4.status})`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// D2 / Segurança — fonte única e invocação sem shell
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
function testFonteUnicaESeguranca() {
|
|
213
|
+
console.log('\n--- D2 (fonte única) e Segurança (git por array, sem shell) ---');
|
|
214
|
+
|
|
215
|
+
const src = fs.readFileSync(SCRIPT, 'utf8');
|
|
216
|
+
|
|
217
|
+
assert(/enforce-cycle-authority/.test(src) && /enforce-ready-oracles/.test(src), 'D2: o instrumento REFERENCIA os dois hooks por path — isto é, os carrega em vez de copiá-los');
|
|
218
|
+
const redefine = /function\s+(extractStatusSection|statusToken|evaluateReadyOracles)\s*\(/.test(src);
|
|
219
|
+
assert(!redefine, 'D2: nenhum dos 3 predicados (extractStatusSection/statusToken/evaluateReadyOracles) é redefinido aqui — uma 2ª implementação poderia divergir do hook sobre o que É uma transição');
|
|
220
|
+
|
|
221
|
+
assert(/execFileSync\(\s*'git'\s*,\s*\[/.test(src), 'Segurança: `git` é invocado por execFileSync com argumentos em ARRAY');
|
|
222
|
+
assert(!/\bexecSync\(|\bexec\(|shell\s*:\s*true/.test(src), 'Segurança: nenhum `exec`/`execSync`/`shell: true` — o path do alvo nunca é concatenado em string de comando');
|
|
223
|
+
|
|
224
|
+
// O instrumento NÃO viaja para instalações (D5). Assertado, não só omitido:
|
|
225
|
+
// sem isto, a próxima passada "conserta" a ausência do manifesto.
|
|
226
|
+
const manifesto = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'installer', 'motor-scripts.json'), 'utf8'));
|
|
227
|
+
assert(
|
|
228
|
+
!manifesto.scripts.some((s) => s.path === 'scripts/derive-ready-transitions.cjs'),
|
|
229
|
+
'D5: o instrumento NÃO está em scripts[] do manifesto — a decisão que ele serve acontece uma vez, no repositório do framework',
|
|
230
|
+
);
|
|
231
|
+
assert(
|
|
232
|
+
manifesto.exclude.includes('derive-ready-transitions.cjs'),
|
|
233
|
+
'D5: o instrumento está no `exclude` do manifesto — a não-distribuição é DECIDIDA, não um esquecimento que o invariante 1 acusaria',
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Parser de log — puro, testável sem git
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
function testParseLog() {
|
|
242
|
+
console.log('\n--- parseLog: puro, sem git ---');
|
|
243
|
+
|
|
244
|
+
const { parseLog } = require(SCRIPT);
|
|
245
|
+
const SEP = '\u0001';
|
|
246
|
+
const texto = `${SEP}abc123|2026-08-09T02:34:21-04:00\ndocs/stories/a.story.md\ndocs/stories/README.md\n\n${SEP}def456|2026-08-08T10:00:00-04:00\ndocs/stories/b.story.md\n`;
|
|
247
|
+
const regs = parseLog(texto);
|
|
248
|
+
assert(regs.length === 2, `parseLog: 2 registros (medido: ${regs.length})`);
|
|
249
|
+
assert(regs[0].sha === 'abc123' && regs[0].iso === '2026-08-09T02:34:21-04:00', 'parseLog: sha e data do cabeçalho');
|
|
250
|
+
assert(regs[0].arquivos.length === 1 && regs[0].arquivos[0] === 'docs/stories/a.story.md', 'parseLog: só `*.story.md` entra (README.md do mesmo commit é descartado)');
|
|
251
|
+
assert(parseLog('').length === 0 && parseLog(null).length === 0, 'parseLog: entrada vazia/nula não vira registro fantasma');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
|
|
256
|
+
console.log('=== derive-ready-transitions.test.cjs — ADR-035 D7 (SF13.8) ===');
|
|
257
|
+
testParseLog();
|
|
258
|
+
testControlePositivo();
|
|
259
|
+
testControleNegativo();
|
|
260
|
+
testFalsoNegativoDeclarado();
|
|
261
|
+
testNuncaTrava();
|
|
262
|
+
testFonteUnicaESeguranca();
|
|
263
|
+
testCorpusReal();
|
|
264
|
+
|
|
265
|
+
if (failures > 0) {
|
|
266
|
+
console.error(`\n${failures} falha(s).`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
console.log('\nTodos os testes passaram.');
|