@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,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* migration-manifest.test.cjs — suíte PRÓPRIA do escritor único (Story SF3.1).
|
|
5
|
+
* NÃO-fake-green: cada recusa é provada por um artefato/estado real, não por relato.
|
|
6
|
+
* Cobre:
|
|
7
|
+
* AC7 escritor único: 7 subcomandos; integrity gravado; hash divergente → exit 3.
|
|
8
|
+
* AC8 baseline snapshot no open-line (listagem + sha256 por arquivo).
|
|
9
|
+
* AC9 close-line binding: run_id forjado / spec_hash divergente / run_id de OUTRO
|
|
10
|
+
* workflow → RECUSA; wf_path RE-EXECUTA validate-pod-workflow (exit 0 exigido).
|
|
11
|
+
* AC10 RAIZ DE CONFIANÇA EM CÓDIGO: verify[] = {cmd:true} NÃO muda o veredito.
|
|
12
|
+
* Mais: retomada idempotente, ordem de fases, coverage, verify re-abre linha stale.
|
|
13
|
+
*
|
|
14
|
+
* Node >= 18. Exit 0/1.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('node:fs');
|
|
18
|
+
const os = require('node:os');
|
|
19
|
+
const path = require('node:path');
|
|
20
|
+
|
|
21
|
+
const m = require('./migration-manifest.cjs');
|
|
22
|
+
const g = require('./forge-generate.cjs');
|
|
23
|
+
|
|
24
|
+
let passed = 0;
|
|
25
|
+
const failures = [];
|
|
26
|
+
function ok(cond, label) {
|
|
27
|
+
if (cond) { passed++; console.log(`[OK ] ${label}`); }
|
|
28
|
+
else { failures.push(label); console.log(`[FALHA] ${label}`); }
|
|
29
|
+
}
|
|
30
|
+
function refuses(fn, code, label) {
|
|
31
|
+
let got = null;
|
|
32
|
+
try { fn(); } catch (e) { got = e.exitCode; }
|
|
33
|
+
ok(got === code, `${label} (exit ${code}${got === code ? '' : ` — obtido ${got}`})`);
|
|
34
|
+
}
|
|
35
|
+
function tmp(name) { return fs.mkdtempSync(path.join(os.tmpdir(), `mm-${name}-`)); }
|
|
36
|
+
|
|
37
|
+
// Cenário base: pod real gerado (wf válido para o re-exec do validador) + manifest.
|
|
38
|
+
function scenario() {
|
|
39
|
+
const dir = tmp('sc');
|
|
40
|
+
const pod = path.join(dir, 'pod');
|
|
41
|
+
const spec = { pod: 'testpod', agents: [{ name: 'builder', output: 'pkg', sections: ['## Contexto', '## Output'] }] };
|
|
42
|
+
const specPath = path.join(dir, 'wf-x.spec.json');
|
|
43
|
+
fs.writeFileSync(specPath, JSON.stringify(spec));
|
|
44
|
+
// SF12.4a/ADR-030 Bloco O — pod-base do cenário (bootstrap do fixture) — 'derived'.
|
|
45
|
+
g.generatePod(spec, pod, { tierOverride: 'STANDARD/COMPLEX', specOrigin: 'derived' });
|
|
46
|
+
const wfPath = path.join(pod, 'workflows', 'wf-testpod.yaml');
|
|
47
|
+
const mf = path.join(dir, 'MIGRATION-sq.yaml');
|
|
48
|
+
const runDir = path.join(dir, 'runs'); fs.mkdirSync(runDir, { recursive: true });
|
|
49
|
+
const goodRun = path.join(runDir, 'good.json');
|
|
50
|
+
fs.writeFileSync(goodRun, JSON.stringify({ pod: 'testpod', workflow: 'wf-x', run_id: 'r1', mode: 'auto', steps: { builder: { status: 'done' } }, updated_at: 'T' }));
|
|
51
|
+
const wrongRun = path.join(runDir, 'wrong.json');
|
|
52
|
+
fs.writeFileSync(wrongRun, JSON.stringify({ pod: 'testpod', workflow: 'wf-OUTRO', run_id: 'r2', mode: 'auto', steps: {}, updated_at: 'T' }));
|
|
53
|
+
return { dir, pod, spec, specPath, wfPath, mf, runDir, goodRun, wrongRun };
|
|
54
|
+
}
|
|
55
|
+
// F1 SINTÉTICA (pós-QA sf3.3): open-line agora exige triagem 'migrate' APROVADA
|
|
56
|
+
// INCONDICIONALMENTE (sem caminho dormente). Os unit tests dão aprovação sintética.
|
|
57
|
+
function approveWf(mf, wf) {
|
|
58
|
+
m.cmdTriageSet(mf, { workflow: wf, disposition: 'migrate', purpose: 'fixture:1', basis: 'dado', now: 'T' });
|
|
59
|
+
m.cmdTriageApprove(mf, { workflow: wf, approvedBy: 'daniel', now: 'T' });
|
|
60
|
+
}
|
|
61
|
+
function initMf(s) { return m.cmdInit(s.mf, { squad: 'sq', squadDir: s.pod, now: 'T0' }); }
|
|
62
|
+
function toGates(s) {
|
|
63
|
+
initMf(s);
|
|
64
|
+
approveWf(s.mf, 'wf-x');
|
|
65
|
+
m.cmdOpenLine(s.mf, { workflow: 'wf-x', spec: s.specPath, podDir: s.pod, pod: 'testpod', owns: ['workflows/wf-testpod.yaml'], now: 'T1' });
|
|
66
|
+
for (const p of ['generated', 'distilled', 'linted', 'gates']) m.cmdAdvance(s.mf, { workflow: 'wf-x', to: p, now: 'T' });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// AC7 — escritor único: subcomandos, integrity, hash divergente → exit 3.
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
{
|
|
73
|
+
const s = scenario();
|
|
74
|
+
const init = initMf(s);
|
|
75
|
+
ok(init.action === 'init' && fs.existsSync(s.mf), 'AC7 init cria o manifest em docs/migration/ (aqui: tmp)');
|
|
76
|
+
ok(/^integrity: "[0-9a-f]{64}"$/m.test(fs.readFileSync(s.mf, 'utf8')), 'AC7 integrity (sha256) gravado a cada escrita');
|
|
77
|
+
// triage exige colunas de evidência
|
|
78
|
+
refuses(() => m.cmdTriageSet(s.mf, { workflow: 'wf-x', disposition: 'migrate', now: 'T' }), 2, 'AC7 triage-set sem --purpose/--basis → recusa');
|
|
79
|
+
m.cmdTriageSet(s.mf, { workflow: 'wf-x', disposition: 'migrate', purpose: 'README.md:12', overlap: 'o.md:3', basis: 'dado', now: 'T' });
|
|
80
|
+
ok(m.readManifest(s.mf).triage.length === 1, 'AC7 triage-set grava a linha com evidência');
|
|
81
|
+
// hash divergente → exit 3 (edição à mão)
|
|
82
|
+
let txt = fs.readFileSync(s.mf, 'utf8').replace('README.md:12', 'ADULTERADO');
|
|
83
|
+
fs.writeFileSync(s.mf, txt);
|
|
84
|
+
refuses(() => m.readManifest(s.mf), 3, 'AC7 manifest editado à mão (hash divergente) → exit 3');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// AC8 — baseline snapshot no open-line.
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
{
|
|
91
|
+
const s = scenario();
|
|
92
|
+
initMf(s); approveWf(s.mf, 'wf-x');
|
|
93
|
+
const ol = m.cmdOpenLine(s.mf, { workflow: 'wf-x', spec: s.specPath, podDir: s.pod, pod: 'testpod', owns: ['workflows/wf-testpod.yaml'], now: 'T1' });
|
|
94
|
+
ok(ol.baseline > 0, 'AC8 open-line grava baseline (listagem da árvore do pod)');
|
|
95
|
+
const line = m.readManifest(s.mf).lines[0];
|
|
96
|
+
ok(Array.isArray(line.baseline) && line.baseline.every((e) => e.path && /^[0-9a-f]{64}$/.test(e.sha256)),
|
|
97
|
+
'AC8 baseline = {path, sha256} por arquivo (para o diff triplo de SF3.3)');
|
|
98
|
+
ok(line.spec_hash && line.owns.includes('workflows/wf-testpod.yaml') && line.phase === 'spec', 'AC8 open-line grava spec_hash+owns+phase=spec');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// AC7 — ordem de fases fail-loud.
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
{
|
|
105
|
+
const s = scenario();
|
|
106
|
+
initMf(s); approveWf(s.mf, 'wf-x');
|
|
107
|
+
m.cmdOpenLine(s.mf, { workflow: 'wf-x', spec: s.specPath, podDir: s.pod, pod: 'testpod', owns: [], now: 'T1' });
|
|
108
|
+
refuses(() => m.cmdAdvance(s.mf, { workflow: 'wf-x', to: 'gates', now: 'T' }), 2, 'AC7 advance fora de ordem (spec→gates pulando fases) → recusa');
|
|
109
|
+
refuses(() => m.cmdAdvance(s.mf, { workflow: 'wf-x', to: 'closed', now: 'T' }), 2, 'AC7 advance não fecha a linha (closed é do close-line)');
|
|
110
|
+
const a = m.cmdAdvance(s.mf, { workflow: 'wf-x', to: 'generated', now: 'T' });
|
|
111
|
+
ok(a.hook === null, 'AC7 advance→generated sem hook');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// AC9 — close-line binding + re-execução do validador estático.
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
{
|
|
118
|
+
const s = scenario(); toGates(s);
|
|
119
|
+
const gatesHook = m.readManifest(s.mf); // já em gates
|
|
120
|
+
ok(gatesHook.lines[0].phase === 'gates', 'AC9 linha em gates pronta para close');
|
|
121
|
+
// run_id forjado (inexistente) → recusa
|
|
122
|
+
refuses(() => m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: s.wfPath, runIds: [path.join(s.runDir, 'nope.json')], now: 'T' }), 2, 'AC9 run_id inexistente (forjado) → RECUSA');
|
|
123
|
+
// run_id de OUTRO workflow (binding não confere) → recusa
|
|
124
|
+
refuses(() => m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: s.wfPath, runIds: [s.wrongRun], now: 'T' }), 2, 'AC9 run_id de OUTRO workflow (binding workflow+pod) → RECUSA');
|
|
125
|
+
// wf_path que NÃO passa validate-pod-workflow → recusa (re-execução real, não só existência)
|
|
126
|
+
const badWf = path.join(s.dir, 'wf-bad.yaml'); fs.writeFileSync(badWf, 'isto não é um contrato de workflow válido\n');
|
|
127
|
+
refuses(() => m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: badWf, runIds: [s.goodRun], now: 'T' }), 2, 'AC9 wf_path inválido: validate-pod-workflow RE-EXECUTADO falha → RECUSA');
|
|
128
|
+
// evidência válida → fecha
|
|
129
|
+
const closed = m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: s.wfPath, runIds: [s.goodRun], now: 'T' });
|
|
130
|
+
ok(closed.phase === 'closed', 'AC9 evidência com binding + wf válido re-executado → FECHA a linha');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// AC9 — spec_hash divergente (spec mudou após open-line) → recusa no close.
|
|
134
|
+
{
|
|
135
|
+
const s = scenario(); toGates(s);
|
|
136
|
+
fs.writeFileSync(s.specPath, JSON.stringify({ pod: 'testpod', agents: ['builder', 'novo'] })); // muda a spec no disco
|
|
137
|
+
refuses(() => m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: s.wfPath, runIds: [s.goodRun], now: 'T' }), 2, 'AC9 spec_hash divergente (spec mudou no disco) → RECUSA');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
// AC10 — RAIZ DE CONFIANÇA EM CÓDIGO: verify[]={cmd:true} não compra nada.
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
{
|
|
144
|
+
const s = scenario(); toGates(s);
|
|
145
|
+
m.cmdCloseLine(s.mf, { workflow: 'wf-x', wfPath: s.wfPath, runIds: [s.goodRun], now: 'T' });
|
|
146
|
+
// verify por código confirma a linha íntegra.
|
|
147
|
+
const v1 = m.cmdVerify(s.mf);
|
|
148
|
+
ok(v1.stale.length === 0, 'AC10 verify: linha fechada com evidência real re-verifica OK por código');
|
|
149
|
+
// Atacante recomputa o hash (limite declarado do integrity) e injeta verify[]={cmd:true}
|
|
150
|
+
// E quebra a evidência real (run_id apontando para arquivo inexistente).
|
|
151
|
+
const doc = m.readManifest(s.mf);
|
|
152
|
+
const line = doc.lines.find((l) => l.workflow === 'wf-x');
|
|
153
|
+
line.verify = [{ cmd: 'true' }];
|
|
154
|
+
line.run_ids = [path.join(s.runDir, 'apagado.json')]; // evidência dinâmica destruída
|
|
155
|
+
m.writeManifest(s.mf, doc); // grava com integrity recomputado (válido)
|
|
156
|
+
ok(m.readManifest(s.mf), 'AC10 integrity recomputado é válido (o hash não é a raiz — limite declarado)');
|
|
157
|
+
const v2 = m.cmdVerify(s.mf);
|
|
158
|
+
ok(v2.stale.length === 1, 'AC10 verify[]={cmd:true} NÃO muda o veredito: evidência quebrada → linha STALE (raiz é código)');
|
|
159
|
+
// e a linha foi REABERTA (stale → phase gates).
|
|
160
|
+
ok(m.readManifest(s.mf).lines.find((l) => l.workflow === 'wf-x').phase === 'gates', 'AC10 linha stale REABERTA (phase volta a gates)');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// coverage — diff squad × manifest (0 sem endereço quando tudo endereçado).
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
{
|
|
167
|
+
const s = scenario();
|
|
168
|
+
const squad = path.join(s.dir, 'squad'); fs.mkdirSync(path.join(squad, 'workflows'), { recursive: true });
|
|
169
|
+
fs.writeFileSync(path.join(squad, 'workflows', 'wf-x.yaml'), 'steps:\n');
|
|
170
|
+
fs.writeFileSync(path.join(squad, 'workflows', 'wf-orfa.yaml'), 'steps:\n');
|
|
171
|
+
m.cmdInit(s.mf, { squad: 'sq', squadDir: s.pod, now: 'T0' });
|
|
172
|
+
m.cmdTriageSet(s.mf, { workflow: 'wf-x', disposition: 'migrate', purpose: 'p:1', basis: 'dado', now: 'T' });
|
|
173
|
+
const cov = m.cmdCoverage(s.mf, { squadDir: squad });
|
|
174
|
+
ok(!cov.clean && cov.unaddressed.some((u) => /wf-orfa/.test(u)), 'coverage detecta o workflow órfão sem endereço (não fecha com diff não-vazio)');
|
|
175
|
+
m.cmdTriageSet(s.mf, { workflow: 'wf-orfa', disposition: 'dispense', purpose: 'p:2', basis: 'julgamento', now: 'T' });
|
|
176
|
+
ok(m.cmdCoverage(s.mf, { squadDir: squad }).clean, 'coverage = 0 sem endereço após triar o órfão');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
console.log(`\n${passed}/${passed + failures.length} verificações do manifest passaram.`);
|
|
180
|
+
if (failures.length) {
|
|
181
|
+
console.error('\nSUÍTE migration-manifest (SF3.1) FALHOU:');
|
|
182
|
+
for (const f of failures) console.error(` - ${f}`);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
console.log('Suíte migration-manifest verde (escritor único + integrity + binding + raiz de confiança em código).');
|
|
186
|
+
process.exit(0);
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* npm-scope-invocation.test.cjs — suíte do rename do pacote npm para
|
|
5
|
+
* `@daniellins/power-claude` (Story SF11.9).
|
|
6
|
+
*
|
|
7
|
+
* Por que esta suíte existe: o nome NÃO-escopado `power-claude` pertence a um
|
|
8
|
+
* terceiro no registry público (`neural-llm-io/power-claude`). Toda prosa do
|
|
9
|
+
* framework que mande alguém rodar `npx power-claude ...` leva o usuário a
|
|
10
|
+
* BAIXAR E EXECUTAR código alheio. Renomear o pacote nos dá um nome seguro para
|
|
11
|
+
* recomendar; NÃO torna o nome inseguro menos perigoso caso alguém o digite.
|
|
12
|
+
* Por isso o sweep (AC8) continua vigiando a string sem escopo para sempre.
|
|
13
|
+
*
|
|
14
|
+
* Oráculo COMPORTAMENTAL, não textual (AC7 — fecha a dívida apontada pelo QA da
|
|
15
|
+
* SF10.20, `docs/stories/sf10.20.story.md:445`): o teste EXECUTA `bin/cli.js`
|
|
16
|
+
* como processo real e assere sobre o STDOUT/STDERR entregue ao usuário, nunca
|
|
17
|
+
* sobre o arquivo-fonte. Grepar o fonte provaria que a string existe no disco;
|
|
18
|
+
* só a execução prova que é ISSO que o usuário lê.
|
|
19
|
+
*
|
|
20
|
+
* Cobre: AC1 (name/bin), AC2 (publishConfig.access), AC7 (comportamental),
|
|
21
|
+
* AC8 (sweep de regressão com allowlist explícita).
|
|
22
|
+
*
|
|
23
|
+
* Node >= 18, sem dependências externas. Exit 0/1.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
const { spawnSync } = require('node:child_process');
|
|
29
|
+
|
|
30
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
31
|
+
const CLI = path.join(REPO_ROOT, 'bin', 'cli.js');
|
|
32
|
+
|
|
33
|
+
const SCOPED = '@daniellins/power-claude';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Padrão do risco: `npx` seguido de `power-claude` SEM escopo.
|
|
37
|
+
* Deliberadamente NÃO casa:
|
|
38
|
+
* - `npx @daniellins/power-claude ...` (o token após `npx` é `@daniellins/...`)
|
|
39
|
+
* - `npx github:daniellins/power-claude ...` (instalação por GitHub, não registry)
|
|
40
|
+
* Ambos os não-casamentos são exercitados por asserção abaixo, para que o
|
|
41
|
+
* próprio padrão do sweep seja provado — e não presumido.
|
|
42
|
+
*/
|
|
43
|
+
const UNSCOPED_NPX = /\bnpx\s+power-claude\b/;
|
|
44
|
+
|
|
45
|
+
/** Arquivos/linhas onde a string SEM escopo é esperada e CORRETA: comentários
|
|
46
|
+
* que documentam o risco (defesa da SF10.20), não instrução de invocação.
|
|
47
|
+
* Preservados pelo AC9 — `git diff` desses arquivos tem de ficar vazio. */
|
|
48
|
+
const SWEEP_ALLOWLIST = [
|
|
49
|
+
{ ref: 'installer/manifest.js:15', mustContain: 'REGISTRY PÚBLICO' },
|
|
50
|
+
{ ref: 'installer/doctor.js:34', mustContain: 'Nunca prescrever' },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const SWEEP_TARGETS = ['bin', 'installer', 'template', 'README.md'];
|
|
54
|
+
|
|
55
|
+
let passed = 0;
|
|
56
|
+
const failures = [];
|
|
57
|
+
function ok(cond, label) {
|
|
58
|
+
if (cond) { passed++; console.log(`[OK ] ${label}`); }
|
|
59
|
+
else { failures.push(label); console.error(`[FALHA] ${label}`); }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ===========================================================================
|
|
63
|
+
// (AC1/AC2) manifesto do pacote — JSON.parse, não grep de texto
|
|
64
|
+
// ===========================================================================
|
|
65
|
+
console.log('--- (AC1/AC2) package.json: name, bin, publishConfig ---');
|
|
66
|
+
|
|
67
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8'));
|
|
68
|
+
|
|
69
|
+
ok(pkg.name === SCOPED, `name === "${SCOPED}" (recebido: "${pkg.name}")`);
|
|
70
|
+
|
|
71
|
+
// A CHAVE de `bin` é o nome do EXECUTÁVEL que o npm põe no PATH — independente
|
|
72
|
+
// do nome (escopado) do pacote. Mantê-la é decisão explícita da story, não
|
|
73
|
+
// omissão: o risco de supply-chain vem de `npx <pacote>`, não do nome do binário.
|
|
74
|
+
ok(pkg.bin && pkg.bin['power-claude'] === 'bin/cli.js',
|
|
75
|
+
'chave de bin permanece "power-claude" -> bin/cli.js (nome do comando, não do pacote)');
|
|
76
|
+
ok(pkg.bin && Object.keys(pkg.bin).length === 1,
|
|
77
|
+
'bin declara exatamente 1 executável (nenhum alias novo introduzido)');
|
|
78
|
+
|
|
79
|
+
// A armadilha central: pacote ESCOPADO nasce PRIVADO no npm. Sem isto,
|
|
80
|
+
// `npm publish` falha — ou, pior, publica privado sem ninguém perceber.
|
|
81
|
+
ok(pkg.publishConfig && pkg.publishConfig.access === 'public',
|
|
82
|
+
'publishConfig.access === "public" (pacote escopado é privado por default)');
|
|
83
|
+
|
|
84
|
+
// ===========================================================================
|
|
85
|
+
// (AC7) ORÁCULO COMPORTAMENTAL — executa o binário real, lê a saída real
|
|
86
|
+
// ===========================================================================
|
|
87
|
+
console.log('--- (AC7) execução real de bin/cli.js: stdout/stderr entregues ao usuário ---');
|
|
88
|
+
|
|
89
|
+
const help = spawnSync(process.execPath, [CLI, '--help'], { encoding: 'utf8' });
|
|
90
|
+
|
|
91
|
+
ok(help.status === 0, `\`node bin/cli.js --help\` sai 0 (recebido: ${help.status})`);
|
|
92
|
+
ok(typeof help.stdout === 'string' && help.stdout.trim() !== '', '--help escreve algo em stdout');
|
|
93
|
+
ok(help.stdout.includes(`npx ${SCOPED}`),
|
|
94
|
+
`stdout de --help contém "npx ${SCOPED}"`);
|
|
95
|
+
ok(!UNSCOPED_NPX.test(help.stdout),
|
|
96
|
+
'stdout de --help NÃO contém `npx power-claude` sem escopo (supply-chain)');
|
|
97
|
+
|
|
98
|
+
// O mesmo HELP chega ao usuário por STDERR nos caminhos de erro do CLI —
|
|
99
|
+
// canal distinto, mesma superfície de orientação. Se o rename tivesse sido
|
|
100
|
+
// aplicado só em parte do texto, este ramo pegaria.
|
|
101
|
+
const bad = spawnSync(process.execPath, [CLI, 'comando-que-nao-existe'], { encoding: 'utf8' });
|
|
102
|
+
ok(bad.status === 2, `argumento desconhecido sai 2 (recebido: ${bad.status})`);
|
|
103
|
+
ok(!UNSCOPED_NPX.test(bad.stderr),
|
|
104
|
+
'stderr do caminho de erro NÃO contém `npx power-claude` sem escopo');
|
|
105
|
+
ok(bad.stderr.includes(`npx ${SCOPED}`),
|
|
106
|
+
`stderr do caminho de erro contém "npx ${SCOPED}"`);
|
|
107
|
+
|
|
108
|
+
const version = spawnSync(process.execPath, [CLI, '--version'], { encoding: 'utf8' });
|
|
109
|
+
ok(version.status === 0, `\`node bin/cli.js --version\` sai 0 (recebido: ${version.status})`);
|
|
110
|
+
ok(version.stdout.trim() === pkg.version,
|
|
111
|
+
`--version imprime a versão do manifesto renomeado (${pkg.version})`);
|
|
112
|
+
ok(!UNSCOPED_NPX.test(version.stdout),
|
|
113
|
+
'stdout de --version NÃO contém `npx power-claude` sem escopo');
|
|
114
|
+
|
|
115
|
+
// ===========================================================================
|
|
116
|
+
// (AC8) SWEEP DE REGRESSÃO — grep programático, allowlist explícita
|
|
117
|
+
// ===========================================================================
|
|
118
|
+
console.log('--- (AC8) sweep: `npx power-claude` sem escopo em bin/, installer/, template/, README.md ---');
|
|
119
|
+
|
|
120
|
+
// O padrão do sweep é ele próprio testado: se `UNSCOPED_NPX` casasse a forma
|
|
121
|
+
// escopada ou a do GitHub, o sweep viraria ruído e seria desligado por alguém.
|
|
122
|
+
ok(!UNSCOPED_NPX.test(`npx ${SCOPED} install`),
|
|
123
|
+
'padrão do sweep NÃO casa a forma escopada (senão o sweep seria falso-positivo)');
|
|
124
|
+
ok(!UNSCOPED_NPX.test('npx github:daniellins/power-claude install'),
|
|
125
|
+
'padrão do sweep NÃO casa `npx github:...` (instalação por GitHub, fora do registry)');
|
|
126
|
+
ok(UNSCOPED_NPX.test('npx power-claude install'),
|
|
127
|
+
'padrão do sweep CASA a forma perigosa sem escopo (o sweep de fato detecta)');
|
|
128
|
+
|
|
129
|
+
function isProbablyBinary(buf) {
|
|
130
|
+
return buf.subarray(0, 8000).includes(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function collectFiles(target) {
|
|
134
|
+
const full = path.join(REPO_ROOT, target);
|
|
135
|
+
if (!fs.existsSync(full)) return [];
|
|
136
|
+
const out = [];
|
|
137
|
+
(function walk(p) {
|
|
138
|
+
const st = fs.statSync(p);
|
|
139
|
+
if (st.isFile()) { out.push(p); return; }
|
|
140
|
+
if (!st.isDirectory()) return;
|
|
141
|
+
for (const entry of fs.readdirSync(p, { withFileTypes: true })) {
|
|
142
|
+
if (entry.name === 'node_modules' || entry.name === '.git') continue;
|
|
143
|
+
walk(path.join(p, entry.name));
|
|
144
|
+
}
|
|
145
|
+
})(full);
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const hits = [];
|
|
150
|
+
for (const target of SWEEP_TARGETS) {
|
|
151
|
+
for (const file of collectFiles(target)) {
|
|
152
|
+
const buf = fs.readFileSync(file);
|
|
153
|
+
if (isProbablyBinary(buf)) continue;
|
|
154
|
+
const rel = path.relative(REPO_ROOT, file);
|
|
155
|
+
buf.toString('utf8').split('\n').forEach((line, i) => {
|
|
156
|
+
if (UNSCOPED_NPX.test(line)) hits.push({ ref: `${rel}:${i + 1}`, line: line.trim() });
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log(` ocorrências encontradas: ${hits.length ? hits.map((h) => h.ref).join(', ') : '(nenhuma)'}`);
|
|
162
|
+
|
|
163
|
+
// Oráculo DECISIVO: o conjunto encontrado é exatamente a allowlist.
|
|
164
|
+
const foundRefs = hits.map((h) => h.ref).sort();
|
|
165
|
+
const allowedRefs = SWEEP_ALLOWLIST.map((a) => a.ref).sort();
|
|
166
|
+
ok(JSON.stringify(foundRefs) === JSON.stringify(allowedRefs),
|
|
167
|
+
`sweep retorna exatamente a allowlist [${allowedRefs.join(', ')}]`);
|
|
168
|
+
|
|
169
|
+
// Nenhuma ocorrência sobrevive em bin/, template/ ou README.md — as superfícies
|
|
170
|
+
// de INSTRUÇÃO. A allowlist inteira vive em installer/, e só em comentário.
|
|
171
|
+
const outsideInstaller = hits.filter((h) => !h.ref.startsWith('installer/'));
|
|
172
|
+
ok(outsideInstaller.length === 0,
|
|
173
|
+
`zero ocorrências em bin/, template/, README.md (sobraram: ${outsideInstaller.map((h) => h.ref).join(', ') || 'nenhuma'})`);
|
|
174
|
+
|
|
175
|
+
// Cada item da allowlist é COMENTÁRIO que documenta o risco — não instrução de
|
|
176
|
+
// invocação. Se alguém transformar um desses comentários em prosa de uso, o
|
|
177
|
+
// `file:line` continuaria batendo, mas esta asserção quebra.
|
|
178
|
+
for (const allowed of SWEEP_ALLOWLIST) {
|
|
179
|
+
const hit = hits.find((h) => h.ref === allowed.ref);
|
|
180
|
+
ok(!!hit && (hit.line.startsWith('*') || hit.line.startsWith('//') || hit.line.startsWith('/*')),
|
|
181
|
+
`${allowed.ref} é comentário (documenta o risco, não prescreve invocação)`);
|
|
182
|
+
ok(!!hit && hit.line.includes(allowed.mustContain),
|
|
183
|
+
`${allowed.ref} preserva o teor de advertência ("${allowed.mustContain}")`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ===========================================================================
|
|
187
|
+
console.log('');
|
|
188
|
+
if (failures.length) {
|
|
189
|
+
console.error(`FALHOU: ${failures.length} asserção(ões) de ${passed + failures.length}`);
|
|
190
|
+
for (const f of failures) console.error(` - ${f}`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
console.log(`OK: ${passed} asserções passaram (SF11.9 — rename npm escopado).`);
|
|
194
|
+
process.exit(0);
|