@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,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// CATALOG: P8 consistency gate. Verifies frontmatter shape + H1 presence +
|
|
5
|
+
// last_review ISO date on every hand-authored .md doc. Distinct from
|
|
6
|
+
// check-doc-links.mjs (link integrity) and check-docs.mjs (src↔docs co-change).
|
|
7
|
+
//
|
|
8
|
+
// Checks (per file):
|
|
9
|
+
// - frontmatter block present with required keys (title, doc_version,
|
|
10
|
+
// status, last_review, owner, canonical_id, tags, related)
|
|
11
|
+
// - `last_review` matches /^\d{4}-\d{2}-\d{2}$/
|
|
12
|
+
// - `status` ∈ {draft, active, deprecated, archived}
|
|
13
|
+
// - `doc_version` matches /^\d+\.\d+\.\d+$/
|
|
14
|
+
// - exactly one top-level H1 (`# ...`) in body
|
|
15
|
+
// - if frontmatter `title` is non-empty, the H1 text matches it (case-sensitive)
|
|
16
|
+
|
|
17
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
18
|
+
import { join, sep, relative } from 'node:path'
|
|
19
|
+
import { walkRepo } from './lib/glob-walk.mjs'
|
|
20
|
+
import { isMainModule } from './lib/run-helpers.mjs'
|
|
21
|
+
import { loadDocGateAllowlist, allowlistSummary } from './lib/doc-gate-allowlist.mjs'
|
|
22
|
+
|
|
23
|
+
const CWD = process.cwd()
|
|
24
|
+
|
|
25
|
+
const SCAN_ROOTS = ['docs', '.claude', '.agents', '.codex', 'examples']
|
|
26
|
+
const ROOT_FILES = [
|
|
27
|
+
'AGENTS.md',
|
|
28
|
+
'README.md',
|
|
29
|
+
'CODE_OF_CONDUCT.md',
|
|
30
|
+
'CONTRIBUTING.md',
|
|
31
|
+
'SECURITY.md',
|
|
32
|
+
'GLOBAL_INVARIANTS.md',
|
|
33
|
+
'OBSIDIAN.md',
|
|
34
|
+
]
|
|
35
|
+
export const SKIP_PATH_SEGMENTS = [
|
|
36
|
+
`${sep}node_modules${sep}`,
|
|
37
|
+
`${sep}dist${sep}`,
|
|
38
|
+
`${sep}.git${sep}`,
|
|
39
|
+
`${sep}.changeset${sep}`,
|
|
40
|
+
`${sep}api${sep}`,
|
|
41
|
+
`${sep}.coverage-tmp${sep}`,
|
|
42
|
+
`${sep}.evidence${sep}`,
|
|
43
|
+
`${sep}report${sep}`,
|
|
44
|
+
// #2408: `internal` used to sit here, which exempted the entire SSOT backbone
|
|
45
|
+
// (FEATURE_MATRIX, PROCESS, TESTING, CANONICAL_PATHS, every ADR) from the one
|
|
46
|
+
// gate that checks frontmatter — a doc tree the gates skip is a doc tree that
|
|
47
|
+
// drifts. What cannot be fixed as a one-liner now lives, dated, in
|
|
48
|
+
// scripts/data/doc-gate-allowlist.json instead.
|
|
49
|
+
`${sep}.claude${sep}plans${sep}`,
|
|
50
|
+
`${sep}.claude${sep}.task${sep}`,
|
|
51
|
+
// #1840 F4 (examples/ viventi): `examples/<name>/` directories are `arbiter
|
|
52
|
+
// init` OUTPUT for a downstream project, regenerated verbatim by
|
|
53
|
+
// scripts/regenerate-examples.mjs — their .md files are governed by the
|
|
54
|
+
// TARGET project's own doc conventions, not arbiter's. The hand-authored
|
|
55
|
+
// walkthroughs directly under examples/ (examples/README.md,
|
|
56
|
+
// examples/go-library.md, …) are NOT skipped — only the generated subtrees.
|
|
57
|
+
`${sep}examples${sep}ts-library${sep}`,
|
|
58
|
+
`${sep}examples${sep}python-library${sep}`,
|
|
59
|
+
`${sep}examples${sep}go-library${sep}`,
|
|
60
|
+
]
|
|
61
|
+
// Auto-generated files that bypass frontmatter requirements
|
|
62
|
+
export const SKIP_FILENAMES = new Set([
|
|
63
|
+
'INDEX.md',
|
|
64
|
+
'DECISIONS.md', // generated digest (gen-adr-readme.mjs) — uses status: generated
|
|
65
|
+
])
|
|
66
|
+
|
|
67
|
+
const REQUIRED_KEYS = [
|
|
68
|
+
'title',
|
|
69
|
+
'doc_version',
|
|
70
|
+
'status',
|
|
71
|
+
'last_review',
|
|
72
|
+
'owner',
|
|
73
|
+
'canonical_id',
|
|
74
|
+
'tags',
|
|
75
|
+
'related',
|
|
76
|
+
]
|
|
77
|
+
const VALID_STATUS = new Set(['draft', 'active', 'deprecated', 'archived'])
|
|
78
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/
|
|
79
|
+
const SEMVER = /^\d+\.\d+\.\d+$/
|
|
80
|
+
|
|
81
|
+
function shouldSkip(absPath) {
|
|
82
|
+
return SKIP_PATH_SEGMENTS.some((s) => absPath.includes(s))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Collect every hand-authored `.md` file under `dir` (recursively). Traversal is delegated to the
|
|
87
|
+
* shared cycle-safe walkRepo (#1521/#1544); this gate's own SKIP_PATH_SEGMENTS + SKIP_FILENAMES are
|
|
88
|
+
* re-applied to each returned path so the visited set is identical to the old hand-rolled walk
|
|
89
|
+
* (minus the symlink-cycle bug), plus walkRepo's widened SKIP_DIRS (build/coverage/.coverage).
|
|
90
|
+
*/
|
|
91
|
+
export function walk(dir) {
|
|
92
|
+
if (!existsSync(dir) || shouldSkip(dir + sep)) return []
|
|
93
|
+
const out = []
|
|
94
|
+
for (const rel of walkRepo(dir)) {
|
|
95
|
+
const full = join(dir, rel)
|
|
96
|
+
if (shouldSkip(full)) continue
|
|
97
|
+
const name = rel.slice(rel.lastIndexOf('/') + 1)
|
|
98
|
+
if (name.endsWith('.md') && !SKIP_FILENAMES.has(name)) out.push(full)
|
|
99
|
+
}
|
|
100
|
+
return out
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function collectFiles() {
|
|
104
|
+
const out = []
|
|
105
|
+
for (const r of SCAN_ROOTS) out.push(...walk(join(CWD, r)))
|
|
106
|
+
for (const f of ROOT_FILES) {
|
|
107
|
+
const abs = join(CWD, f)
|
|
108
|
+
if (existsSync(abs) && statSync(abs).isFile()) out.push(abs)
|
|
109
|
+
}
|
|
110
|
+
return out
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseFrontmatter(content) {
|
|
114
|
+
if (!content.startsWith('---')) return { present: false }
|
|
115
|
+
const lines = content.split('\n')
|
|
116
|
+
if (lines[0] !== '---') return { present: false }
|
|
117
|
+
for (let i = 1; i < lines.length; i++) {
|
|
118
|
+
if (lines[i] === '---') {
|
|
119
|
+
const block = lines.slice(1, i)
|
|
120
|
+
const kv = new Map()
|
|
121
|
+
for (const ln of block) {
|
|
122
|
+
const m = ln.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/)
|
|
123
|
+
if (m) kv.set(m[1], m[2].replace(/^['"]|['"]$/g, '').trim())
|
|
124
|
+
}
|
|
125
|
+
return { present: true, kv, bodyStart: i + 1 }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { present: false }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function findH1s(content, bodyStart) {
|
|
132
|
+
const lines = content.split('\n').slice(bodyStart)
|
|
133
|
+
const h1s = []
|
|
134
|
+
let inFence = false
|
|
135
|
+
for (const ln of lines) {
|
|
136
|
+
if (ln.startsWith('```')) inFence = !inFence
|
|
137
|
+
if (inFence) continue
|
|
138
|
+
const m = ln.match(/^#\s+(.+?)\s*$/)
|
|
139
|
+
if (m) h1s.push(m[1].trim())
|
|
140
|
+
}
|
|
141
|
+
return h1s
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function main() {
|
|
145
|
+
const allow = loadDocGateAllowlist('doc-style')
|
|
146
|
+
process.stdout.write(allowlistSummary('check-doc-style', allow))
|
|
147
|
+
|
|
148
|
+
const files = collectFiles()
|
|
149
|
+
const errors = []
|
|
150
|
+
const warnings = []
|
|
151
|
+
|
|
152
|
+
for (const file of files) {
|
|
153
|
+
const rel = relative(CWD, file)
|
|
154
|
+
if (allow.has(rel)) continue
|
|
155
|
+
const content = readFileSync(file, 'utf-8')
|
|
156
|
+
const fm = parseFrontmatter(content)
|
|
157
|
+
if (!fm.present) {
|
|
158
|
+
errors.push(`${rel}: missing frontmatter block`)
|
|
159
|
+
continue
|
|
160
|
+
}
|
|
161
|
+
// HARD: required keys must be present.
|
|
162
|
+
const missing = REQUIRED_KEYS.filter((k) => !fm.kv.has(k))
|
|
163
|
+
if (missing.length > 0) {
|
|
164
|
+
errors.push(`${rel}: missing frontmatter key(s): ${missing.join(', ')}`)
|
|
165
|
+
}
|
|
166
|
+
// HARD: last_review must be ISO date when set.
|
|
167
|
+
if (
|
|
168
|
+
fm.kv.has('last_review') &&
|
|
169
|
+
fm.kv.get('last_review') &&
|
|
170
|
+
!ISO_DATE.test(fm.kv.get('last_review'))
|
|
171
|
+
) {
|
|
172
|
+
errors.push(`${rel}: last_review "${fm.kv.get('last_review')}" is not ISO date (YYYY-MM-DD)`)
|
|
173
|
+
}
|
|
174
|
+
// HARD: doc_version must be semver when set.
|
|
175
|
+
if (
|
|
176
|
+
fm.kv.has('doc_version') &&
|
|
177
|
+
fm.kv.get('doc_version') &&
|
|
178
|
+
!SEMVER.test(fm.kv.get('doc_version'))
|
|
179
|
+
) {
|
|
180
|
+
errors.push(`${rel}: doc_version "${fm.kv.get('doc_version')}" is not semver (X.Y.Z)`)
|
|
181
|
+
}
|
|
182
|
+
// SOFT: status should be one of the canonical lifecycle values.
|
|
183
|
+
if (fm.kv.has('status') && fm.kv.get('status') && !VALID_STATUS.has(fm.kv.get('status'))) {
|
|
184
|
+
warnings.push(
|
|
185
|
+
`${rel}: non-canonical status "${fm.kv.get('status')}" (canonical: ${[...VALID_STATUS].join(', ')})`,
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
// SOFT: every doc should have an H1; multi-H1 should be reviewed.
|
|
189
|
+
const h1s = findH1s(content, fm.bodyStart ?? 0)
|
|
190
|
+
if (h1s.length === 0) {
|
|
191
|
+
warnings.push(`${rel}: no H1 heading found in body`)
|
|
192
|
+
} else if (h1s.length > 1) {
|
|
193
|
+
warnings.push(`${rel}: ${h1s.length} H1 headings — exactly one preferred`)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (errors.length === 0) {
|
|
198
|
+
if (warnings.length > 0) {
|
|
199
|
+
process.stdout.write(
|
|
200
|
+
` check-doc-style: ${files.length} files OK; ${warnings.length} soft warning(s)\n`,
|
|
201
|
+
)
|
|
202
|
+
for (const w of warnings.slice(0, 20)) process.stdout.write(` [warn] ${w}\n`)
|
|
203
|
+
if (warnings.length > 20)
|
|
204
|
+
process.stdout.write(` [warn] ... +${warnings.length - 20} more\n`)
|
|
205
|
+
} else {
|
|
206
|
+
process.stdout.write(` check-doc-style: all ${files.length} files OK\n`)
|
|
207
|
+
}
|
|
208
|
+
process.exit(0)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
process.stdout.write(
|
|
212
|
+
` check-doc-style: ${errors.length} hard error(s) across ${files.length} files\n`,
|
|
213
|
+
)
|
|
214
|
+
for (const e of errors) process.stdout.write(` ${e}\n`)
|
|
215
|
+
if (warnings.length > 0) {
|
|
216
|
+
process.stdout.write(
|
|
217
|
+
` check-doc-style: ${warnings.length} additional soft warning(s) (not failure)\n`,
|
|
218
|
+
)
|
|
219
|
+
for (const w of warnings.slice(0, 10)) process.stdout.write(` [warn] ${w}\n`)
|
|
220
|
+
if (warnings.length > 10) process.stdout.write(` [warn] ... +${warnings.length - 10} more\n`)
|
|
221
|
+
}
|
|
222
|
+
process.exit(1)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Only run main when invoked as CLI (not imported in tests).
|
|
226
|
+
if (isMainModule(import.meta.url)) {
|
|
227
|
+
main()
|
|
228
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// arbiter — native-TS gold-audit engine (#1373). Reimplements the upstream reference gold-audit
|
|
4
|
+
// registry evaluator natively in node (zero Python dependency for consumer projects). The score is
|
|
5
|
+
// computed by code, never by an AI (owner hard requirement). Same repo + same registry ⇒
|
|
6
|
+
// byte-identical output (determinism). Wired into scripts/check-all.mjs as a no-regress gate.
|
|
7
|
+
//
|
|
8
|
+
// Reads a per-stack registry (standards/gold-registry.yml) → per-check verdict Y/P/N/NA/NV with
|
|
9
|
+
// evidence (file [+ line]) → an aggregate score + dimension table. Adds a monotonic ratchet
|
|
10
|
+
// baseline (.gold-audit-baseline.json), a no-regress merge gate (--check), and a false-gap
|
|
11
|
+
// meta-gate (--strict, RISKY>0 fails). The shared evaluator lives in scripts/lib/gold-audit-lib.mjs
|
|
12
|
+
// so the CLI, the gold-report consumer, and the tests share one code path.
|
|
13
|
+
//
|
|
14
|
+
// Exit codes (INV-53 contract): 0 PASS/advisory, 1 FAIL (regression / RISKY / stale), 2 IO error.
|
|
15
|
+
//
|
|
16
|
+
// Usage:
|
|
17
|
+
// node scripts/gold-audit.mjs [--json [path]] [--check] [--strict] [--update-baseline]
|
|
18
|
+
// [--registry P] [--profile P] [--baseline P] [--help]
|
|
19
|
+
// --json [P] emit the scored payload as JSON (to stdout, or to file P)
|
|
20
|
+
// --check no-regress gate: exit 1 if score/Y dropped below the baseline
|
|
21
|
+
// (bootstraps a missing baseline and exits 0)
|
|
22
|
+
// --require-baseline N1 fail-closed disarm: with --check, a missing baseline is a HARD FAIL
|
|
23
|
+
// (refuse to silently re-bootstrap — deleting the baseline must not pass)
|
|
24
|
+
// --strict false-gap meta-gate: exit 1 if any check is RISKY
|
|
25
|
+
// --update-baseline monotonically ratchet the baseline (never lowers a field)
|
|
26
|
+
// --stack S select per-stack registry standards/gold-registry.<S>.yml (unless
|
|
27
|
+
// --registry is given); also a presentation hint
|
|
28
|
+
// --class C brownfieldClass for the level band: gold|light|medium|heavy (default gold)
|
|
29
|
+
// --registry P registry path (default standards/gold-registry.yml)
|
|
30
|
+
// --profile P overlay profile path (default standards/gold-profile)
|
|
31
|
+
// --baseline P baseline path (default .gold-audit-baseline.json)
|
|
32
|
+
// --thresholds P brownfield-class threshold SSOT (default standards/thresholds.yml) —
|
|
33
|
+
// resolves value-op threshold_ref per --class
|
|
34
|
+
// --help, -h show this help
|
|
35
|
+
//
|
|
36
|
+
// The default/--json output carries a deterministic LEVEL band (L0–L3 keyed by brownfieldClass)
|
|
37
|
+
// and a "what's missing" gap report (the N/P checks + evidence, grouped by dimension). These are
|
|
38
|
+
// presentation-only keys appended to the payload; the no-regress baseline (score/yCount/dimensions)
|
|
39
|
+
// is unaffected (#1414).
|
|
40
|
+
|
|
41
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
42
|
+
import { dirname, resolve } from 'node:path'
|
|
43
|
+
import { parse as parseYaml } from 'yaml'
|
|
44
|
+
import {
|
|
45
|
+
evaluate,
|
|
46
|
+
checkNoRegress,
|
|
47
|
+
ratchet,
|
|
48
|
+
baselineOf,
|
|
49
|
+
levelBand,
|
|
50
|
+
gapReport,
|
|
51
|
+
freshness,
|
|
52
|
+
} from './lib/gold-audit-lib.mjs'
|
|
53
|
+
|
|
54
|
+
const args = process.argv.slice(2)
|
|
55
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
56
|
+
process.stdout.write(
|
|
57
|
+
[
|
|
58
|
+
'Usage: node scripts/gold-audit.mjs [options]',
|
|
59
|
+
'',
|
|
60
|
+
'Deterministic registry→Y/P/N gold-audit engine (the score is code-computed, never AI).',
|
|
61
|
+
'',
|
|
62
|
+
' --json [P] emit the scored payload as JSON (stdout, or file P)',
|
|
63
|
+
' --check no-regress gate: exit 1 if score/Y dropped vs baseline',
|
|
64
|
+
' --require-baseline N1 disarm guard: with --check, a missing baseline is a HARD FAIL',
|
|
65
|
+
' --strict false-gap meta-gate: exit 1 if any RISKY check exists',
|
|
66
|
+
' --check-fresh freshness gate: exit 1 if value-check reports are STALE (none present)',
|
|
67
|
+
' --stale-hours N freshness window in hours for --check-fresh / the banner (default 24)',
|
|
68
|
+
' --update-baseline monotonically ratchet the baseline (never lowers a field)',
|
|
69
|
+
' --stack S select per-stack registry standards/gold-registry.<S>.yml',
|
|
70
|
+
' --class C brownfieldClass for the level band: gold|light|medium|heavy',
|
|
71
|
+
' --registry P registry path (default standards/gold-registry.yml)',
|
|
72
|
+
' --profile P overlay profile path (default standards/gold-profile)',
|
|
73
|
+
' --baseline P baseline path (default .gold-audit-baseline.json)',
|
|
74
|
+
' --thresholds P brownfield-class threshold SSOT (resolves value-op threshold_ref)',
|
|
75
|
+
' --help, -h show this help',
|
|
76
|
+
'',
|
|
77
|
+
].join('\n'),
|
|
78
|
+
)
|
|
79
|
+
process.exit(0)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const flag = (name) => args.includes(name)
|
|
83
|
+
const opt = (name, def) => {
|
|
84
|
+
const i = args.indexOf(name)
|
|
85
|
+
return i >= 0 && args[i + 1] && !args[i + 1].startsWith('--') ? args[i + 1] : def
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const CWD = process.cwd()
|
|
89
|
+
// --stack S selects a per-stack registry (standards/gold-registry.<S>.yml) unless --registry is
|
|
90
|
+
// given explicitly. --class C overrides the brownfieldClass used for the level band (#1414).
|
|
91
|
+
const STACK = opt('--stack', null)
|
|
92
|
+
const CLASS = opt('--class', 'gold')
|
|
93
|
+
const REGISTRY = opt(
|
|
94
|
+
'--registry',
|
|
95
|
+
STACK ? `standards/gold-registry.${STACK}.yml` : 'standards/gold-registry.yml',
|
|
96
|
+
)
|
|
97
|
+
const PROFILE = opt('--profile', 'standards/gold-profile')
|
|
98
|
+
const BASELINE = opt('--baseline', '.gold-audit-baseline.json')
|
|
99
|
+
// --thresholds P: the brownfield-class SSOT used to resolve value-op `threshold_ref` per --class
|
|
100
|
+
// (#1413). The value op reads pre-generated tool reports; the bar differs by brownfield class.
|
|
101
|
+
const THRESHOLDS = opt('--thresholds', 'standards/thresholds.yml')
|
|
102
|
+
// #1473: freshness window (hours) for --check-fresh and the advisory banner.
|
|
103
|
+
const STALE_HOURS = Number(opt('--stale-hours', 24))
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Enrich the raw scored payload with the #1414 presentation fields (level band + gap report).
|
|
107
|
+
* Appended as NEW keys so the no-regress baseline (score/yCount/dimensions) is untouched; the
|
|
108
|
+
* level band is keyed by --class (deterministic — no fs-dependent auto-detection in the engine).
|
|
109
|
+
*/
|
|
110
|
+
function withPresentation(result) {
|
|
111
|
+
return { ...result, level: levelBand(result.score, CLASS), gaps: gapReport(result) }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function loadOverlays() {
|
|
115
|
+
const abs = resolve(CWD, PROFILE)
|
|
116
|
+
if (!existsSync(abs)) return new Set()
|
|
117
|
+
try {
|
|
118
|
+
const doc = parseYaml(readFileSync(abs, 'utf-8')) || {}
|
|
119
|
+
return new Set(Array.isArray(doc.overlays) ? doc.overlays : [])
|
|
120
|
+
} catch {
|
|
121
|
+
return new Set()
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Load the brownfield-class threshold SSOT (standards/thresholds.yml): threshold_ref → per-class bar.
|
|
127
|
+
* Absent/malformed ⇒ {} (value checks with an unresolvable threshold then score N, never silent-Y).
|
|
128
|
+
*/
|
|
129
|
+
function loadThresholds() {
|
|
130
|
+
const abs = resolve(CWD, THRESHOLDS)
|
|
131
|
+
if (!existsSync(abs)) return {}
|
|
132
|
+
try {
|
|
133
|
+
const doc = parseYaml(readFileSync(abs, 'utf-8')) || {}
|
|
134
|
+
return doc && typeof doc.thresholds === 'object' && doc.thresholds !== null
|
|
135
|
+
? doc.thresholds
|
|
136
|
+
: {}
|
|
137
|
+
} catch {
|
|
138
|
+
return {}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function readBaseline() {
|
|
143
|
+
const abs = resolve(CWD, BASELINE)
|
|
144
|
+
if (!existsSync(abs)) return null
|
|
145
|
+
try {
|
|
146
|
+
return JSON.parse(readFileSync(abs, 'utf-8'))
|
|
147
|
+
} catch (err) {
|
|
148
|
+
process.stderr.write(`gold-audit: ERROR — malformed ${BASELINE}: ${err.message}\n`)
|
|
149
|
+
process.exit(2)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function writeBaseline(payload) {
|
|
154
|
+
const abs = resolve(CWD, BASELINE)
|
|
155
|
+
mkdirSync(dirname(abs), { recursive: true })
|
|
156
|
+
writeFileSync(abs, JSON.stringify(payload, null, 2) + '\n', 'utf-8')
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function main() {
|
|
160
|
+
const regAbs = resolve(CWD, REGISTRY)
|
|
161
|
+
if (!existsSync(regAbs)) {
|
|
162
|
+
process.stdout.write(`gold-audit: SKIP — no registry at ${REGISTRY}\n`)
|
|
163
|
+
return 0
|
|
164
|
+
}
|
|
165
|
+
let registry
|
|
166
|
+
try {
|
|
167
|
+
registry = parseYaml(readFileSync(regAbs, 'utf-8'))
|
|
168
|
+
} catch (err) {
|
|
169
|
+
process.stderr.write(`gold-audit: ERROR — malformed ${REGISTRY}: ${err.message}\n`)
|
|
170
|
+
return 2
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const overlays = loadOverlays()
|
|
174
|
+
// #1413: value-op checks resolve threshold_ref per --class from the thresholds SSOT.
|
|
175
|
+
const result = evaluate(registry, overlays, CWD, {
|
|
176
|
+
thresholds: loadThresholds(),
|
|
177
|
+
brownfieldClass: CLASS,
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// --strict false-gap meta-gate: never score on a fragile (RISKY) registry.
|
|
181
|
+
if (flag('--strict') && result.riskyCount > 0) {
|
|
182
|
+
const risky = result.checks.filter((c) => c.risk === 'RISKY').map((c) => c.id)
|
|
183
|
+
process.stderr.write(
|
|
184
|
+
`gold-audit: FAIL — false-gap meta-gate: ${result.riskyCount} RISKY check(s): ${risky.join(', ')}\n`,
|
|
185
|
+
)
|
|
186
|
+
return 1
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// --check-fresh freshness gate (#1473): fail-closed exit 1 when the value-check reports are STALE
|
|
190
|
+
// (declared but NONE present — the tools never ran). Out-of-band: the wall-clock never touches the
|
|
191
|
+
// scored payload or the no-regress baseline. PARTIAL/FRESH are advisory (exit 0).
|
|
192
|
+
if (flag('--check-fresh')) {
|
|
193
|
+
// #1580: pass the active overlay set so freshness ignores reports for checks the engine NA's.
|
|
194
|
+
const f = freshness(registry, CWD, { staleHours: STALE_HOURS, overlays })
|
|
195
|
+
const c = f.counts
|
|
196
|
+
if (f.status === 'STALE') {
|
|
197
|
+
process.stderr.write(
|
|
198
|
+
`gold-audit: FAIL — freshness STALE: ${c.present}/${c.total} value-check report(s) present ` +
|
|
199
|
+
`(the tools never ran). Regenerate the reports or remove the value checks.\n`,
|
|
200
|
+
)
|
|
201
|
+
return 1
|
|
202
|
+
}
|
|
203
|
+
process.stdout.write(
|
|
204
|
+
`gold-audit: freshness ${f.status} (${c.fresh}/${c.total} report(s) within ${f.staleHours}h)\n`,
|
|
205
|
+
)
|
|
206
|
+
return 0
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// --update-baseline: monotonic ratchet (can only tighten).
|
|
210
|
+
if (flag('--update-baseline')) {
|
|
211
|
+
const next = ratchet(result, readBaseline())
|
|
212
|
+
writeBaseline(next)
|
|
213
|
+
process.stdout.write(
|
|
214
|
+
`gold-audit: baseline ratcheted → ${BASELINE} (score=${next.score}, Y=${next.yCount})\n`,
|
|
215
|
+
)
|
|
216
|
+
return 0
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// --check no-regress gate.
|
|
220
|
+
if (flag('--check')) {
|
|
221
|
+
const baseline = readBaseline()
|
|
222
|
+
if (baseline === null) {
|
|
223
|
+
// N1 (fail-closed disarm, #1412): with --require-baseline, a configured engine whose
|
|
224
|
+
// baseline is absent is a HARD FAIL — silently re-bootstrapping would erase the regression
|
|
225
|
+
// record (delete the baseline ⇒ any regression vanishes). The committed gate uses this flag.
|
|
226
|
+
if (flag('--require-baseline')) {
|
|
227
|
+
process.stderr.write(
|
|
228
|
+
`gold-audit: FAIL — N1 disarm guard: --require-baseline set but ${BASELINE} is missing.\n` +
|
|
229
|
+
` A configured gold engine must carry a committed baseline; refusing to silently re-bootstrap.\n` +
|
|
230
|
+
` Bootstrap once with: node scripts/gold-audit.mjs --check (without --require-baseline).\n`,
|
|
231
|
+
)
|
|
232
|
+
return 1
|
|
233
|
+
}
|
|
234
|
+
writeBaseline(baselineOf(result))
|
|
235
|
+
process.stdout.write(
|
|
236
|
+
`gold-audit: baseline initialized → ${BASELINE} (score=${result.score}, Y=${result.yCount})\n`,
|
|
237
|
+
)
|
|
238
|
+
return 0
|
|
239
|
+
}
|
|
240
|
+
if (process.env.ALLOW_GOLD_REGRESS === '1') {
|
|
241
|
+
process.stdout.write('gold-audit: ALLOW_GOLD_REGRESS=1 — skipping no-regress gate\n')
|
|
242
|
+
return 0
|
|
243
|
+
}
|
|
244
|
+
const verdict = checkNoRegress(result, baseline)
|
|
245
|
+
if (!verdict.ok) {
|
|
246
|
+
process.stderr.write(`gold-audit: FAIL — no-regress gate:\n`)
|
|
247
|
+
for (const r of verdict.reasons) process.stderr.write(` ${r}\n`)
|
|
248
|
+
return 1
|
|
249
|
+
}
|
|
250
|
+
process.stdout.write(
|
|
251
|
+
`gold-audit: no-regress OK (score=${result.score} >= ${baseline.score}, Y=${result.yCount} >= ${baseline.yCount})\n`,
|
|
252
|
+
)
|
|
253
|
+
return 0
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Default / --json: emit the scored payload enriched with the #1414 level band + gap report.
|
|
257
|
+
const enriched = withPresentation(result)
|
|
258
|
+
|
|
259
|
+
// --cockpit-data (#1475): the data envelope the TS `--cockpit` renderer consumes — the SAME scored
|
|
260
|
+
// payload PLUS the out-of-band freshness object (wall-clock). Kept SEPARATE from `--json` so the
|
|
261
|
+
// scored artifact (no-regress baseline, bake snapshots) stays byte-deterministic + freshness-free.
|
|
262
|
+
if (flag('--cockpit-data')) {
|
|
263
|
+
const fresh = freshness(registry, CWD, { staleHours: STALE_HOURS, overlays })
|
|
264
|
+
process.stdout.write(JSON.stringify({ payload: enriched, freshness: fresh }) + '\n')
|
|
265
|
+
return 0
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (flag('--json')) {
|
|
269
|
+
const out = opt('--json', null)
|
|
270
|
+
const text = JSON.stringify(enriched, null, 2) + '\n'
|
|
271
|
+
if (out) {
|
|
272
|
+
mkdirSync(dirname(resolve(CWD, out)), { recursive: true })
|
|
273
|
+
writeFileSync(resolve(CWD, out), text, 'utf-8')
|
|
274
|
+
process.stdout.write(`gold-audit: wrote ${out}\n`)
|
|
275
|
+
} else {
|
|
276
|
+
process.stdout.write(text)
|
|
277
|
+
}
|
|
278
|
+
return 0
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Advisory freshness banner (out-of-band; never in the --json scored payload). Only shown when the
|
|
282
|
+
// registry declares value-check reports — otherwise there is nothing to be fresh/stale about.
|
|
283
|
+
const fresh = freshness(registry, CWD, { staleHours: STALE_HOURS, overlays })
|
|
284
|
+
if (fresh.counts.total > 0) {
|
|
285
|
+
process.stdout.write(
|
|
286
|
+
`gold-audit: freshness ${fresh.status} ` +
|
|
287
|
+
`(${fresh.counts.fresh}/${fresh.counts.total} report(s) within ${fresh.staleHours}h)\n`,
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const band = enriched.level
|
|
292
|
+
const toNext = band.nextLevel === null ? '' : ` · ${band.toNextLevel} to ${band.nextLevel}`
|
|
293
|
+
process.stdout.write(
|
|
294
|
+
`gold-audit: ${band.level} (${band.brownfieldClass}) · score ${result.score}${toNext} · ` +
|
|
295
|
+
`Y ${result.yCount}/${result.totals.checks} · RISKY ${result.riskyCount} ` +
|
|
296
|
+
`(N ${result.totals.n}, P ${result.totals.p}, NA ${result.totals.na}, NV ${result.totals.nv})\n`,
|
|
297
|
+
)
|
|
298
|
+
if (enriched.gaps.length > 0) {
|
|
299
|
+
process.stdout.write(`gold-audit: what's missing (${enriched.gaps.length} family/families):\n`)
|
|
300
|
+
for (const g of enriched.gaps) {
|
|
301
|
+
process.stdout.write(` ${g.dimension}:\n`)
|
|
302
|
+
for (const c of g.checks) {
|
|
303
|
+
const ev = c.evidence
|
|
304
|
+
? ` [${c.evidence.file ?? ''}${c.evidence.detail ? `: ${c.evidence.detail}` : ''}]`
|
|
305
|
+
: ''
|
|
306
|
+
process.stdout.write(` ${c.verdict} ${c.id} ${c.title}${ev}\n`)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return 0
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
process.exit(main())
|
|
315
|
+
} catch (err) {
|
|
316
|
+
// Fail-closed: an unexpected crash is a hard gate failure, never a silent pass.
|
|
317
|
+
process.stderr.write(`gold-audit: unexpected error — ${err?.message ?? err}\n`)
|
|
318
|
+
process.exit(1)
|
|
319
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
//
|
|
3
|
+
// #2408: the dated allowlist shared by the three doc gates (check-doc-links,
|
|
4
|
+
// check-doc-style, check-phantom-command-scan). Removing `internal` from the
|
|
5
|
+
// link/style SKIP lists and teaching the phantom scan to read fenced blocks
|
|
6
|
+
// surfaces defects whose FIX is a prose/product decision owned by a sibling
|
|
7
|
+
// M-A/M-B issue — those files get a dated entry here instead of a silent skip,
|
|
8
|
+
// so the gate is green AND the debt is on a clock.
|
|
9
|
+
//
|
|
10
|
+
// Entry shape: { path, rule, reason, issue, expires }
|
|
11
|
+
// path repo-relative POSIX path of the file being excused
|
|
12
|
+
// rule which gate the excuse applies to (see RULES)
|
|
13
|
+
// reason why it cannot be fixed as a path/frontmatter one-liner right now
|
|
14
|
+
// issue the batch issue that owns the real fix
|
|
15
|
+
// expires ISO date; the gate goes RED the day after
|
|
16
|
+
//
|
|
17
|
+
// FAIL-CLOSED by construction: a missing file, a malformed file, a
|
|
18
|
+
// malformed entry or an expired entry all exit non-zero. There is no
|
|
19
|
+
// "could not read the allowlist, so allow everything" branch — that would
|
|
20
|
+
// turn the escape hatch into a bypass.
|
|
21
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
22
|
+
import { dirname, relative, resolve } from 'node:path'
|
|
23
|
+
import { fileURLToPath } from 'node:url'
|
|
24
|
+
|
|
25
|
+
// Resolved from THIS module's location, not process.cwd(): the gates are also
|
|
26
|
+
// run against synthetic fixture trees (cwd=<tmpdir>), where a cwd-relative
|
|
27
|
+
// lookup would silently find nothing and quietly fail open.
|
|
28
|
+
const DEFAULT_PATH = resolve(
|
|
29
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
30
|
+
'..',
|
|
31
|
+
'data',
|
|
32
|
+
'doc-gate-allowlist.json',
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
export const RULES = new Set(['doc-links', 'doc-style', 'phantom-command'])
|
|
36
|
+
|
|
37
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/
|
|
38
|
+
const REQUIRED_KEYS = ['path', 'rule', 'reason', 'issue', 'expires']
|
|
39
|
+
|
|
40
|
+
function fail(message) {
|
|
41
|
+
process.stdout.write(` doc-gate-allowlist: ${message}\n`)
|
|
42
|
+
process.exit(1)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Shape-validate ONE entry. Every failure is fatal: a malformed excuse is a
|
|
47
|
+
* silent hole in three gates at once.
|
|
48
|
+
*/
|
|
49
|
+
function validateEntry(entry, index, path) {
|
|
50
|
+
const missing = REQUIRED_KEYS.filter((k) => typeof entry?.[k] !== 'string' || !entry[k])
|
|
51
|
+
if (missing.length > 0) fail(`${path} entry #${index} missing key(s): ${missing.join(', ')}`)
|
|
52
|
+
if (!RULES.has(entry.rule)) fail(`${path} entry #${index} has unknown rule "${entry.rule}"`)
|
|
53
|
+
if (!ISO_DATE.test(entry.expires))
|
|
54
|
+
fail(`${path} entry #${index} expires "${entry.expires}" is not an ISO date (YYYY-MM-DD)`)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Resolve the allowlist path: `--allowlist=<path>` on argv (fixture seam) or the default. */
|
|
58
|
+
function resolveAllowlistPath() {
|
|
59
|
+
const override = process.argv.find((a) => a.startsWith('--allowlist='))
|
|
60
|
+
return override ? resolve(override.slice('--allowlist='.length)) : DEFAULT_PATH
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Read + JSON-parse the allowlist, exiting non-zero on anything unreadable. */
|
|
64
|
+
function readAllowlistEntries(path) {
|
|
65
|
+
if (!existsSync(path)) fail(`${path} not found — the allowlist is required (fail-closed)`)
|
|
66
|
+
let parsed
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(readFileSync(path, 'utf-8'))
|
|
69
|
+
} catch (err) {
|
|
70
|
+
// Surfaced and exited inline rather than through fail(): an unreadable or
|
|
71
|
+
// unparseable allowlist must visibly stop the gate at the catch site.
|
|
72
|
+
process.stdout.write(
|
|
73
|
+
` doc-gate-allowlist: ${path} failed to parse: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
74
|
+
)
|
|
75
|
+
process.exit(1)
|
|
76
|
+
}
|
|
77
|
+
if (!Array.isArray(parsed?.entries)) fail(`${path} has no \`entries\` array`)
|
|
78
|
+
return parsed.entries
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Load the allowlist and return the excused-path set for one `rule`.
|
|
83
|
+
*
|
|
84
|
+
* Expiry is validated across EVERY entry, not just the requested rule's: an
|
|
85
|
+
* entry that has run out of time is stale debt no matter which gate happens to
|
|
86
|
+
* load the file first.
|
|
87
|
+
*
|
|
88
|
+
* The path may be overridden with `--allowlist=<path>` on the calling gate's
|
|
89
|
+
* argv (fixture seam, same shape as check-phantom-command-scan's `--ledger=`).
|
|
90
|
+
*
|
|
91
|
+
* @param {string} rule one of RULES
|
|
92
|
+
* @param {string} [todayIso] ISO date to compare `expires` against (defaults to today)
|
|
93
|
+
* @returns {{ has: (relPath: string) => boolean, size: number, path: string }}
|
|
94
|
+
*/
|
|
95
|
+
export function loadDocGateAllowlist(rule, todayIso = new Date().toISOString().slice(0, 10)) {
|
|
96
|
+
if (!RULES.has(rule)) fail(`unknown rule "${rule}" (known: ${[...RULES].join(', ')})`)
|
|
97
|
+
|
|
98
|
+
const path = resolveAllowlistPath()
|
|
99
|
+
const entries = readAllowlistEntries(path)
|
|
100
|
+
|
|
101
|
+
const excused = new Set()
|
|
102
|
+
const expired = []
|
|
103
|
+
for (const [i, entry] of entries.entries()) {
|
|
104
|
+
validateEntry(entry, i, path)
|
|
105
|
+
if (entry.expires < todayIso) expired.push(`${entry.path} (${entry.rule}, ${entry.issue})`)
|
|
106
|
+
if (entry.rule === rule) excused.add(entry.path)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (expired.length > 0) {
|
|
110
|
+
fail(
|
|
111
|
+
`${expired.length} entry/entries expired — fix the file or re-date the entry with its owner:\n` +
|
|
112
|
+
expired.map((e) => ` expired: ${e}`).join('\n'),
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return { has: (relPath) => excused.has(relPath), size: excused.size, path }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Human-readable one-liner every gate prints, on every exit path. */
|
|
120
|
+
export function allowlistSummary(gate, allow) {
|
|
121
|
+
const rel = relative(process.cwd(), allow.path)
|
|
122
|
+
return ` ${gate}: ${allow.size} file(s) allowlisted (${rel.startsWith('..') ? allow.path : rel})\n`
|
|
123
|
+
}
|