@getarbiter/cli 0.5.0
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.
- package/CHANGELOG.md +713 -0
- package/LICENSE +202 -0
- package/NOTICE +31 -0
- package/PRIVACY.md +111 -0
- package/README.md +237 -0
- package/THIRD_PARTY_LICENSES.md +472 -0
- package/dist/.src-manifest.json +1 -0
- package/dist/capabilities/host-probe.js +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +87 -0
- package/dist/commands/adopt-policy.js +3 -0
- package/dist/commands/configure-interactive.js +3 -0
- package/dist/commands/configure.js +5 -0
- package/dist/commands/cross-model-review.js +3 -0
- package/dist/commands/diff.js +20 -0
- package/dist/commands/doc-set.js +3 -0
- package/dist/commands/doctor/clean.js +2 -0
- package/dist/commands/doctor/fail-open-census.js +12 -0
- package/dist/commands/doctor/health.js +11 -0
- package/dist/commands/doctor/prove-gates.js +13 -0
- package/dist/commands/doctor/recover-lock.js +12 -0
- package/dist/commands/doctor/repair-state.js +6 -0
- package/dist/commands/doctor/tool-pin-extract.js +4 -0
- package/dist/commands/doctor/tool-pins.js +9 -0
- package/dist/commands/doctor-interactive.js +2 -0
- package/dist/commands/doctor.js +2 -0
- package/dist/commands/explain.js +19 -0
- package/dist/commands/gate-exec.js +4 -0
- package/dist/commands/gold-audit.js +14 -0
- package/dist/commands/graph.js +5 -0
- package/dist/commands/init/build-arbiter-config.js +1 -0
- package/dist/commands/init/generate.js +42 -0
- package/dist/commands/init/github-setup.js +5 -0
- package/dist/commands/init/maturity-gates.js +10 -0
- package/dist/commands/init/resolve-config.js +3 -0
- package/dist/commands/init/toolchain.js +10 -0
- package/dist/commands/init/types.js +1 -0
- package/dist/commands/init.js +17 -0
- package/dist/commands/method-interactive.js +4 -0
- package/dist/commands/method.js +11 -0
- package/dist/commands/obsidian.js +2 -0
- package/dist/commands/plugin.js +8 -0
- package/dist/commands/pr-merged.js +2 -0
- package/dist/commands/retire-policy.js +3 -0
- package/dist/commands/review-diff.js +3 -0
- package/dist/commands/settings.js +7 -0
- package/dist/commands/ship-config.js +2 -0
- package/dist/commands/ship-profile.js +2 -0
- package/dist/commands/ship-review.js +1 -0
- package/dist/commands/ship-tier.js +2 -0
- package/dist/commands/ship-train.js +2 -0
- package/dist/commands/task-mark.js +2 -0
- package/dist/commands/task-note.js +3 -0
- package/dist/commands/task-record-red.js +2 -0
- package/dist/commands/task-record-tech-debt.js +4 -0
- package/dist/commands/task-ship.js +3 -0
- package/dist/commands/task-state.js +6 -0
- package/dist/commands/task.js +59 -0
- package/dist/commands/update.js +60 -0
- package/dist/commands/upgrade-level-interactive.js +2 -0
- package/dist/commands/upgrade-level.js +7 -0
- package/dist/commands/verify-plan.js +8 -0
- package/dist/commands/verify-tdd.js +2 -0
- package/dist/commands/verify.js +7 -0
- package/dist/commands/wizard/coherence.js +1 -0
- package/dist/commands/worktree-prune.js +4 -0
- package/dist/commands/worktree.js +39 -0
- package/dist/compatibility/cross-language-matrix.json +540 -0
- package/dist/compatibility/index.d.ts +4 -0
- package/dist/compatibility/index.js +2 -0
- package/dist/compatibility/matcher.js +1 -0
- package/dist/compatibility/matrix.json +27 -0
- package/dist/compatibility/parsers.d.ts +38 -0
- package/dist/compatibility/parsers.js +1 -0
- package/dist/compatibility/probe.d.ts +41 -0
- package/dist/compatibility/probe.js +4 -0
- package/dist/compatibility/report.js +2 -0
- package/dist/compatibility/schema.d.ts +80 -0
- package/dist/compatibility/schema.js +1 -0
- package/dist/compatibility/skills-matrix.json +98 -0
- package/dist/compatibility/skills-validator.d.ts +30 -0
- package/dist/compatibility/skills-validator.js +4 -0
- package/dist/compatibility/tooling-proposals.json +5 -0
- package/dist/config/arbiter-ignore.js +3 -0
- package/dist/config/collaboration-mode-defaults.js +1 -0
- package/dist/config/diff.js +1 -0
- package/dist/config/env-overrides.js +3 -0
- package/dist/config/env-registry.js +2 -0
- package/dist/config/levels.js +1 -0
- package/dist/config/migrations/index.js +2 -0
- package/dist/config/migrations/v0-to-v1.js +2 -0
- package/dist/config/migrations/v1-to-v2.js +2 -0
- package/dist/config/migrations/v2-to-v3.js +2 -0
- package/dist/config/migrations/v3-to-v4.js +2 -0
- package/dist/config/override-resolver.js +2 -0
- package/dist/config/resolve-project-config.js +2 -0
- package/dist/config/resolve-project-name.js +2 -0
- package/dist/config/schema.d.ts +480 -0
- package/dist/config/schema.js +1 -0
- package/dist/config/test-pyramid-profiles.js +1 -0
- package/dist/config/thresholds.js +2 -0
- package/dist/conformance/dimensions.js +3 -0
- package/dist/conformance/engine.js +7 -0
- package/dist/conformance/gate-proofs.js +4 -0
- package/dist/conformance/shared.js +2 -0
- package/dist/detectors/axis.js +1 -0
- package/dist/detectors/build.js +2 -0
- package/dist/detectors/existing.js +2 -0
- package/dist/detectors/external-model.js +2 -0
- package/dist/detectors/framework.js +2 -0
- package/dist/detectors/git.js +11 -0
- package/dist/detectors/github.js +2 -0
- package/dist/detectors/lanes.js +5 -0
- package/dist/detectors/language-hooks.js +117 -0
- package/dist/detectors/language.js +2 -0
- package/dist/detectors/package-manager.js +2 -0
- package/dist/detectors/package.js +2 -0
- package/dist/detectors/scaffold-wiring.js +2 -0
- package/dist/detectors/workflow-collision.js +4 -0
- package/dist/evidence/gate-binding.js +4 -0
- package/dist/evidence/git-checks.js +3 -0
- package/dist/evidence/load.js +2 -0
- package/dist/evidence/provenance.js +2 -0
- package/dist/evidence/summary.js +2 -0
- package/dist/evidence/tdd-reexecute.js +2 -0
- package/dist/evidence/tdd.js +4 -0
- package/dist/experimental/index.js +2 -0
- package/dist/experimental/parse-argv.js +2 -0
- package/dist/experimental/registry.js +2 -0
- package/dist/generators/agents-claude.js +2 -0
- package/dist/generators/agents-md.js +2 -0
- package/dist/generators/anti-drift-validators.js +3 -0
- package/dist/generators/anti-proforma.js +2 -0
- package/dist/generators/api-e2e.js +2 -0
- package/dist/generators/api-middleware.js +2 -0
- package/dist/generators/archunit.js +2 -0
- package/dist/generators/audit-toolchain.js +2 -0
- package/dist/generators/auth.js +2 -0
- package/dist/generators/behavioral-tests.js +2 -0
- package/dist/generators/boundaries.js +2 -0
- package/dist/generators/check-all.js +2 -0
- package/dist/generators/check-stack-conformity.js +2 -0
- package/dist/generators/ci-five-lane.js +2 -0
- package/dist/generators/ci-tier.js +2 -0
- package/dist/generators/claude.js +3 -0
- package/dist/generators/codex-hooks.js +2 -0
- package/dist/generators/codex-known-limitations.js +2 -0
- package/dist/generators/codex.js +15 -0
- package/dist/generators/commit-footer.js +2 -0
- package/dist/generators/compliance-menu.js +2 -0
- package/dist/generators/compliance.js +2 -0
- package/dist/generators/conformance.js +2 -0
- package/dist/generators/contract-testing.js +2 -0
- package/dist/generators/coverage.js +2 -0
- package/dist/generators/debt-gates.js +24 -0
- package/dist/generators/debt-ratchet.js +2 -0
- package/dist/generators/derived-class.js +2 -0
- package/dist/generators/doc-set.js +4 -0
- package/dist/generators/docs.js +2 -0
- package/dist/generators/duplication.js +2 -0
- package/dist/generators/e2e-constitution.js +2 -0
- package/dist/generators/env-template.js +2 -0
- package/dist/generators/evidence-retention.js +2 -0
- package/dist/generators/feature-matrix.js +2 -0
- package/dist/generators/frontend-governance.js +2 -0
- package/dist/generators/frontend-quality.js +2 -0
- package/dist/generators/gap.js +2 -0
- package/dist/generators/gdpr.js +2 -0
- package/dist/generators/githooks.js +2 -0
- package/dist/generators/github-setup.js +2 -0
- package/dist/generators/github.js +2 -0
- package/dist/generators/gitignore.js +2 -0
- package/dist/generators/global-invariants.js +3 -0
- package/dist/generators/go-boundaries.js +2 -0
- package/dist/generators/gold-kit.js +2 -0
- package/dist/generators/infra.js +2 -0
- package/dist/generators/integration-testing.js +7 -0
- package/dist/generators/iso27001.js +2 -0
- package/dist/generators/iso9001.js +2 -0
- package/dist/generators/labels.js +2 -0
- package/dist/generators/local-wrapper.js +2 -0
- package/dist/generators/modulith.js +2 -0
- package/dist/generators/mutation.js +2 -0
- package/dist/generators/observability.js +2 -0
- package/dist/generators/operations.js +2 -0
- package/dist/generators/perf-k6.js +2 -0
- package/dist/generators/pharma.js +2 -0
- package/dist/generators/playwright-python.js +2 -0
- package/dist/generators/playwright-ts.js +2 -0
- package/dist/generators/pr-tooling.js +2 -0
- package/dist/generators/python-boundaries.js +2 -0
- package/dist/generators/quality.js +2 -0
- package/dist/generators/registry.js +2 -0
- package/dist/generators/regulated.js +2 -0
- package/dist/generators/resilience.js +2 -0
- package/dist/generators/risk-register.js +2 -0
- package/dist/generators/root.js +2 -0
- package/dist/generators/rust-boundaries.js +2 -0
- package/dist/generators/safety-class.js +2 -0
- package/dist/generators/security.js +2 -0
- package/dist/generators/seed.js +2 -0
- package/dist/generators/self-validation.js +2 -0
- package/dist/generators/ship-driver.js +2 -0
- package/dist/generators/skill-names.json +17 -0
- package/dist/generators/skills.js +2 -0
- package/dist/generators/smoke-journeys.js +2 -0
- package/dist/generators/solo-exception.js +2 -0
- package/dist/generators/ssot.js +2 -0
- package/dist/generators/stride-enforcement.js +2 -0
- package/dist/generators/suppressions.js +2 -0
- package/dist/generators/test-pyramid-manifest.js +3 -0
- package/dist/generators/test-taxonomy.js +2 -0
- package/dist/generators/wiki.js +2 -0
- package/dist/github/branch-protection.js +2 -0
- package/dist/github/classify-gh-error.js +2 -0
- package/dist/github/labels.js +2 -0
- package/dist/github/project-board.js +2 -0
- package/dist/graph/builders/adr.js +4 -0
- package/dist/graph/builders/ast.js +3 -0
- package/dist/graph/builders/canon.js +2 -0
- package/dist/graph/builders/evidence.js +2 -0
- package/dist/graph/builders/inv.js +1 -0
- package/dist/graph/builders/req.js +3 -0
- package/dist/graph/builders/test-nodes.js +3 -0
- package/dist/graph/builders/utils.js +2 -0
- package/dist/graph/load.js +2 -0
- package/dist/graph/model.js +2 -0
- package/dist/graph/query.js +3 -0
- package/dist/graph/store.js +1 -0
- package/dist/i18n/en.json +293 -0
- package/dist/i18n/index.js +4 -0
- package/dist/i18n/types.js +2 -0
- package/dist/integrations/companions.js +2 -0
- package/dist/integrations/external-review.js +10 -0
- package/dist/integrations/plugin-schema.js +2 -0
- package/dist/integrations/skill-detector.js +7 -0
- package/dist/integrations/skills-matrix.js +2 -0
- package/dist/integrations/types.d.ts +23 -0
- package/dist/integrations/types.js +2 -0
- package/dist/internal/cli-deprecation-registry.js +2 -0
- package/dist/internal/deprecate.js +3 -0
- package/dist/internal/experimental-warn.js +3 -0
- package/dist/invariants/catalog.d.ts +2 -0
- package/dist/invariants/catalog.js +1 -0
- package/dist/invariants/filter.d.ts +28 -0
- package/dist/invariants/filter.js +1 -0
- package/dist/invariants/index.d.ts +4 -0
- package/dist/invariants/index.js +2 -0
- package/dist/invariants/tiers.js +1 -0
- package/dist/invariants/types.d.ts +1 -0
- package/dist/invariants/types.js +1 -0
- package/dist/kit/applicability.js +3 -0
- package/dist/kit/audit-report.js +3 -0
- package/dist/kit/brownfield-detect.js +4 -0
- package/dist/kit/canonical-mapping.json +1 -0
- package/dist/kit/catalog.js +2 -0
- package/dist/kit/catalog.json +1 -0
- package/dist/kit/derived.json +1 -0
- package/dist/kit/emit-issues.js +8 -0
- package/dist/kit/measure.js +5 -0
- package/dist/kit/redaction.js +3 -0
- package/dist/kit/schema.js +2 -0
- package/dist/kit/taxonomy.js +2 -0
- package/dist/kit/thresholds.d.ts +12 -0
- package/dist/kit/thresholds.js +2 -0
- package/dist/kit/wave-engine.js +1 -0
- package/dist/recipes/loader.js +6 -0
- package/dist/recipes/schema.js +2 -0
- package/dist/risk/classifier.js +2 -0
- package/dist/risk/sha-check.js +2 -0
- package/dist/state/backups.js +2 -0
- package/dist/state/envelope.js +2 -0
- package/dist/state/generated-manifest.js +3 -0
- package/dist/state/manifest-key.js +2 -0
- package/dist/state/migrations/index.js +1 -0
- package/dist/state/migrations/v0-to-v1.js +2 -0
- package/dist/state/retired-renders.js +2 -0
- package/dist/templates/.nvmrc.ejs +1 -0
- package/dist/templates/HANDOFF.template.md +45 -0
- package/dist/templates/__tests__/contract/error-shape.contract.test.ts.ejs +47 -0
- package/dist/templates/agents-md/AGENTS.md.ejs +517 -0
- package/dist/templates/api-e2e/README.md.ejs +33 -0
- package/dist/templates/api-e2e/go-httptest.go.ejs +43 -0
- package/dist/templates/api-e2e/java-restassured.java.ejs +28 -0
- package/dist/templates/api-e2e/kotlin-restassured.kt.ejs +30 -0
- package/dist/templates/api-e2e/manifest.json.ejs +8 -0
- package/dist/templates/api-e2e/postman.collection.json.ejs +30 -0
- package/dist/templates/api-e2e/python-httpx.py.ejs +17 -0
- package/dist/templates/api-e2e/run.sh.ejs +61 -0
- package/dist/templates/api-e2e/ts-supertest.test.ts.ejs +18 -0
- package/dist/templates/archunit/AntiCyclicTest.java.ejs +29 -0
- package/dist/templates/archunit/AntiProformaExempt.java.ejs +35 -0
- package/dist/templates/archunit/AntiProformaTest.java.ejs +104 -0
- package/dist/templates/archunit/ArchitectureTest.java.ejs +87 -0
- package/dist/templates/archunit/DependencyFlowTest.java.ejs +55 -0
- package/dist/templates/archunit/DomainPurityTest.java.ejs +47 -0
- package/dist/templates/archunit/NamingConventionsTest.java.ejs +54 -0
- package/dist/templates/archunit/NoH2ArchTest.java.ejs +30 -0
- package/dist/templates/archunit/NoMockMvcTest.java.ejs +71 -0
- package/dist/templates/archunit/PortsIndependenceTest.java.ejs +55 -0
- package/dist/templates/archunit/RestAssuredArchTest.java.ejs +32 -0
- package/dist/templates/archunit/RestAssuredBaseIT.java.ejs +66 -0
- package/dist/templates/archunit/TestCoverageArchTest.java.ejs +29 -0
- package/dist/templates/archunit/arch-test-deps-maven.md.ejs +42 -0
- package/dist/templates/archunit/arch-test-deps.gradle.ejs +14 -0
- package/dist/templates/audit/gdpr/check-gdpr-controls.mjs.ejs +102 -0
- package/dist/templates/audit/gdpr/controls-to-gates.md.ejs +42 -0
- package/dist/templates/audit/gdpr/data-flow-map.md.ejs +30 -0
- package/dist/templates/audit/gdpr/dpia.md.ejs +45 -0
- package/dist/templates/audit/generic/audit-gate-rules.md.ejs +24 -0
- package/dist/templates/audit/generic/audit-trail-policy.md.ejs +38 -0
- package/dist/templates/audit/iso27001/iso27001-controls-gate-map.md.ejs +60 -0
- package/dist/templates/auth/setup.md.ejs +661 -0
- package/dist/templates/behavioral-tests/ExampleBehavioralTest.java.ejs +67 -0
- package/dist/templates/behavioral-tests/TESTING_POLICY.md.ejs +116 -0
- package/dist/templates/behavioral-tests/bdd/ExampleBddIT.java.ejs +19 -0
- package/dist/templates/behavioral-tests/bdd/ExampleSteps.java.ejs +61 -0
- package/dist/templates/behavioral-tests/bdd/example.feature.ejs +14 -0
- package/dist/templates/behavioral-tests/bdd/example.steps.ts.ejs +37 -0
- package/dist/templates/behavioral-tests/bdd/example_bdd_test.rs.ejs +64 -0
- package/dist/templates/behavioral-tests/bdd/example_test.go.ejs +80 -0
- package/dist/templates/behavioral-tests/bdd/test_example_bdd.py.ejs +47 -0
- package/dist/templates/behavioral-tests/eslint-playwright.json.ejs +10 -0
- package/dist/templates/behavioral-tests/eslint.config.playwright.mjs.ejs +29 -0
- package/dist/templates/behavioral-tests/example.behavioral.test.ts.ejs +47 -0
- package/dist/templates/behavioral-tests/example_behavioral_test.go.ejs +51 -0
- package/dist/templates/behavioral-tests/example_behavioral_test.rs.ejs +47 -0
- package/dist/templates/behavioral-tests/test_example_behavioral.py.ejs +40 -0
- package/dist/templates/boundaries/.eslintrc-boundaries.cjs.ejs +81 -0
- package/dist/templates/boundaries/.eslintrc-frontend-spa.cjs.ejs +79 -0
- package/dist/templates/boundaries/.importlinter.ejs +48 -0
- package/dist/templates/boundaries/check-boundaries-go.mjs.ejs +94 -0
- package/dist/templates/boundaries/check-boundaries-python.mjs.ejs +118 -0
- package/dist/templates/boundaries/check-boundaries-rust.mjs.ejs +111 -0
- package/dist/templates/boundaries/check-boundaries.mjs.ejs +34 -0
- package/dist/templates/boundaries/clippy.toml.ejs +50 -0
- package/dist/templates/boundaries/deny.toml.ejs +56 -0
- package/dist/templates/boundaries/eslint.config.boundaries.mjs.ejs +112 -0
- package/dist/templates/boundaries/eslint.config.frontend-spa.mjs.ejs +93 -0
- package/dist/templates/boundaries/golangci-boundaries.yml.ejs +70 -0
- package/dist/templates/boundaries/ruff-boundaries.toml.ejs +32 -0
- package/dist/templates/claude/CLAUDE.md.ejs +78 -0
- package/dist/templates/claude/agents/agent-write-classes.json +30 -0
- package/dist/templates/claude/agents/bridge-reviewer.md.ejs +68 -0
- package/dist/templates/claude/agents/codebase-scanner.md.ejs +69 -0
- package/dist/templates/claude/agents/context-checker.md.ejs +73 -0
- package/dist/templates/claude/agents/red-team.md.ejs +134 -0
- package/dist/templates/claude/commands/close-gold-gap.md.ejs +43 -0
- package/dist/templates/claude/commands/drain.md.ejs +81 -0
- package/dist/templates/claude/commands/gold-audit.md.ejs +43 -0
- package/dist/templates/claude/commands/impact.md.ejs +39 -0
- package/dist/templates/claude/commands/levelup.md.ejs +61 -0
- package/dist/templates/claude/commands/ship.md.ejs +902 -0
- package/dist/templates/claude/commands/tabletop.md.ejs +46 -0
- package/dist/templates/claude/commands/task.md.ejs +87 -0
- package/dist/templates/claude/commands/wt-close.md.ejs +58 -0
- package/dist/templates/claude/commands/wt-list.md.ejs +48 -0
- package/dist/templates/claude/commands/wt-open.md.ejs +61 -0
- package/dist/templates/claude/commands/wt-prune.md.ejs +38 -0
- package/dist/templates/claude/hooks/check-circular-deps.mjs.ejs +56 -0
- package/dist/templates/claude/hooks/check-no-orphan-todo.mjs.ejs +45 -0
- package/dist/templates/claude/hooks/check-no-pii.mjs.ejs +121 -0
- package/dist/templates/claude/hooks/check-no-placeholders.mjs.ejs +71 -0
- package/dist/templates/claude/hooks/check-no-skipped-tests.mjs +80 -0
- package/dist/templates/claude/hooks/check-no-unused-exports.mjs +62 -0
- package/dist/templates/claude/hooks/closer-mode-guard.mjs.ejs +102 -0
- package/dist/templates/claude/hooks/debug-state-on-failure.mjs.ejs +98 -0
- package/dist/templates/claude/hooks/enforce-gate-before-pr.mjs +142 -0
- package/dist/templates/claude/hooks/enforce-read-only.mjs +28 -0
- package/dist/templates/claude/hooks/exitplanmode-banner.mjs.ejs +43 -0
- package/dist/templates/claude/hooks/guard-done-evidence.mjs.ejs +85 -0
- package/dist/templates/claude/hooks/guard-task-completion.mjs.ejs +56 -0
- package/dist/templates/claude/hooks/hooks.mjs.ejs +127 -0
- package/dist/templates/claude/hooks/lib.mjs.ejs +523 -0
- package/dist/templates/claude/hooks/post-brainstorm-stop.mjs +48 -0
- package/dist/templates/claude/hooks/post-commit-check.mjs.ejs +65 -0
- package/dist/templates/claude/hooks/post-commit-checklists/go/backend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/go/docs.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/go/frontend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/java/backend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/java/docs.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/java/frontend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/python/backend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/python/docs.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/python/frontend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/rust/backend.ejs +5 -0
- package/dist/templates/claude/hooks/post-commit-checklists/rust/docs.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/rust/frontend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/ts/backend.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/ts/docs.ejs +4 -0
- package/dist/templates/claude/hooks/post-commit-checklists/ts/frontend.ejs +5 -0
- package/dist/templates/claude/hooks/post-edit-dispatch.mjs.ejs +73 -0
- package/dist/templates/claude/hooks/post-subagent-release.mjs +80 -0
- package/dist/templates/claude/hooks/pre-compact.mjs.ejs +79 -0
- package/dist/templates/claude/hooks/pre-edit-plan-anchor.mjs.ejs +225 -0
- package/dist/templates/claude/hooks/pre-edit-ssot-guard.mjs +204 -0
- package/dist/templates/claude/hooks/pre-spawn-worktree-guard.mjs +129 -0
- package/dist/templates/claude/hooks/skill-forced-eval.mjs.ejs +281 -0
- package/dist/templates/claude/hooks/stop-dangerous.mjs +86 -0
- package/dist/templates/claude/hooks/stop-evidence-guard.mjs.ejs +245 -0
- package/dist/templates/claude/hooks/stop-finding-loss.mjs.ejs +168 -0
- package/dist/templates/claude/hooks/wiki-on-commit.mjs.ejs +38 -0
- package/dist/templates/claude/knowledge-map.json.ejs +26 -0
- package/dist/templates/claude/rules/05-agent-lifecycle.md +7 -0
- package/dist/templates/claude/rules/25-todo-folder-policy.md +5 -0
- package/dist/templates/claude/rules/40-context-economy.md +32 -0
- package/dist/templates/claude/rules/45-mcp-fallback.md +25 -0
- package/dist/templates/claude/rules/50-batch-execution.md +75 -0
- package/dist/templates/claude/rules/55-brainstorm-terminal-state.md +44 -0
- package/dist/templates/claude/rules/60-incidental-capture.md +43 -0
- package/dist/templates/claude/rules/75-impact-vault-reading.md +43 -0
- package/dist/templates/claude/rules/90-exec-protocol.md.ejs +40 -0
- package/dist/templates/claude/rules/95-closer-mode.md +45 -0
- package/dist/templates/claude/settings.json.ejs +165 -0
- package/dist/templates/claude/skills/architect-review/SKILL.md.ejs +82 -0
- package/dist/templates/claude/skills/brainstorming/SKILL.md.ejs +86 -0
- package/dist/templates/claude/skills/clean-code/SKILL.md.ejs +39 -0
- package/dist/templates/claude/skills/close-gold-gap/SKILL.md.ejs +58 -0
- package/dist/templates/claude/skills/codebase-audit/SKILL.md.ejs +88 -0
- package/dist/templates/claude/skills/configure/SKILL.md.ejs +72 -0
- package/dist/templates/claude/skills/epic-decompose/SKILL.md.ejs +86 -0
- package/dist/templates/claude/skills/gold-audit/SKILL.md.ejs +91 -0
- package/dist/templates/claude/skills/impact/SKILL.md.ejs +104 -0
- package/dist/templates/claude/skills/levelup/SKILL.md.ejs +146 -0
- package/dist/templates/claude/skills/tabletop/SKILL.md.ejs +118 -0
- package/dist/templates/claude/skills/tdd/SKILL.md.ejs +157 -0
- package/dist/templates/claude/skills/understand-code/SKILL.md.ejs +93 -0
- package/dist/templates/claude/skills/verification/SKILL.md.ejs +68 -0
- package/dist/templates/claude/skills/wave-drain/SKILL.md.ejs +491 -0
- package/dist/templates/codex/CODEX.md.ejs +140 -0
- package/dist/templates/codex/codex-adapter.mjs +132 -0
- package/dist/templates/codex/config.toml.ejs +189 -0
- package/dist/templates/compliance/compliance-mapping.md.ejs +124 -0
- package/dist/templates/compliance/compliance-menu.md.ejs +89 -0
- package/dist/templates/contract-testing/CONTRACTS_POLICY.md.ejs +30 -0
- package/dist/templates/contract-testing/api-snapshots/config-keys-baseline.json.ejs +1 -0
- package/dist/templates/contract-testing/api-snapshots/config-response-baseline.json.ejs +1 -0
- package/dist/templates/contract-testing/api-snapshots/enum-values-baseline.json.ejs +1 -0
- package/dist/templates/contract-testing/api-snapshots/error-shape-baseline.json.ejs +6 -0
- package/dist/templates/contract-testing/api-snapshots/openapi-baseline.json.ejs +12 -0
- package/dist/templates/contract-testing/api-snapshots/openapi-content-types-baseline.json.ejs +3 -0
- package/dist/templates/contract-testing/api-snapshots/openapi-paths-baseline.json.ejs +1 -0
- package/dist/templates/contract-testing/api-snapshots/openapi-required-fields-baseline.json.ejs +1 -0
- package/dist/templates/contract-testing/api-snapshots/openapi-response-status-baseline.json.ejs +3 -0
- package/dist/templates/contract-testing/api-snapshots/test-snapshot.json.ejs +4 -0
- package/dist/templates/contract-testing/env/.env.pact.ejs +4 -0
- package/dist/templates/contract-testing/graphql/GraphqlSchemaTest.java.ejs +29 -0
- package/dist/templates/contract-testing/graphql/graphql-inspector.test.ts.ejs +20 -0
- package/dist/templates/contract-testing/graphql/graphql_schema_test.go.ejs +27 -0
- package/dist/templates/contract-testing/graphql/graphql_schema_test.rs.ejs +27 -0
- package/dist/templates/contract-testing/graphql/test_graphql_schema.py.ejs +21 -0
- package/dist/templates/contract-testing/grpc/GrpcContractTest.java.ejs +23 -0
- package/dist/templates/contract-testing/grpc/buf-breaking.yml.ejs +6 -0
- package/dist/templates/contract-testing/grpc/buf.yaml.ejs +11 -0
- package/dist/templates/contract-testing/grpc/grpc-contract.test.ts.ejs +16 -0
- package/dist/templates/contract-testing/grpc/grpc_contract_test.go.ejs +22 -0
- package/dist/templates/contract-testing/grpc/grpc_contract_test.rs.ejs +22 -0
- package/dist/templates/contract-testing/grpc/test_grpc_contract.py.ejs +18 -0
- package/dist/templates/contract-testing/message-queue/SchemaRegistryCheckIT.java.ejs +44 -0
- package/dist/templates/contract-testing/message-queue/schema-registry-check.ts.ejs +42 -0
- package/dist/templates/contract-testing/message-queue/schema_registry_test.go.ejs +71 -0
- package/dist/templates/contract-testing/message-queue/schema_registry_test.rs.ejs +61 -0
- package/dist/templates/contract-testing/message-queue/test_schema_registry.py.ejs +31 -0
- package/dist/templates/contract-testing/pact-samples/assignment-response.json.ejs +7 -0
- package/dist/templates/contract-testing/pact-samples/availability-response.json.ejs +13 -0
- package/dist/templates/contract-testing/pact-samples/availability-rule-response.json.ejs +8 -0
- package/dist/templates/contract-testing/pact-samples/capacity-response.json.ejs +11 -0
- package/dist/templates/contract-testing/pact-samples/fully-booked-response.json.ejs +6 -0
- package/dist/templates/contract-testing/pact-samples/schedule-override-response.json.ejs +7 -0
- package/dist/templates/contract-testing/rest-owned/PactVerificationIT.java.ejs +31 -0
- package/dist/templates/contract-testing/rest-owned/pact-consumer.test.ts.ejs +36 -0
- package/dist/templates/contract-testing/rest-owned/pact-deps.gradle.ejs +15 -0
- package/dist/templates/contract-testing/rest-owned/pact_consumer_test.go.ejs +48 -0
- package/dist/templates/contract-testing/rest-owned/pact_consumer_test.rs.ejs +23 -0
- package/dist/templates/contract-testing/rest-owned/test_pact_consumer.py.ejs +35 -0
- package/dist/templates/contract-testing/rest-public/OpenApiDiffIT.java.ejs +44 -0
- package/dist/templates/contract-testing/rest-public/export-openapi-java.gradle.ejs +13 -0
- package/dist/templates/contract-testing/rest-public/export-openapi.mjs.ejs +21 -0
- package/dist/templates/contract-testing/rest-public/export_openapi.go.ejs +30 -0
- package/dist/templates/contract-testing/rest-public/export_openapi.py.ejs +27 -0
- package/dist/templates/contract-testing/rest-public/export_openapi.rs.ejs +32 -0
- package/dist/templates/contract-testing/rest-public/openapi-diff.ts.ejs +42 -0
- package/dist/templates/contract-testing/rest-public/openapi_diff_test.go.ejs +35 -0
- package/dist/templates/contract-testing/rest-public/openapi_diff_test.rs.ejs +36 -0
- package/dist/templates/contract-testing/rest-public/test_openapi_diff.py.ejs +32 -0
- package/dist/templates/coverage/.coveragerc.ejs +26 -0
- package/dist/templates/coverage/.tarpaulin.toml.ejs +30 -0
- package/dist/templates/coverage/Cargo.toml.profile.release.ejs +24 -0
- package/dist/templates/coverage/jacoco-maven-setup.md.ejs +72 -0
- package/dist/templates/coverage/jacoco.gradle.ejs +49 -0
- package/dist/templates/coverage/kover.gradle.ejs +35 -0
- package/dist/templates/coverage/vitest.browser.config.ts.ejs +47 -0
- package/dist/templates/coverage/vitest.config.ts.ejs +47 -0
- package/dist/templates/docs/CODING_STANDARDS.md.ejs +81 -0
- package/dist/templates/docs/FEATURE_MATRIX.md.ejs +84 -0
- package/dist/templates/docs/GAP.md.ejs +58 -0
- package/dist/templates/docs/ISO27001_ANNEX_A.md.ejs +144 -0
- package/dist/templates/docs/MASTER_TEST_PLAN.md.ejs +52 -0
- package/dist/templates/docs/POST_MERGE_REVIEW_TEMPLATE.md.ejs +63 -0
- package/dist/templates/docs/SECURE_CODING_CHECKLIST.md.ejs +61 -0
- package/dist/templates/docs/adr/ADR-000_template.md.ejs +28 -0
- package/dist/templates/docs/bugs/bug-analysis.md.ejs +47 -0
- package/dist/templates/docs/bugs/bug-report.md.ejs +51 -0
- package/dist/templates/docs/bugs/bug-verification.md.ejs +42 -0
- package/dist/templates/docs/runbooks/deployment.md.ejs +119 -0
- package/dist/templates/docs/runbooks/prod-checklist.md.ejs +90 -0
- package/dist/templates/docs/runbooks/rollback.md.ejs +124 -0
- package/dist/templates/docs/runbooks/troubleshooting.md.ejs +130 -0
- package/dist/templates/docs/skeletons/arc42-canvas.md.ejs +46 -0
- package/dist/templates/docs/skeletons/arc42-full.md.ejs +59 -0
- package/dist/templates/docs/skeletons/decision-registry.md.ejs +38 -0
- package/dist/templates/docs/skeletons/er-model.md.ejs +19 -0
- package/dist/templates/docs/skeletons/glossary.md.ejs +8 -0
- package/dist/templates/docs/skeletons/governance.md.ejs +13 -0
- package/dist/templates/docs/skeletons/slo.md.ejs +21 -0
- package/dist/templates/docs/skeletons/technical-debt.md.ejs +8 -0
- package/dist/templates/docs/skeletons/test-strategy.md.ejs +14 -0
- package/dist/templates/docs/skeletons/threat-model-4q.md.ejs +20 -0
- package/dist/templates/docs/skeletons/threat-model-stride.md.ejs +22 -0
- package/dist/templates/docs/specs/atomic-task-list.md.ejs +57 -0
- package/dist/templates/docs/steering/product.md.ejs +44 -0
- package/dist/templates/docs/steering/structure.md.ejs +49 -0
- package/dist/templates/docs/steering/tech.md.ejs +53 -0
- package/dist/templates/documentation/cli-catalog.md.ejs +21 -0
- package/dist/templates/e2e/E2E_CONSTITUTION.md.ejs +77 -0
- package/dist/templates/e2e/playwright-python/conftest.py.ejs +22 -0
- package/dist/templates/e2e/playwright-python/run_axe.py.ejs +99 -0
- package/dist/templates/e2e/playwright-python/test_a11y.py.ejs +38 -0
- package/dist/templates/e2e/playwright-python/test_smoke.py.ejs +28 -0
- package/dist/templates/e2e/playwright-ts/a11y.spec.ts.ejs +20 -0
- package/dist/templates/e2e/playwright-ts/render-smoke.spec.ts.ejs +90 -0
- package/dist/templates/e2e/playwright-ts/run-axe.ts.ejs +74 -0
- package/dist/templates/e2e/smoke-journeys/journeys.spec.ts.ejs +53 -0
- package/dist/templates/evidence-files.json.ejs +13 -0
- package/dist/templates/frontend/FE_DESIGN_PRINCIPLES.md.ejs +115 -0
- package/dist/templates/frontend/FRONTEND_CONSTITUTION.md.ejs +170 -0
- package/dist/templates/frontend/design-tokens.json.ejs +107 -0
- package/dist/templates/frontend/vrt-setup.md.ejs +83 -0
- package/dist/templates/githooks/commit-msg.ejs +60 -0
- package/dist/templates/githooks/pre-commit.ejs +95 -0
- package/dist/templates/githooks/pre-push.ejs +251 -0
- package/dist/templates/githooks/setup-hooks.sh.ejs +8 -0
- package/dist/templates/github/PULL_REQUEST_TEMPLATE.md +37 -0
- package/dist/templates/github/PULL_REQUEST_TEMPLATE.md.ejs +52 -0
- package/dist/templates/github/actions/build-cache/action.yml.ejs +84 -0
- package/dist/templates/github/actions/nas-ssh/action.yml.ejs +53 -0
- package/dist/templates/github/actions/setup-java-maven/action.yml.ejs +53 -0
- package/dist/templates/github/actions/setup-node-pnpm/action.yml.ejs +39 -0
- package/dist/templates/github/actions/sign-and-attest/action.yml.ejs +53 -0
- package/dist/templates/github/dependabot.yml.ejs +66 -0
- package/dist/templates/github/extended-ci-paths.txt.ejs +38 -0
- package/dist/templates/github/issue-templates/bug-report.yml +72 -0
- package/dist/templates/github/issue-templates/compliance-item.yml.ejs +75 -0
- package/dist/templates/github/issue-templates/config.yml +2 -0
- package/dist/templates/github/issue-templates/epic.yml +66 -0
- package/dist/templates/github/issue-templates/feature-request.yml +24 -0
- package/dist/templates/github/issue-templates/task-brief.yml.ejs +125 -0
- package/dist/templates/github/labels.yml.ejs +161 -0
- package/dist/templates/github/scripts/sticky-failure-issue.sh.ejs +61 -0
- package/dist/templates/github/workflows/01-pr-fast.yml.ejs +1089 -0
- package/dist/templates/github/workflows/02-pr-extended.yml.ejs +512 -0
- package/dist/templates/github/workflows/03-human-approval.yml.ejs +76 -0
- package/dist/templates/github/workflows/04-deploy-test.yml.ejs +425 -0
- package/dist/templates/github/workflows/05-release.yml.ejs +813 -0
- package/dist/templates/github/workflows/06-nightly-lite.yml.ejs +125 -0
- package/dist/templates/github/workflows/06-nightly.yml.ejs +25 -0
- package/dist/templates/github/workflows/07-weekly-lite.yml.ejs +221 -0
- package/dist/templates/github/workflows/07-weekly.yml.ejs +23 -0
- package/dist/templates/github/workflows/08-monthly.yml.ejs +23 -0
- package/dist/templates/github/workflows/09-heartbeat.yml.ejs +268 -0
- package/dist/templates/github/workflows/10-deploy-prod.yml.ejs +144 -0
- package/dist/templates/github/workflows/11-k6-on-demand.yml.ejs +43 -0
- package/dist/templates/github/workflows/12-mutation-scheduled.yml.ejs +100 -0
- package/dist/templates/github/workflows/13-archunit-extended.yml.ejs +33 -0
- package/dist/templates/github/workflows/14-license-scan.yml.ejs +45 -0
- package/dist/templates/github/workflows/15-codeql.yml.ejs +117 -0
- package/dist/templates/github/workflows/16-frontend-quality.yml.ejs +154 -0
- package/dist/templates/github/workflows/17-ossf-scorecard.yml.ejs +46 -0
- package/dist/templates/github/workflows/18-frontend-lane.yml.ejs +50 -0
- package/dist/templates/github/workflows/_ai-draft-check.yml.ejs +44 -0
- package/dist/templates/github/workflows/_contract-postman.yml.ejs +93 -0
- package/dist/templates/github/workflows/_cosign-copy/aws-ecs.ejs +90 -0
- package/dist/templates/github/workflows/_cosign-copy/azure-container-app.ejs +97 -0
- package/dist/templates/github/workflows/_cosign-copy/gcp-cloud-run.ejs +102 -0
- package/dist/templates/github/workflows/_cosign-copy/ghcr.ejs +76 -0
- package/dist/templates/github/workflows/_cosign-copy/nas-compose.ejs +69 -0
- package/dist/templates/github/workflows/_deploy/aws-ecs.ejs +78 -0
- package/dist/templates/github/workflows/_deploy/azure-container-app.ejs +59 -0
- package/dist/templates/github/workflows/_deploy/gcp-cloud-run.ejs +71 -0
- package/dist/templates/github/workflows/_deploy/ghcr.ejs +19 -0
- package/dist/templates/github/workflows/_deploy/nas-compose.ejs +45 -0
- package/dist/templates/github/workflows/_k6-runner.yml.ejs +107 -0
- package/dist/templates/github/workflows/_label-on-approve.yml.ejs +44 -0
- package/dist/templates/github/workflows/_label-sync.yml.ejs +58 -0
- package/dist/templates/github/workflows/_monthly.yml.ejs +343 -0
- package/dist/templates/github/workflows/_nightly.yml.ejs +826 -0
- package/dist/templates/github/workflows/_notify.yml.ejs +96 -0
- package/dist/templates/github/workflows/_partials/macos-keychain-bypass.ejs +6 -0
- package/dist/templates/github/workflows/_partials/macos-keychain-restore.ejs +6 -0
- package/dist/templates/github/workflows/_partials/scheduled-heavy-jobs.ejs +117 -0
- package/dist/templates/github/workflows/_partials/sigstore-preflight.ejs +8 -0
- package/dist/templates/github/workflows/_partials/trivy-fs-java.ejs +27 -0
- package/dist/templates/github/workflows/_post-merge-notify.yml.ejs +228 -0
- package/dist/templates/github/workflows/_pr-staleness.yml.ejs +85 -0
- package/dist/templates/github/workflows/_shared-security.yml.ejs +132 -0
- package/dist/templates/github/workflows/_sigstore-retry-sign.yml.ejs +102 -0
- package/dist/templates/github/workflows/_weekly.yml.ejs +313 -0
- package/dist/templates/github/workflows/drift-shadow.yml.ejs +51 -0
- package/dist/templates/github/workflows/five-lane/ci.yml.ejs +54 -0
- package/dist/templates/github/workflows/five-lane/nightly.yml.ejs +70 -0
- package/dist/templates/github/workflows/five-lane/release.yml.ejs +53 -0
- package/dist/templates/github/workflows/five-lane/weekly.yml.ejs +72 -0
- package/dist/templates/github/workflows/issue-state.yml.ejs +93 -0
- package/dist/templates/global-invariants/GLOBAL_INVARIANTS.md.ejs +34 -0
- package/dist/templates/governance/RACI.md.ejs +21 -0
- package/dist/templates/governance/ci-mental-model.md.ejs +268 -0
- package/dist/templates/governance/contract-integrity-policy.md.ejs +116 -0
- package/dist/templates/governance/enterprise-compliance-baseline.md.ejs +111 -0
- package/dist/templates/governance/evidence-retention.md.ejs +43 -0
- package/dist/templates/governance/gdpr-erasure-runbook.md.ejs +165 -0
- package/dist/templates/governance/qa-audit-phases.md.ejs +129 -0
- package/dist/templates/governance/risk-assessment-template.md.ejs +105 -0
- package/dist/templates/governance/risk-register.md.ejs +76 -0
- package/dist/templates/governance/solo-dev-exception.md.ejs +96 -0
- package/dist/templates/governance/validation-evidence.md.ejs +131 -0
- package/dist/templates/infra/azure/containerapp.tpl.yaml.ejs +74 -0
- package/dist/templates/infra/nas-compose/deploy.sh.ejs +114 -0
- package/dist/templates/integration-testing/AbstractIntegrationTest.java.ejs +36 -0
- package/dist/templates/integration-testing/NoH2ArchTest.java.ejs +24 -0
- package/dist/templates/integration-testing/conftest.py.ejs +20 -0
- package/dist/templates/integration-testing/db_fixture.rs.ejs +48 -0
- package/dist/templates/integration-testing/eslint-no-fake-db.json.ejs +19 -0
- package/dist/templates/integration-testing/eslint.config.no-fake-db.mjs.ejs +46 -0
- package/dist/templates/integration-testing/main_test.go.ejs +53 -0
- package/dist/templates/integration-testing/main_test_sqlite.go.ejs +37 -0
- package/dist/templates/integration-testing/test-setup.ts.ejs +26 -0
- package/dist/templates/integration-testing/testcontainers-deps.gradle.ejs +9 -0
- package/dist/templates/java/DeprecationInterceptor.java.ejs +50 -0
- package/dist/templates/java/archunit-hexagonal.ejs +69 -0
- package/dist/templates/java/modulith/ApplicationModulesTest.java.ejs +21 -0
- package/dist/templates/java/modulith/modulith-deps.gradle.ejs +13 -0
- package/dist/templates/java/modulith/modulith-maven-setup.md.ejs +21 -0
- package/dist/templates/java/pharma/AuditEvent.java.ejs +138 -0
- package/dist/templates/java/pharma/AuditMapper.java.ejs +60 -0
- package/dist/templates/java/pharma/archunit-pharma.ejs +128 -0
- package/dist/templates/kit/GLOBAL_KIT.md.ejs +11 -0
- package/dist/templates/kit/dim.md.ejs +33 -0
- package/dist/templates/llms-txt.config.json.ejs +22 -0
- package/dist/templates/local-wrapper/.env.example.ejs +15 -0
- package/dist/templates/local-wrapper/Makefile.ejs +44 -0
- package/dist/templates/local-wrapper/run.sh.ejs +5 -0
- package/dist/templates/middleware/410-gone-handler.ts.ejs +41 -0
- package/dist/templates/middleware/correlation-id.ts.ejs +32 -0
- package/dist/templates/middleware/deprecation.ts.ejs +45 -0
- package/dist/templates/middleware/error-handler.ts.ejs +73 -0
- package/dist/templates/middleware/payload-size-limit.ts.ejs +51 -0
- package/dist/templates/mutation/README.md.ejs +67 -0
- package/dist/templates/mutation/cargo-mutants.toml.ejs +9 -0
- package/dist/templates/mutation/mutmut-config.toml.ejs +7 -0
- package/dist/templates/mutation/parse-mutants.mjs.ejs +44 -0
- package/dist/templates/mutation/parse-mutmut.py.ejs +44 -0
- package/dist/templates/mutation/pitest-l2-setup.md.ejs +66 -0
- package/dist/templates/mutation/pitest-maven-setup.md.ejs +64 -0
- package/dist/templates/mutation/pitest.gradle.ejs +23 -0
- package/dist/templates/mutation/stryker.conf.json.ejs +17 -0
- package/dist/templates/observability/setup.md.ejs +495 -0
- package/dist/templates/operations/handbook.md.ejs +217 -0
- package/dist/templates/perf/bundle-budget.json.ejs +29 -0
- package/dist/templates/perf/k6/reports/csv-report.py.ejs +91 -0
- package/dist/templates/perf/k6/reports/html-report.py.ejs +114 -0
- package/dist/templates/perf/k6/reports/json-report.py.ejs +74 -0
- package/dist/templates/perf/k6/scenarios/breakpoint.js.ejs +26 -0
- package/dist/templates/perf/k6/scenarios/burst.js.ejs +43 -0
- package/dist/templates/perf/k6/scenarios/endurance.js.ejs +36 -0
- package/dist/templates/perf/k6/scenarios/load.js.ejs +26 -0
- package/dist/templates/perf/k6/scenarios/ramp-down.js.ejs +29 -0
- package/dist/templates/perf/k6/scenarios/ramp-up.js.ejs +32 -0
- package/dist/templates/perf/k6/scenarios/smoke.js.ejs +23 -0
- package/dist/templates/perf/k6/scenarios/soak.js.ejs +26 -0
- package/dist/templates/perf/k6/scenarios/spike.js.ejs +29 -0
- package/dist/templates/perf/k6/scenarios/steady-state.js.ejs +31 -0
- package/dist/templates/perf/k6/scenarios/stress.js.ejs +29 -0
- package/dist/templates/perf/k6/scenarios/volume.js.ejs +36 -0
- package/dist/templates/perf/k6/seed/test-data.sql.ejs +59 -0
- package/dist/templates/perf/lighthouserc.json.ejs +41 -0
- package/dist/templates/quality/iso9001/CAPA_LOG.md.ejs +36 -0
- package/dist/templates/quality/iso9001/DOCUMENT_CONTROL.md.ejs +36 -0
- package/dist/templates/quality/iso9001/REQUIREMENTS_TRACEABILITY.md.ejs +61 -0
- package/dist/templates/regulated/overlay.json.ejs +26 -0
- package/dist/templates/regulated/regulated-overlay.md.ejs +40 -0
- package/dist/templates/resilience/RESILIENCE.md.ejs +310 -0
- package/dist/templates/root/.gitignore.ejs +85 -0
- package/dist/templates/root/CODEOWNERS.ejs +18 -0
- package/dist/templates/root/CONTRIBUTING.md.ejs +62 -0
- package/dist/templates/root/SECURITY.md.ejs +19 -0
- package/dist/templates/root/TEST_TAXONOMY.md.ejs +100 -0
- package/dist/templates/root/commitlint.config.js.ejs +4 -0
- package/dist/templates/root/docs/METHOD/CANONICAL_PATHS.md.ejs +24 -0
- package/dist/templates/root/docs/METHOD/ENGINEERING_DEFAULTS.md.ejs +136 -0
- package/dist/templates/root/docs/METHOD/KNOWLEDGE_MAP.md.ejs +90 -0
- package/dist/templates/root/docs/METHOD/PATTERNS_CATALOG.md.ejs +51 -0
- package/dist/templates/root/docs/METHOD/REUSE_REGISTRY.md.ejs +26 -0
- package/dist/templates/root/docs/METHOD/REUSE_REGISTRY_SPEC.md.ejs +80 -0
- package/dist/templates/root/docs/METHOD/SSOT_CORE_SET.md.ejs +62 -0
- package/dist/templates/root/docs/METHOD/TRACK_ROUTER.md.ejs +39 -0
- package/dist/templates/root/docs/SYSTEM/CANON.md.ejs +359 -0
- package/dist/templates/root/docs/SYSTEM/FAIL_CLOSED.md.ejs +171 -0
- package/dist/templates/root/editorconfig.ejs +39 -0
- package/dist/templates/root/tsconfig.json.ejs +21 -0
- package/dist/templates/rust/clippy.toml.ejs +14 -0
- package/dist/templates/schemas/milestone.schema.json.ejs +164 -0
- package/dist/templates/schemas/rtm-verdict.schema.json.ejs +52 -0
- package/dist/templates/schemas/source-record.schema.json.ejs +91 -0
- package/dist/templates/schemas/tabletop-evidence.schema.json.ejs +53 -0
- package/dist/templates/schemas/use-case.schema.json.ejs +59 -0
- package/dist/templates/scripts/apply-branch-protection.mjs.ejs +70 -0
- package/dist/templates/scripts/audit-toolchain.mjs.ejs +112 -0
- package/dist/templates/scripts/bg-run.sh.ejs +59 -0
- package/dist/templates/scripts/capacity-probe.mjs.ejs +147 -0
- package/dist/templates/scripts/capture-debt-baseline.mjs.ejs +99 -0
- package/dist/templates/scripts/check-acceptance.mjs.ejs +298 -0
- package/dist/templates/scripts/check-action-pins.mjs.ejs +215 -0
- package/dist/templates/scripts/check-agent-return.mjs.ejs +177 -0
- package/dist/templates/scripts/check-all.mjs.ejs +1746 -0
- package/dist/templates/scripts/check-anti-fake-green.mjs.ejs +80 -0
- package/dist/templates/scripts/check-anti-proforma.mjs.ejs +547 -0
- package/dist/templates/scripts/check-api-e2e.mjs.ejs +106 -0
- package/dist/templates/scripts/check-arc42-slots.mjs.ejs +25 -0
- package/dist/templates/scripts/check-assertion-delta.mjs.ejs +287 -0
- package/dist/templates/scripts/check-audit-dry-pass.mjs.ejs +176 -0
- package/dist/templates/scripts/check-bundle-size.mjs.ejs +151 -0
- package/dist/templates/scripts/check-canonical-paths.mjs.ejs +39 -0
- package/dist/templates/scripts/check-ci-tiers.mjs.ejs +111 -0
- package/dist/templates/scripts/check-claude-md-lint.mjs.ejs +142 -0
- package/dist/templates/scripts/check-collab-mode-wired.mjs.ejs +60 -0
- package/dist/templates/scripts/check-commit-footer-rationale.mjs.ejs +170 -0
- package/dist/templates/scripts/check-constraint-scan.mjs.ejs +681 -0
- package/dist/templates/scripts/check-consumer-audit.mjs.ejs +414 -0
- package/dist/templates/scripts/check-continue-on-error.mjs.ejs +227 -0
- package/dist/templates/scripts/check-cross-model-review.mjs.ejs +458 -0
- package/dist/templates/scripts/check-decision-registry.mjs.ejs +101 -0
- package/dist/templates/scripts/check-doc-freshness.mjs.ejs +17 -0
- package/dist/templates/scripts/check-doc-links.mjs.ejs +98 -0
- package/dist/templates/scripts/check-doc-set.mjs.ejs +18 -0
- package/dist/templates/scripts/check-docs.mjs.ejs +71 -0
- package/dist/templates/scripts/check-domain-api-surface.mjs.ejs +80 -0
- package/dist/templates/scripts/check-drift.mjs.ejs +167 -0
- package/dist/templates/scripts/check-duplication.mjs.ejs +45 -0
- package/dist/templates/scripts/check-e2e-escalation.mjs.ejs +199 -0
- package/dist/templates/scripts/check-e2e-quarantine.mjs.ejs +68 -0
- package/dist/templates/scripts/check-emission-parity.mjs.ejs +91 -0
- package/dist/templates/scripts/check-exit-code-contract.mjs.ejs +138 -0
- package/dist/templates/scripts/check-fail-closed-audit.mjs.ejs +389 -0
- package/dist/templates/scripts/check-fe-boundaries.mjs.ejs +184 -0
- package/dist/templates/scripts/check-feature-matrix.mjs.ejs +835 -0
- package/dist/templates/scripts/check-frontend-lane.mjs.ejs +73 -0
- package/dist/templates/scripts/check-grace-window.mjs.ejs +102 -0
- package/dist/templates/scripts/check-handoff-doc.mjs.ejs +192 -0
- package/dist/templates/scripts/check-hook-routing.mjs.ejs +224 -0
- package/dist/templates/scripts/check-image-pins.mjs.ejs +90 -0
- package/dist/templates/scripts/check-inline-suppressions.mjs.ejs +153 -0
- package/dist/templates/scripts/check-iso9001.mjs.ejs +146 -0
- package/dist/templates/scripts/check-knowledge-map.mjs.ejs +49 -0
- package/dist/templates/scripts/check-local-ci-parity.mjs.ejs +382 -0
- package/dist/templates/scripts/check-m16-handoff.mjs.ejs +112 -0
- package/dist/templates/scripts/check-merge-method.mjs.ejs +92 -0
- package/dist/templates/scripts/check-milestones.mjs.ejs +678 -0
- package/dist/templates/scripts/check-min-test-execution.mjs.ejs +225 -0
- package/dist/templates/scripts/check-muted-test.mjs.ejs +270 -0
- package/dist/templates/scripts/check-no-stub-redirects.mjs.ejs +154 -0
- package/dist/templates/scripts/check-no-tracked-artifacts.mjs.ejs +134 -0
- package/dist/templates/scripts/check-oracle-discrimination.mjs.ejs +244 -0
- package/dist/templates/scripts/check-pii-scan.mjs.ejs +67 -0
- package/dist/templates/scripts/check-pipe-tee-hazard.mjs.ejs +85 -0
- package/dist/templates/scripts/check-pr-size-gate.mjs.ejs +85 -0
- package/dist/templates/scripts/check-refutation-verdicts.mjs.ejs +256 -0
- package/dist/templates/scripts/check-regulated-overlay.mjs.ejs +158 -0
- package/dist/templates/scripts/check-render-smoke.mjs.ejs +100 -0
- package/dist/templates/scripts/check-reuse-registry.mjs.ejs +44 -0
- package/dist/templates/scripts/check-review-completion.mjs.ejs +708 -0
- package/dist/templates/scripts/check-safety-adopt-ratchet.mjs.ejs +142 -0
- package/dist/templates/scripts/check-secret-presence.mjs.ejs +191 -0
- package/dist/templates/scripts/check-secret-scan.mjs.ejs +82 -0
- package/dist/templates/scripts/check-skip-critical-e2e.mjs.ejs +142 -0
- package/dist/templates/scripts/check-smoke-journeys.mjs.ejs +272 -0
- package/dist/templates/scripts/check-solo-reactivation.mjs.ejs +102 -0
- package/dist/templates/scripts/check-sources.mjs.ejs +245 -0
- package/dist/templates/scripts/check-ssot-core.mjs.ejs +45 -0
- package/dist/templates/scripts/check-stack-conformity.mjs.ejs +160 -0
- package/dist/templates/scripts/check-stride-traceability.mjs.ejs +101 -0
- package/dist/templates/scripts/check-suppression-expiry.mjs.ejs +79 -0
- package/dist/templates/scripts/check-suppression-rationale.mjs.ejs +76 -0
- package/dist/templates/scripts/check-suppressions.mjs.ejs +150 -0
- package/dist/templates/scripts/check-tabletop-evidence.mjs.ejs +499 -0
- package/dist/templates/scripts/check-tdd-evidence.mjs.ejs +381 -0
- package/dist/templates/scripts/check-test-naming.mjs.ejs +151 -0
- package/dist/templates/scripts/check-test-pyramid.mjs.ejs +170 -0
- package/dist/templates/scripts/check-test-scope-tier.mjs.ejs +208 -0
- package/dist/templates/scripts/check-tier-coverage.mjs.ejs +71 -0
- package/dist/templates/scripts/check-todo-max-age.mjs.ejs +205 -0
- package/dist/templates/scripts/check-touched-vs-manifest.mjs.ejs +179 -0
- package/dist/templates/scripts/check-unwired-guards.mjs.ejs +367 -0
- package/dist/templates/scripts/check-use-cases.mjs.ejs +345 -0
- package/dist/templates/scripts/check-validator-helptext.mjs.ejs +80 -0
- package/dist/templates/scripts/check-wiki-lint.mjs.ejs +162 -0
- package/dist/templates/scripts/check-workflow-docs-sync.mjs.ejs +91 -0
- package/dist/templates/scripts/check-workflow-job-naming.mjs.ejs +102 -0
- package/dist/templates/scripts/check-workflow-perms.mjs.ejs +54 -0
- package/dist/templates/scripts/check-workflow-runners.mjs.ejs +87 -0
- package/dist/templates/scripts/check-workflow-sha-pinning.mjs.ejs +89 -0
- package/dist/templates/scripts/check-workflow-test-integrity.mjs.ejs +235 -0
- package/dist/templates/scripts/checks/check-rust-no-unsafe.mjs.ejs +58 -0
- package/dist/templates/scripts/checks/check-rust-no-unwrap.mjs.ejs +61 -0
- package/dist/templates/scripts/ci-classify-changes.mjs.ejs +119 -0
- package/dist/templates/scripts/conformance.mjs.ejs +37 -0
- package/dist/templates/scripts/constraint-map.json.ejs +25 -0
- package/dist/templates/scripts/debt-lib.mjs.ejs +1015 -0
- package/dist/templates/scripts/debt-report.mjs.ejs +199 -0
- package/dist/templates/scripts/domain-api-surface.json.ejs +23 -0
- package/dist/templates/scripts/done-evidence.mjs.ejs +359 -0
- package/dist/templates/scripts/evidence-collect.mjs.ejs +264 -0
- package/dist/templates/scripts/evidence-prune.mjs.ejs +96 -0
- package/dist/templates/scripts/evidence-rotate.mjs.ejs +53 -0
- package/dist/templates/scripts/evidence-writer.sh.ejs +220 -0
- package/dist/templates/scripts/gate-registry.yml.ejs +286 -0
- package/dist/templates/scripts/gen-doc-index.mjs.ejs +19 -0
- package/dist/templates/scripts/gen-gap.mjs.ejs +153 -0
- package/dist/templates/scripts/gen-llms-txt.mjs.ejs +18 -0
- package/dist/templates/scripts/gen-wiki.mjs.ejs +196 -0
- package/dist/templates/scripts/gh-cleanup-expired-artifacts.mjs.ejs +134 -0
- package/dist/templates/scripts/gold-audit.mjs.ejs +19 -0
- package/dist/templates/scripts/i18n-literal-scanner.mjs.ejs +175 -0
- package/dist/templates/scripts/ingest-zap-report.mjs.ejs +107 -0
- package/dist/templates/scripts/inject-pact-samples.sh.ejs +96 -0
- package/dist/templates/scripts/issue-readiness.mjs.ejs +84 -0
- package/dist/templates/scripts/knowledge-map-update.mjs.ejs +32 -0
- package/dist/templates/scripts/lib/acceptance-criteria.mjs.ejs +213 -0
- package/dist/templates/scripts/lib/agent-return-validate.mjs.ejs +481 -0
- package/dist/templates/scripts/lib/coverage-gate.mjs.ejs +54 -0
- package/dist/templates/scripts/lib/e2e-reliability.mjs.ejs +207 -0
- package/dist/templates/scripts/lib/ephemeral-server.mjs.ejs +148 -0
- package/dist/templates/scripts/lib/evidence-binding.mjs.ejs +140 -0
- package/dist/templates/scripts/lib/exact-sha-policy.mjs.ejs +233 -0
- package/dist/templates/scripts/lib/gate-args.mjs.ejs +20 -0
- package/dist/templates/scripts/lib/gate-evidence.mjs.ejs +622 -0
- package/dist/templates/scripts/lib/gate-mutex.mjs.ejs +340 -0
- package/dist/templates/scripts/lib/glob-walk.mjs.ejs +148 -0
- package/dist/templates/scripts/lib/run-helpers.mjs.ejs +416 -0
- package/dist/templates/scripts/lib/seed-common.sh.ejs +105 -0
- package/dist/templates/scripts/lib/waiter-count.mjs.ejs +62 -0
- package/dist/templates/scripts/muted-tests-baseline.json.ejs +4 -0
- package/dist/templates/scripts/optional-emissions.json.ejs +117 -0
- package/dist/templates/scripts/oracle-discrimination-baseline.json.ejs +6 -0
- package/dist/templates/scripts/pid-watch.sh.ejs +78 -0
- package/dist/templates/scripts/pii-scan.mjs.ejs +125 -0
- package/dist/templates/scripts/pr-merge-watch.mjs.ejs +445 -0
- package/dist/templates/scripts/record-agent-return.mjs.ejs +279 -0
- package/dist/templates/scripts/record-journey-evidence.mjs.ejs +69 -0
- package/dist/templates/scripts/rework-log.mjs.ejs +172 -0
- package/dist/templates/scripts/run-postman-tests.sh.ejs +112 -0
- package/dist/templates/scripts/schemas/agent-return-external.schema.json +74 -0
- package/dist/templates/scripts/schemas/agent-return.schema.json.ejs +181 -0
- package/dist/templates/scripts/schemas/cross-model-dispatch.schema.json +95 -0
- package/dist/templates/scripts/seed-test-data.sh.ejs +99 -0
- package/dist/templates/scripts/self-validation.mjs.ejs +126 -0
- package/dist/templates/scripts/setup-repo.sh.ejs +78 -0
- package/dist/templates/scripts/spotbugs-baseline.json.ejs +4 -0
- package/dist/templates/scripts/test-gate-layering.mjs.ejs +92 -0
- package/dist/templates/scripts/validate-api-snapshots.mjs.ejs +86 -0
- package/dist/templates/scripts/validate-k6-scenarios.mjs.ejs +96 -0
- package/dist/templates/scripts/validate-openapi-field-types.mjs.ejs +124 -0
- package/dist/templates/scripts/validate-postman-collection.mjs.ejs +159 -0
- package/dist/templates/scripts/verify-fe-coverage.mjs.ejs +138 -0
- package/dist/templates/scripts/verify-i18n-parity.mjs.ejs +114 -0
- package/dist/templates/scripts/verify-module-coverage.mjs.ejs +207 -0
- package/dist/templates/scripts/verify-mutation-baseline.mjs.ejs +209 -0
- package/dist/templates/scripts/verify-spotbugs.mjs.ejs +216 -0
- package/dist/templates/scripts/verify-tokens.mjs.ejs +177 -0
- package/dist/templates/security/RISK_ASSESSMENT.md.ejs +35 -0
- package/dist/templates/security/STRIDE.md.ejs +24 -0
- package/dist/templates/security/gitleaks.toml.ejs +21 -0
- package/dist/templates/security/zap/baseline-auth.context.ejs +58 -0
- package/dist/templates/security/zap/rules.tsv.ejs +100 -0
- package/dist/templates/ship/TICK_PROMPT.md.ejs +55 -0
- package/dist/templates/ship/supervisor.sh.ejs +46 -0
- package/dist/templates/smoke-journeys/manifest.json.ejs +1 -0
- package/dist/templates/sonar-project.properties.ejs +25 -0
- package/dist/templates/standards/doc-profile.ejs +27 -0
- package/dist/templates/standards/gold-doc-set.yml.ejs +528 -0
- package/dist/templates/standards/gold-registry.java.yml.ejs +266 -0
- package/dist/templates/standards/gold-registry.typescript.yml.ejs +104 -0
- package/dist/templates/standards/gold-registry.yml.ejs +119 -0
- package/dist/templates/standards/thresholds.yml.ejs +86 -0
- package/dist/templates/static-analysis/.dependency-cruiser.cjs.ejs +78 -0
- package/dist/templates/static-analysis/.golangci.yml.ejs +70 -0
- package/dist/templates/static-analysis/.shellcheckrc.ejs +13 -0
- package/dist/templates/static-analysis/.yamllint.yml.ejs +41 -0
- package/dist/templates/static-analysis/checkstyle.xml.ejs +83 -0
- package/dist/templates/static-analysis/detekt.yml.ejs +26 -0
- package/dist/templates/static-analysis/eslint.config.mjs.ejs +54 -0
- package/dist/templates/static-analysis/eslint.config.static.mjs.ejs +38 -0
- package/dist/templates/static-analysis/eslintrc-static.json.ejs +30 -0
- package/dist/templates/static-analysis/jscpd.json.ejs +25 -0
- package/dist/templates/static-analysis/knip.json.ejs +26 -0
- package/dist/templates/static-analysis/pmd-ruleset.xml.ejs +92 -0
- package/dist/templates/static-analysis/prettierignore.ejs +59 -0
- package/dist/templates/static-analysis/prettierrc.json.ejs +10 -0
- package/dist/templates/static-analysis/requirements-dev.txt.ejs +11 -0
- package/dist/templates/static-analysis/ruff.toml.ejs +40 -0
- package/dist/templates/static-analysis/rustfmt.toml.ejs +3 -0
- package/dist/templates/static-analysis/spotbugs-exclude.xml.ejs +120 -0
- package/dist/templates/static-analysis/spotbugs.gradle.ejs +18 -0
- package/dist/templates/static-analysis/spotless.gradle.ejs +38 -0
- package/dist/templates/static-analysis/stylelintrc.json.ejs +16 -0
- package/dist/templates/suppressions/archunit-baseline.json.ejs +1 -0
- package/dist/templates/suppressions/consumer-audit-allowlist.json.ejs +1 -0
- package/dist/templates/suppressions/gitleaksignore.ejs +20 -0
- package/dist/templates/suppressions/pii-allowlist.json.ejs +1 -0
- package/dist/templates/suppressions/suppressions-schema.json.ejs +39 -0
- package/dist/templates/suppressions/trivyignore.ejs +17 -0
- package/dist/templates/testing/test-taxonomy.md.ejs +120 -0
- package/dist/test/example.behavioral.test.js +2 -0
- package/dist/types/memory.d.ts +19 -0
- package/dist/types/memory.js +1 -0
- package/dist/types/plan.d.ts +102 -0
- package/dist/types/plan.js +2 -0
- package/dist/types/plugin.d.ts +45 -0
- package/dist/types/plugin.js +1 -0
- package/dist/utils/canon-loader.js +2 -0
- package/dist/utils/channel.js +1 -0
- package/dist/utils/config.d.ts +79 -0
- package/dist/utils/config.js +5 -0
- package/dist/utils/confirm-downgrade.js +5 -0
- package/dist/utils/env.js +2 -0
- package/dist/utils/error-catalog.js +2 -0
- package/dist/utils/errors.js +2 -0
- package/dist/utils/evidence-log.js +3 -0
- package/dist/utils/file-lock.js +2 -0
- package/dist/utils/first-run.js +8 -0
- package/dist/utils/fs.js +3 -0
- package/dist/utils/github-issue-helper.js +4 -0
- package/dist/utils/gradle.js +21 -0
- package/dist/utils/json-output.js +2 -0
- package/dist/utils/logger-config.js +4 -0
- package/dist/utils/logger.js +3 -0
- package/dist/utils/maturity-check.js +2 -0
- package/dist/utils/pkg.js +3 -0
- package/dist/utils/platform.js +2 -0
- package/dist/utils/plugin-loader.js +2 -0
- package/dist/utils/plugin-worker.js +2 -0
- package/dist/utils/prettier-format.js +2 -0
- package/dist/utils/profiler.js +2 -0
- package/dist/utils/render.js +2 -0
- package/dist/utils/replay.js +3 -0
- package/dist/utils/run-cli.js +6 -0
- package/dist/utils/run-id.js +3 -0
- package/dist/utils/safe-read.js +2 -0
- package/dist/utils/task-id.js +2 -0
- package/dist/utils/today.js +2 -0
- package/dist/utils/tty.js +2 -0
- package/dist/utils/walk-dir.js +2 -0
- package/dist/verify/rules/drive-by-scope.js +1 -0
- package/dist/verify/rules/orphan-todos.js +1 -0
- package/dist/verify/rules/registry.js +1 -0
- package/dist/verify/rules/skip-patterns.js +1 -0
- package/dist/verify/rules/types.d.ts +15 -0
- package/dist/verify/rules/types.js +1 -0
- package/dist/verify/rules/ui-language.js +1 -0
- package/dist/verify/run.js +3 -0
- package/dist/wizard/archetype-defaults.js +1 -0
- package/dist/wizard/presets.js +1 -0
- package/dist/wizard/prompts.js +44 -0
- package/dist/wizard/types.d.ts +637 -0
- package/dist/wizard/types.js +1 -0
- package/dist/worktree/harvest.js +2 -0
- package/dist/worktree/links.js +2 -0
- package/dist/worktree/paths.js +2 -0
- package/dist/worktree/validate.js +3 -0
- package/package.json +124 -0
- package/scripts/check-arc42-slots.mjs +738 -0
- package/scripts/check-doc-freshness.mjs +236 -0
- package/scripts/check-doc-set.mjs +243 -0
- package/scripts/check-doc-style.mjs +228 -0
- package/scripts/gold-audit.mjs +319 -0
- package/scripts/lib/doc-gate-allowlist.mjs +123 -0
- package/scripts/lib/doc-set-resolve.mjs +274 -0
- package/scripts/lib/glob-walk.mjs +148 -0
- package/scripts/lib/gold-audit-lib.mjs +1260 -0
- package/scripts/lib/run-helpers.mjs +413 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// CATALOG: INV-137 enforcement. Reads smoke-journeys.json at repo root; asserts the declared
|
|
4
|
+
// CATALOG: login/CRUD/authz acceptance floor is COVERED — every `required` journey must have
|
|
5
|
+
// CATALOG: ≥1 matching spec (glob-based, OR semantics). Reuses INV-124's algorithm but with
|
|
6
|
+
// CATALOG: INV-126's fail-closed default: applicability is archetype-computed, so a journey
|
|
7
|
+
// CATALOG: applicable to the archetype is `required` (absent status ⇒ required, never silently
|
|
8
|
+
// CATALOG: n/a). `n/a` needs a rationale ≥20 chars; all-n/a is a hard fail. A whole archetype
|
|
9
|
+
// CATALOG: with no interactive journeys declares applicable:false ⇒ SKIP (like INV-126
|
|
10
|
+
// CATALOG: required:false). SKIP when manifest absent. Boundary: file PRESENCE only — assertion
|
|
11
|
+
// CATALOG: quality is INV-118, and CI execution is the render-smoke/e2e lane's job. Because
|
|
12
|
+
// CATALOG: applicability is genuine (archetype-computed), a wired-but-dead CI job can never be
|
|
13
|
+
// CATALOG: laundered into a legitimate `n/a` here.
|
|
14
|
+
// Exit codes (INV-53): 0=PASS/SKIP, 1=policy violation, 2=schema/walk/path-traversal error
|
|
15
|
+
// Usage: node scripts/check-smoke-journeys.mjs [--help]
|
|
16
|
+
import { readFileSync, existsSync } from 'node:fs'
|
|
17
|
+
import { join, resolve } from 'node:path'
|
|
18
|
+
import { globMatch, validateGlob, walkRepo } from './lib/glob-walk.mjs'
|
|
19
|
+
|
|
20
|
+
const ROOT = resolve(process.cwd())
|
|
21
|
+
const MANIFEST_PATH = join(ROOT, 'smoke-journeys.json')
|
|
22
|
+
const ARBITER_PATH = join(ROOT, 'arbiter.json')
|
|
23
|
+
const REASON_MIN_LEN = 20
|
|
24
|
+
// #2043 (AC-2043.1): the login/CRUD/authz acceptance floor. A project overrides the
|
|
25
|
+
// declared set via arbiter.json's smokeJourneys.requiredJourneys (schema-validated,
|
|
26
|
+
// src/config/schema.ts); absent ⇒ this trio.
|
|
27
|
+
const DEFAULT_REQUIRED_JOURNEYS = ['auth', 'crud', 'authz']
|
|
28
|
+
|
|
29
|
+
const HELP = `Usage: node scripts/check-smoke-journeys.mjs [--help]
|
|
30
|
+
|
|
31
|
+
Enforces that every declared smoke journey in smoke-journeys.json is COVERED by at
|
|
32
|
+
least one real spec file — the login/CRUD/authz acceptance floor (INV-137).
|
|
33
|
+
|
|
34
|
+
Rules:
|
|
35
|
+
applicable:false — SKIP (archetype has no interactive login/CRUD/authz journeys).
|
|
36
|
+
status:"required" — at least one glob must match ≥1 file in the repo tree.
|
|
37
|
+
OR semantics: passes if ANY glob matches. Absent status ⇒ required
|
|
38
|
+
(fail-closed: a journey applicable to the archetype is never silently n/a).
|
|
39
|
+
status:"n/a" — must carry a rationale ≥${REASON_MIN_LEN} chars (auditable, genuine
|
|
40
|
+
non-applicability only — NOT a "the CI job is dead" escape hatch).
|
|
41
|
+
All n/a — exit 1 (a fully-skipped floor defeats the gate).
|
|
42
|
+
|
|
43
|
+
SKIP:
|
|
44
|
+
When smoke-journeys.json is absent (e.g. non-governed projects), gate exits 0.
|
|
45
|
+
Re-init with arbiter init to generate the manifest.
|
|
46
|
+
|
|
47
|
+
Exit codes:
|
|
48
|
+
0 — pass or SKIP (manifest absent / applicable:false)
|
|
49
|
+
1 — policy violation
|
|
50
|
+
2 — schema error, walk error, or path-traversal glob detected`
|
|
51
|
+
|
|
52
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
53
|
+
process.stdout.write(`${HELP}\n`)
|
|
54
|
+
process.exit(0)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function globCount(pattern, allFiles) {
|
|
58
|
+
return allFiles.filter((f) => globMatch(pattern, f)).length
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Reads+parses arbiter.json. Returns null when absent/racily-removed (nothing to compare
|
|
62
|
+
// against); exits directly (INV-96 fail-closed) on a real read or parse error.
|
|
63
|
+
function loadArbiterConfig() {
|
|
64
|
+
if (!existsSync(ARBITER_PATH)) return null
|
|
65
|
+
|
|
66
|
+
let raw
|
|
67
|
+
try {
|
|
68
|
+
raw = readFileSync(ARBITER_PATH, 'utf-8')
|
|
69
|
+
} catch (err) {
|
|
70
|
+
if (err && err.code === 'ENOENT') return null // race: file removed between existsSync and read
|
|
71
|
+
process.stderr.write(
|
|
72
|
+
`[check-smoke-journeys] ERROR — cannot read arbiter.json: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
73
|
+
)
|
|
74
|
+
process.exit(2)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(raw)
|
|
79
|
+
} catch (err) {
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
`[check-smoke-journeys] FAIL — arbiter.json is malformed (${err instanceof Error ? err.message : String(err)}); ` +
|
|
82
|
+
`cannot verify archetype — fix the file or run arbiter update to regenerate\n`,
|
|
83
|
+
)
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Archetype mismatch guard: stale manifests detectable at gate time. A missing/racily-removed
|
|
89
|
+
// arbiter.json legitimately skips the guard (loadArbiterConfig returns null); a CORRUPT one
|
|
90
|
+
// already exited fail-closed above — silently skipping the archetype check is exactly when
|
|
91
|
+
// manifest drift is most likely to hide.
|
|
92
|
+
function checkArchetypeMatch(manifest, arbiter) {
|
|
93
|
+
if (!arbiter) return
|
|
94
|
+
|
|
95
|
+
const mismatch =
|
|
96
|
+
arbiter.archetype && manifest.archetype && arbiter.archetype !== manifest.archetype
|
|
97
|
+
if (!mismatch) return
|
|
98
|
+
|
|
99
|
+
process.stderr.write(
|
|
100
|
+
`[check-smoke-journeys] FAIL — manifest generated for archetype ${manifest.archetype} ` +
|
|
101
|
+
`but arbiter.json declares ${arbiter.archetype} — run arbiter update to regenerate\n`,
|
|
102
|
+
)
|
|
103
|
+
process.exit(1)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// AC-2043.1: the manifest must DECLARE every journey in the configured trio (by id) —
|
|
107
|
+
// not just the ones a team happened to write. A missing member is a hard fail naming it,
|
|
108
|
+
// independent of the coverage checks below (a subset that IS fully covered still fails).
|
|
109
|
+
// Gated on arbiter.json being present/loadable: an ungoverned project (no arbiter.json)
|
|
110
|
+
// has no configured floor to compare against, so the pre-#2043 declared-only behavior
|
|
111
|
+
// stands — same precedent as checkArchetypeMatch above.
|
|
112
|
+
function checkTrioFloor(manifest, arbiter) {
|
|
113
|
+
if (!arbiter) return
|
|
114
|
+
|
|
115
|
+
const smokeJourneys = isRecord(arbiter.smokeJourneys) ? arbiter.smokeJourneys : undefined
|
|
116
|
+
const requiredJourneys =
|
|
117
|
+
smokeJourneys &&
|
|
118
|
+
Array.isArray(smokeJourneys.requiredJourneys) &&
|
|
119
|
+
smokeJourneys.requiredJourneys.length > 0
|
|
120
|
+
? smokeJourneys.requiredJourneys
|
|
121
|
+
: DEFAULT_REQUIRED_JOURNEYS
|
|
122
|
+
|
|
123
|
+
const declaredIds = new Set(
|
|
124
|
+
manifest.journeys.filter((j) => j && typeof j.id === 'string').map((j) => j.id),
|
|
125
|
+
)
|
|
126
|
+
const missing = requiredJourneys.filter((id) => !declaredIds.has(id))
|
|
127
|
+
if (missing.length === 0) return
|
|
128
|
+
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
`[check-smoke-journeys] FAIL — smoke-journeys.json is missing required journey(s): ` +
|
|
131
|
+
`${missing.join(', ')} — declare each (status required or n/a with rationale) or ` +
|
|
132
|
+
`adjust smokeJourneys.requiredJourneys in arbiter.json\n`,
|
|
133
|
+
)
|
|
134
|
+
process.exit(1)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function isRecord(value) {
|
|
138
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function checkNaJourney(id, name, journey) {
|
|
142
|
+
const rationale = typeof journey.rationale === 'string' ? journey.rationale.trim() : ''
|
|
143
|
+
if (rationale.length >= REASON_MIN_LEN) return false
|
|
144
|
+
process.stderr.write(
|
|
145
|
+
`[check-smoke-journeys] FAIL — journey ${id} (${name}) is n/a but rationale is ` +
|
|
146
|
+
`${rationale.length} chars (min ${REASON_MIN_LEN}): "${rationale}"\n`,
|
|
147
|
+
)
|
|
148
|
+
return true
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function checkRequiredJourney(id, name, journey, allFiles) {
|
|
152
|
+
const globs = Array.isArray(journey.globs) ? journey.globs : []
|
|
153
|
+
if (globs.length === 0) {
|
|
154
|
+
process.stderr.write(
|
|
155
|
+
`[check-smoke-journeys] FAIL — required journey ${id} (${name}) has no glob patterns ` +
|
|
156
|
+
`— add patterns or mark as n/a with rationale\n`,
|
|
157
|
+
)
|
|
158
|
+
return true
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Validate globs for path traversal
|
|
162
|
+
for (const g of globs) {
|
|
163
|
+
if (!validateGlob(g)) {
|
|
164
|
+
process.stderr.write(
|
|
165
|
+
`[check-smoke-journeys] ERROR — glob "${g}" in journey ${id} contains path traversal ` +
|
|
166
|
+
`or is absolute — only relative, non-traversal globs are allowed\n`,
|
|
167
|
+
)
|
|
168
|
+
process.exit(2)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// OR semantics: passes if ANY glob matches at least one file
|
|
173
|
+
const found = globs.some((g) => globCount(g, allFiles) > 0)
|
|
174
|
+
if (found) return false
|
|
175
|
+
|
|
176
|
+
process.stderr.write(
|
|
177
|
+
`[check-smoke-journeys] FAIL — journey ${id} (${name}) declared but empty ` +
|
|
178
|
+
`— no files matched: ${globs.join(', ')}\n`,
|
|
179
|
+
)
|
|
180
|
+
return true
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Validates one journey. Returns { isNa, violated } — main() aggregates counts/exit codes so
|
|
184
|
+
// exit(2) schema-error paths (path-traversal globs) stay a hard process exit from here.
|
|
185
|
+
function checkJourney(journey, allFiles) {
|
|
186
|
+
const id = typeof journey.id === 'string' ? journey.id : '?'
|
|
187
|
+
const name = typeof journey.name === 'string' ? journey.name : id
|
|
188
|
+
// Fail-closed default: only an explicit "n/a" is n/a; anything else (incl. an absent
|
|
189
|
+
// status) is REQUIRED — a journey applicable to the archetype cannot be silently skipped.
|
|
190
|
+
const isNa = journey.status === 'n/a'
|
|
191
|
+
const violated = isNa
|
|
192
|
+
? checkNaJourney(id, name, journey)
|
|
193
|
+
: checkRequiredJourney(id, name, journey, allFiles)
|
|
194
|
+
return { isNa, violated }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Loads smoke-journeys.json. SKIP-exits when absent; exits fail-closed on invalid JSON.
|
|
198
|
+
function loadManifest() {
|
|
199
|
+
if (!existsSync(MANIFEST_PATH)) {
|
|
200
|
+
process.stdout.write('[check-smoke-journeys] SKIP — smoke-journeys.json not found\n')
|
|
201
|
+
process.exit(0)
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
return JSON.parse(readFileSync(MANIFEST_PATH, 'utf-8'))
|
|
205
|
+
} catch (err) {
|
|
206
|
+
process.stderr.write(`[check-smoke-journeys] ERROR — invalid JSON: ${err.message}\n`)
|
|
207
|
+
process.exit(2)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function main() {
|
|
212
|
+
const manifest = loadManifest()
|
|
213
|
+
const arbiterConfig = loadArbiterConfig()
|
|
214
|
+
checkArchetypeMatch(manifest, arbiterConfig)
|
|
215
|
+
|
|
216
|
+
// Applicability SKIP (INV-126 precedent): an archetype with no interactive login/CRUD/authz
|
|
217
|
+
// journeys declares applicable:false. Checked BEFORE the all-n/a / rationale guards so a
|
|
218
|
+
// legitimately non-applicable archetype never trips them. Only an EXPLICIT false skips —
|
|
219
|
+
// an absent flag is fail-closed (falls through to the journeys checks).
|
|
220
|
+
if (manifest.applicable === false) {
|
|
221
|
+
process.stdout.write(
|
|
222
|
+
'[check-smoke-journeys] SKIP — applicable:false (archetype has no interactive smoke journeys)\n',
|
|
223
|
+
)
|
|
224
|
+
process.exit(0)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!Array.isArray(manifest.journeys)) {
|
|
228
|
+
process.stderr.write(
|
|
229
|
+
'[check-smoke-journeys] ERROR — manifest.journeys must be an array (schema error)\n',
|
|
230
|
+
)
|
|
231
|
+
process.exit(2)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
checkTrioFloor(manifest, arbiterConfig)
|
|
235
|
+
|
|
236
|
+
// Collect all repo files once
|
|
237
|
+
const allFiles = walkRepo(ROOT)
|
|
238
|
+
|
|
239
|
+
let violations = 0
|
|
240
|
+
let naCount = 0
|
|
241
|
+
const totalJourneys = manifest.journeys.length
|
|
242
|
+
|
|
243
|
+
for (const journey of manifest.journeys) {
|
|
244
|
+
const { isNa, violated } = checkJourney(journey, allFiles)
|
|
245
|
+
if (isNa) naCount++
|
|
246
|
+
if (violated) violations++
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// All-n/a hard fail
|
|
250
|
+
if (naCount > 0 && naCount === totalJourneys) {
|
|
251
|
+
process.stderr.write(
|
|
252
|
+
`[check-smoke-journeys] FAIL — all ${totalJourneys} declared journey(s) are n/a — ` +
|
|
253
|
+
`a fully-skipped floor defeats the gate\n`,
|
|
254
|
+
)
|
|
255
|
+
process.exit(1)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (violations > 0) {
|
|
259
|
+
process.stderr.write(`[check-smoke-journeys] FAIL — ${violations} violation(s) found\n`)
|
|
260
|
+
process.exit(1)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
process.stdout.write(`[check-smoke-journeys] OK — ${totalJourneys} journey(s) verified\n`)
|
|
264
|
+
process.exit(0)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
await main()
|
|
269
|
+
} catch (err) {
|
|
270
|
+
process.stderr.write(`[check-smoke-journeys] ERROR — unexpected: ${err.message}\n`)
|
|
271
|
+
process.exit(2)
|
|
272
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* check-solo-reactivation.mjs — Single-developer exception reactivation check
|
|
5
|
+
*
|
|
6
|
+
* Enforces the reactivation trigger for trunk-solo+<%= governanceLevel %> projects (#1250).
|
|
7
|
+
* Per docs/governance/SOLO_DEV_EXCEPTION.md §11.10(k):
|
|
8
|
+
* - Fires (exit 1) when ≥3 distinct authors are active in the trailing 30 days
|
|
9
|
+
* - Fires (exit 1) when EXTERNAL_AUDIT=true environment variable is set
|
|
10
|
+
*
|
|
11
|
+
* Runs nightly via .github/workflows/06-nightly-lite.yml
|
|
12
|
+
* Generated by arbiter — do not edit manually.
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync } from 'node:child_process'
|
|
15
|
+
|
|
16
|
+
const AUTHOR_THRESHOLD = 3
|
|
17
|
+
const LOOKBACK_DAYS = 30
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Count distinct author emails in git log for the trailing N days.
|
|
21
|
+
* Case-insensitive deduplication (git may emit different casings).
|
|
22
|
+
* Returns 0 if git log produces no output (new repo or no commits in window).
|
|
23
|
+
*/
|
|
24
|
+
function countDistinctAuthors(days) {
|
|
25
|
+
try {
|
|
26
|
+
const since = `${days} days ago`
|
|
27
|
+
const output = execFileSync('git', ['log', `--since=${since}`, '--format=%ae'], {
|
|
28
|
+
encoding: 'utf-8',
|
|
29
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
30
|
+
}).trim()
|
|
31
|
+
|
|
32
|
+
if (!output) return 0
|
|
33
|
+
|
|
34
|
+
const emails = output
|
|
35
|
+
.split('\n')
|
|
36
|
+
.map((e) => e.trim().toLowerCase())
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
return new Set(emails).size
|
|
39
|
+
} catch (err) {
|
|
40
|
+
// git not available or not a git repository — fail closed
|
|
41
|
+
console.error('check-solo-reactivation: git not available or not a git repo — failing closed')
|
|
42
|
+
console.error(err)
|
|
43
|
+
process.exit(1)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function main() {
|
|
48
|
+
const externalAudit = process.env['EXTERNAL_AUDIT'] === 'true'
|
|
49
|
+
const authorCount = countDistinctAuthors(LOOKBACK_DAYS)
|
|
50
|
+
|
|
51
|
+
const authorThresholdExceeded = authorCount >= AUTHOR_THRESHOLD
|
|
52
|
+
const triggered = authorThresholdExceeded || externalAudit
|
|
53
|
+
|
|
54
|
+
if (!triggered) {
|
|
55
|
+
console.log(
|
|
56
|
+
`check-solo-reactivation: OK — ${authorCount} distinct author(s) in trailing ${LOOKBACK_DAYS}d (threshold: ${AUTHOR_THRESHOLD}). External audit: ${externalAudit}.`,
|
|
57
|
+
)
|
|
58
|
+
process.exit(0)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Trigger: print clear remediation instructions and exit 1
|
|
62
|
+
console.error('')
|
|
63
|
+
console.error('╔══════════════════════════════════════════════════════════════╗')
|
|
64
|
+
console.error('║ SOLO-DEV EXCEPTION REACTIVATION TRIGGERED ║')
|
|
65
|
+
console.error('╚══════════════════════════════════════════════════════════════╝')
|
|
66
|
+
console.error('')
|
|
67
|
+
|
|
68
|
+
if (authorThresholdExceeded) {
|
|
69
|
+
console.error(
|
|
70
|
+
`REASON: ${authorCount} distinct author(s) detected in trailing ${LOOKBACK_DAYS} days`,
|
|
71
|
+
)
|
|
72
|
+
console.error(` (threshold: ≥${AUTHOR_THRESHOLD} authors triggers reactivation)`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (externalAudit) {
|
|
76
|
+
console.error('REASON: EXTERNAL_AUDIT=true environment variable is set')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.error('')
|
|
80
|
+
console.error('REQUIRED ACTIONS:')
|
|
81
|
+
console.error('')
|
|
82
|
+
console.error(' 1. Add CODEOWNERS file with required reviewers:')
|
|
83
|
+
console.error(' echo "* @your-reviewer" > CODEOWNERS')
|
|
84
|
+
console.error('')
|
|
85
|
+
console.error(' 2. Update arbiter.json to require peer review:')
|
|
86
|
+
console.error(' node dist/cli.js configure --set collaborationMode=peer-review')
|
|
87
|
+
console.error('')
|
|
88
|
+
console.error(' 3. Regenerate governance files:')
|
|
89
|
+
console.error(' node dist/cli.js update')
|
|
90
|
+
console.error('')
|
|
91
|
+
console.error(' 4. Enable branch protection with required reviewer:')
|
|
92
|
+
console.error(' node scripts/apply-branch-protection.mjs')
|
|
93
|
+
console.error('')
|
|
94
|
+
console.error(
|
|
95
|
+
'See docs/governance/SOLO_DEV_EXCEPTION.md for the full reactivation procedure.',
|
|
96
|
+
)
|
|
97
|
+
console.error('')
|
|
98
|
+
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main()
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// <%= projectName %> — docs/SOURCES.md gate (INV-147)
|
|
4
|
+
// Generated by arbiter (src/templates/scripts/check-sources.mjs.ejs)
|
|
5
|
+
//
|
|
6
|
+
// Ported from arbiter's own scripts/check-sources.mjs (#2480 wave 5). The rule is identical; only
|
|
7
|
+
// the registry's path differs, because a governed project keeps its documents flat under docs/
|
|
8
|
+
// while arbiter keeps its own under docs/internal/PRODUCT/. Nothing else is scoped down: the
|
|
9
|
+
// property this proves needs no arbiter-internal catalog, only a repository-contained excerpt.
|
|
10
|
+
//
|
|
11
|
+
// scripts/check-sources.mjs
|
|
12
|
+
// L1 gate, tier 1: a cited source is quotable, and the quotation checks out.
|
|
13
|
+
//
|
|
14
|
+
// Why a hash AND a substring check, when either alone looks sufficient:
|
|
15
|
+
// - the substring check alone passes on an excerpt someone edited after the fact, so the
|
|
16
|
+
// evidence could drift away from what was actually read;
|
|
17
|
+
// - the hash alone proves the excerpt is unchanged but says nothing about whether the project's
|
|
18
|
+
// quotation appears in it at all.
|
|
19
|
+
// Together they make "this source says X" falsifiable without a network call, which is what lets
|
|
20
|
+
// the rule run in a pre-commit hook on a machine with no credentials.
|
|
21
|
+
//
|
|
22
|
+
// Explicitly NOT done here, and not by accident:
|
|
23
|
+
// - the `url` is recorded provenance, never dereferenced. A gate that fails when a website is
|
|
24
|
+
// down fails for a reason unrelated to the claim it guards; link-liveness is a separate,
|
|
25
|
+
// advisory, networked concern.
|
|
26
|
+
// - relevance ("does this source actually support the decision") is a judgement, not a decidable
|
|
27
|
+
// property. Tier 2 puts that to independent skeptics; tier 1 refuses to pretend it can settle
|
|
28
|
+
// it deterministically.
|
|
29
|
+
//
|
|
30
|
+
// Usage: node scripts/check-sources.mjs [--dir <repo>] [--json]
|
|
31
|
+
// Exit: 0 pass or skip, 1 violation, 2 error (INV-53).
|
|
32
|
+
//
|
|
33
|
+
// Exports for unit tests: extractSourcesBlock, findDuplicateSourceIds, checkExcerptEvidence
|
|
34
|
+
|
|
35
|
+
import { readRegularFileSync } from './lib/run-helpers.mjs'
|
|
36
|
+
import { existsSync, realpathSync } from 'node:fs'
|
|
37
|
+
import { execFileSync } from 'node:child_process'
|
|
38
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
|
39
|
+
import { fileURLToPath } from 'node:url'
|
|
40
|
+
import { createHash } from 'node:crypto'
|
|
41
|
+
import { loadSchema, validateSchema } from './lib/agent-return-validate.mjs'
|
|
42
|
+
|
|
43
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url))
|
|
44
|
+
const SOURCES_REL = join('docs', 'SOURCES.md')
|
|
45
|
+
const SCHEMA_REL = join('schemas', 'source-record.schema.json')
|
|
46
|
+
const START = '<!-- SOURCES_START -->'
|
|
47
|
+
const END = '<!-- SOURCES_END -->'
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Pull the fenced JSON out of the sentinel block. Throws on a malformed block: a registry that
|
|
51
|
+
* cannot be parsed is an ERROR, never an empty list, because "no sources" and "the file is broken"
|
|
52
|
+
* must not produce the same green.
|
|
53
|
+
* @param {string} markdown
|
|
54
|
+
* @returns {{ sources: unknown[] }}
|
|
55
|
+
*/
|
|
56
|
+
export function extractSourcesBlock(markdown) {
|
|
57
|
+
const start = markdown.indexOf(START)
|
|
58
|
+
const end = markdown.indexOf(END)
|
|
59
|
+
if (start < 0 || end < 0 || end < start) {
|
|
60
|
+
throw new Error(`SOURCES.md is missing its ${START} / ${END} sentinel block`)
|
|
61
|
+
}
|
|
62
|
+
const inner = markdown.slice(start + START.length, end)
|
|
63
|
+
const fence = /```(?:json)?\s*([\s\S]*?)```/.exec(inner)
|
|
64
|
+
if (!fence) throw new Error('SOURCES.md sentinel block contains no fenced JSON')
|
|
65
|
+
return JSON.parse(fence[1])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @param {Array<Record<string, unknown>>} sources @returns {string[]} */
|
|
69
|
+
export function findDuplicateSourceIds(sources) {
|
|
70
|
+
const seen = new Set()
|
|
71
|
+
const violations = []
|
|
72
|
+
for (const s of sources) {
|
|
73
|
+
const id = String(s['id'])
|
|
74
|
+
if (seen.has(id)) violations.push(`duplicate source id "${id}"`)
|
|
75
|
+
seen.add(id)
|
|
76
|
+
}
|
|
77
|
+
return violations
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Tier 1 proper, for one source: the excerpt exists, hashes to what was recorded, and contains
|
|
82
|
+
* every quoted span literally.
|
|
83
|
+
* @param {Record<string, unknown>} source
|
|
84
|
+
* @param {string} root
|
|
85
|
+
* @returns {string[]}
|
|
86
|
+
*/
|
|
87
|
+
export function checkExcerptEvidence(source, root) {
|
|
88
|
+
const id = String(source['id'])
|
|
89
|
+
const rel = String(source['excerpt_path'] ?? '')
|
|
90
|
+
const violations = []
|
|
91
|
+
if (!rel) return [`${id}: no excerpt_path — a source with no committed excerpt cannot be checked`]
|
|
92
|
+
const abs = resolve(root, rel)
|
|
93
|
+
if (!isContained(root, abs)) {
|
|
94
|
+
return [`${id}: excerpt path ${rel} resolves outside the repository`]
|
|
95
|
+
}
|
|
96
|
+
const indexRel = relative(root, abs)
|
|
97
|
+
if (!existsSync(abs)) {
|
|
98
|
+
return [
|
|
99
|
+
`${id}: excerpt file ${rel} does not exist — the quotation has nothing to check against`,
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
const physicalRoot = realpathSync(root)
|
|
103
|
+
const physicalExcerpt = realpathSync(abs)
|
|
104
|
+
if (!isContained(physicalRoot, physicalExcerpt)) {
|
|
105
|
+
return [`${id}: excerpt path ${rel} resolves outside the repository`]
|
|
106
|
+
}
|
|
107
|
+
const physicalRel = relative(physicalRoot, physicalExcerpt)
|
|
108
|
+
if (!isGitIndexed(root, indexRel) || !isGitIndexed(physicalRoot, physicalRel)) {
|
|
109
|
+
return [
|
|
110
|
+
`${id}: excerpt file ${rel} or its resolved content is not tracked by Git — commit it, ` +
|
|
111
|
+
`or stage a newly added excerpt before this pre-commit check`,
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
const raw = readRegularFileSync(abs)
|
|
115
|
+
violations.push(...hashMismatch(id, raw, String(source['content_hash'])))
|
|
116
|
+
violations.push(...unquotedCitations(id, raw.toString('utf-8'), rel, source['citations']))
|
|
117
|
+
return violations
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** True when candidate is within root, including root itself. */
|
|
121
|
+
function isContained(root, candidate) {
|
|
122
|
+
const path = relative(root, candidate)
|
|
123
|
+
return path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Git-index membership accepts both committed files and files staged for their first commit. */
|
|
127
|
+
function isGitIndexed(root, rel) {
|
|
128
|
+
try {
|
|
129
|
+
const indexed = execFileSync(
|
|
130
|
+
'git',
|
|
131
|
+
['--literal-pathspecs', 'ls-files', '--error-unmatch', '-z', '--', rel],
|
|
132
|
+
{ cwd: root, stdio: ['ignore', 'pipe', 'ignore'] },
|
|
133
|
+
)
|
|
134
|
+
return indexed.equals(Buffer.from(`${rel}\0`))
|
|
135
|
+
// FAIL-OPEN-INTENT: Git cannot prove index membership, so this source is rejected.
|
|
136
|
+
} catch {
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The excerpt must still BE the excerpt that was read. @returns {string[]} */
|
|
142
|
+
function hashMismatch(id, raw, recorded) {
|
|
143
|
+
const actual = createHash('sha256').update(raw).digest('hex')
|
|
144
|
+
if (actual === recorded) return []
|
|
145
|
+
return [
|
|
146
|
+
`${id}: excerpt hash mismatch — recorded ${recorded.slice(0, 16)}…, file now hashes to ` +
|
|
147
|
+
`${actual.slice(0, 16)}…. The committed evidence is no longer the evidence that was read; ` +
|
|
148
|
+
`re-take the excerpt and re-record its hash.`,
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Every quoted span must appear verbatim — this is the half a hash cannot cover. @returns {string[]} */
|
|
153
|
+
function unquotedCitations(id, text, rel, citations) {
|
|
154
|
+
const violations = []
|
|
155
|
+
for (const citation of Array.isArray(citations) ? citations : []) {
|
|
156
|
+
const quoted = String(/** @type {Record<string, unknown>} */ (citation)['quoted_text'] ?? '')
|
|
157
|
+
if (quoted && !text.includes(quoted)) {
|
|
158
|
+
violations.push(
|
|
159
|
+
`${id}: quoted_text is not a literal substring of ${rel} — ` +
|
|
160
|
+
`"${quoted.slice(0, 60)}${quoted.length > 60 ? '…' : ''}"`,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return violations
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** @param {string[]} argv */
|
|
168
|
+
function parseArgs(argv) {
|
|
169
|
+
const i = argv.indexOf('--dir')
|
|
170
|
+
return {
|
|
171
|
+
root: i >= 0 && argv[i + 1] ? resolve(argv[i + 1]) : process.cwd(),
|
|
172
|
+
json: argv.includes('--json'),
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** @param {boolean} json @param {string} verdict @param {string} message @param {string[]} violations */
|
|
177
|
+
function report(json, verdict, message, violations) {
|
|
178
|
+
if (json) {
|
|
179
|
+
process.stdout.write(`${JSON.stringify({ verdict, message, violations }, null, 2)}\n`)
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
if (verdict === 'skip') {
|
|
183
|
+
process.stdout.write(`[SKIP] check-sources: ${message}\n`)
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
for (const v of violations) process.stderr.write(`check-sources: FAIL — ${v}\n`)
|
|
187
|
+
if (verdict === 'pass') process.stdout.write(`check-sources: PASS — ${message}\n`)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** @param {string[]} argv @returns {number} */
|
|
191
|
+
function main(argv) {
|
|
192
|
+
const { root, json } = parseArgs(argv)
|
|
193
|
+
const path = join(root, SOURCES_REL)
|
|
194
|
+
if (!existsSync(path)) {
|
|
195
|
+
report(json, 'skip', `${SOURCES_REL} absent — this project cites no external sources`, [])
|
|
196
|
+
return 0
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let doc
|
|
200
|
+
try {
|
|
201
|
+
doc = extractSourcesBlock(readRegularFileSync(path, 'utf-8'))
|
|
202
|
+
} catch (err) {
|
|
203
|
+
process.stderr.write(`check-sources: ${SOURCES_REL} could not be parsed — ${err.message}\n`)
|
|
204
|
+
return 2
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
let schema
|
|
208
|
+
try {
|
|
209
|
+
schema = loadSchema(resolve(scriptDir, '..', SCHEMA_REL))
|
|
210
|
+
} catch (err) {
|
|
211
|
+
process.stderr.write(`check-sources: cannot load ${SCHEMA_REL} — ${err.message}\n`)
|
|
212
|
+
return 2
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const schemaViolations = validateSchema(doc, schema, schema, 'sources')
|
|
216
|
+
if (schemaViolations.length > 0) {
|
|
217
|
+
report(json, 'fail', 'schema violations', schemaViolations)
|
|
218
|
+
return 1
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const sources = /** @type {Array<Record<string, unknown>>} */ (doc.sources)
|
|
222
|
+
const violations = [
|
|
223
|
+
...findDuplicateSourceIds(sources),
|
|
224
|
+
...sources.flatMap((s) => checkExcerptEvidence(s, root)),
|
|
225
|
+
]
|
|
226
|
+
if (violations.length > 0) {
|
|
227
|
+
report(json, 'fail', 'source evidence violations', violations)
|
|
228
|
+
return 1
|
|
229
|
+
}
|
|
230
|
+
const quotes = sources.reduce(
|
|
231
|
+
(n, s) => n + (Array.isArray(s['citations']) ? s['citations'].length : 0),
|
|
232
|
+
0,
|
|
233
|
+
)
|
|
234
|
+
report(json, 'pass', `${sources.length} source(s), ${quotes} quotation(s) verified literal`, [])
|
|
235
|
+
return 0
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
239
|
+
try {
|
|
240
|
+
process.exit(main(process.argv.slice(2)))
|
|
241
|
+
} catch (err) {
|
|
242
|
+
process.stderr.write(`check-sources: ${err?.stack ?? err}\n`)
|
|
243
|
+
process.exit(2)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// <%= projectName %> — SSOT core set gate (INV-47)
|
|
3
|
+
// Gate: verify every file listed in SSOT_CORE_SET.md exists on disk.
|
|
4
|
+
// Exits 0: all entries exist or no SSOT_CORE_SET.md found (bootstrap mode).
|
|
5
|
+
// Exits 1: one or more listed files are missing.
|
|
6
|
+
// Part of the anti-drift validator family (W6).
|
|
7
|
+
// Usage: node scripts/check-ssot-core.mjs [--help]
|
|
8
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
|
|
11
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
12
|
+
process.stdout.write('Usage: node scripts/check-ssot-core.mjs [--help]\nVerify every file listed in SSOT_CORE_SET.md exists on disk.\n');
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SSOT_FILE = join(process.cwd(), 'docs', 'METHOD', 'SSOT_CORE_SET.md');
|
|
17
|
+
|
|
18
|
+
if (!existsSync(SSOT_FILE)) {
|
|
19
|
+
console.log(' check-ssot-core: no SSOT_CORE_SET.md found — skipping (bootstrap mode)');
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const content = readFileSync(SSOT_FILE, 'utf-8');
|
|
24
|
+
|
|
25
|
+
const PATH_ITEM = /^[ \t]*-[ \t]+`([^`]+)`/gm;
|
|
26
|
+
|
|
27
|
+
const missing = [];
|
|
28
|
+
for (const match of content.matchAll(PATH_ITEM)) {
|
|
29
|
+
const filePath = match[1];
|
|
30
|
+
const abs = join(process.cwd(), filePath);
|
|
31
|
+
if (!existsSync(abs)) {
|
|
32
|
+
missing.push(filePath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (missing.length === 0) {
|
|
37
|
+
console.log(' check-ssot-core: all SSOT_CORE_SET entries exist');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log(` check-ssot-core: ${missing.length} missing file(s) listed in SSOT_CORE_SET.md:`);
|
|
42
|
+
for (const f of missing) {
|
|
43
|
+
console.log(` missing: ${f}`);
|
|
44
|
+
}
|
|
45
|
+
process.exit(1);
|