@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,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* context-budget.cjs — PostToolUse hook (matcher: Read)
|
|
4
|
+
*
|
|
5
|
+
* Advisory-only: avisa quando um arquivo lido excede o orçamento de contexto
|
|
6
|
+
* (> 32KB ≈ 8k tokens). NUNCA bloqueia. Qualquer erro → exit 0 silencioso.
|
|
7
|
+
* Node puro, sem dependências.
|
|
8
|
+
*/
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const BUDGET_BYTES = 32 * 1024; // 32KB ~ 8k tokens
|
|
14
|
+
const STDIN_TIMEOUT_MS = 2000;
|
|
15
|
+
|
|
16
|
+
// Guarda global: nunca deixar o hook pendurar nem falhar com código != 0.
|
|
17
|
+
const killTimer = setTimeout(() => process.exit(0), STDIN_TIMEOUT_MS + 500);
|
|
18
|
+
killTimer.unref();
|
|
19
|
+
|
|
20
|
+
function main(raw) {
|
|
21
|
+
try {
|
|
22
|
+
const input = JSON.parse(raw);
|
|
23
|
+
const filePath = input && input.tool_input && input.tool_input.file_path;
|
|
24
|
+
if (!filePath || typeof filePath !== 'string') return process.exit(0);
|
|
25
|
+
|
|
26
|
+
let stat;
|
|
27
|
+
try {
|
|
28
|
+
stat = fs.statSync(filePath);
|
|
29
|
+
} catch {
|
|
30
|
+
return process.exit(0); // arquivo não existe / inacessível → silêncio
|
|
31
|
+
}
|
|
32
|
+
if (!stat.isFile() || stat.size <= BUDGET_BYTES) return process.exit(0);
|
|
33
|
+
|
|
34
|
+
const sizeKB = Math.round(stat.size / 1024);
|
|
35
|
+
const approxTokens = Math.round(stat.size / 4 / 1000);
|
|
36
|
+
process.stdout.write(
|
|
37
|
+
JSON.stringify({
|
|
38
|
+
hookSpecificOutput: {
|
|
39
|
+
hookEventName: 'PostToolUse',
|
|
40
|
+
additionalContext:
|
|
41
|
+
`[context-budget] O arquivo lido (${filePath}, ~${sizeKB}KB / ~${approxTokens}k tokens) ` +
|
|
42
|
+
`excede o orçamento de leitura (32KB). Prefira ler por offset/limit apenas o trecho necessário, ` +
|
|
43
|
+
`ou extrair o essencial para knowledge/ e referenciar de lá.`,
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
return process.exit(0);
|
|
48
|
+
} catch {
|
|
49
|
+
return process.exit(0); // advisory: nunca falhar
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
let raw = '';
|
|
55
|
+
process.stdin.setEncoding('utf8');
|
|
56
|
+
process.stdin.on('data', (chunk) => {
|
|
57
|
+
raw += chunk;
|
|
58
|
+
if (raw.length > 1024 * 1024) process.exit(0); // input anômalo → silêncio
|
|
59
|
+
});
|
|
60
|
+
process.stdin.on('end', () => main(raw));
|
|
61
|
+
process.stdin.on('error', () => process.exit(0));
|
|
62
|
+
} catch {
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* POWER CLAUDE — PreToolUse hook: as 2 garantias de AUTORIDADE do ciclo que
|
|
6
|
+
* não podem depender só de disciplina (`DF-SF12.3-2`).
|
|
7
|
+
*
|
|
8
|
+
* Predicado 1 — só o papel QA marca `Status: Done` numa story (`*.story.md`).
|
|
9
|
+
* Predicado 2 — só o papel QA escreve em `docs/qa/gates/*.yaml`.
|
|
10
|
+
* Predicado 3 — o papel Dev não edita código enquanto a story associada
|
|
11
|
+
* (derivada da branch) está `Draft`.
|
|
12
|
+
*
|
|
13
|
+
* Canal de identidade: `input.agent_type` (o `subagent_type` literal do
|
|
14
|
+
* despacho, ex. "pc-qa") e `input.agent_id` (presente só em subagente —
|
|
15
|
+
* ausente, não vazio, no main thread). Medido, não deduzido — ver AC41 da
|
|
16
|
+
* story SF12.3. NUNCA process.env: não é escrevível pela plataforma, e um
|
|
17
|
+
* agente que editasse `.claude/settings.json` (chave `env`) poderia se
|
|
18
|
+
* autoproclamar — a mesma razão pela qual `enforce-git-push-authority.cjs`
|
|
19
|
+
* (Bloco M da mesma story) deixou de usar env var.
|
|
20
|
+
*
|
|
21
|
+
* Alcance declarado: tool calls `Edit`/`Write` apenas. Escrita por `Bash`
|
|
22
|
+
* (`sed -i`, heredoc, `python -c` etc.) e por `MultiEdit` está FORA do
|
|
23
|
+
* alcance — avaliado e rejeitado estender o matcher a `Bash` (viraria
|
|
24
|
+
* heurística de texto de comando, falso-positivo caro).
|
|
25
|
+
*
|
|
26
|
+
* Matriz allow/deny/ask — roster FECHADO de 7 papéis
|
|
27
|
+
* ({pc-analyst, pc-planner, pc-architect, pc-po, pc-dev, pc-qa, pc-devops}).
|
|
28
|
+
* `deny` só quando o papel lido é POSITIVAMENTE conhecido e POSITIVAMENTE
|
|
29
|
+
* errado (predicados 1/2); identidade ambígua (main thread, fora do roster,
|
|
30
|
+
* JSON ilegível) NUNCA vira `deny` silencioso — sempre `ask` (ou silêncio
|
|
31
|
+
* total quando não há nem estrutura para perguntar, predicado 3).
|
|
32
|
+
*
|
|
33
|
+
* SEGUNDO EIXO do mesmo contrato (`ADR-032` Emenda 3, story SF13.9): além da
|
|
34
|
+
* identidade, a EVIDÊNCIA. O predicado 1 lê o `## Status` por TOKEN, com uma
|
|
35
|
+
* escada de 3 degraus — evidência FIRME (`statusToken === 'done'`) é
|
|
36
|
+
* deny-capaz; evidência AMBÍGUA (o texto menciona "done" sem que o token seja
|
|
37
|
+
* `done`: `Not Done`, `~~Done~~`, `QA Done`, `Ready (o QA ainda não marcou
|
|
38
|
+
* Done)`) vira `ask` com o motivo NOMEADO; ausência vira silêncio. O
|
|
39
|
+
* `.includes('done')` dos dois lados está SUPERADO — não repetir: ele negava
|
|
40
|
+
* negações E deixava passar um bypass em dois passos (ver `evaluatePredicate1`).
|
|
41
|
+
*
|
|
42
|
+
* Custo: o hook sai em silêncio o MAIS CEDO possível — primeiro `tool_name`,
|
|
43
|
+
* depois o formato do `file_path`, e só então lê disco/simula a edição.
|
|
44
|
+
*
|
|
45
|
+
* Robustez (AC41 medido): `input.agent_type` está AUSENTE (não vazio) no
|
|
46
|
+
* main thread — nenhum método de string é chamado sobre ele sem checar
|
|
47
|
+
* presença antes; um TypeError faria o hook não emitir decisão nenhuma
|
|
48
|
+
* (fail-open silencioso, pior que qualquer `ask`).
|
|
49
|
+
*
|
|
50
|
+
* Circuito de destravamento (docs/mecanismos/hooks-de-autoridade-do-ciclo.md
|
|
51
|
+
* §Destravamento; `.claude/hooks/README.md`): (a) editar o arquivo fora da
|
|
52
|
+
* sessão do Claude Code; (b) remover/comentar a entrada em
|
|
53
|
+
* `.claude/settings.json`, corrigir o predicado, reinstalar.
|
|
54
|
+
*
|
|
55
|
+
* Sem dependências externas (roda em qualquer instalação limpa).
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
const fs = require('fs');
|
|
59
|
+
const path = require('path');
|
|
60
|
+
|
|
61
|
+
const ROSTER = new Set([
|
|
62
|
+
'pc-analyst',
|
|
63
|
+
'pc-planner',
|
|
64
|
+
'pc-architect',
|
|
65
|
+
'pc-po',
|
|
66
|
+
'pc-dev',
|
|
67
|
+
'pc-qa',
|
|
68
|
+
'pc-devops',
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
const MECANISMO_DOC = 'docs/mecanismos/hooks-de-autoridade-do-ciclo.md';
|
|
72
|
+
|
|
73
|
+
function readStdin() {
|
|
74
|
+
try {
|
|
75
|
+
return fs.readFileSync(0, 'utf8');
|
|
76
|
+
} catch {
|
|
77
|
+
return '';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function parseInput(rawInput) {
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(rawInput || '{}');
|
|
84
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isStoryFilePath(filePath) {
|
|
91
|
+
return /\.story\.md$/i.test(filePath);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isGateFilePath(filePath) {
|
|
95
|
+
return /(^|[\\/])docs[\\/]qa[\\/]gates[\\/][^\\/]+\.ya?ml$/i.test(filePath);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function isUnderDocsPath(filePath) {
|
|
99
|
+
return /(^|[\\/])docs([\\/]|$)/i.test(filePath);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function normalizeStatusText(text) {
|
|
103
|
+
return String(text || '')
|
|
104
|
+
.replace(/\*\*/g, '')
|
|
105
|
+
.toLowerCase()
|
|
106
|
+
.trim();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// `statusToken` — o TOKEN inicial do `## Status` (`ADR-032` Emenda 3, E3.2).
|
|
110
|
+
// Responde "qual é o token", NUNCA "devo disparar": quem decide quanta
|
|
111
|
+
// evidência cada decisão exige é a ESCADA do sítio de chamada, e as escadas
|
|
112
|
+
// dos dois consumidores (a trava de `Ready` e o P1 daqui) são deliberadamente
|
|
113
|
+
// diferentes porque as decisões que elas emitem custam coisas diferentes
|
|
114
|
+
// (E3.10). Uniformizá-las "por consistência" reverte a decisão.
|
|
115
|
+
//
|
|
116
|
+
// Três passos, cada um com caso alcançável medido: `normalizeStatusText`
|
|
117
|
+
// (INALTERADA) responde por `**Ready**`; o strip de decoração à esquerda
|
|
118
|
+
// responde por `` `Ready` ``; a corrida de letras responde por `Ready (…)`,
|
|
119
|
+
// `Ready — …`, `Ready.` — e pelas negativas `Readyish`/`Not Ready`.
|
|
120
|
+
//
|
|
121
|
+
// Duas restrições NORMATIVAS sobre o conjunto de decoração, cada uma com AC
|
|
122
|
+
// próprio na SF13.9 — leituras anteriores que as afrouxavam estão SUPERADAS,
|
|
123
|
+
// não repetir:
|
|
124
|
+
// • `~` fica FORA. Com ele dentro, `~~Done~~` daria token `done` ⇒ `deny`
|
|
125
|
+
// sobre um status que o autor RISCOU. Com ele fora, cai no degrau de
|
|
126
|
+
// menção e vira `ask` (E3.2, extensão). Preço declarado e aceito:
|
|
127
|
+
// `~~Ready~~` não dispara a trava de `Ready` (gatilho `T-E3-RISCADO`).
|
|
128
|
+
// • `#` fica FORA. Com ele dentro, `## Done — selado pelo QA` (texto de
|
|
129
|
+
// seção VAZADA por `extractStatusSection` quando `## Status` está vazia)
|
|
130
|
+
// daria token `done` ⇒ `deny` sobre seção que não é a de status. É esta
|
|
131
|
+
// restrição que contém o vazamento ESTRUTURALMENTE, sem consertar o
|
|
132
|
+
// extrator (gatilho `T-E3-EXTRATOR`). Nota factual (`ADR-032` Emenda 4,
|
|
133
|
+
// E4.1): a demonstração `## QA Results — Done` da Emenda 3 é FALSA — com
|
|
134
|
+
// `#` no strip ela dá token `qa`, não `done`; leitura superada.
|
|
135
|
+
//
|
|
136
|
+
// Este comentário NÃO enumera o roster de status, de propósito: a enumeração
|
|
137
|
+
// que estava escrita aqui vinha do `ADR-032` `E3.2` e estava ERRADA nos dois
|
|
138
|
+
// sentidos — omitia `inprogress`, que é mandatório no ciclo, e incluía um
|
|
139
|
+
// status que nenhum documento do framework define. Leitura SUPERADA, não
|
|
140
|
+
// repetir (`ADR-032` Emenda 5, `E5.1`/`E5.3`/`E5.5`). Nenhum predicado deste
|
|
141
|
+
// hook enumera o roster: P1 compara contra `'done'`, P3 contra `'draft'` — um
|
|
142
|
+
// literal cada, e é assim que deve continuar.
|
|
143
|
+
//
|
|
144
|
+
// Limite honesto: a corrida é `[a-z]` ASCII, então palavra acentuada trunca
|
|
145
|
+
// (`Concluída (Done)` ⇒ `conclu`). Inofensivo porque o token só é comparado
|
|
146
|
+
// contra o roster de status, todo ASCII — cuja FONTE DA VERDADE é
|
|
147
|
+
// `.claude/rules/authority.md` (âncora `<!-- roster:status -->`), nunca este
|
|
148
|
+
// arquivo nem o ADR. Token truncado nunca casa: cai no degrau de menção do P1,
|
|
149
|
+
// nunca em decisão firme.
|
|
150
|
+
function statusToken(text) {
|
|
151
|
+
const norm = normalizeStatusText(text);
|
|
152
|
+
const semDecoracao = norm.replace(/^[\s*_`]+/, '');
|
|
153
|
+
const m = /^[a-z]+/.exec(semDecoracao);
|
|
154
|
+
return m ? m[0] : '';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// `doneEvidence` — os 3 níveis de evidência de que o status é `Done`
|
|
158
|
+
// (`ADR-032` Emenda 3, E3.9). O token puro NÃO bastaria aqui: trocar
|
|
159
|
+
// `includes('done')` por `statusToken(...) === 'done'` transformaria os falsos
|
|
160
|
+
// positivos em SILÊNCIO, e `QA Done`/`Concluída (Done)` passariam a selar
|
|
161
|
+
// `Done` sem ninguém ver — trocar um falso positivo caro por um falso negativo
|
|
162
|
+
// silencioso é exatamente a troca que este mecanismo existe para não fazer.
|
|
163
|
+
function doneEvidence(sectionText) {
|
|
164
|
+
if (statusToken(sectionText) === 'done') return 'token'; // firme
|
|
165
|
+
if (normalizeStatusText(sectionText).includes('done')) return 'mencao'; // ambígua
|
|
166
|
+
return 'nenhuma';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Extrai o texto da seção que segue o heading `## Status`, até o próximo
|
|
170
|
+
// heading de nível 1/2 ou o fim do arquivo.
|
|
171
|
+
function extractStatusSection(content) {
|
|
172
|
+
const match = /^##\s*Status\s*\n([\s\S]*?)(?=\n#{1,2}\s|\s*$)/m.exec(String(content || ''));
|
|
173
|
+
return match ? match[1] : '';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Simula o conteúdo resultante de um Edit/Write sem escrever em disco.
|
|
177
|
+
function simulateResult(input) {
|
|
178
|
+
const filePath = input?.tool_input?.file_path;
|
|
179
|
+
if (typeof filePath !== 'string' || !filePath) return null;
|
|
180
|
+
|
|
181
|
+
let before = '';
|
|
182
|
+
try {
|
|
183
|
+
before = fs.readFileSync(filePath, 'utf8');
|
|
184
|
+
} catch {
|
|
185
|
+
before = ''; // arquivo novo (Write) — "antes" é string vazia, de propósito
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let after = before;
|
|
189
|
+
if (input.tool_name === 'Write') {
|
|
190
|
+
after = typeof input.tool_input.content === 'string' ? input.tool_input.content : '';
|
|
191
|
+
} else if (input.tool_name === 'Edit') {
|
|
192
|
+
const oldStr = input.tool_input.old_string;
|
|
193
|
+
const newStr = input.tool_input.new_string;
|
|
194
|
+
if (typeof oldStr === 'string' && typeof newStr === 'string') {
|
|
195
|
+
if (input.tool_input.replace_all) {
|
|
196
|
+
after = oldStr === '' ? before : before.split(oldStr).join(newStr);
|
|
197
|
+
} else {
|
|
198
|
+
const idx = before.indexOf(oldStr);
|
|
199
|
+
after = idx === -1 ? before : before.slice(0, idx) + newStr + before.slice(idx + oldStr.length);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return { filePath, before, after };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function resolveGitDir(cwd) {
|
|
208
|
+
try {
|
|
209
|
+
const gitPath = path.join(cwd, '.git');
|
|
210
|
+
const stat = fs.statSync(gitPath);
|
|
211
|
+
if (stat.isDirectory()) return gitPath;
|
|
212
|
+
if (stat.isFile()) {
|
|
213
|
+
const content = fs.readFileSync(gitPath, 'utf8');
|
|
214
|
+
const m = /^gitdir:\s*(.+)\s*$/m.exec(content);
|
|
215
|
+
if (m) {
|
|
216
|
+
const gitdir = m[1].trim();
|
|
217
|
+
return path.isAbsolute(gitdir) ? gitdir : path.resolve(cwd, gitdir);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} catch {
|
|
221
|
+
// sem repositório resolvível — trata como não resolvido
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Lê `.git/HEAD` diretamente (nunca spawna `git` — hook roda em caminho
|
|
227
|
+
// quente de todo Edit/Write).
|
|
228
|
+
function resolveBranch(cwd) {
|
|
229
|
+
const gitDir = resolveGitDir(cwd);
|
|
230
|
+
if (!gitDir) return null;
|
|
231
|
+
try {
|
|
232
|
+
const head = fs.readFileSync(path.join(gitDir, 'HEAD'), 'utf8').trim();
|
|
233
|
+
const m = /^ref:\s*refs\/heads\/(.+)$/.exec(head);
|
|
234
|
+
return m ? m[1] : null; // null em detached HEAD
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Token entre a PRIMEIRA barra e o PRIMEIRO hífen seguinte — sem presumir
|
|
241
|
+
// prefixo de tipo (`feat/`) nem prefixo de id (`sf`). Ex.: `docs/sf12.3-x`
|
|
242
|
+
// → `sf12.3`; `feat/1.6-slug` → `1.6`.
|
|
243
|
+
function resolveStoryIdFromBranch(branch) {
|
|
244
|
+
if (typeof branch !== 'string') return null;
|
|
245
|
+
const m = /^[a-z]+\/([^/-]+)-/.exec(branch);
|
|
246
|
+
return m ? m[1] : null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Matriz allow/deny/ask (roster fechado). `requiredRole` XOR `forbiddenRole`.
|
|
250
|
+
function decide(agentType, agentId, { requiredRole, forbiddenRole, denyOnMismatch }) {
|
|
251
|
+
if (agentId === undefined) return 'ask'; // main thread — sem identidade de subagente
|
|
252
|
+
if (typeof agentType !== 'string' || !ROSTER.has(agentType)) return 'ask'; // fora do roster fechado
|
|
253
|
+
|
|
254
|
+
const isMatch = requiredRole ? agentType === requiredRole : agentType !== forbiddenRole;
|
|
255
|
+
if (isMatch) return 'allow';
|
|
256
|
+
return denyOnMismatch ? 'deny' : 'ask';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// P1 — a ESCADA DE 3 DEGRAUS (`ADR-032` Emenda 3, E3.9).
|
|
260
|
+
//
|
|
261
|
+
// O predicado anterior — `!before.includes('done') && after.includes('done')`
|
|
262
|
+
// nos DOIS lados — está SUPERADO, não repetir. Ele tinha dois defeitos
|
|
263
|
+
// OPOSTOS, ambos medidos, e consertar só um deles é pior que não consertar:
|
|
264
|
+
// 1. Falso positivo (lado `depois`): `InReview — não está Done ainda` contém
|
|
265
|
+
// a substring "done", logo NEGAVA uma negação. `deny` não tem caminho de
|
|
266
|
+
// aprovação dentro da sessão — bloqueia até editar `settings.json`.
|
|
267
|
+
// 2. Bypass em dois passos (lado `antes`): `Ready (aguardando o Done do QA)`
|
|
268
|
+
// já contém "done" em prosa, então `!before.includes('done')` era falso e
|
|
269
|
+
// o hook CALAVA — um papel não-QA selava `Done` em duas escritas, sem
|
|
270
|
+
// interrupção nenhuma. Consertar só o `depois` deixa este lado trivial.
|
|
271
|
+
//
|
|
272
|
+
// A escada é o contrato do próprio hook (cabeçalho, `deny` só sobre alvo
|
|
273
|
+
// "positivamente conhecido e positivamente errado") aplicado a um SEGUNDO
|
|
274
|
+
// eixo: identidade ambígua nunca vira `deny` ⇒ evidência ambígua nunca vira
|
|
275
|
+
// `deny`. Mesmo princípio, não exceção a ele.
|
|
276
|
+
//
|
|
277
|
+
// Devolve `{ decision, evidencia }` para que `main()` classifique a evidência
|
|
278
|
+
// UMA vez e passe o rótulo a `buildMessage` — evitando uma 2ª leitura do mesmo
|
|
279
|
+
// arquivo no caminho quente (TOCTOU: a razão emitida poderia discordar da
|
|
280
|
+
// decisão se o arquivo mudasse entre as duas leituras).
|
|
281
|
+
function classifyPredicate1(input) {
|
|
282
|
+
const sim = simulateResult(input);
|
|
283
|
+
if (!sim) return { decision: null, evidencia: null };
|
|
284
|
+
|
|
285
|
+
const antes = doneEvidence(extractStatusSection(sim.before));
|
|
286
|
+
const depois = doneEvidence(extractStatusSection(sim.after));
|
|
287
|
+
|
|
288
|
+
if (antes === 'token') return { decision: null, evidencia: depois }; // já estava Done
|
|
289
|
+
if (depois === 'token') {
|
|
290
|
+
// evidência FIRME ⇒ deny-capaz (é aqui que o bypass de 2 passos fecha:
|
|
291
|
+
// menção no "antes" não é token, logo não conta como "já estava Done").
|
|
292
|
+
return {
|
|
293
|
+
decision: decide(input.agent_type, input.agent_id, { requiredRole: 'pc-qa', denyOnMismatch: true }),
|
|
294
|
+
evidencia: 'token',
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (depois === 'mencao' && antes === 'nenhuma') {
|
|
298
|
+
// evidência AMBÍGUA ⇒ `ask`, nunca `deny` — e o motivo é NOMEADO em
|
|
299
|
+
// `buildMessage`, senão é indistinguível do `ask` de identidade ambígua.
|
|
300
|
+
return {
|
|
301
|
+
decision: decide(input.agent_type, input.agent_id, { requiredRole: 'pc-qa', denyOnMismatch: false }),
|
|
302
|
+
evidencia: 'mencao',
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return { decision: null, evidencia: depois }; // ausência de evidência ⇒ silêncio
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Superfície pública estável (a suíte e os oráculos da SF13.9 comparam contra
|
|
309
|
+
// a string nua `'deny'`/`'ask'`/`null`): delega, nunca reimplementa.
|
|
310
|
+
function evaluatePredicate1(input) {
|
|
311
|
+
return classifyPredicate1(input).decision;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function evaluatePredicate2(input) {
|
|
315
|
+
return decide(input.agent_type, input.agent_id, { requiredRole: 'pc-qa', denyOnMismatch: true });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function evaluatePredicate3(input) {
|
|
319
|
+
const cwd = typeof input.cwd === 'string' ? input.cwd : null;
|
|
320
|
+
if (!cwd) return null; // sem cwd, sem como resolver — pass-through
|
|
321
|
+
|
|
322
|
+
const branch = resolveBranch(cwd);
|
|
323
|
+
const storyId = resolveStoryIdFromBranch(branch);
|
|
324
|
+
if (!storyId) return null; // branch fora do padrão — pass-through (AC16)
|
|
325
|
+
|
|
326
|
+
const storyPath = path.join(cwd, 'docs', 'stories', `${storyId}.story.md`);
|
|
327
|
+
let storyContent;
|
|
328
|
+
try {
|
|
329
|
+
storyContent = fs.readFileSync(storyPath, 'utf8');
|
|
330
|
+
} catch {
|
|
331
|
+
return null; // arquivo de story inexistente — pass-through (AC16)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Por TOKEN, não por igualdade estrita (`ADR-032` E3.5): `Draft (aguardando
|
|
335
|
+
// PO)` é `Draft`, e a igualdade estrita ficava muda diante de qualquer prosa
|
|
336
|
+
// no `## Status` — leitura SUPERADA, não repetir. Escada de 2 degraus (este
|
|
337
|
+
// sítio nunca emite `deny`), diferente da do P1, por desenho (E3.10).
|
|
338
|
+
const status = statusToken(extractStatusSection(storyContent));
|
|
339
|
+
if (status !== 'draft') return null; // não é Draft — sem interferência (AC17)
|
|
340
|
+
|
|
341
|
+
return decide(input.agent_type, input.agent_id, { forbiddenRole: 'pc-dev', denyOnMismatch: false });
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function emitDecision(permissionDecision, permissionDecisionReason) {
|
|
345
|
+
process.stdout.write(JSON.stringify({
|
|
346
|
+
hookSpecificOutput: {
|
|
347
|
+
hookEventName: 'PreToolUse',
|
|
348
|
+
permissionDecision,
|
|
349
|
+
permissionDecisionReason,
|
|
350
|
+
},
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function agentLabel(input) {
|
|
355
|
+
return typeof input.agent_type === 'string' && input.agent_type
|
|
356
|
+
? input.agent_type
|
|
357
|
+
: 'desconhecida (main thread ou identidade ausente)';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// `evidencia` é o rótulo já computado por `classifyPredicate1` (`'token'` /
|
|
361
|
+
// `'mencao'` / `'nenhuma'`). Quando ausente (chamada de teste ou de outro
|
|
362
|
+
// consumidor), é recomputado a partir das mesmas funções puras — reuso, não
|
|
363
|
+
// 2ª implementação. Nomear o motivo é obrigatório: sem ele, o `ask` por
|
|
364
|
+
// EVIDÊNCIA ambígua e o `ask` por IDENTIDADE ambígua saem com a mesma
|
|
365
|
+
// redação, e nem o dono nem um AC conseguem distinguir os dois motivos.
|
|
366
|
+
function buildMessage(predicate, filePath, input, evidencia) {
|
|
367
|
+
const identidade = agentLabel(input);
|
|
368
|
+
const destravamento = `Se isto é um falso positivo, veja ${MECANISMO_DOC} §Destravamento.`;
|
|
369
|
+
|
|
370
|
+
if (predicate === 1) {
|
|
371
|
+
let ev = evidencia;
|
|
372
|
+
if (ev === undefined || ev === null) {
|
|
373
|
+
const sim = simulateResult(input);
|
|
374
|
+
ev = sim ? doneEvidence(extractStatusSection(sim.after)) : 'nenhuma';
|
|
375
|
+
}
|
|
376
|
+
if (ev === 'mencao') {
|
|
377
|
+
return `Predicado 1 (só QA marca Status: Done): "${filePath}" tem evidência ambígua de Done na seção "## Status" — o texto MENCIONA "done" (negação, riscado, prosa ou palavra colada) sem que o token do status seja "done". Evidência ambígua nunca vira deny: por isso isto é uma pergunta, não um bloqueio. Papel exigido para selar Done: pc-qa. Identidade lida: ${identidade}. ${destravamento}`;
|
|
378
|
+
}
|
|
379
|
+
return `Predicado 1 (só QA marca Status: Done): "${filePath}" está transicionando para Done. Papel exigido: pc-qa. Identidade lida: ${identidade}. ${destravamento}`;
|
|
380
|
+
}
|
|
381
|
+
if (predicate === 2) {
|
|
382
|
+
return `Predicado 2 (só QA escreve gate file): "${filePath}" é exclusivo do papel QA. Papel exigido: pc-qa. Identidade lida: ${identidade}. ${destravamento}`;
|
|
383
|
+
}
|
|
384
|
+
return `Predicado 3 (Dev não edita sobre story Draft): a story associada à branch atual está Draft e "${filePath}" não é a story nem está sob docs/. Papel exigido: qualquer papel diferente de pc-dev (ou aprovação humana). Identidade lida: ${identidade}. ${destravamento}`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function main() {
|
|
388
|
+
const rawInput = readStdin();
|
|
389
|
+
const input = parseInput(rawInput);
|
|
390
|
+
|
|
391
|
+
if (!input) {
|
|
392
|
+
// Fail-closed proporcional (AC22), assimétrico por predicado:
|
|
393
|
+
// predicados 1/2 (Done/gate file) — texto bruto aparentando um dos dois → ask, nunca deny;
|
|
394
|
+
// predicado 3 (Dev × Draft) — sem JSON válido a story ativa não é resolvível → silêncio total.
|
|
395
|
+
const looksLikeDoneTransition = /status/i.test(rawInput) && /done/i.test(rawInput);
|
|
396
|
+
const looksLikeGateFile = /docs\/qa\/gates/i.test(rawInput);
|
|
397
|
+
if (looksLikeDoneTransition || looksLikeGateFile) {
|
|
398
|
+
emitDecision(
|
|
399
|
+
'ask',
|
|
400
|
+
`O hook não conseguiu interpretar o input do PreToolUse e o texto bruto aparenta tocar Status/Done ou um gate file de QA. Aprovação humana necessária. Se isto é um falso positivo, veja ${MECANISMO_DOC} §Destravamento.`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (input.tool_name !== 'Edit' && input.tool_name !== 'Write') return;
|
|
407
|
+
|
|
408
|
+
const filePath = input?.tool_input?.file_path;
|
|
409
|
+
if (typeof filePath !== 'string' || !filePath) return;
|
|
410
|
+
|
|
411
|
+
let predicate = null;
|
|
412
|
+
let decision = null;
|
|
413
|
+
let evidencia = null;
|
|
414
|
+
|
|
415
|
+
if (isStoryFilePath(filePath)) {
|
|
416
|
+
predicate = 1;
|
|
417
|
+
const classificado = classifyPredicate1(input);
|
|
418
|
+
decision = classificado.decision;
|
|
419
|
+
evidencia = classificado.evidencia;
|
|
420
|
+
} else if (isGateFilePath(filePath)) {
|
|
421
|
+
predicate = 2;
|
|
422
|
+
decision = evaluatePredicate2(input);
|
|
423
|
+
} else if (!isUnderDocsPath(filePath)) {
|
|
424
|
+
predicate = 3;
|
|
425
|
+
decision = evaluatePredicate3(input);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (!decision || decision === 'allow') return; // silêncio total
|
|
429
|
+
|
|
430
|
+
emitDecision(decision, buildMessage(predicate, filePath, input, evidencia));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (require.main === module) {
|
|
434
|
+
main();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
module.exports = {
|
|
438
|
+
ROSTER,
|
|
439
|
+
decide,
|
|
440
|
+
extractStatusSection,
|
|
441
|
+
normalizeStatusText,
|
|
442
|
+
statusToken,
|
|
443
|
+
doneEvidence,
|
|
444
|
+
simulateResult,
|
|
445
|
+
resolveGitDir,
|
|
446
|
+
resolveBranch,
|
|
447
|
+
resolveStoryIdFromBranch,
|
|
448
|
+
classifyPredicate1,
|
|
449
|
+
evaluatePredicate1,
|
|
450
|
+
evaluatePredicate2,
|
|
451
|
+
evaluatePredicate3,
|
|
452
|
+
isStoryFilePath,
|
|
453
|
+
isGateFilePath,
|
|
454
|
+
isUnderDocsPath,
|
|
455
|
+
parseInput,
|
|
456
|
+
main,
|
|
457
|
+
};
|