@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,325 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// derive-ready-transitions — a contagem de `D-Dono-2` (i) se DERIVA do git.
|
|
6
|
+
//
|
|
7
|
+
// `ADR-035` (D1-D8). Instrumento OFFLINE, executado sob demanda, fora do
|
|
8
|
+
// caminho quente de qualquer hook. Ele responde "quantas transições reais
|
|
9
|
+
// `Draft`→`Ready` já existem, e qual veredito a v1 da trava emite sobre cada
|
|
10
|
+
// uma" — sem que o hook precise escrever nada, em nenhuma instalação.
|
|
11
|
+
//
|
|
12
|
+
// Contratos que este arquivo honra, cada um com AC próprio na `SF13.8`:
|
|
13
|
+
//
|
|
14
|
+
// • D1 — deriva de `git log --no-merges --name-only -- <dir-de-stories>`,
|
|
15
|
+
// comparando o blob de `<sha>^` com o de `<sha>` para cada `*.story.md`
|
|
16
|
+
// tocado. O alvo é ARGUMENTO: roda contra qualquer repositório, read-only.
|
|
17
|
+
// • D2 — FONTE ÚNICA. `extractStatusSection`/`statusToken` vêm de
|
|
18
|
+
// `enforce-cycle-authority.cjs`; `evaluateReadyOracles`/`loadValidator`
|
|
19
|
+
// vêm de `enforce-ready-oracles.cjs`. Nenhum predicado é reimplementado
|
|
20
|
+
// aqui — uma 2ª implementação poderia divergir do hook sobre o que é uma
|
|
21
|
+
// transição, e a contagem passaria a medir outra coisa que não o hook.
|
|
22
|
+
// • D3 — reporta AS DUAS leituras de `D-Dono-2`: o total do histórico e o
|
|
23
|
+
// total desde um marco (`--since`), mais o veredito por transição.
|
|
24
|
+
// • D4 — NUNCA é trava: `exit 0` SEMPRE, inclusive contra repositório
|
|
25
|
+
// inexistente. Toda falha vira DIAGNOSTICO impresso, nunca exceção
|
|
26
|
+
// propagada e nunca silêncio. Quem promove a trava a `deny` é o dono,
|
|
27
|
+
// lendo o número — nenhuma automação decide por ele.
|
|
28
|
+
// • D5 — NÃO viaja para instalações (`installer/motor-scripts.json`,
|
|
29
|
+
// `exclude`). A decisão que ele serve acontece uma vez, no repositório do
|
|
30
|
+
// framework; instalações são alcançadas de fora, com o alvo como argumento.
|
|
31
|
+
//
|
|
32
|
+
// Segurança (`ADR-035`, seção Segurança): `git` é invocado por `execFileSync`
|
|
33
|
+
// com argumentos em ARRAY — nenhuma variante que interprete shell, nenhuma
|
|
34
|
+
// opção que ligue shell, e o path do repositório-alvo entra como argumento de
|
|
35
|
+
// processo, jamais concatenado em string de comando. Nada do conteúdo lido é
|
|
36
|
+
// executado: o instrumento lê blobs e chama funções puras.
|
|
37
|
+
//
|
|
38
|
+
// Limitação conhecida e DECLARADA (`ADR-035` M7, dívida 1): transição que não
|
|
39
|
+
// chegou a commit é invisível — em particular a classe `<ausente>->ready` (a
|
|
40
|
+
// story nasce `Ready` num commit só). Teto medido: 20 em 90 (22%) no
|
|
41
|
+
// framework. A perda sempre SUBTRAI, nunca infla: para um limiar de "pelo
|
|
42
|
+
// menos 10", errar para baixo é o lado seguro de errar.
|
|
43
|
+
//
|
|
44
|
+
// Uso:
|
|
45
|
+
// node scripts/derive-ready-transitions.cjs [<repoPath>] [--rev <ref>]
|
|
46
|
+
// [--since <ref|data>] [--stories-dir <dir>]
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
const path = require('path');
|
|
50
|
+
const { execFileSync } = require('child_process');
|
|
51
|
+
|
|
52
|
+
const HOOKS_DIR = path.join(__dirname, '..', 'template', '.claude', 'hooks');
|
|
53
|
+
const CYCLE_AUTHORITY_PATH = path.join(HOOKS_DIR, 'enforce-cycle-authority.cjs');
|
|
54
|
+
const READY_ORACLES_PATH = path.join(HOOKS_DIR, 'enforce-ready-oracles.cjs');
|
|
55
|
+
|
|
56
|
+
const DEFAULT_STORIES_DIR = 'docs/stories';
|
|
57
|
+
const STORY_FILE_RE = /\.story\.md$/i;
|
|
58
|
+
const GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
59
|
+
|
|
60
|
+
// Separador de registro no `git log`: um byte que não aparece em sha, data
|
|
61
|
+
// nem path. Evita ter de adivinhar onde termina um commit e começa o próximo.
|
|
62
|
+
const REC_SEP = '\u0001';
|
|
63
|
+
|
|
64
|
+
function out(line) {
|
|
65
|
+
process.stdout.write(`${line}\n`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function diagnostico(msg) {
|
|
69
|
+
out(`DIAGNOSTICO: ${msg}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- git ---------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
// Toda invocação de git passa por aqui. `args` é sempre array; `repo` entra
|
|
75
|
+
// como argumento de `-C`, jamais interpolado em string de comando.
|
|
76
|
+
function git(repo, args) {
|
|
77
|
+
return execFileSync('git', ['-C', repo].concat(args), {
|
|
78
|
+
encoding: 'utf8',
|
|
79
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
80
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function gitOrNull(repo, args) {
|
|
85
|
+
try {
|
|
86
|
+
return git(repo, args);
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- CLI ---------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
function parseArgv(argv) {
|
|
95
|
+
const opts = {
|
|
96
|
+
repoPath: '.',
|
|
97
|
+
rev: 'HEAD',
|
|
98
|
+
since: null,
|
|
99
|
+
storiesDir: DEFAULT_STORIES_DIR,
|
|
100
|
+
erro: null,
|
|
101
|
+
};
|
|
102
|
+
let posicional = false;
|
|
103
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
104
|
+
const a = argv[i];
|
|
105
|
+
if (a === '--rev' || a === '--since' || a === '--stories-dir') {
|
|
106
|
+
const v = argv[i + 1];
|
|
107
|
+
if (typeof v !== 'string' || v.startsWith('--')) {
|
|
108
|
+
opts.erro = `a opção ${a} exige um valor`;
|
|
109
|
+
return opts;
|
|
110
|
+
}
|
|
111
|
+
if (a === '--rev') opts.rev = v;
|
|
112
|
+
if (a === '--since') opts.since = v;
|
|
113
|
+
if (a === '--stories-dir') opts.storiesDir = v;
|
|
114
|
+
i += 1;
|
|
115
|
+
} else if (a.startsWith('--')) {
|
|
116
|
+
opts.erro = `opção desconhecida: ${a}`;
|
|
117
|
+
return opts;
|
|
118
|
+
} else if (!posicional) {
|
|
119
|
+
opts.repoPath = a;
|
|
120
|
+
posicional = true;
|
|
121
|
+
} else {
|
|
122
|
+
opts.erro = `argumento posicional em excesso: ${a}`;
|
|
123
|
+
return opts;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return opts;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// --- derivação ---------------------------------------------------------
|
|
130
|
+
|
|
131
|
+
// Quebra a saída de `git log --name-only` em `{ sha, iso, arquivos[] }`.
|
|
132
|
+
// Puro: recebe texto, devolve estrutura — testável sem git.
|
|
133
|
+
function parseLog(texto) {
|
|
134
|
+
const registros = [];
|
|
135
|
+
for (const bruto of String(texto || '').split(REC_SEP)) {
|
|
136
|
+
const bloco = bruto.replace(/^\n+/, '');
|
|
137
|
+
if (!bloco.trim()) continue;
|
|
138
|
+
const linhas = bloco.split('\n');
|
|
139
|
+
const cabecalho = linhas.shift();
|
|
140
|
+
const barra = cabecalho.indexOf('|');
|
|
141
|
+
if (barra < 0) continue;
|
|
142
|
+
const sha = cabecalho.slice(0, barra).trim();
|
|
143
|
+
const iso = cabecalho.slice(barra + 1).trim();
|
|
144
|
+
const arquivos = linhas.map((l) => l.trim()).filter((l) => l && STORY_FILE_RE.test(l));
|
|
145
|
+
if (!sha) continue;
|
|
146
|
+
registros.push({ sha, iso, arquivos });
|
|
147
|
+
}
|
|
148
|
+
return registros;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function main(argv) {
|
|
152
|
+
const opts = parseArgv(argv);
|
|
153
|
+
out('derive-ready-transitions — instrumento offline (ADR-035, D1-D8). Nunca trava: exit 0 sempre.');
|
|
154
|
+
if (opts.erro) {
|
|
155
|
+
diagnostico(`${opts.erro}. Uso: node scripts/derive-ready-transitions.cjs [<repoPath>] [--rev <ref>] [--since <ref|data>] [--stories-dir <dir>]`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 1. Módulos irmãos (D2). Carregados ANTES de tocar o repositório: sem eles
|
|
160
|
+
// não há predicado nenhum, e "0 transições" seria indistinguível de
|
|
161
|
+
// "não consegui decidir" — a mesma classe de silêncio que o `ADR-032`
|
|
162
|
+
// Emenda 2 recusa no hook.
|
|
163
|
+
let cycleAuthority;
|
|
164
|
+
let readyOracles;
|
|
165
|
+
try {
|
|
166
|
+
cycleAuthority = require(CYCLE_AUTHORITY_PATH);
|
|
167
|
+
readyOracles = require(READY_ORACLES_PATH);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
diagnostico(`não consegui carregar os módulos do framework (${CYCLE_AUTHORITY_PATH}, ${READY_ORACLES_PATH}): ${err && err.message}`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const faltando = [
|
|
173
|
+
['extractStatusSection', cycleAuthority],
|
|
174
|
+
['statusToken', cycleAuthority],
|
|
175
|
+
['evaluateReadyOracles', readyOracles],
|
|
176
|
+
['loadValidator', readyOracles],
|
|
177
|
+
].filter(([nome, mod]) => !mod || typeof mod[nome] !== 'function').map(([nome]) => nome);
|
|
178
|
+
if (faltando.length > 0) {
|
|
179
|
+
diagnostico(`superfície de export incompleta nos módulos do framework — faltam: ${faltando.join(', ')} (skew de template, ADR-019). Sem eles a derivação não é confiável; não conto nada.`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const secaoStatus = cycleAuthority.extractStatusSection;
|
|
183
|
+
const token = cycleAuthority.statusToken;
|
|
184
|
+
|
|
185
|
+
// 2. Repositório-alvo.
|
|
186
|
+
const repo = path.resolve(opts.repoPath);
|
|
187
|
+
const topo = gitOrNull(repo, ['rev-parse', '--show-toplevel']);
|
|
188
|
+
if (topo === null) {
|
|
189
|
+
diagnostico(`"${repo}" não é um repositório git acessível (ou o path não existe) — nada a derivar.`);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const repoRoot = topo.trim();
|
|
193
|
+
const revResolvido = gitOrNull(repo, ['rev-parse', '--verify', `${opts.rev}^{commit}`]);
|
|
194
|
+
if (revResolvido === null) {
|
|
195
|
+
diagnostico(`o rev "${opts.rev}" não resolve para um commit em "${repoRoot}" — nada a derivar.`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const revSha = revResolvido.trim();
|
|
199
|
+
|
|
200
|
+
out(`repo=${repoRoot}`);
|
|
201
|
+
out(`rev=${revSha} (${opts.rev})`);
|
|
202
|
+
out(`stories-dir=${opts.storiesDir}`);
|
|
203
|
+
|
|
204
|
+
// 3. Pares (commit × story) tocados.
|
|
205
|
+
const log = gitOrNull(repo, [
|
|
206
|
+
'log',
|
|
207
|
+
revSha,
|
|
208
|
+
'--no-merges',
|
|
209
|
+
'--name-only',
|
|
210
|
+
'--pretty=format:%x01%H|%cI',
|
|
211
|
+
'--',
|
|
212
|
+
opts.storiesDir,
|
|
213
|
+
]);
|
|
214
|
+
if (log === null) {
|
|
215
|
+
diagnostico(`git log falhou em "${repoRoot}" para o rev "${opts.rev}" e o diretório "${opts.storiesDir}" — nada a derivar.`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const registros = parseLog(log);
|
|
219
|
+
const pares = registros.reduce((n, r) => n + r.arquivos.length, 0);
|
|
220
|
+
|
|
221
|
+
// 4. Transições: `draft` antes, `ready` depois, pelos MESMOS predicados do
|
|
222
|
+
// hook. `<sha>^` não existe no commit-raiz — o blob "antes" é string
|
|
223
|
+
// vazia por desenho (a story nasce naquele commit), nunca exceção solta.
|
|
224
|
+
const transicoes = [];
|
|
225
|
+
for (const reg of registros) {
|
|
226
|
+
for (const arquivo of reg.arquivos) {
|
|
227
|
+
const depoisBruto = gitOrNull(repo, ['show', `${reg.sha}:${arquivo}`]);
|
|
228
|
+
if (depoisBruto === null) continue; // arquivo removido neste commit
|
|
229
|
+
if (token(secaoStatus(depoisBruto)) !== 'ready') continue;
|
|
230
|
+
const antesBruto = gitOrNull(repo, ['show', `${reg.sha}^:${arquivo}`]) || '';
|
|
231
|
+
if (token(secaoStatus(antesBruto)) !== 'draft') continue;
|
|
232
|
+
transicoes.push({ sha: reg.sha, iso: reg.iso, arquivo, conteudo: depoisBruto });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
out(`commits=${registros.length} pares=${pares}`);
|
|
237
|
+
out(`total=${transicoes.length}`);
|
|
238
|
+
|
|
239
|
+
// 5. Leitura restrita ao marco (D3). Um sha vira RANGE DE ANCESTRALIDADE
|
|
240
|
+
// (`<since>..<rev>`) — semântica nativa do git, imune ao erro de
|
|
241
|
+
// granularidade de DIA que produziu o `17` corrigido na tabela M3 do
|
|
242
|
+
// `ADR-035`. Uma data vira comparação de instante (>=, como `--since`
|
|
243
|
+
// do git), nunca comparação de string de data.
|
|
244
|
+
if (opts.since) {
|
|
245
|
+
const sinceSha = gitOrNull(repo, ['rev-parse', '--verify', `${opts.since}^{commit}`]);
|
|
246
|
+
if (sinceSha !== null) {
|
|
247
|
+
const marco = sinceSha.trim();
|
|
248
|
+
const rangeBruto = gitOrNull(repo, ['rev-list', `${marco}..${revSha}`]);
|
|
249
|
+
if (rangeBruto === null) {
|
|
250
|
+
out(`desde: indisponivel — git rev-list ${marco}..${revSha} falhou`);
|
|
251
|
+
} else {
|
|
252
|
+
const noRange = new Set(rangeBruto.split('\n').map((l) => l.trim()).filter(Boolean));
|
|
253
|
+
const n = transicoes.filter((t) => noRange.has(t.sha)).length;
|
|
254
|
+
const dataMarco = (gitOrNull(repo, ['log', '-1', '--pretty=format:%cI', marco]) || '').trim();
|
|
255
|
+
out(`desde=${n} marco=${marco.slice(0, 8)} (${opts.since}, ${dataMarco}) criterio=ancestralidade ${marco.slice(0, 8)}..${revSha.slice(0, 8)}`);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
const corte = Date.parse(opts.since);
|
|
259
|
+
if (Number.isNaN(corte)) {
|
|
260
|
+
out(`desde: indisponivel — "${opts.since}" não resolve nem para commit nem para data`);
|
|
261
|
+
} else {
|
|
262
|
+
const n = transicoes.filter((t) => {
|
|
263
|
+
const q = Date.parse(t.iso);
|
|
264
|
+
return !Number.isNaN(q) && q >= corte;
|
|
265
|
+
}).length;
|
|
266
|
+
out(`desde=${n} marco=${new Date(corte).toISOString()} criterio=instante>=corte`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
out('desde: (não solicitado — passe --since <sha|data> para a leitura restrita ao marco de D-Dono-2)');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 6. Replay do veredito da v1 (D2/D3) sobre o conteúdo RESULTANTE de cada
|
|
274
|
+
// transição. É possível porque o hook é PURO: o veredito é função total
|
|
275
|
+
// do conteúdo, e o conteúdo resultante é o que o git guarda.
|
|
276
|
+
// O validador vem do repositório-ALVO — D2 é sobre os PREDICADOS
|
|
277
|
+
// (sempre do framework), não sobre o corpus que eles avaliam.
|
|
278
|
+
const validador = readyOracles.loadValidator(repoRoot);
|
|
279
|
+
const vereditos = new Map();
|
|
280
|
+
if (!validador.ok) {
|
|
281
|
+
out(`replay: indisponivel — scripts/validate-story-acs.cjs ausente ou não carregável em "${validador.path}" (${validador.error && validador.error.message}). O total acima NÃO depende disto.`);
|
|
282
|
+
} else {
|
|
283
|
+
let comAsk = 0;
|
|
284
|
+
const linhasAsk = [];
|
|
285
|
+
for (const t of transicoes) {
|
|
286
|
+
let hits;
|
|
287
|
+
try {
|
|
288
|
+
hits = readyOracles.evaluateReadyOracles(t.conteudo, validador.mod);
|
|
289
|
+
} catch (err) {
|
|
290
|
+
hits = [{ predicate: 'ERRO', id: null, detail: String(err && err.message) }];
|
|
291
|
+
}
|
|
292
|
+
const rotulos = (hits || []).map((h) => `${h.predicate}${h.id ? `/${h.id}` : ''}`);
|
|
293
|
+
vereditos.set(`${t.sha}:${t.arquivo}`, rotulos);
|
|
294
|
+
if (rotulos.length > 0) {
|
|
295
|
+
comAsk += 1;
|
|
296
|
+
linhasAsk.push(`ASK ${t.iso.slice(0, 10)} ${t.sha.slice(0, 8)} ${path.basename(t.arquivo)} :: ${rotulos.join(', ')}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
out(`replay: ask=${comAsk} silencio=${transicoes.length - comAsk} (validador=${validador.path})`);
|
|
300
|
+
for (const l of linhasAsk) out(l);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 7. Cada transição é auditável individualmente — não um total agregado que
|
|
304
|
+
// ninguém pode conferir (`ADR-035`, critério 2: falsificabilidade).
|
|
305
|
+
out('--- transicoes draft->ready (mais recente primeiro): sha data arquivo veredito ---');
|
|
306
|
+
for (const t of transicoes) {
|
|
307
|
+
const rotulos = vereditos.get(`${t.sha}:${t.arquivo}`);
|
|
308
|
+
const veredito = rotulos === undefined ? 'sem-replay' : (rotulos.length > 0 ? `ask(${rotulos.join(', ')})` : 'silencio');
|
|
309
|
+
out(`${t.sha.slice(0, 8)} ${t.iso.slice(0, 10)} ${t.arquivo} ${veredito}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// D4: `exit 0` SEMPRE. A rede é aqui, e é a única — nenhuma rota interna tem
|
|
314
|
+
// try/catch próprio para a mesma classe de falha, senão esta nunca seria
|
|
315
|
+
// exercitada e viraria letra morta (mesma disciplina de `runWithFailSafe`).
|
|
316
|
+
if (require.main === module) {
|
|
317
|
+
try {
|
|
318
|
+
main(process.argv.slice(2));
|
|
319
|
+
} catch (err) {
|
|
320
|
+
diagnostico(`exceção não prevista (${err && err.message}) — o instrumento NUNCA trava: seguindo com exit 0.`);
|
|
321
|
+
}
|
|
322
|
+
process.exitCode = 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
module.exports = { parseLog, parseArgv, main };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* forge-additive.test.cjs — suíte do TIER AGREGADO + MODO ADITIVO (Story SF3.1).
|
|
5
|
+
* Cobre, com pods sintéticos em diretório temporário:
|
|
6
|
+
* AC1 tier agregado do disco (forge-assess-tier --pod-dir / aggregateSpec).
|
|
7
|
+
* AC2 tierOverride: generatePod NÃO re-classifica; forge-upgrade-pod passa o agregado.
|
|
8
|
+
* AC3 DoD1: spec de 2 etapas sobre pod COMPLEX → aparato COMPLEX (squad-io + memória).
|
|
9
|
+
* AC4 --additive recusa colisão de workflowId/template/step-id fora de owns[] (exit 2).
|
|
10
|
+
* AC5 merge por seção do squad-io + guard do memory/README.md (M2).
|
|
11
|
+
* AC6 retomada idempotente por spec_hash+owns[]; spec divergente sobre linha aberta.
|
|
12
|
+
*
|
|
13
|
+
* Node >= 18. Exit 0/1.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('node:fs');
|
|
17
|
+
const os = require('node:os');
|
|
18
|
+
const path = require('node:path');
|
|
19
|
+
const { spawnSync } = require('node:child_process');
|
|
20
|
+
|
|
21
|
+
const at = require('./forge-assess-tier.cjs');
|
|
22
|
+
const g = require('./forge-generate.cjs');
|
|
23
|
+
const { upgradePod } = require('./forge-upgrade-pod.cjs');
|
|
24
|
+
|
|
25
|
+
const SCRIPTS = __dirname;
|
|
26
|
+
let passed = 0;
|
|
27
|
+
const failures = [];
|
|
28
|
+
function ok(cond, label) {
|
|
29
|
+
if (cond) { passed++; console.log(`[OK ] ${label}`); }
|
|
30
|
+
else { failures.push(label); console.log(`[FALHA] ${label}`); }
|
|
31
|
+
}
|
|
32
|
+
function tmp(name) { return fs.mkdtempSync(path.join(os.tmpdir(), `fa-${name}-`)); }
|
|
33
|
+
// SF12.4a/ADR-030 Bloco O — `generatePod` exige `opts.specOrigin`. Estes testes cobrem
|
|
34
|
+
// mecânica ADITIVA/regeneração (owns[]/merge/idempotência), não o Bloco C — 'derived'
|
|
35
|
+
// (mesma leniência de `*upgrade-pod`/`*harden-learning`) evita acoplar esta suíte aos
|
|
36
|
+
// 3 campos canônicos, que são cobertos à parte pelo Bloco O da suíte SF12.4a.
|
|
37
|
+
const DERIVED = { specOrigin: 'derived' };
|
|
38
|
+
function mkPod(dir, agentNames) {
|
|
39
|
+
fs.mkdirSync(path.join(dir, 'agents'), { recursive: true });
|
|
40
|
+
for (const n of agentNames) fs.writeFileSync(path.join(dir, 'agents', `${n}.md`), `# agente ${n}\n`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// AC1 — tier AGREGADO do disco: soma spec + disco.
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
const podA = tmp('podA');
|
|
47
|
+
mkPod(podA, ['a', 'b', 'c', 'd']); // 4 agentes em disco
|
|
48
|
+
const spec2 = { pod: 'p', agents: ['x', 'y'] }; // 2 etapas → SIMPLE isolado
|
|
49
|
+
ok(at.classifyTier(spec2).tier === 'SIMPLE', 'AC1 spec de 2 etapas ISOLADA classifica SIMPLE (baseline do furo)');
|
|
50
|
+
const disk = at.podDiskCounts(podA);
|
|
51
|
+
ok(disk.agents === 4 && disk.workflows === 0 && disk.handoffs === 0, 'AC1 podDiskCounts lê 4 agentes do disco');
|
|
52
|
+
ok(at.classifyTier(at.aggregateSpec(spec2, podA)).tier === 'STANDARD/COMPLEX',
|
|
53
|
+
'AC1 tier AGREGADO (spec 2 + disco 4 = 6 agentes) → STANDARD/COMPLEX');
|
|
54
|
+
// squad-io e wf-*.yaml.smoke.json são EXCLUÍDOS da contagem de workflows.
|
|
55
|
+
const podW = tmp('podW');
|
|
56
|
+
mkPod(podW, ['a']);
|
|
57
|
+
fs.mkdirSync(path.join(podW, 'workflows'), { recursive: true });
|
|
58
|
+
fs.writeFileSync(path.join(podW, 'workflows', 'wf-real.yaml'), 'steps:\n');
|
|
59
|
+
fs.writeFileSync(path.join(podW, 'workflows', 'wf-real.smoke.json'), '{}');
|
|
60
|
+
fs.writeFileSync(path.join(podW, 'squad-io.yaml'), 'pod: p\nhandoffs:\n - from: a\n to: b\n artifact: x\n');
|
|
61
|
+
const diskW = at.podDiskCounts(podW);
|
|
62
|
+
ok(diskW.workflows === 1, 'AC1 conta wf-*.yaml e EXCLUI .smoke.json');
|
|
63
|
+
ok(diskW.handoffs === 1, 'AC1 conta handoffs declarados no squad-io.yaml');
|
|
64
|
+
// CLI --pod-dir
|
|
65
|
+
const specFile = path.join(podA, 'spec.json'); fs.writeFileSync(specFile, JSON.stringify(spec2));
|
|
66
|
+
const cli = spawnSync(process.execPath, [path.join(SCRIPTS, 'forge-assess-tier.cjs'), specFile, '--pod-dir', podA], { encoding: 'utf8' });
|
|
67
|
+
ok(/STANDARD\/COMPLEX/.test(cli.stdout), 'AC1 CLI --pod-dir imprime tier agregado STANDARD/COMPLEX');
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// AC2/AC3 — tierOverride + DoD1 fim-a-fim: aparato COMPLEX gerado.
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
const outSimple = tmp('outSimple');
|
|
73
|
+
const rNoOverride = g.generatePod(spec2, outSimple, DERIVED); // sem override → SIMPLE
|
|
74
|
+
ok(rNoOverride.tier === 'SIMPLE' && !fs.existsSync(path.join(outSimple, 'squad-io.yaml')),
|
|
75
|
+
'AC2 sem override: spec de 2 etapas gera SIMPLE (sem squad-io) — comportamento SF1.4 intacto');
|
|
76
|
+
const outCplx = tmp('outCplx');
|
|
77
|
+
const rOverride = g.generatePod(spec2, outCplx, { tierOverride: 'STANDARD/COMPLEX', ...DERIVED });
|
|
78
|
+
ok(rOverride.tier === 'STANDARD/COMPLEX', 'AC2 tierOverride: generatePod NÃO re-classifica (usa o tier recebido)');
|
|
79
|
+
ok(fs.existsSync(path.join(outCplx, 'squad-io.yaml')), 'AC3 DoD1: squad-io.yaml presente (merge de handoff)');
|
|
80
|
+
ok(fs.existsSync(path.join(outCplx, 'memory', 'learnings.consolidated.md')), 'AC3 DoD1: memória operante presente');
|
|
81
|
+
|
|
82
|
+
// AC2 — forge-upgrade-pod PASSA o assessment agregado como tierOverride.
|
|
83
|
+
const podUp = tmp('podUp');
|
|
84
|
+
mkPod(podUp, ['a', 'b', 'c']); // 3 agentes → agregado STANDARD/COMPLEX
|
|
85
|
+
fs.writeFileSync(path.join(podUp, 'pod-spec.json'), JSON.stringify({ pod: 'up', agents: ['a'] })); // spec do workflow: 1 agente
|
|
86
|
+
// SF6.2/ADR-004 §2: dry-run agora é ZERO escrita — o aparato COMPLEX em disco só existe
|
|
87
|
+
// sob --apply. Verificar disk-state exige apply (o caminho real de escrita); a plano de
|
|
88
|
+
// dry-run (byte-identidade) é coberto em forge.test.cjs. Intenção do AC2 preservada.
|
|
89
|
+
const up = upgradePod(podUp, { apply: true });
|
|
90
|
+
ok(up.tier === 'STANDARD/COMPLEX', 'AC2 upgrade-pod: assessment agregado (3 agentes) = STANDARD/COMPLEX');
|
|
91
|
+
ok(fs.existsSync(path.join(podUp, 'squad-io.yaml')) && fs.existsSync(path.join(podUp, 'memory', 'learnings.consolidated.md')),
|
|
92
|
+
'AC2 upgrade-pod: aparato COMPLEX gerado sob --apply (spec de 1 agente NÃO rebaixa; tier agregado do disco manda)');
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// AC4 — modo aditivo: recusa colisão fora de owns[].
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
const outAdd = tmp('outAdd');
|
|
98
|
+
const base = g.generatePod(spec2, outAdd, { tierOverride: 'STANDARD/COMPLEX', ...DERIVED });
|
|
99
|
+
let collided = false; let code = null; let kind = null;
|
|
100
|
+
try { g.generatePod(spec2, outAdd, { additive: true, tierOverride: 'STANDARD/COMPLEX', owns: [], ...DERIVED }); }
|
|
101
|
+
catch (e) { collided = true; code = e.exitCode; kind = e.collision && e.collision.kind; }
|
|
102
|
+
ok(collided && code === 2, 'AC4 colisão de template/workflowId fora de owns[] → exit 2');
|
|
103
|
+
ok(/template|workflowId|step-id/.test(kind || ''), 'AC4 diagnóstico nomeia a classe de colisão');
|
|
104
|
+
// owned → regenera deterministicamente, SEM exit 2 (não colide contra o próprio trabalho).
|
|
105
|
+
const ownsAll = base.written.map((p) => path.relative(outAdd, p));
|
|
106
|
+
let ownedOk = true;
|
|
107
|
+
try { g.generatePod(spec2, outAdd, { additive: true, tierOverride: 'STANDARD/COMPLEX', owns: ownsAll, ...DERIVED }); }
|
|
108
|
+
catch (e) { ownedOk = false; }
|
|
109
|
+
ok(ownedOk, 'AC4/AC6 artefato em owns[] regenera sem colisão (não recusa o próprio trabalho)');
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// AC5 — merge por seção do squad-io + guard do memory/README.md.
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
const outMerge = tmp('outMerge');
|
|
115
|
+
const m1 = g.generatePod(spec2, outMerge, { tierOverride: 'STANDARD/COMPLEX', ...DERIVED });
|
|
116
|
+
const io = path.join(outMerge, 'squad-io.yaml');
|
|
117
|
+
fs.writeFileSync(io, `${fs.readFileSync(io, 'utf8')}\nvetos:\n - regra_pre_existente\n`);
|
|
118
|
+
// grava conteúdo curado no README de memória, para provar o guard.
|
|
119
|
+
const readme = path.join(outMerge, 'memory', 'README.md');
|
|
120
|
+
fs.writeFileSync(readme, '# README CURADO À MÃO — não sobrescrever\n');
|
|
121
|
+
const spec3 = { pod: 'p', agents: ['x', 'z'] }; // handoff x→z novo
|
|
122
|
+
const rMerge = g.generatePod(spec3, outMerge, { additive: true, tierOverride: 'STANDARD/COMPLEX', owns: m1.written.map((p) => path.relative(outMerge, p)), ...DERIVED });
|
|
123
|
+
const mergedIo = fs.readFileSync(io, 'utf8');
|
|
124
|
+
ok(/vetos:/.test(mergedIo) && /regra_pre_existente/.test(mergedIo), 'AC5 merge preserva seção pré-existente (vetos) do squad-io');
|
|
125
|
+
ok(/to: z/.test(mergedIo) && /to: y/.test(mergedIo), 'AC5 merge UNE handoffs (novo z + original y)');
|
|
126
|
+
ok((rMerge.merged || []).some((p) => p.endsWith('squad-io.yaml')), 'AC5 merge registrado no relatório (não em written)');
|
|
127
|
+
ok(fs.readFileSync(readme, 'utf8').includes('CURADO À MÃO'), 'AC5 guard do memory/README.md: conteúdo curado PRESERVADO (fecha M2)');
|
|
128
|
+
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// AC6 — retomada idempotente vs spec divergente (via manifest open-line).
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
const mm = require('./migration-manifest.cjs');
|
|
133
|
+
const wd = tmp('resume');
|
|
134
|
+
const podR = path.join(wd, 'pod'); mkPod(podR, ['a']);
|
|
135
|
+
const specR = path.join(wd, 'wf-r.spec.json'); fs.writeFileSync(specR, JSON.stringify(spec2));
|
|
136
|
+
const mf = path.join(wd, 'MIGRATION-r.yaml');
|
|
137
|
+
// Pós-QA sf3.3: init exige --squad-dir; open-line exige triagem 'migrate' aprovada.
|
|
138
|
+
mm.cmdInit(mf, { squad: 'r', squadDir: podR, now: 'T0' });
|
|
139
|
+
mm.cmdTriageSet(mf, { workflow: 'wf-r', disposition: 'migrate', purpose: 'fixture:1', basis: 'dado', now: 'T0' });
|
|
140
|
+
mm.cmdTriageApprove(mf, { workflow: 'wf-r', approvedBy: 'daniel', now: 'T0' });
|
|
141
|
+
mm.cmdOpenLine(mf, { workflow: 'wf-r', spec: specR, podDir: podR, owns: ['templates/x-tmpl.md'], now: 'T1' });
|
|
142
|
+
mm.cmdAdvance(mf, { workflow: 'wf-r', to: 'generated', now: 'T2' });
|
|
143
|
+
const resume = mm.cmdOpenLine(mf, { workflow: 'wf-r', spec: specR, podDir: podR, now: 'T3' });
|
|
144
|
+
ok(resume.resumed === true && resume.phase === 'generated', 'AC6 mesmo spec_hash + linha aberta → RETOMA da fase registrada (nunca exit 2)');
|
|
145
|
+
fs.writeFileSync(specR, JSON.stringify({ pod: 'p', agents: ['x', 'y', 'w'] })); // muda a spec
|
|
146
|
+
let divergeCode = null;
|
|
147
|
+
try { mm.cmdOpenLine(mf, { workflow: 'wf-r', spec: specR, podDir: podR, now: 'T4' }); }
|
|
148
|
+
catch (e) { divergeCode = e.exitCode; }
|
|
149
|
+
ok(divergeCode === 2, 'AC6 spec_hash divergente sobre linha aberta → exit 2 (exige --amend)');
|
|
150
|
+
|
|
151
|
+
console.log(`\n${passed}/${passed + failures.length} verificações (tier agregado + modo aditivo) passaram.`);
|
|
152
|
+
if (failures.length) {
|
|
153
|
+
console.error('\nSUÍTE forge-additive (SF3.1) FALHOU:');
|
|
154
|
+
for (const f of failures) console.error(` - ${f}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
console.log('Suíte forge-additive verde (C.1 tier agregado + C.2 aditivo/merge/guard/retomada).');
|
|
158
|
+
process.exit(0);
|