@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,345 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// <%= projectName %> — docs/USE_CASES.md gate (UC-NN, INV-149)
|
|
4
|
+
//
|
|
5
|
+
// Emitted twin of arbiter's scripts/check-use-cases.mjs. The rules are identical; only the three
|
|
6
|
+
// document paths differ, because a governed project keeps its documents flat under docs/ while
|
|
7
|
+
// arbiter keeps its own under docs/internal/PRODUCT/ and docs/internal/METHOD/. That divergence is
|
|
8
|
+
// pinned in .dogfood-divergences.json and is the whole of it.
|
|
9
|
+
//
|
|
10
|
+
// This gate does its real work HERE rather than in arbiter, and the asymmetry is structural, not
|
|
11
|
+
// an omission. arbiter's feature matrix rows are cross-cutting capability areas, so one of its use
|
|
12
|
+
// cases would name nearly all of them and the link would carry no information. In a product, a use
|
|
13
|
+
// case names one or two features — that ratio is what makes the edge worth checking.
|
|
14
|
+
// CATALOG: validates the use-case SSOT against schemas/use-case.schema.json, resolves every
|
|
15
|
+
// CATALOG: featureId into the feature matrix, and joins use cases to the tabletop scenarios that
|
|
16
|
+
// CATALOG: exercise them — in both directions, so neither a use case nothing walks nor a scenario
|
|
17
|
+
// CATALOG: naming a use case that does not exist can hide.
|
|
18
|
+
// CATALOG: rejected fold-in into check-feature-matrix.mjs because that gate reads the matrix as
|
|
19
|
+
// CATALOG: the SSOT and grades each requirement's evidence chain; this one reads a different
|
|
20
|
+
// CATALOG: document and treats the matrix as a NAMESPACE to resolve into. A matrix can be
|
|
21
|
+
// CATALOG: perfectly graded while every use case pointing at it names a feature that was renamed.
|
|
22
|
+
// CATALOG: rejected fold-in into check-tabletop-evidence.mjs because that gate owns the scenario
|
|
23
|
+
// CATALOG: catalogue and its evidence; the join is read from this side because the dangling
|
|
24
|
+
// CATALOG: direction that matters (a use case nothing exercises) is invisible from the scenario.
|
|
25
|
+
//
|
|
26
|
+
// scripts/check-use-cases.mjs
|
|
27
|
+
// L1 gate (UC-NN, #2480 wave 8): a use case names an actor, a goal, and features that exist.
|
|
28
|
+
//
|
|
29
|
+
// Asserts:
|
|
30
|
+
// 1. the SSOT's fenced JSON block parses and satisfies schemas/use-case.schema.json — which is
|
|
31
|
+
// where `featureIds` minItems:1 lives, because a use case demanding no feature is a promise
|
|
32
|
+
// with nothing behind it,
|
|
33
|
+
// 2. no two use cases share an id,
|
|
34
|
+
// 3. every featureId resolves to a row in the feature matrix. This is the rule the whole gate
|
|
35
|
+
// exists for: a use-case matrix decays by renames, and a dangling featureId reads exactly
|
|
36
|
+
// like coverage,
|
|
37
|
+
// 4. THE JOIN, both ways — a tabletop scenario's `Exercises:` names a declared use case, and a
|
|
38
|
+
// use case whose status is `exercised` is named by some scenario. A status nobody walks is a
|
|
39
|
+
// claim, and this gate's job is to make it a checkable one,
|
|
40
|
+
// 5. `status: linked` or `exercised` requires every featureId to resolve (rule 3 applies to all
|
|
41
|
+
// rows; the ladder adds no exemption, it only adds the scenario requirement).
|
|
42
|
+
//
|
|
43
|
+
// A missing SSOT is a SKIP, not a violation: a project need not have codified its use cases.
|
|
44
|
+
// The skip prints its reason and surfaces as `verdict: "skip"` under --json, so it cannot be
|
|
45
|
+
// mistaken for a pass by a reader or by runCheck's marker grep.
|
|
46
|
+
//
|
|
47
|
+
// --emit writes the machine projection forma consumes (schema arbiter-use-cases-v1), written ONLY
|
|
48
|
+
// after every rule has passed — so an invalid set cannot produce a projection, the property the
|
|
49
|
+
// milestone gate established and the reason the emit lives in the gate rather than in a generator.
|
|
50
|
+
//
|
|
51
|
+
// Usage: node scripts/check-use-cases.mjs [--dir <repo>] [--json] [--emit <path>]
|
|
52
|
+
// Exit: 0 pass or skip, 1 violation, 2 error (INV-53).
|
|
53
|
+
//
|
|
54
|
+
// Exports for unit tests: extractBlock, findDuplicateIds, findDanglingFeatures, parseMatrixIds,
|
|
55
|
+
// parseScenarioExercises, findJoinViolations, collectViolations,
|
|
56
|
+
// useCaseProjection
|
|
57
|
+
|
|
58
|
+
import { existsSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
59
|
+
import { dirname, join, resolve } from 'node:path'
|
|
60
|
+
import { fileURLToPath } from 'node:url'
|
|
61
|
+
import { isMainModule, readRegularFileSync } from './lib/run-helpers.mjs'
|
|
62
|
+
import { loadSchema, validateSchema } from './lib/agent-return-validate.mjs'
|
|
63
|
+
|
|
64
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url))
|
|
65
|
+
const SSOT_REL = join('docs', 'USE_CASES.md')
|
|
66
|
+
const MATRIX_REL = join('docs', 'FEATURE_MATRIX.md')
|
|
67
|
+
const SCENARIOS_REL = join('docs', 'TABLETOP-SCENARIOS.md')
|
|
68
|
+
const SCHEMA_REL = join('schemas', 'use-case.schema.json')
|
|
69
|
+
const SENTINEL = 'USE_CASES'
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The fenced JSON between `<!-- USE_CASES_START -->` and `<!-- USE_CASES_END -->`. The SSOT is a
|
|
73
|
+
* markdown document carrying a machine block, exactly as the ID registry is: a use-case matrix is
|
|
74
|
+
* read by people far more often than by this gate, and a bare .json would optimise for the rarer
|
|
75
|
+
* reader.
|
|
76
|
+
* @returns {{ ok: true, document: unknown } | { ok: false, error: string }}
|
|
77
|
+
*/
|
|
78
|
+
export function extractBlock(text) {
|
|
79
|
+
const start = text.indexOf(`<!-- ${SENTINEL}_START -->`)
|
|
80
|
+
const end = text.indexOf(`<!-- ${SENTINEL}_END -->`)
|
|
81
|
+
if (start === -1 || end === -1 || end < start) {
|
|
82
|
+
return { ok: false, error: `has no ${SENTINEL}_START/${SENTINEL}_END sentinel pair` }
|
|
83
|
+
}
|
|
84
|
+
const fence = /```json\n([\s\S]*?)\n```/.exec(text.slice(start, end))
|
|
85
|
+
if (!fence)
|
|
86
|
+
return { ok: false, error: `has no \`\`\`json fence between the ${SENTINEL} sentinels` }
|
|
87
|
+
try {
|
|
88
|
+
return { ok: true, document: JSON.parse(fence[1]) }
|
|
89
|
+
// FAIL-OPEN-INTENT: not fail-open — a malformed block is RETURNED as a blocking result and the caller exits 1 naming the file. The audit reads a catch that does not rethrow; this one surfaces the error through its return type instead, which is the same contract the artifact-schema hook uses.
|
|
90
|
+
} catch (err) {
|
|
91
|
+
return { ok: false, error: `block is not valid JSON — ${err.message}` }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Duplicate ids. The schema validates each item alone and cannot see them. */
|
|
96
|
+
export function findDuplicateIds(useCases) {
|
|
97
|
+
const seen = new Set()
|
|
98
|
+
const out = []
|
|
99
|
+
for (const uc of useCases) {
|
|
100
|
+
const id = String(uc['id'])
|
|
101
|
+
if (seen.has(id)) out.push(`duplicate use-case id "${id}"`)
|
|
102
|
+
seen.add(id)
|
|
103
|
+
}
|
|
104
|
+
return out
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Every feature id declared in the matrix's table rows. */
|
|
108
|
+
export function parseMatrixIds(matrixText) {
|
|
109
|
+
const ids = new Set()
|
|
110
|
+
for (const line of matrixText.split('\n')) {
|
|
111
|
+
const m = /^\|\s*([A-Za-z][A-Za-z0-9_-]*)\s*\|/.exec(line)
|
|
112
|
+
if (!m) continue
|
|
113
|
+
const id = m[1]
|
|
114
|
+
// The header row and the separator are the two non-rows that match the shape.
|
|
115
|
+
if (/^(feature_id|id|---+)$/i.test(id)) continue
|
|
116
|
+
ids.add(id)
|
|
117
|
+
}
|
|
118
|
+
return ids
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* featureIds naming nothing in the matrix. The decay mode this gate exists for: a matrix row gets
|
|
123
|
+
* renamed, every use case pointing at it keeps reading like coverage, and nothing notices.
|
|
124
|
+
*/
|
|
125
|
+
export function findDanglingFeatures(useCases, matrixIds) {
|
|
126
|
+
const out = []
|
|
127
|
+
for (const uc of useCases) {
|
|
128
|
+
for (const f of Array.isArray(uc['featureIds']) ? uc['featureIds'] : []) {
|
|
129
|
+
if (matrixIds.has(String(f))) continue
|
|
130
|
+
out.push(
|
|
131
|
+
`use case ${String(uc['id'])}: featureId "${String(f)}" is not a row in ${MATRIX_REL}`,
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return out
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** `- **Exercises:** \`UC-NN\`` per scenario block, as a map of use-case id -> scenario headings. */
|
|
139
|
+
export function parseScenarioExercises(text) {
|
|
140
|
+
const byUseCase = new Map()
|
|
141
|
+
for (const block of text.split(/^## (?=\d+\. )/m).slice(1)) {
|
|
142
|
+
const body = `## ${block}`
|
|
143
|
+
const heading = body.split('\n')[0].replace(/^## /, '').trim()
|
|
144
|
+
const line = /^- \*\*Exercises:\*\*\s*(.*)$/m.exec(body)
|
|
145
|
+
if (!line) continue
|
|
146
|
+
for (const m of line[1].matchAll(/UC-[0-9]{2,3}/g)) {
|
|
147
|
+
if (!byUseCase.has(m[0])) byUseCase.set(m[0], [])
|
|
148
|
+
byUseCase.get(m[0]).push(heading)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return byUseCase
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The join, both ways. A scenario naming a use case that does not exist, and a use case CLAIMING
|
|
156
|
+
* `exercised` that no scenario walks. The second direction is the one invisible from the scenario
|
|
157
|
+
* side, which is why the join is read from here.
|
|
158
|
+
*/
|
|
159
|
+
export function findJoinViolations(useCases, exercises) {
|
|
160
|
+
const known = new Set(useCases.map((uc) => String(uc['id'])))
|
|
161
|
+
const out = []
|
|
162
|
+
for (const [id, headings] of exercises) {
|
|
163
|
+
if (known.has(id)) continue
|
|
164
|
+
out.push(
|
|
165
|
+
`${SCENARIOS_REL}: scenario "${headings[0]}" exercises "${id}", which is not a declared use case`,
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
for (const uc of useCases) {
|
|
169
|
+
if (String(uc['status']) !== 'exercised') continue
|
|
170
|
+
const id = String(uc['id'])
|
|
171
|
+
if (exercises.has(id)) continue
|
|
172
|
+
out.push(
|
|
173
|
+
`use case ${id} claims status "exercised" but no tabletop scenario names it — status is not a walk`,
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
return out
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Every structural rule, once the document is known schema-valid. */
|
|
180
|
+
export function collectViolations(useCases, matrixIds, exercises) {
|
|
181
|
+
return [
|
|
182
|
+
...findDuplicateIds(useCases),
|
|
183
|
+
...findDanglingFeatures(useCases, matrixIds),
|
|
184
|
+
...findJoinViolations(useCases, exercises),
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function report(json, verdict, message, violations) {
|
|
189
|
+
if (json) {
|
|
190
|
+
process.stdout.write(`${JSON.stringify({ verdict, message, violations }, null, 2)}\n`)
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
if (verdict === 'skip') {
|
|
194
|
+
process.stdout.write(`[SKIP] check-use-cases: ${message}\n`)
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
for (const v of violations) process.stderr.write(`check-use-cases: FAIL — ${v}\n`)
|
|
198
|
+
if (verdict === 'pass') process.stdout.write(`check-use-cases: PASS — ${message}\n`)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Rewrite `useCases.useCases[2]` as `UC-30` so a schema error names the row a reader can find. */
|
|
202
|
+
export function annotateSchemaViolations(violations, useCases) {
|
|
203
|
+
return violations.map((v) =>
|
|
204
|
+
v.replace(/^useCases\.useCases\[(\d+)\]/, (_m, i) => {
|
|
205
|
+
const id = useCases[Number(i)]?.['id']
|
|
206
|
+
return id ? `use case ${String(id)}` : `use case #${i}`
|
|
207
|
+
}),
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The machine projection a viewer consumes. Only what a traceability view needs: who wants what,
|
|
213
|
+
* which features it rests on, and whether a scenario has actually walked it.
|
|
214
|
+
*
|
|
215
|
+
* `exercisedBy` is DERIVED here rather than copied from the declared `status`, because the two can
|
|
216
|
+
* disagree and only one of them is checkable — the gate has just proven which scenarios name this
|
|
217
|
+
* use case, so the projection carries the measurement, not the claim.
|
|
218
|
+
* @param {Array<Record<string, unknown>>} useCases
|
|
219
|
+
* @param {Map<string, string[]>} exercises
|
|
220
|
+
*/
|
|
221
|
+
export function useCaseProjection(useCases, exercises) {
|
|
222
|
+
return {
|
|
223
|
+
schema: 'arbiter-use-cases-v1',
|
|
224
|
+
useCases: [...useCases]
|
|
225
|
+
.sort((a, b) => String(a['id']).localeCompare(String(b['id'])))
|
|
226
|
+
.map((uc) => {
|
|
227
|
+
const id = String(uc['id'])
|
|
228
|
+
/** @type {Record<string, unknown>} */
|
|
229
|
+
const row = {
|
|
230
|
+
id,
|
|
231
|
+
actor: uc['actor'],
|
|
232
|
+
goal: uc['goal'],
|
|
233
|
+
featureIds: [...(Array.isArray(uc['featureIds']) ? uc['featureIds'] : [])].sort(),
|
|
234
|
+
exercisedBy: (exercises.get(id) ?? []).slice().sort(),
|
|
235
|
+
}
|
|
236
|
+
// Omitted when absent rather than defaulted, so "no journey declared" stays distinguishable
|
|
237
|
+
// from "declared as belonging to none".
|
|
238
|
+
if (Array.isArray(uc['journeyIds'])) row['journeyIds'] = [...uc['journeyIds']].sort()
|
|
239
|
+
if (typeof uc['prdRef'] === 'string') row['prdRef'] = uc['prdRef']
|
|
240
|
+
if (typeof uc['status'] === 'string') row['status'] = uc['status']
|
|
241
|
+
return row
|
|
242
|
+
}),
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Load the schema and validate. A schema that will not load is exit 2, not 1 (INV-53): the gate
|
|
248
|
+
* could not tell, which is a different claim from "a use case is wrong" and must not be filed as
|
|
249
|
+
* one — the emitted twin ships its schema alongside it precisely so this cannot happen silently.
|
|
250
|
+
* @returns {{ code: number } | { doc: Record<string, unknown> }}
|
|
251
|
+
*/
|
|
252
|
+
function validateDocument(document, json) {
|
|
253
|
+
let schema
|
|
254
|
+
try {
|
|
255
|
+
schema = loadSchema(resolve(scriptDir, '..', SCHEMA_REL))
|
|
256
|
+
} catch (err) {
|
|
257
|
+
process.stderr.write(`check-use-cases: cannot load ${SCHEMA_REL} — ${err.message}\n`)
|
|
258
|
+
return { code: 2 }
|
|
259
|
+
}
|
|
260
|
+
const violations = validateSchema(document, schema, schema, 'useCases')
|
|
261
|
+
if (violations.length === 0) return { doc: document }
|
|
262
|
+
const list = Array.isArray(document?.useCases) ? document.useCases : []
|
|
263
|
+
report(json, 'fail', 'schema violations', annotateSchemaViolations(violations, list))
|
|
264
|
+
return { code: 1 }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Write the projection. Called only after every rule has passed. */
|
|
268
|
+
function emitProjection(emit, useCases, exercises, json) {
|
|
269
|
+
mkdirSync(dirname(emit), { recursive: true })
|
|
270
|
+
const doc = useCaseProjection(useCases, exercises)
|
|
271
|
+
writeFileSync(emit, `${JSON.stringify(doc, null, 2)}\n`, 'utf-8')
|
|
272
|
+
if (!json) process.stdout.write(`check-use-cases: projection written to ${emit}\n`)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** @param {string[]} argv */
|
|
276
|
+
function parseArgs(argv) {
|
|
277
|
+
const i = argv.indexOf('--dir')
|
|
278
|
+
const e = argv.indexOf('--emit')
|
|
279
|
+
return {
|
|
280
|
+
root: i >= 0 && argv[i + 1] ? resolve(argv[i + 1]) : process.cwd(),
|
|
281
|
+
json: argv.includes('--json'),
|
|
282
|
+
emit: e >= 0 && argv[e + 1] ? resolve(argv[e + 1]) : null,
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function main(argv) {
|
|
287
|
+
const { root, json, emit } = parseArgs(argv)
|
|
288
|
+
const ssot = join(root, SSOT_REL)
|
|
289
|
+
if (!existsSync(ssot)) {
|
|
290
|
+
report(json, 'skip', `${SSOT_REL} absent — no use cases codified in this project`, [])
|
|
291
|
+
return 0
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const extracted = extractBlock(readRegularFileSync(ssot, 'utf-8'))
|
|
295
|
+
if (!extracted.ok) {
|
|
296
|
+
report(json, 'fail', 'unreadable SSOT', [`${SSOT_REL} ${extracted.error}`])
|
|
297
|
+
return 1
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const validated = validateDocument(extracted.document, json)
|
|
301
|
+
if (validated.code !== undefined) return validated.code
|
|
302
|
+
const doc = validated.doc
|
|
303
|
+
|
|
304
|
+
const useCases = doc.useCases
|
|
305
|
+
const matrixPath = join(root, MATRIX_REL)
|
|
306
|
+
if (!existsSync(matrixPath)) {
|
|
307
|
+
// Not a skip: use cases EXIST and every one of them names features. Without the matrix the
|
|
308
|
+
// central rule cannot run, and passing anyway would report coverage this gate never checked.
|
|
309
|
+
report(json, 'fail', 'missing namespace', [
|
|
310
|
+
`${useCases.length} use case(s) declared but ${MATRIX_REL} is absent — every featureId is unresolvable`,
|
|
311
|
+
])
|
|
312
|
+
return 1
|
|
313
|
+
}
|
|
314
|
+
const matrixIds = parseMatrixIds(readRegularFileSync(matrixPath, 'utf-8'))
|
|
315
|
+
|
|
316
|
+
const scenariosPath = join(root, SCENARIOS_REL)
|
|
317
|
+
const exercises = existsSync(scenariosPath)
|
|
318
|
+
? parseScenarioExercises(readRegularFileSync(scenariosPath, 'utf-8'))
|
|
319
|
+
: new Map()
|
|
320
|
+
|
|
321
|
+
const violations = collectViolations(useCases, matrixIds, exercises)
|
|
322
|
+
if (violations.length > 0) {
|
|
323
|
+
report(json, 'fail', 'structural violations', violations)
|
|
324
|
+
return 1
|
|
325
|
+
}
|
|
326
|
+
if (emit) emitProjection(emit, useCases, exercises, json)
|
|
327
|
+
const walked = useCases.filter((uc) => exercises.has(String(uc['id']))).length
|
|
328
|
+
report(
|
|
329
|
+
json,
|
|
330
|
+
'pass',
|
|
331
|
+
`${useCases.length} use case(s), every featureId resolves, ${walked} exercised by a scenario`,
|
|
332
|
+
[],
|
|
333
|
+
)
|
|
334
|
+
return 0
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (isMainModule(import.meta.url)) {
|
|
338
|
+
try {
|
|
339
|
+
process.exit(main(process.argv.slice(2)))
|
|
340
|
+
} catch (err) {
|
|
341
|
+
// Exit 2, not 1 (INV-53): 1 means a use case is wrong, 2 means the gate could not tell.
|
|
342
|
+
process.stderr.write(`check-use-cases: ERROR — ${err?.stack ?? err}\n`)
|
|
343
|
+
process.exit(2)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// <%= projectName %> — validator --help text coverage check (INV-89)
|
|
3
|
+
// Validates that all anti-drift check-*.mjs scripts support a --help flag.
|
|
4
|
+
// Exits 0 when all anti-drift validators have --help; exits 1 when any are missing it.
|
|
5
|
+
// Part of the anti-drift validator family (W6).
|
|
6
|
+
//
|
|
7
|
+
// Usage: node scripts/check-validator-helptext.mjs [--dir <path>] [--help]
|
|
8
|
+
|
|
9
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
10
|
+
import { join, resolve } from 'node:path';
|
|
11
|
+
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
14
|
+
process.stdout.write(
|
|
15
|
+
[
|
|
16
|
+
'Usage: node scripts/check-validator-helptext.mjs [options]',
|
|
17
|
+
'',
|
|
18
|
+
'Validates that all anti-drift check-*.mjs scripts support a --help flag.',
|
|
19
|
+
'Exits 0 when all validators have --help; exits 1 when any are missing it.',
|
|
20
|
+
'',
|
|
21
|
+
'Options:',
|
|
22
|
+
' --dir <path> Root directory to scan (default: cwd)',
|
|
23
|
+
' --help, -h Show this help and exit',
|
|
24
|
+
'',
|
|
25
|
+
].join('\n'),
|
|
26
|
+
);
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const dirArg = args.indexOf('--dir');
|
|
31
|
+
const CWD = dirArg >= 0 && args[dirArg + 1] ? resolve(args[dirArg + 1]) : process.cwd();
|
|
32
|
+
|
|
33
|
+
const SCRIPTS_DIR = join(CWD, 'scripts');
|
|
34
|
+
|
|
35
|
+
// Anti-drift validator family marker
|
|
36
|
+
const FAMILY_MARKER = 'anti-drift validator family (W6)';
|
|
37
|
+
|
|
38
|
+
let violations = 0;
|
|
39
|
+
let checked = 0;
|
|
40
|
+
|
|
41
|
+
if (!existsSync(SCRIPTS_DIR)) {
|
|
42
|
+
process.stdout.write('check-validator-helptext: SKIP — no scripts/ directory found\n');
|
|
43
|
+
// #2052: recognized marker so runCheck surfaces SKIP, not PASS, in the gate summary.
|
|
44
|
+
process.stdout.write('[SKIP] no scripts/ directory found\n');
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const entries = readdirSync(SCRIPTS_DIR, { withFileTypes: true });
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
if (!entry.isFile()) continue;
|
|
51
|
+
if (!entry.name.startsWith('check-') || !entry.name.endsWith('.mjs')) continue;
|
|
52
|
+
|
|
53
|
+
const fullPath = join(SCRIPTS_DIR, entry.name);
|
|
54
|
+
let content;
|
|
55
|
+
try {
|
|
56
|
+
content = readFileSync(fullPath, 'utf-8');
|
|
57
|
+
} catch {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Only check anti-drift family scripts
|
|
62
|
+
if (!content.includes(FAMILY_MARKER)) continue;
|
|
63
|
+
|
|
64
|
+
checked++;
|
|
65
|
+
if (!content.includes('--help')) {
|
|
66
|
+
process.stderr.write(`[FAIL] ${entry.name}: no --help flag support found (INV-89)\n`);
|
|
67
|
+
violations++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (violations > 0) {
|
|
72
|
+
process.stderr.write(
|
|
73
|
+
`check-validator-helptext: FAIL — ${violations}/${checked} validator(s) missing --help support (INV-89)\n`,
|
|
74
|
+
);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
process.stdout.write(
|
|
78
|
+
`check-validator-helptext: OK — all ${checked} anti-drift validators support --help (INV-89)\n`,
|
|
79
|
+
);
|
|
80
|
+
process.exit(0);
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// CATALOG: Validates wiki/ for broken wikilinks, orphan pages, stale source hashes, and citation integrity (INV-116).
|
|
4
|
+
// CATALOG: Rejected fold-in into check-doc-links.mjs because [[wikilinks]] have distinct syntax from markdown links.
|
|
5
|
+
// CATALOG: Rejected fold-in into check-ssot-core.mjs because wiki/ is generated content, not a curated SSOT inventory.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// node scripts/check-wiki-lint.mjs # run against wiki/ in CWD
|
|
9
|
+
// node scripts/check-wiki-lint.mjs --wiki-dir <dir> # run against a specific wiki dir
|
|
10
|
+
// node scripts/check-wiki-lint.mjs --assert-stale # keep the stale dimension for an untracked wiki (#2585)
|
|
11
|
+
// Exits 0 if all clean; exits 1 if any violation found.
|
|
12
|
+
|
|
13
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
14
|
+
import { join, resolve } from 'node:path';
|
|
15
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
16
|
+
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const wikiDirArg = args.find((a) => a.startsWith('--wiki-dir='))?.split('=')[1]
|
|
19
|
+
?? (args[args.indexOf('--wiki-dir') + 1] !== undefined && !args[args.indexOf('--wiki-dir') + 1].startsWith('-')
|
|
20
|
+
? args[args.indexOf('--wiki-dir') + 1]
|
|
21
|
+
: null);
|
|
22
|
+
const root = process.cwd();
|
|
23
|
+
const WIKI_DIR = wikiDirArg ? resolve(wikiDirArg) : join(root, 'wiki');
|
|
24
|
+
|
|
25
|
+
if (!existsSync(WIKI_DIR)) {
|
|
26
|
+
process.stdout.write(' check-wiki-lint: wiki/ not found — skipping (bootstrap mode)\n');
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const mdFiles = readdirSync(WIKI_DIR).filter((f) => f.endsWith('.md'));
|
|
31
|
+
if (mdFiles.length === 0) {
|
|
32
|
+
process.stdout.write(' check-wiki-lint: wiki/ is empty — skipping (bootstrap mode)\n');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function parseFrontmatter(text) {
|
|
37
|
+
if (!text.startsWith('---\n')) return {};
|
|
38
|
+
const end = text.indexOf('\n---', 4);
|
|
39
|
+
if (end === -1) return {};
|
|
40
|
+
const fm = {};
|
|
41
|
+
for (const line of text.slice(4, end).split('\n')) {
|
|
42
|
+
const colon = line.indexOf(':');
|
|
43
|
+
if (colon === -1) continue;
|
|
44
|
+
fm[line.slice(0, colon).trim()] = line.slice(colon + 1).trim().replace(/^['"]|['"]$/g, '');
|
|
45
|
+
}
|
|
46
|
+
return fm;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function extractWikilinks(text) {
|
|
50
|
+
return [...text.matchAll(/\[\[([^\]]+?)\]\]/g)].map((m) => m[1].trim()).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function slug(filename) {
|
|
54
|
+
return filename.replace(/\.md$/, '').toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const pages = new Map();
|
|
58
|
+
for (const file of mdFiles) {
|
|
59
|
+
const text = readFileSync(join(WIKI_DIR, file), 'utf-8');
|
|
60
|
+
const fm = parseFrontmatter(text);
|
|
61
|
+
const links = extractWikilinks(text).map((l) => l.toLowerCase());
|
|
62
|
+
pages.set(slug(file), { file, fm, links });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let violations = 0;
|
|
66
|
+
|
|
67
|
+
for (const [, { file, links }] of pages) {
|
|
68
|
+
for (const link of links) {
|
|
69
|
+
if (!pages.has(link)) {
|
|
70
|
+
process.stdout.write(
|
|
71
|
+
` check-wiki-lint [broken-link]: wiki/${file} references [[${link}]] which does not exist\n`,
|
|
72
|
+
);
|
|
73
|
+
violations++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const indexSlug = 'index';
|
|
79
|
+
if (!pages.has(indexSlug)) {
|
|
80
|
+
process.stdout.write(' check-wiki-lint [orphan]: wiki/INDEX.md not found\n');
|
|
81
|
+
violations++;
|
|
82
|
+
} else {
|
|
83
|
+
const reachable = new Set([indexSlug]);
|
|
84
|
+
const queue = [indexSlug];
|
|
85
|
+
while (queue.length > 0) {
|
|
86
|
+
const current = queue.shift();
|
|
87
|
+
const page = pages.get(current);
|
|
88
|
+
if (!page) continue;
|
|
89
|
+
for (const link of page.links) {
|
|
90
|
+
if (!reachable.has(link) && pages.has(link)) {
|
|
91
|
+
reachable.add(link);
|
|
92
|
+
queue.push(link);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const [s, { file }] of pages) {
|
|
97
|
+
if (s === indexSlug) continue;
|
|
98
|
+
if (!reachable.has(s)) {
|
|
99
|
+
process.stdout.write(
|
|
100
|
+
` check-wiki-lint [orphan]: wiki/${file} is unreachable from INDEX.md\n`,
|
|
101
|
+
);
|
|
102
|
+
violations++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// stale: asserted only when the wiki dir is git-tracked (#2585). An untracked (generated,
|
|
108
|
+
// gitignored) wiki goes stale as a side effect of merging; that is not a review property.
|
|
109
|
+
const ls = spawnSync('git', ['ls-files', '--', WIKI_DIR], { encoding: 'utf-8', cwd: root });
|
|
110
|
+
const wikiTracked = ls.status === 0 && ls.stdout.trim().length > 0;
|
|
111
|
+
// --assert-stale: a caller asking about freshness itself (arbiter obsidian --validate-only) keeps it.
|
|
112
|
+
const assertStale = wikiTracked || args.includes('--assert-stale');
|
|
113
|
+
if (!assertStale) {
|
|
114
|
+
process.stdout.write(
|
|
115
|
+
' check-wiki-lint [stale:skip] — wiki dir is not git-tracked (generated, gitignored), so ' +
|
|
116
|
+
'page freshness is local derived state, not a review property (#2585); ' +
|
|
117
|
+
'run `node scripts/gen-wiki.mjs` to refresh it\n',
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const [, { file, fm }] of assertStale ? pages : []) {
|
|
122
|
+
const sourcePath = fm['source'];
|
|
123
|
+
const sourceSha = fm['source_sha'];
|
|
124
|
+
if (!sourcePath || !sourceSha) continue;
|
|
125
|
+
const absSource = join(root, sourcePath);
|
|
126
|
+
if (!existsSync(absSource)) continue;
|
|
127
|
+
try {
|
|
128
|
+
const actualSha = execFileSync('git', ['hash-object', absSource], { encoding: 'utf-8', cwd: root }).trim();
|
|
129
|
+
if (actualSha !== sourceSha) {
|
|
130
|
+
process.stdout.write(` check-wiki-lint [stale]: wiki/${file} source_sha is stale\n`);
|
|
131
|
+
violations++;
|
|
132
|
+
}
|
|
133
|
+
} catch { /* git not available */ }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let trackedFiles = new Set();
|
|
137
|
+
try {
|
|
138
|
+
const lsOutput = execFileSync('git', ['ls-files', '--', 'docs/'], { encoding: 'utf-8', cwd: root });
|
|
139
|
+
trackedFiles = new Set(lsOutput.trim().split('\n').filter(Boolean));
|
|
140
|
+
} catch { /* git not available */ }
|
|
141
|
+
|
|
142
|
+
for (const [, { file, fm }] of pages) {
|
|
143
|
+
if (slug(file) === 'index') continue;
|
|
144
|
+
const sourcePath = fm['source'];
|
|
145
|
+
if (!sourcePath) {
|
|
146
|
+
process.stdout.write(` check-wiki-lint [citation]: wiki/${file} missing source: field\n`);
|
|
147
|
+
violations++;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (trackedFiles.size > 0 && !trackedFiles.has(sourcePath)) {
|
|
151
|
+
process.stdout.write(` check-wiki-lint [citation]: wiki/${file} source '${sourcePath}' not tracked\n`);
|
|
152
|
+
violations++;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (violations === 0) {
|
|
157
|
+
process.stdout.write(` check-wiki-lint: ${mdFiles.length} wiki pages OK\n`);
|
|
158
|
+
process.exit(0);
|
|
159
|
+
} else {
|
|
160
|
+
process.stdout.write(` check-wiki-lint: ${violations} violation(s) found\n`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// <%= projectName %> — workflow documentation sync checker (INV-89)
|
|
3
|
+
// Validates that all workflow files are documented in docs/ directory.
|
|
4
|
+
// Exits 0 when all workflows are documented; exits 0 (WARN) when undocumented found.
|
|
5
|
+
// Part of the anti-drift validator family (W6).
|
|
6
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
7
|
+
import { join, resolve, basename } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
11
|
+
process.stdout.write([
|
|
12
|
+
'Usage: node scripts/check-workflow-docs-sync.mjs [options]',
|
|
13
|
+
'',
|
|
14
|
+
'Validates that all workflow files are documented in docs/ directory.',
|
|
15
|
+
'Exits 0 when all workflows are documented; exits 0 (WARN) when undocumented found.',
|
|
16
|
+
'',
|
|
17
|
+
'Options:',
|
|
18
|
+
' --dir <path> Root directory to scan (default: cwd)',
|
|
19
|
+
' --help, -h Show this help and exit',
|
|
20
|
+
'',
|
|
21
|
+
].join('\n'));
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const dirArg = args.indexOf('--dir');
|
|
26
|
+
const CWD = dirArg >= 0 && args[dirArg + 1] ? resolve(args[dirArg + 1]) : process.cwd();
|
|
27
|
+
const WORKFLOWS_DIR = join(CWD, '.github', 'workflows');
|
|
28
|
+
const DOCS_DIR = join(CWD, 'docs');
|
|
29
|
+
const EXEMPT_PREFIXES = ['_'];
|
|
30
|
+
|
|
31
|
+
if (!existsSync(WORKFLOWS_DIR)) {
|
|
32
|
+
process.stdout.write('check-workflow-docs-sync: SKIP — no .github/workflows/ directory\n');
|
|
33
|
+
// #2052: recognized marker so runCheck surfaces SKIP, not PASS, in the gate summary.
|
|
34
|
+
process.stdout.write('[SKIP] no .github/workflows/ directory\n');
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
if (!existsSync(DOCS_DIR)) {
|
|
38
|
+
process.stdout.write('check-workflow-docs-sync: SKIP — no docs/ directory\n');
|
|
39
|
+
// #2052: recognized marker so runCheck surfaces SKIP, not PASS, in the gate summary.
|
|
40
|
+
process.stdout.write('[SKIP] no docs/ directory\n');
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function gatherDocContent(dir) {
|
|
45
|
+
let content = '';
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
49
|
+
} catch {
|
|
50
|
+
return content;
|
|
51
|
+
}
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (entry.isSymbolicLink()) continue;
|
|
54
|
+
const full = join(dir, entry.name);
|
|
55
|
+
if (entry.isDirectory()) {
|
|
56
|
+
content += gatherDocContent(full);
|
|
57
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
58
|
+
try {
|
|
59
|
+
content += readFileSync(full, 'utf-8') + '\n';
|
|
60
|
+
} catch { /* ignore */ }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return content;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const docContent = gatherDocContent(DOCS_DIR);
|
|
67
|
+
let violations = 0;
|
|
68
|
+
let checked = 0;
|
|
69
|
+
|
|
70
|
+
const wfEntries = readdirSync(WORKFLOWS_DIR, { withFileTypes: true });
|
|
71
|
+
for (const entry of wfEntries) {
|
|
72
|
+
if (!entry.isFile()) continue;
|
|
73
|
+
if (!entry.name.endsWith('.yml') && !entry.name.endsWith('.yaml')) continue;
|
|
74
|
+
const name = basename(entry.name, entry.name.endsWith('.yml') ? '.yml' : '.yaml');
|
|
75
|
+
if (EXEMPT_PREFIXES.some((p) => entry.name.startsWith(p))) continue;
|
|
76
|
+
checked++;
|
|
77
|
+
if (!docContent.includes(name) && !docContent.includes(entry.name)) {
|
|
78
|
+
process.stderr.write(`[WARN] workflow "${entry.name}" not referenced in any docs/ markdown (INV-89)\n`);
|
|
79
|
+
violations++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (violations > 0) {
|
|
84
|
+
process.stdout.write(
|
|
85
|
+
`check-workflow-docs-sync: WARN — ${violations}/${checked} workflow(s) not documented in docs/ (INV-89)\n`,
|
|
86
|
+
);
|
|
87
|
+
// Warning only — docs are often written after implementation
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
process.stdout.write(`check-workflow-docs-sync: OK — all ${checked} workflows referenced in docs/ (INV-89)\n`);
|
|
91
|
+
process.exit(0);
|