@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,1089 @@
|
|
|
1
|
+
<% const _lanes = Array.isArray(lanes) ? lanes : []; const _multiLane = _lanes.length >= 2; const _bs = (typeof branchingStrategy !== 'undefined' ? branchingStrategy : 'github-flow'); %><% const _collabMode = (typeof collaborationMode !== 'undefined' && collaborationMode) ? collaborationMode : undefined; const _humanApproval = _collabMode !== 'trunk-solo'; /* trunk-solo: the sole human is the PR author and cannot self-approve — drop the impossible gate (INV-74) */ %># Reference: docs/REFERENCE/workflow-pr-fast.md
|
|
2
|
+
name: PR Fast (T1)
|
|
3
|
+
|
|
4
|
+
permissions:
|
|
5
|
+
contents: read
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
<% if (_bs === 'github-flow-with-develop') { %>
|
|
10
|
+
branches: [main, develop]
|
|
11
|
+
<% } else { %>
|
|
12
|
+
branches: [main]
|
|
13
|
+
<% } %>
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
# #2476 — deliberately NO `branches:` filter on this trigger. On a pull_request
|
|
16
|
+
# event `branches:` filters the BASE branch, not the head, so the former
|
|
17
|
+
# `branches: [main]` created NO WORKFLOW RUN AT ALL for a pull request stacked on
|
|
18
|
+
# a task or train branch: it displayed no failing checks because it had no checks,
|
|
19
|
+
# and any "no failing checks ⇒ mergeable" read was satisfied by a pull request
|
|
20
|
+
# that was never tested. Branch protection is no backstop — protection is
|
|
21
|
+
# configured on the BASE branch and a task/train branch carries none. Run creation
|
|
22
|
+
# is therefore unconditional in the base branch; per-branch economy stays INSIDE
|
|
23
|
+
# the workflow, in the job-level `if:` guards below, where a skipped job still
|
|
24
|
+
# reports a result the `ci-required` aggregator reads. The `push:` trigger above
|
|
25
|
+
# keeps its branch list: that lane is the post-merge catch-net for long-lived
|
|
26
|
+
# branches, and widening it would multiply runner cost on every task-branch push
|
|
27
|
+
# for coverage this pull_request trigger already provides. #2486 separately keys
|
|
28
|
+
# PR concurrency by head AND base while preserving the push key. Base-trigger
|
|
29
|
+
# coverage is enforced by scripts/check-workflow-test-integrity.mjs.
|
|
30
|
+
pull_request:
|
|
31
|
+
types: [opened, synchronize, reopened, labeled, ready_for_review, unlabeled]
|
|
32
|
+
|
|
33
|
+
# Cancel in-progress runs on the same ref; main always completes (#357).
|
|
34
|
+
concurrency:
|
|
35
|
+
group: pr-fast-${{ github.head_ref || github.ref_name }}${{ github.base_ref && format('-{0}', github.base_ref) || '' }}
|
|
36
|
+
<% if (_bs === 'github-flow-with-develop') { %>
|
|
37
|
+
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }}
|
|
38
|
+
<% } else { %>
|
|
39
|
+
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
40
|
+
<% } %>
|
|
41
|
+
|
|
42
|
+
jobs:
|
|
43
|
+
config-lint:
|
|
44
|
+
name: Config Lint (yaml + shell)
|
|
45
|
+
# gold-align (#1506 yamllint / #1507 shellcheck): a language-agnostic style/
|
|
46
|
+
# structure lint lane. yamllint checks non-workflow YAML (indentation, duplicate
|
|
47
|
+
# keys, trailing spaces, document structure) — complementary to actionlint, which
|
|
48
|
+
# owns .github/workflows *semantics*. shellcheck checks generated *.sh for unquoted
|
|
49
|
+
# expansions / unsafe word-splitting at warning severity. Both BLOCKING; both
|
|
50
|
+
# version-pinned for reproducibility. Each linter no-ops cleanly (green) when the
|
|
51
|
+
# repo carries no matching files. Committed .yamllint.yml / .shellcheckrc (when
|
|
52
|
+
# present) are auto-discovered and make the rules explicit + tunable.
|
|
53
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
54
|
+
timeout-minutes: 60
|
|
55
|
+
permissions:
|
|
56
|
+
contents: read
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
59
|
+
- name: Install shellcheck (pinned)
|
|
60
|
+
run: |
|
|
61
|
+
mkdir -p "$RUNNER_TEMP/bin"
|
|
62
|
+
curl -sSfL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz \
|
|
63
|
+
| tar -xJ -C "$RUNNER_TEMP/bin" --strip-components=1 shellcheck-v0.10.0/shellcheck
|
|
64
|
+
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
|
|
65
|
+
- name: shellcheck (generated shell, blocking at warning severity)
|
|
66
|
+
# .shellcheckrc (when present) is auto-discovered. No *.sh ⇒ no-op (green).
|
|
67
|
+
run: |
|
|
68
|
+
files=$(git ls-files '*.sh')
|
|
69
|
+
if [ -n "$files" ]; then
|
|
70
|
+
echo "$files" | xargs shellcheck --severity=warning
|
|
71
|
+
else
|
|
72
|
+
echo "shellcheck: no *.sh files — skipping"
|
|
73
|
+
fi
|
|
74
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.12'
|
|
77
|
+
- name: Install yamllint (pinned)
|
|
78
|
+
run: pip install yamllint==1.35.1
|
|
79
|
+
- name: yamllint (non-workflow YAML, blocking on errors)
|
|
80
|
+
# actionlint owns .github/workflows semantics; exclude them to avoid overlap.
|
|
81
|
+
# A committed .yamllint.yml (when present) is auto-discovered and authoritative;
|
|
82
|
+
# otherwise fall back to yamllint's built-in `relaxed` preset — both block on
|
|
83
|
+
# ERRORS only (line-length etc. stay advisory warnings). No matching YAML ⇒ no-op.
|
|
84
|
+
run: |
|
|
85
|
+
files=$(git ls-files '*.yml' '*.yaml' ':!.github/workflows/**')
|
|
86
|
+
if [ -n "$files" ]; then
|
|
87
|
+
if [ -f .yamllint.yml ] || [ -f .yamllint.yaml ] || [ -f .yamllint ]; then
|
|
88
|
+
echo "$files" | xargs yamllint
|
|
89
|
+
else
|
|
90
|
+
echo "$files" | xargs yamllint -d relaxed
|
|
91
|
+
fi
|
|
92
|
+
else
|
|
93
|
+
echo "yamllint: no non-workflow YAML — skipping"
|
|
94
|
+
fi
|
|
95
|
+
<% if (locals.enableSoloDevMode) { %>
|
|
96
|
+
solo-dev-gate:
|
|
97
|
+
name: Solo-Dev Gate (INV-59)
|
|
98
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
99
|
+
timeout-minutes: 60
|
|
100
|
+
steps:
|
|
101
|
+
- run: echo "solo-dev mode — local L2 gate guards merge via INV-59 parity check"
|
|
102
|
+
<% } else { %><% if (enableSecurityScanning) { %>
|
|
103
|
+
security-early-fail:
|
|
104
|
+
name: Security (PII + Secrets)
|
|
105
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
106
|
+
timeout-minutes: 60
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
109
|
+
with:
|
|
110
|
+
fetch-depth: 0
|
|
111
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
112
|
+
with:
|
|
113
|
+
node-version-file: '.nvmrc'
|
|
114
|
+
package-manager-cache: false
|
|
115
|
+
- name: PII scan (INV-12, HARD)
|
|
116
|
+
run: node scripts/pii-scan.mjs
|
|
117
|
+
- name: Install gitleaks
|
|
118
|
+
run: |
|
|
119
|
+
mkdir -p "$RUNNER_TEMP/bin"
|
|
120
|
+
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.27.2/gitleaks_8.27.2_linux_x64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" gitleaks
|
|
121
|
+
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
|
|
122
|
+
- name: Gitleaks secrets scan (INV-11)
|
|
123
|
+
# --log-opts="HEAD" (#1908): without it, gitleaks defaults to scanning
|
|
124
|
+
# ALL refs reachable in the checkout's object DB (fetch-depth: 0 above
|
|
125
|
+
# fetches every remote branch, not just this one). That let an unrelated,
|
|
126
|
+
# unmerged branch's commit cross-contaminate every other PR's scan.
|
|
127
|
+
# Scoping to HEAD still walks this ref's FULL history (no depth lost) —
|
|
128
|
+
# it just stops other branches' commits from being scanned here. The
|
|
129
|
+
# nightly `gitleaks-history` job intentionally keeps `--all --full-history`
|
|
130
|
+
# as the deep, cross-branch safety net.
|
|
131
|
+
run: |
|
|
132
|
+
gitleaks detect --source . --config .gitleaks.toml \
|
|
133
|
+
--gitleaks-ignore-path suppressions/.gitleaksignore \
|
|
134
|
+
--log-opts="HEAD" \
|
|
135
|
+
--exit-code 1 --redact
|
|
136
|
+
<% } %>
|
|
137
|
+
<% if (governanceLevel !== 'L1' || _multiLane) { %>
|
|
138
|
+
classify-changes:
|
|
139
|
+
name: Classify Changes
|
|
140
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
141
|
+
timeout-minutes: 60
|
|
142
|
+
outputs:
|
|
143
|
+
docs_only: ${{ steps.classify.outputs.docs_only }}
|
|
144
|
+
backend_changed: ${{ steps.classify.outputs.backend_changed }}
|
|
145
|
+
frontend_changed: ${{ steps.classify.outputs.frontend_changed }}
|
|
146
|
+
infra_changed: ${{ steps.classify.outputs.infra_changed }}
|
|
147
|
+
high_risk: ${{ steps.classify.outputs.high_risk }}
|
|
148
|
+
steps:
|
|
149
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
150
|
+
with:
|
|
151
|
+
fetch-depth: 0
|
|
152
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
153
|
+
with:
|
|
154
|
+
node-version-file: '.nvmrc'
|
|
155
|
+
package-manager-cache: false
|
|
156
|
+
- id: classify
|
|
157
|
+
if: hashFiles('scripts/ci-classify-changes.mjs') != ''
|
|
158
|
+
run: node scripts/ci-classify-changes.mjs
|
|
159
|
+
env:
|
|
160
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha || 'origin/main' }}
|
|
161
|
+
HEAD_SHA: ${{ github.sha }}
|
|
162
|
+
<% } %>
|
|
163
|
+
<% if (_multiLane) { %>
|
|
164
|
+
cross-stack-guard:
|
|
165
|
+
name: Cross-Stack Guard
|
|
166
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
167
|
+
timeout-minutes: 60
|
|
168
|
+
needs: [classify-changes]
|
|
169
|
+
if: github.event_name == 'pull_request'
|
|
170
|
+
permissions:
|
|
171
|
+
pull-requests: write
|
|
172
|
+
steps:
|
|
173
|
+
<% if (isL3Plus) { %>
|
|
174
|
+
- name: Enforce cross-stack split
|
|
175
|
+
if: needs.classify-changes.outputs.backend_changed == 'true' && needs.classify-changes.outputs.frontend_changed == 'true'
|
|
176
|
+
run: |
|
|
177
|
+
echo "::error::This PR touches both frontend and backend lanes. Split into separate PRs."
|
|
178
|
+
exit 1
|
|
179
|
+
<% } else { %>
|
|
180
|
+
- name: Warn cross-stack changes
|
|
181
|
+
if: needs.classify-changes.outputs.backend_changed == 'true' && needs.classify-changes.outputs.frontend_changed == 'true'
|
|
182
|
+
continue-on-error: true
|
|
183
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
184
|
+
with:
|
|
185
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
186
|
+
script: |
|
|
187
|
+
github.rest.issues.createComment({
|
|
188
|
+
issue_number: context.issue.number,
|
|
189
|
+
owner: context.repo.owner,
|
|
190
|
+
repo: context.repo.repo,
|
|
191
|
+
body: '> [!WARNING]\n> This PR touches both **frontend** and **backend** lanes. Consider splitting into separate PRs for cleaner review and safer deployment.'
|
|
192
|
+
})
|
|
193
|
+
<% } %>
|
|
194
|
+
<% } %>
|
|
195
|
+
<% if (enableSecurityScanning) { %> dependency-review:
|
|
196
|
+
name: Dependency Review (supply-chain)
|
|
197
|
+
# A1 (#1502): the canonical FAST PR supply-chain gate. dependency-review-action
|
|
198
|
+
# diffs the PR's dependency-manifest changes and fails on a newly-introduced
|
|
199
|
+
# vulnerable dependency — keeping slow full-tree scanners off the always-path.
|
|
200
|
+
# PR-only (the action diffs base...head and errors on push). Fail severity is
|
|
201
|
+
# configurable via the DEPENDENCY_REVIEW_FAIL_SEVERITY repo variable (default: high).
|
|
202
|
+
# Floor: enableSecurityScanning — the same always-path gate as security-early-fail.
|
|
203
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
204
|
+
timeout-minutes: 60
|
|
205
|
+
# PR-only AND GHAS-gated (#1685): dependency-review-action HARD-errors when the
|
|
206
|
+
# repo lacks Dependency Graph + GitHub Advanced Security, which reds every PR
|
|
207
|
+
# while GHAS is off. A JOB-LEVEL guard makes the job SKIP (result=skipped, which
|
|
208
|
+
# the ci-required aggregator treats as non-failure) until GHAS is enabled by
|
|
209
|
+
# setting the GHAS_ENABLED repo variable to 'true'. NOT step-level
|
|
210
|
+
# continue-on-error: that would violate INV-80 and silently neuter the gate once
|
|
211
|
+
# GHAS is on. With the var set, a real finding still fails the job and blocks.
|
|
212
|
+
if: github.event_name == 'pull_request' && vars.GHAS_ENABLED == 'true'
|
|
213
|
+
permissions:
|
|
214
|
+
contents: read
|
|
215
|
+
steps:
|
|
216
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
217
|
+
- name: Dependency review (fail on newly-introduced high-severity deps)
|
|
218
|
+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
219
|
+
with:
|
|
220
|
+
fail-on-severity: ${{ vars.DEPENDENCY_REVIEW_FAIL_SEVERITY || 'high' }}
|
|
221
|
+
<% } %>
|
|
222
|
+
<% if (governanceLevel !== 'L1' || _multiLane) { %> iac-scan:
|
|
223
|
+
name: IaC Scan (infra-changed)
|
|
224
|
+
# A1 (#1502): consume the classify-changes `infra_changed` signal (previously
|
|
225
|
+
# classified but UNUSED) — scan terraform / kubernetes / dockerfile only when the
|
|
226
|
+
# PR actually touches infrastructure-as-code, keeping the always-path lean.
|
|
227
|
+
# #1785: was pinned to a LITERAL `runs-on: ubuntu-latest` on the (disproven)
|
|
228
|
+
# assumption that GitHub-hosted runners are never containerized (#1756).
|
|
229
|
+
# Evidence (run 28693108584) showed a job pinned to literal `ubuntu-latest`
|
|
230
|
+
# actually serviced by self-hosted `arbiter-slot-build-3` — the label alone
|
|
231
|
+
# never guaranteed real GitHub-hosted infra here. Rather than keep trusting
|
|
232
|
+
# an unverified runner label, Checkov now runs as a plain pip-installed CLI
|
|
233
|
+
# (bridgecrewio/checkov-action was only a Docker convenience wrapper around
|
|
234
|
+
# it) — no docker-container action, no workspace bind-mount, the whole
|
|
235
|
+
# defect class sidestepped entirely (same pattern as the osv-scanner static-
|
|
236
|
+
# binary fix, #1767). Enforced by scripts/check-docker-action-runner-safety.mjs.
|
|
237
|
+
# #1894: routed through the same `RUNNER_LABELS_TEST` expression as every other
|
|
238
|
+
# job. The former literal `ubuntu-latest` used to be intercepted by the self-
|
|
239
|
+
# hosted fleet (#1785 evidence), but the fleet dropped the `ubuntu-latest`
|
|
240
|
+
# label, so the literal pin fell through to real GitHub-hosted infra and failed
|
|
241
|
+
# (spending-limit block). The expression defaults to `["ubuntu-latest"]` when
|
|
242
|
+
# the var is unset (consumers unaffected); arbiter's own repo sets it to the
|
|
243
|
+
# self-hosted labels. Checkov/tflint are plain CLIs (no docker-action), so the
|
|
244
|
+
# runner class remains moot for the #1785 safety class either way.
|
|
245
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
246
|
+
timeout-minutes: 60
|
|
247
|
+
needs: [classify-changes]
|
|
248
|
+
if: needs.classify-changes.outputs.infra_changed == 'true'
|
|
249
|
+
permissions:
|
|
250
|
+
contents: read
|
|
251
|
+
steps:
|
|
252
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
253
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
254
|
+
with:
|
|
255
|
+
python-version: '3.12'
|
|
256
|
+
- name: Install Checkov (pinned, no Docker — #1785)
|
|
257
|
+
run: pip install checkov==3.3.7
|
|
258
|
+
- name: Checkov IaC scan (<%= locals.checkovSelfScope ? 'terraform/kubernetes/dockerfile' : 'all frameworks' %>)
|
|
259
|
+
run: |
|
|
260
|
+
<% if (locals.checkovSelfScope) { -%>
|
|
261
|
+
# #1685 (arbiter self-scan): `all` over-scoped THIS repo (github_actions
|
|
262
|
+
# + secrets policies across dozens of workflows/fixtures) even though
|
|
263
|
+
# arbiter carries ZERO terraform/kubernetes/dockerfile IaC — redding
|
|
264
|
+
# self-CI. `--framework` takes repeated values (checkov's own nargs='+'
|
|
265
|
+
# CLI, no word-splitting footgun now that the docker-action wrapper is
|
|
266
|
+
# gone, #1785): 0 findings — honestly SCOPED, not soft-fail-suppressed.
|
|
267
|
+
# Hard-fail stays checkov's default (no soft-fail flag passed): a real
|
|
268
|
+
# misconfig would still block (INV-80). Self-only; consumers (the
|
|
269
|
+
# shipped template's `else` branch below) are NOT affected.
|
|
270
|
+
checkov --directory . --framework terraform kubernetes dockerfile --quiet --compact
|
|
271
|
+
<% } else { -%>
|
|
272
|
+
# #1685: `all` is checkov's documented-valid multi-framework value (also
|
|
273
|
+
# its own default scope). Hard-fail stays the default (no soft-fail
|
|
274
|
+
# flag passed): a real misconfiguration must block (INV-80).
|
|
275
|
+
checkov --directory . --framework all --quiet --compact
|
|
276
|
+
<% } -%>
|
|
277
|
+
# #1509 gold-align: Checkov scans for known misconfigurations; tflint is the
|
|
278
|
+
# Terraform-specific *linter* (provider-aware deprecations, invalid arg
|
|
279
|
+
# combinations, unused declarations). Reference-grade IaC pipelines run it
|
|
280
|
+
# BLOCKING — no soft-fail. `--recursive` exits 0 when the repo carries no
|
|
281
|
+
# `.tf` files, so non-Terraform infra changes (k8s/dockerfile) stay green.
|
|
282
|
+
- name: Setup tflint (Terraform linter)
|
|
283
|
+
uses: terraform-linters/setup-tflint@6e1e0642c0289bd619021bf6b34e3c08ed1e005a # v6.3.0
|
|
284
|
+
- name: tflint (Terraform lint, blocking)
|
|
285
|
+
run: tflint --recursive --no-color
|
|
286
|
+
<% } %>
|
|
287
|
+
<% if (language === 'typescript') { %>
|
|
288
|
+
<% const _tsNeeds=[]; if(enableSecurityScanning) _tsNeeds.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _tsNeeds.push('classify-changes'); %>
|
|
289
|
+
<% if (locals.ciPreTestBuild) { %> build-workspace:
|
|
290
|
+
name: Build Workspace (cache)
|
|
291
|
+
# E2 (#1500): build dist ONCE and share it run-id-keyed via the build-cache
|
|
292
|
+
# composite, instead of unit/contract/integration/behavioral each re-running
|
|
293
|
+
# `npm run build`. The composite's restore is non-blocking (cache miss ⇒ rebuild).
|
|
294
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
295
|
+
timeout-minutes: 60
|
|
296
|
+
<% { const _bwNeeds=[]; if(governanceLevel !== 'L1' || _multiLane) _bwNeeds.push('classify-changes'); if(_bwNeeds.length){ %> needs: [<%= _bwNeeds.join(', ') %>]
|
|
297
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
298
|
+
<% } } %> steps:
|
|
299
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
300
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
301
|
+
- name: Build + cache workspace (shared via run-id key)
|
|
302
|
+
uses: ./.github/actions/build-cache
|
|
303
|
+
with:
|
|
304
|
+
op: save
|
|
305
|
+
|
|
306
|
+
<% } %> gate:
|
|
307
|
+
name: Lint + Typecheck
|
|
308
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
309
|
+
timeout-minutes: 60
|
|
310
|
+
<% if(_tsNeeds.length){ %> needs: [<%= _tsNeeds.join(', ') %>]
|
|
311
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
312
|
+
<% } %> steps:
|
|
313
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
314
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
315
|
+
- run: npm run typecheck
|
|
316
|
+
- run: npm run lint
|
|
317
|
+
<% if (enableSecurityScanning) { %>
|
|
318
|
+
- name: Dep audit (INV-13)
|
|
319
|
+
run: npm audit --omit=dev --audit-level=high
|
|
320
|
+
<% } %>
|
|
321
|
+
|
|
322
|
+
<% if (!locals.enableNativeBakeE2E) { %> unit-tests:
|
|
323
|
+
name: Unit Tests
|
|
324
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
325
|
+
timeout-minutes: 60
|
|
326
|
+
needs: [gate<% if (language === 'typescript' && locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
327
|
+
strategy:
|
|
328
|
+
max-parallel: 2
|
|
329
|
+
<% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
330
|
+
<% } %> steps:
|
|
331
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
332
|
+
with:
|
|
333
|
+
# TDD evidence can name an older commit; reachability requires history.
|
|
334
|
+
fetch-depth: 0
|
|
335
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
336
|
+
<% if (locals.ciPreTestBuild) { %> - name: Restore cached workspace build (non-blocking)
|
|
337
|
+
uses: ./.github/actions/build-cache
|
|
338
|
+
with:
|
|
339
|
+
op: restore
|
|
340
|
+
- run: node scripts/build-kit.mjs
|
|
341
|
+
<% } %> - name: Install psmisc (fuser — #2098 gate-exec queue-depth advisory)
|
|
342
|
+
# scripts/lib/waiter-count.mjs shells out to `fuser` to count real flock
|
|
343
|
+
# waiters; unlike gitleaks/actionlint (single-binary GitHub-release
|
|
344
|
+
# tarballs, pinned in scripts/ci-tools.json), psmisc has no such release
|
|
345
|
+
# artifact, so apt is the install path here. flock itself (util-linux)
|
|
346
|
+
# is already present on the runner image; only fuser (psmisc) is missing.
|
|
347
|
+
# Root (self-hosted) uses apt-get directly; non-root (e.g. GitHub-hosted
|
|
348
|
+
# ubuntu-latest, where every consumer of this template lands by default)
|
|
349
|
+
# needs sudo. Skip entirely if fuser is already on PATH.
|
|
350
|
+
run: |
|
|
351
|
+
if ! command -v fuser >/dev/null 2>&1; then
|
|
352
|
+
if [ "$(id -u)" -eq 0 ]; then
|
|
353
|
+
apt-get update -qq && apt-get install -y -qq psmisc
|
|
354
|
+
else
|
|
355
|
+
sudo apt-get update -qq && sudo apt-get install -y -qq psmisc
|
|
356
|
+
fi
|
|
357
|
+
fi
|
|
358
|
+
# `--reporter=junit` ALONE replaces the console reporter, so a failing run
|
|
359
|
+
# names no test in the job log — the only record is the uploaded junit.xml,
|
|
360
|
+
# which is unreadable from a webhook or a log tail. Both reporters are
|
|
361
|
+
# passed so the log stays diagnosable and the artifact keeps its schema;
|
|
362
|
+
# `--outputFile.junit=` is the per-reporter form vitest requires once more
|
|
363
|
+
# than one reporter is active.
|
|
364
|
+
- run: npm run test:unit<% if (enableDebtGates) { %> -- --reporter=default --reporter=junit --outputFile.junit=test-results/junit.xml<% } %>
|
|
365
|
+
<% if (enableDebtGates) { %>
|
|
366
|
+
- name: Upload test results
|
|
367
|
+
id: upload-test-results
|
|
368
|
+
if: always()
|
|
369
|
+
# Supplementary artifact — never let an Artifacts-quota hiccup fail the
|
|
370
|
+
# job whose actual signal (the test run above) already passed.
|
|
371
|
+
continue-on-error: true
|
|
372
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
373
|
+
with:
|
|
374
|
+
name: test-results-unit-${{ github.run_id }}
|
|
375
|
+
path: test-results/
|
|
376
|
+
retention-days: 7
|
|
377
|
+
<% } %>
|
|
378
|
+
<% } -%>
|
|
379
|
+
<%# #1875: contract-tests/integration-tests/behavioral-tests moved OFF the
|
|
380
|
+
always-run T1 lane to 02-pr-extended.yml.ejs (T2, conditionally triggered).
|
|
381
|
+
They used to fan out from `gate` unconditionally on every PR — on arbiter's
|
|
382
|
+
own dogfooded CI, `contract-tests` alone measured ~12min, blowing the
|
|
383
|
+
15min T1 budget (ADR-090). docs/REFERENCE/ci-tier-workflows.md already
|
|
384
|
+
documented the "Extended gate" tier as the correct home for this suite;
|
|
385
|
+
the template just hadn't caught up. -%>
|
|
386
|
+
|
|
387
|
+
<% } %><% if (language === 'rust') { %>
|
|
388
|
+
gate:
|
|
389
|
+
name: Lint + Test (Rust)
|
|
390
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
391
|
+
timeout-minutes: 60
|
|
392
|
+
<% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
|
|
393
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
394
|
+
<% } } %> steps:
|
|
395
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
396
|
+
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
|
397
|
+
with:
|
|
398
|
+
components: clippy, rustfmt
|
|
399
|
+
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
400
|
+
- run: cargo fmt --check
|
|
401
|
+
- run: cargo clippy -- -D warnings
|
|
402
|
+
- run: cargo test
|
|
403
|
+
<% if (enableSecurityScanning) { %>
|
|
404
|
+
- name: Dep audit (INV-13)
|
|
405
|
+
uses: rustsec/audit-check@e9159ac5f7d7d873ce074ca134da2f445c0a4a61 # v1
|
|
406
|
+
with:
|
|
407
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
408
|
+
<% } %>
|
|
409
|
+
<% } %><% if (language === 'java') { %>
|
|
410
|
+
<% const _javaNeeds=[]; if(enableSecurityScanning) _javaNeeds.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _javaNeeds.push('classify-changes'); %>
|
|
411
|
+
<% /* #1278: build-reactor runs in PARALLEL with security-early-fail (not after it) to keep the maven critical path under the 15m T1 budget. security still HARD-blocks merge via ci-required, and `gate` (lint) still gates on it, preserving the early-fail signal on the lint lane. Tradeoff: wasted compile compute on a security-failing PR — not lost coverage or developer feedback. */ const _reactorNeeds=[]; if(governanceLevel !== 'L1' || _multiLane) _reactorNeeds.push('classify-changes'); %>
|
|
412
|
+
<% if (buildTool === 'maven') { %> build-reactor:
|
|
413
|
+
name: Build Maven Reactor (#1226)
|
|
414
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
415
|
+
permissions:
|
|
416
|
+
contents: read
|
|
417
|
+
<% if(_reactorNeeds.length){ %> needs: [<%= _reactorNeeds.join(', ') %>]
|
|
418
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
419
|
+
<% } %> steps:
|
|
420
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
421
|
+
- uses: ./.github/actions/setup-java-maven
|
|
422
|
+
- name: Pre-fetch plugins and dependencies (offline cache)
|
|
423
|
+
run: mvn dependency:go-offline --batch-mode -q
|
|
424
|
+
- name: Build reactor (compile main + test classes, skip test execution)
|
|
425
|
+
# -DskipTests runs the test-compile phase but skips execution, so
|
|
426
|
+
# target/classes and target/test-classes are produced once here and
|
|
427
|
+
# reused by every test job below — no per-job recompile (#1278).
|
|
428
|
+
run: mvn --batch-mode -DskipTests install
|
|
429
|
+
- name: Pack M2 repository + compiled target/ trees
|
|
430
|
+
# m2-reactor.tar stays byte-identical to its prior form (rooted at $HOME/.m2).
|
|
431
|
+
# target-reactor.tar is additive (#1278): every module's compiled target/
|
|
432
|
+
# (main + test classes) in its own tar rooted at the workspace, so downstream
|
|
433
|
+
# run-only test goals (surefire:test) never recompile.
|
|
434
|
+
run: |
|
|
435
|
+
mkdir -p "${{ runner.temp }}/.m2-reactor"
|
|
436
|
+
tar -cf "${{ runner.temp }}/.m2-reactor/m2-reactor.tar" -C "$HOME/.m2" repository
|
|
437
|
+
find . -type d -name target -prune -print0 \
|
|
438
|
+
| tar -cf "${{ runner.temp }}/.m2-reactor/target-reactor.tar" --null -T -
|
|
439
|
+
- name: Upload reactor M2 + target artifact
|
|
440
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
441
|
+
with:
|
|
442
|
+
name: reactor-m2-${{ github.run_id }}
|
|
443
|
+
path: ${{ runner.temp }}/.m2-reactor/*.tar
|
|
444
|
+
retention-days: 7
|
|
445
|
+
overwrite: true
|
|
446
|
+
|
|
447
|
+
<% } %> gate:
|
|
448
|
+
name: Lint (Java)
|
|
449
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
450
|
+
<% { const _gateNeeds=[..._javaNeeds]; if(buildTool === 'maven') _gateNeeds.push('build-reactor'); if(_gateNeeds.length){ %> needs: [<%= _gateNeeds.join(', ') %>]
|
|
451
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
452
|
+
<% } } %> steps:
|
|
453
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
454
|
+
- uses: ./.github/actions/setup-java-maven
|
|
455
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
456
|
+
- run: ./gradlew checkstyleMain
|
|
457
|
+
<%# E1 (#1502): Trivy fs (dep CVE) runs at nightly cadence in 06-nightly
|
|
458
|
+
`dep-cve-refresh`, not on the PR gate. The INV-13 dep-audit floor for java is
|
|
459
|
+
preserved there. -%>
|
|
460
|
+
<% } else { %> - name: Download reactor M2 artifact
|
|
461
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
462
|
+
with:
|
|
463
|
+
name: reactor-m2-${{ github.run_id }}
|
|
464
|
+
path: ${{ runner.temp }}/.m2-reactor
|
|
465
|
+
- run: mvn checkstyle:check --offline
|
|
466
|
+
<%# E1 (#1502): Trivy fs (dep CVE) runs at nightly cadence in 06-nightly `dep-cve-refresh`. -%>
|
|
467
|
+
<% } %>
|
|
468
|
+
|
|
469
|
+
unit-tests:
|
|
470
|
+
name: Unit Tests (Java)
|
|
471
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
472
|
+
timeout-minutes: 60
|
|
473
|
+
<% if(buildTool === 'maven'){ /* tests need compiled classes from build-reactor, not lint; off the gate hop (#1278) */ %> needs: [build-reactor<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
474
|
+
<% } else { %> needs: [gate<% if (language === 'typescript' && locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
475
|
+
<% } %> strategy:
|
|
476
|
+
max-parallel: 2
|
|
477
|
+
<% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
478
|
+
<% } %> steps:
|
|
479
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
480
|
+
- uses: ./.github/actions/setup-java-maven
|
|
481
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
482
|
+
- run: ./gradlew test
|
|
483
|
+
<% if (enableDebtGates) { %>
|
|
484
|
+
- name: Upload test results
|
|
485
|
+
id: upload-test-results
|
|
486
|
+
if: always()
|
|
487
|
+
# Supplementary artifact — never let an Artifacts-quota hiccup fail the
|
|
488
|
+
# job whose actual signal (the test run above) already passed.
|
|
489
|
+
continue-on-error: true
|
|
490
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
491
|
+
with:
|
|
492
|
+
name: test-results-unit-${{ github.run_id }}
|
|
493
|
+
path: build/test-results/
|
|
494
|
+
retention-days: 7
|
|
495
|
+
<% } %>
|
|
496
|
+
<% } else { %> - name: Download reactor M2 artifact
|
|
497
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
498
|
+
with:
|
|
499
|
+
name: reactor-m2-${{ github.run_id }}
|
|
500
|
+
path: ${{ runner.temp }}/.m2-reactor
|
|
501
|
+
- run: mvn surefire:test -Punit --offline
|
|
502
|
+
<% if (enableDebtGates) { %>
|
|
503
|
+
- name: Upload test results
|
|
504
|
+
id: upload-test-results
|
|
505
|
+
if: always()
|
|
506
|
+
# Supplementary artifact — never let an Artifacts-quota hiccup fail the
|
|
507
|
+
# job whose actual signal (the test run above) already passed.
|
|
508
|
+
continue-on-error: true
|
|
509
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
510
|
+
with:
|
|
511
|
+
name: test-results-unit-${{ github.run_id }}
|
|
512
|
+
path: target/surefire-reports/
|
|
513
|
+
retention-days: 7
|
|
514
|
+
<% } %>
|
|
515
|
+
<% } %>
|
|
516
|
+
|
|
517
|
+
<% if (governanceLevel !== 'L1') { %> archunit-tests:
|
|
518
|
+
name: ArchUnit Architecture Tests (Java)
|
|
519
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
520
|
+
timeout-minutes: 30
|
|
521
|
+
# #1512 gold-align: the lightweight *ArchTest JUnit5 architecture rules
|
|
522
|
+
# (dependency-direction / layering / package-boundary) run BLOCKING on EVERY PR.
|
|
523
|
+
# Previously they ran only on the weekly 13-archunit-extended cron, leaving up to a
|
|
524
|
+
# 7-day fake-green window for a merged architecture regression. The heavier
|
|
525
|
+
# full module-graph analysis (the Modulith suite) stays on that weekly cron.
|
|
526
|
+
<% if(buildTool === 'maven'){ %> needs: [build-reactor<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
527
|
+
<% } else { %> needs: [gate<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
528
|
+
<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
529
|
+
<% } %> steps:
|
|
530
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
531
|
+
- uses: ./.github/actions/setup-java-maven
|
|
532
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
533
|
+
- run: ./gradlew test --tests "*ArchTest"
|
|
534
|
+
<% } else { %> - name: Download reactor M2 artifact
|
|
535
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
536
|
+
with:
|
|
537
|
+
name: reactor-m2-${{ github.run_id }}
|
|
538
|
+
path: ${{ runner.temp }}/.m2-reactor
|
|
539
|
+
- run: mvn surefire:test -Dtest="*ArchTest" --offline
|
|
540
|
+
<% } %>
|
|
541
|
+
<% } %>
|
|
542
|
+
<%# #1875: contract-tests/integration-tests/behavioral-tests (Java) moved OFF
|
|
543
|
+
the always-run T1 lane to 02-pr-extended.yml.ejs (T2, conditionally
|
|
544
|
+
triggered) — mirrors the TypeScript move above. -%>
|
|
545
|
+
|
|
546
|
+
<% } %><% if (language === 'go') { %>
|
|
547
|
+
gate:
|
|
548
|
+
name: Lint + Test (Go)
|
|
549
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
550
|
+
timeout-minutes: 60
|
|
551
|
+
<% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
|
|
552
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
553
|
+
<% } } %> steps:
|
|
554
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
555
|
+
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
|
556
|
+
with:
|
|
557
|
+
go-version-file: 'go.mod'
|
|
558
|
+
- run: go vet ./...
|
|
559
|
+
- run: golangci-lint run
|
|
560
|
+
- run: go test ./... -race -coverprofile=coverage.out
|
|
561
|
+
<% if (enableSecurityScanning) { %>
|
|
562
|
+
- name: Dep audit govulncheck (INV-13)
|
|
563
|
+
uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1
|
|
564
|
+
with:
|
|
565
|
+
# The action re-checkouts by default; after the explicit checkout above the
|
|
566
|
+
# second internal checkout adds a duplicate Authorization extraheader and
|
|
567
|
+
# git fails with 400 "Duplicate header" on private repos (#1865).
|
|
568
|
+
repo-checkout: false
|
|
569
|
+
<% } %>
|
|
570
|
+
<% } %><% if (language === 'python') { %>
|
|
571
|
+
gate:
|
|
572
|
+
name: Lint + Test (Python)
|
|
573
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
574
|
+
timeout-minutes: 60
|
|
575
|
+
<% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
|
|
576
|
+
<% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
577
|
+
<% } } %> steps:
|
|
578
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
579
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
580
|
+
with:
|
|
581
|
+
python-version: '3.12'
|
|
582
|
+
cache: 'pip'
|
|
583
|
+
- run: pip install -e ".[dev]"
|
|
584
|
+
- run: ruff check .
|
|
585
|
+
- run: ruff format --check .
|
|
586
|
+
- run: pytest --cov --junitxml=test-results/junit.xml
|
|
587
|
+
<% if (enableSecurityScanning) { %>
|
|
588
|
+
- name: Dep audit (INV-13)
|
|
589
|
+
run: pip-audit
|
|
590
|
+
<% } %>
|
|
591
|
+
<% if (enableDebtGates) { %>
|
|
592
|
+
- name: Upload test results
|
|
593
|
+
id: upload-test-results
|
|
594
|
+
if: always()
|
|
595
|
+
# Supplementary artifact — never let an Artifacts-quota hiccup fail the
|
|
596
|
+
# job whose actual signal (the test run above) already passed.
|
|
597
|
+
continue-on-error: true
|
|
598
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
599
|
+
with:
|
|
600
|
+
name: test-results-${{ github.run_id }}
|
|
601
|
+
path: test-results/
|
|
602
|
+
retention-days: 7
|
|
603
|
+
<% } %>
|
|
604
|
+
<% } %>
|
|
605
|
+
|
|
606
|
+
<% if (governanceLevel !== 'L1') { %>
|
|
607
|
+
docs-check:
|
|
608
|
+
name: Docs Check
|
|
609
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
610
|
+
timeout-minutes: 60
|
|
611
|
+
if: github.event_name == 'pull_request'
|
|
612
|
+
steps:
|
|
613
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
614
|
+
with:
|
|
615
|
+
fetch-depth: 0
|
|
616
|
+
- name: Check docs updated with code changes
|
|
617
|
+
env:
|
|
618
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
619
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
620
|
+
run: |
|
|
621
|
+
# #356: rebased-aware via merge-base; bypass via [skip-docs] commit token.
|
|
622
|
+
MB=$(git merge-base "$BASE_SHA" "$HEAD_SHA" || echo "$BASE_SHA")
|
|
623
|
+
CHANGED=$(git diff --name-only "$MB" "$HEAD_SHA")
|
|
624
|
+
LOG=$(git log --format=%B "$MB..$HEAD_SHA" || true)
|
|
625
|
+
|
|
626
|
+
HAS_CODE=$(echo "$CHANGED" | grep -E '^(src/|__tests__/)' || true)
|
|
627
|
+
HAS_DOCS=$(echo "$CHANGED" | grep -E '^(docs/|README\.md)' || true)
|
|
628
|
+
BYPASS=$(echo "$LOG" | grep -F '[skip-docs]' || true)
|
|
629
|
+
|
|
630
|
+
if [ -n "$HAS_CODE" ] && [ -z "$HAS_DOCS" ] && [ -z "$BYPASS" ]; then
|
|
631
|
+
echo "::error::Code changed without documentation update"
|
|
632
|
+
echo ""
|
|
633
|
+
echo "Files changed in src/ or __tests__/:"
|
|
634
|
+
echo "$HAS_CODE"
|
|
635
|
+
echo ""
|
|
636
|
+
echo "Please update docs/ or README.md, or add [skip-docs] to a commit message to bypass."
|
|
637
|
+
exit 1
|
|
638
|
+
fi
|
|
639
|
+
echo "Docs check passed."
|
|
640
|
+
<% } %>
|
|
641
|
+
|
|
642
|
+
<% if (enableDebtGates) { %>
|
|
643
|
+
debt-gates:
|
|
644
|
+
name: Tech Debt Gates
|
|
645
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
646
|
+
timeout-minutes: 60
|
|
647
|
+
needs: [gate]
|
|
648
|
+
# E1 (#1502): the PR leg keeps only the FAST static-analysis gates
|
|
649
|
+
# (knip/madge/pmd/spotbugs/clippy/ruff/golangci). The whole-suite coverage
|
|
650
|
+
# re-run that used to live here was a SECOND full test execution on the PR
|
|
651
|
+
# (the unit/integration jobs already ran the suite, and `gate-full` runs
|
|
652
|
+
# check-all L2 which enforces the coverage threshold). The threshold floor is
|
|
653
|
+
# therefore preserved on PR via gate-full; the heavy coverage report (HTML/lcov
|
|
654
|
+
# artifact) is produced at nightly cadence in 06-nightly `coverage-report`.
|
|
655
|
+
steps:
|
|
656
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
657
|
+
<% if (language === 'typescript') { %>
|
|
658
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
659
|
+
<% if (locals.ciPreTestBuild) { %> - run: npm run build && node scripts/build-kit.mjs
|
|
660
|
+
<% } %> - run: npx knip
|
|
661
|
+
- run: npx madge --circular --extensions ts,tsx,js,jsx src
|
|
662
|
+
<% } %><% if (language === 'rust') { %>
|
|
663
|
+
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
|
664
|
+
with:
|
|
665
|
+
components: clippy
|
|
666
|
+
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
667
|
+
- run: cargo clippy -- -W clippy::pedantic -D warnings
|
|
668
|
+
<% } %><% if (language === 'java') { %>
|
|
669
|
+
- uses: ./.github/actions/setup-java-maven
|
|
670
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
671
|
+
- run: ./gradlew pmdMain
|
|
672
|
+
- run: ./gradlew spotbugsMain
|
|
673
|
+
<% } else { %> - name: Download reactor M2 artifact
|
|
674
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
675
|
+
with:
|
|
676
|
+
name: reactor-m2-${{ github.run_id }}
|
|
677
|
+
path: ${{ runner.temp }}/.m2-reactor
|
|
678
|
+
- run: mvn pmd:check --offline
|
|
679
|
+
- run: mvn spotbugs:check --offline
|
|
680
|
+
<% } %><% } %><% if (language === 'go') { %>
|
|
681
|
+
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
|
682
|
+
with:
|
|
683
|
+
go-version-file: 'go.mod'
|
|
684
|
+
- run: golangci-lint run --enable gocyclo,gocognit,deadcode,unused
|
|
685
|
+
<% } %><% if (language === 'python') { %>
|
|
686
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
687
|
+
with:
|
|
688
|
+
python-version: '3.12'
|
|
689
|
+
cache: 'pip'
|
|
690
|
+
- run: pip install -e ".[dev]"
|
|
691
|
+
- run: ruff check --select C901,PLR0911,PLR0912,PLR0913,PLR0915 .
|
|
692
|
+
- run: ruff check --select F401,F811 .
|
|
693
|
+
<% } %>
|
|
694
|
+
<% } %>
|
|
695
|
+
|
|
696
|
+
<% if (governanceLevel !== 'L1') { %>
|
|
697
|
+
sonar-scan:
|
|
698
|
+
name: SonarCloud Scan
|
|
699
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
700
|
+
timeout-minutes: 60
|
|
701
|
+
needs: [gate]
|
|
702
|
+
steps:
|
|
703
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
704
|
+
with:
|
|
705
|
+
fetch-depth: 0
|
|
706
|
+
<% if (language === 'java') { %>
|
|
707
|
+
- uses: ./.github/actions/setup-java-maven
|
|
708
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
709
|
+
<% } %><% } else if (language === 'typescript') { %>
|
|
710
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
711
|
+
<% } %>
|
|
712
|
+
<% const _sonarCmd = (language === 'java' && buildTool === 'gradle') ? './gradlew sonarqube' : (language === 'java') ? 'mvn sonar:sonar' : 'npx sonar-scanner'; %>
|
|
713
|
+
- name: SonarCloud Scan (PR decoration — incremental new-code analysis)
|
|
714
|
+
# E1 (#1502): on PRs Sonar runs in pull-request mode — it decorates the PR
|
|
715
|
+
# with new-code findings only (incremental), NOT a full deep scan. The full
|
|
716
|
+
# branch baseline runs on merge-to-main below and nightly (06-nightly
|
|
717
|
+
# `sonar-deep-scan`), keeping the PR path fast.
|
|
718
|
+
if: env.SONAR_TOKEN != '' && github.event_name == 'pull_request'
|
|
719
|
+
env:
|
|
720
|
+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
721
|
+
# untrusted refs pass through env (never inlined into the script body).
|
|
722
|
+
PR_KEY: ${{ github.event.pull_request.number }}
|
|
723
|
+
PR_BRANCH: ${{ github.head_ref }}
|
|
724
|
+
PR_BASE: ${{ github.base_ref }}
|
|
725
|
+
run: |
|
|
726
|
+
<%= _sonarCmd %> -Dsonar.token="$SONAR_TOKEN" \
|
|
727
|
+
-Dsonar.pullrequest.key="$PR_KEY" \
|
|
728
|
+
-Dsonar.pullrequest.branch="$PR_BRANCH" \
|
|
729
|
+
-Dsonar.pullrequest.base="$PR_BASE"
|
|
730
|
+
- name: SonarCloud Scan (full branch baseline)
|
|
731
|
+
# Push to a long-lived branch refreshes the full-project baseline so the
|
|
732
|
+
# PR decoration above has a fresh reference to diff new code against.
|
|
733
|
+
if: env.SONAR_TOKEN != '' && github.event_name != 'pull_request'
|
|
734
|
+
env:
|
|
735
|
+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
736
|
+
run: |
|
|
737
|
+
<%= _sonarCmd %> -Dsonar.token="$SONAR_TOKEN"
|
|
738
|
+
<% } %>
|
|
739
|
+
|
|
740
|
+
<% if (contractType && contractType !== 'none' && governanceLevel !== 'L1') { %>
|
|
741
|
+
|
|
742
|
+
contract-verify:
|
|
743
|
+
name: Contract Verify
|
|
744
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
745
|
+
timeout-minutes: 60
|
|
746
|
+
needs: [gate]
|
|
747
|
+
steps:
|
|
748
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
749
|
+
<% if (language === 'typescript') { %>
|
|
750
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
751
|
+
<% if (contractType === 'rest-owned' || contractType === 'rest-public') { %>
|
|
752
|
+
- name: Run Pact contract tests
|
|
753
|
+
if: vars.PACT_BROKER_BASE_URL != ''
|
|
754
|
+
run: npx pact-broker can-i-deploy --pacticipant <%= projectName %> --latest
|
|
755
|
+
env:
|
|
756
|
+
PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
|
|
757
|
+
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
758
|
+
<% } else if (contractType === 'graphql') { %>
|
|
759
|
+
- name: Run GraphQL schema contract tests
|
|
760
|
+
run: npx graphql-inspector diff schema.graphql
|
|
761
|
+
<% } else if (contractType === 'grpc') { %>
|
|
762
|
+
- name: Run gRPC contract tests
|
|
763
|
+
run: npx buf breaking --against .git#branch=main
|
|
764
|
+
<% } else if (contractType === 'message-queue') { %>
|
|
765
|
+
- name: Run Pact messaging contract tests
|
|
766
|
+
if: vars.PACT_BROKER_BASE_URL != ''
|
|
767
|
+
run: npx pact-broker can-i-deploy --pacticipant <%= projectName %> --latest
|
|
768
|
+
env:
|
|
769
|
+
PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
|
|
770
|
+
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
771
|
+
<% } %>
|
|
772
|
+
<% } else if (language === 'java') { %>
|
|
773
|
+
- uses: ./.github/actions/setup-java-maven
|
|
774
|
+
<% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
|
|
775
|
+
<% } %>
|
|
776
|
+
<% if (contractType === 'rest-owned' || contractType === 'rest-public' || contractType === 'message-queue') { %>
|
|
777
|
+
- name: Run Pact contract tests
|
|
778
|
+
if: vars.PACT_BROKER_BASE_URL != ''
|
|
779
|
+
run: <%= buildTool === 'gradle' ? './gradlew pactPublish pactVerify' : 'mvn pact:publish pact:verify' %>
|
|
780
|
+
env:
|
|
781
|
+
PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
|
|
782
|
+
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
783
|
+
<% } else if (contractType === 'graphql') { %>
|
|
784
|
+
- name: Run GraphQL contract tests
|
|
785
|
+
run: <%= buildTool === 'gradle' ? './gradlew test --tests *.graphql.*' : 'mvn test -Dtest=*GraphQL*' %>
|
|
786
|
+
<% } else if (contractType === 'grpc') { %>
|
|
787
|
+
- name: Run gRPC contract tests
|
|
788
|
+
run: <%= buildTool === 'gradle' ? './gradlew test --tests *.grpc.*' : 'mvn test -Dtest=*Grpc*' %>
|
|
789
|
+
<% } %>
|
|
790
|
+
<% } else if (language === 'rust') { %>
|
|
791
|
+
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
|
792
|
+
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
|
793
|
+
- name: Run contract tests
|
|
794
|
+
run: cargo test --test '*contract*'
|
|
795
|
+
<% } else if (language === 'go') { %>
|
|
796
|
+
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
|
797
|
+
with:
|
|
798
|
+
go-version-file: 'go.mod'
|
|
799
|
+
- name: Run contract tests
|
|
800
|
+
run: go test -tags contract -run Contract ./...
|
|
801
|
+
<% } else if (language === 'python') { %>
|
|
802
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
803
|
+
with:
|
|
804
|
+
python-version: '3.12'
|
|
805
|
+
cache: 'pip'
|
|
806
|
+
- run: pip install -e ".[dev]"
|
|
807
|
+
- name: Run contract tests
|
|
808
|
+
run: pytest tests/contract/
|
|
809
|
+
<% } %>
|
|
810
|
+
<% } %>
|
|
811
|
+
<% if (governanceLevel !== 'L1') { %>
|
|
812
|
+
gate-full:
|
|
813
|
+
name: Full Gate (L2, INV-59)
|
|
814
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
815
|
+
<% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); _n.push('classify-changes'); %>
|
|
816
|
+
needs: [<%= _n.join(', ') %>]
|
|
817
|
+
if: needs.classify-changes.outputs.docs_only != 'true'
|
|
818
|
+
<% } %>
|
|
819
|
+
timeout-minutes: 60
|
|
820
|
+
steps:
|
|
821
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
822
|
+
with:
|
|
823
|
+
fetch-depth: 0
|
|
824
|
+
<% if (language === 'typescript') { %>
|
|
825
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
826
|
+
<% } else { %>
|
|
827
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
828
|
+
with:
|
|
829
|
+
node-version-file: '.nvmrc'
|
|
830
|
+
package-manager-cache: false
|
|
831
|
+
<% } %>
|
|
832
|
+
- name: Install gitleaks
|
|
833
|
+
run: |
|
|
834
|
+
mkdir -p "$RUNNER_TEMP/bin"
|
|
835
|
+
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.27.2/gitleaks_8.27.2_linux_x64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" gitleaks
|
|
836
|
+
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
|
|
837
|
+
- name: Install actionlint
|
|
838
|
+
run: |
|
|
839
|
+
mkdir -p "$RUNNER_TEMP/bin"
|
|
840
|
+
curl -sSfL https://github.com/rhysd/actionlint/releases/download/v1.7.3/actionlint_1.7.3_linux_amd64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" actionlint
|
|
841
|
+
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
|
|
842
|
+
- name: Install psmisc (fuser — #2098 gate-exec queue-depth advisory)
|
|
843
|
+
# Mirrors the identical step in the Unit Tests job (see there for the
|
|
844
|
+
# full rationale) so this job's own gate-exec queue-depth advisory
|
|
845
|
+
# works too, independent of whether Unit Tests already ran on this
|
|
846
|
+
# runner. For arbiter's own repo, `check-all.mjs L2` below also runs
|
|
847
|
+
# the waiter-count/gate-exec test suite directly.
|
|
848
|
+
run: |
|
|
849
|
+
if ! command -v fuser >/dev/null 2>&1; then
|
|
850
|
+
if [ "$(id -u)" -eq 0 ]; then
|
|
851
|
+
apt-get update -qq && apt-get install -y -qq psmisc
|
|
852
|
+
else
|
|
853
|
+
sudo apt-get update -qq && sudo apt-get install -y -qq psmisc
|
|
854
|
+
fi
|
|
855
|
+
fi
|
|
856
|
+
- name: Build
|
|
857
|
+
run: npm run build<% if (locals.ciPreTestBuild) { %> && node scripts/build-kit.mjs<% } %>
|
|
858
|
+
- name: Gate-spine erosion ratchet (#2291)
|
|
859
|
+
# DELIBERATELY its own step, ahead of and independent of check-all.mjs.
|
|
860
|
+
# This gate fails when `arbiter update` had to WITHHOLD a protected file —
|
|
861
|
+
# most importantly scripts/check-all.mjs itself, the file where this project
|
|
862
|
+
# wires its own checks. Registering it only in gate-registry.yml would deliver
|
|
863
|
+
# it through scripts/check-all.mjs, i.e. through the very file being withheld:
|
|
864
|
+
# on a project whose spine is frozen the ratchet would never run, and the
|
|
865
|
+
# erosion it exists to catch would stay invisible for exactly as long as it
|
|
866
|
+
# matters. Workflows are arbiter-owned and are not withheld, so this step
|
|
867
|
+
# reaches a frozen consumer. Do not fold it into the gate step below.
|
|
868
|
+
run: node scripts/check-safety-adopt-ratchet.mjs
|
|
869
|
+
- name: Run full L2 gate (== pre-push)
|
|
870
|
+
run: node scripts/check-all.mjs L2 --json gate-result.json
|
|
871
|
+
- name: Upload gate-result artifact (activates INV-59 runtime parity)
|
|
872
|
+
id: upload-gate-result
|
|
873
|
+
if: always()
|
|
874
|
+
# check-local-ci-parity.mjs already treats a missing gate-result artifact
|
|
875
|
+
# as a graceful skip, not a hard failure — an Artifacts-quota hiccup on
|
|
876
|
+
# this upload must not fail the job the real gate already ran in.
|
|
877
|
+
continue-on-error: true
|
|
878
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
879
|
+
with:
|
|
880
|
+
name: gate-result
|
|
881
|
+
path: gate-result.json
|
|
882
|
+
retention-days: 7
|
|
883
|
+
<% } %>
|
|
884
|
+
|
|
885
|
+
<% if (_humanApproval) { %> human-approval-required:
|
|
886
|
+
name: Human Approval Required (INV-74)
|
|
887
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
888
|
+
if: github.event_name == 'pull_request'
|
|
889
|
+
steps:
|
|
890
|
+
- name: Assert approved-by-human label (anti-bot gate)
|
|
891
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
892
|
+
with:
|
|
893
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
894
|
+
script: |
|
|
895
|
+
const labels = context.payload.pull_request.labels.map(l => l.name);
|
|
896
|
+
if (!labels.includes('approved-by-human')) {
|
|
897
|
+
core.setFailed(
|
|
898
|
+
'PR requires the "approved-by-human" label applied by a human reviewer. ' +
|
|
899
|
+
'See 03-human-approval.yml — a bot approval does not satisfy this check.'
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
<% } %>
|
|
903
|
+
<% if (language === 'typescript' && locals.enableNativeBakeE2E) { %> generated-gate-min:
|
|
904
|
+
name: Generated-gate min cell (TS, the gate-thesis on every PR)
|
|
905
|
+
# B5 (arbiter audit, gate-thesis reliability): arbiter's core promise —
|
|
906
|
+
# `arbiter init` on a project → the GENERATED project's own gate is green out
|
|
907
|
+
# of the box — was proven only nightly (generated-gate-e2e in _nightly.yml,
|
|
908
|
+
# VITEST_L2=1) or weekly (generator-matrix.yml). A regression in that promise
|
|
909
|
+
# could land on main and ride unnoticed for up to 24h. This is the minimal,
|
|
910
|
+
# fast slice of that same proof (ts-backend-web-db + ts-library — the two
|
|
911
|
+
# TypeScript functional-tier fixtures, ~25-30s locally) promoted to a
|
|
912
|
+
# PR-required check so the thesis is verified on every merge, not just at
|
|
913
|
+
# night. The other 4 languages' cells stay nightly-only (their toolchain
|
|
914
|
+
# install cost does not belong on the always-path of every PR). Self-only
|
|
915
|
+
# (enableNativeBakeE2E): downstream-generated projects do not ship arbiter's
|
|
916
|
+
# own __tests__/fixtures/real-projects/ harness, so this never renders for them.
|
|
917
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
918
|
+
timeout-minutes: 15
|
|
919
|
+
needs: [gate<% if (locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
|
|
920
|
+
<% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
|
|
921
|
+
<% } %> steps:
|
|
922
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
923
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
924
|
+
<% if (locals.ciPreTestBuild) { %> - name: Restore cached workspace build (non-blocking)
|
|
925
|
+
uses: ./.github/actions/build-cache
|
|
926
|
+
with:
|
|
927
|
+
op: restore
|
|
928
|
+
- run: node scripts/build-kit.mjs
|
|
929
|
+
<% } %> - name: Generated-gate e2e — TypeScript cell (VITEST_L2=1)
|
|
930
|
+
env:
|
|
931
|
+
VITEST_L2: "1"
|
|
932
|
+
run: |
|
|
933
|
+
npx vitest run --config vitest.integration.config.ts \
|
|
934
|
+
__tests__/integration/e2e/functional/fixture-functional.test.ts \
|
|
935
|
+
-t typescript
|
|
936
|
+
|
|
937
|
+
<% } %> ci-required:
|
|
938
|
+
name: CI Required
|
|
939
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
940
|
+
timeout-minutes: 60
|
|
941
|
+
<%
|
|
942
|
+
const _ciNeeds = ['gate'];
|
|
943
|
+
if (_humanApproval) _ciNeeds.push('human-approval-required');
|
|
944
|
+
if (language === 'java' && buildTool === 'maven') _ciNeeds.push('build-reactor');
|
|
945
|
+
// #1875: contract-tests/integration-tests/behavioral-tests moved to the T2
|
|
946
|
+
// (02-pr-extended) conditional lane — only unit-tests stays on the always-run
|
|
947
|
+
// T1 path.
|
|
948
|
+
if ((language === 'typescript' || language === 'java') && !locals.enableNativeBakeE2E) {
|
|
949
|
+
_ciNeeds.push('unit-tests');
|
|
950
|
+
}
|
|
951
|
+
if (language === 'typescript' && locals.enableNativeBakeE2E) _ciNeeds.push('generated-gate-min');
|
|
952
|
+
// #1512: the per-PR ArchUnit (*ArchTest) lane is a BLOCKING required check for Java L2+.
|
|
953
|
+
if (language === 'java' && governanceLevel !== 'L1') _ciNeeds.push('archunit-tests');
|
|
954
|
+
if (enableSecurityScanning) _ciNeeds.push('security-early-fail', 'dependency-review');
|
|
955
|
+
if (governanceLevel !== 'L1' || _multiLane) _ciNeeds.push('iac-scan');
|
|
956
|
+
if (governanceLevel !== 'L1') _ciNeeds.push('docs-check', 'sonar-scan', 'gate-full');
|
|
957
|
+
if (enableDebtGates) _ciNeeds.push('debt-gates');
|
|
958
|
+
if (contractType && contractType !== 'none' && governanceLevel !== 'L1') _ciNeeds.push('contract-verify');
|
|
959
|
+
if (governanceLevel !== 'L1' || _multiLane) _ciNeeds.push('classify-changes');
|
|
960
|
+
if (_multiLane) _ciNeeds.push('cross-stack-guard');
|
|
961
|
+
%>
|
|
962
|
+
<%
|
|
963
|
+
// #1296 — docs-only PRs SKIP the code jobs (classify-changes gating); the
|
|
964
|
+
// aggregator accepts `skipped` for those jobs ONLY under docs_only=true, and
|
|
965
|
+
// requires the classification itself to have succeeded (fail-closed).
|
|
966
|
+
const _hasClassify = (governanceLevel !== 'L1' || _multiLane);
|
|
967
|
+
%> needs: [<%= _ciNeeds.join(', ') %>]
|
|
968
|
+
if: always()
|
|
969
|
+
steps:
|
|
970
|
+
<% if (_hasClassify) { %> - env:
|
|
971
|
+
DOCS_ONLY: ${{ needs.classify-changes.outputs.docs_only }}
|
|
972
|
+
run: |
|
|
973
|
+
<% } else { %> - run: |
|
|
974
|
+
<% } %>
|
|
975
|
+
<% if (_hasClassify) { %> if [[ "${{ needs.classify-changes.result }}" != "success" ]]; then
|
|
976
|
+
echo "classify-changes failed — cannot trust docs_only, failing closed"
|
|
977
|
+
exit 1
|
|
978
|
+
fi
|
|
979
|
+
# success, or skipped ONLY when the docs-only classification skipped the job
|
|
980
|
+
ok() { [[ "$1" == "success" || ( "$DOCS_ONLY" == "true" && "$1" == "skipped" ) ]]; }
|
|
981
|
+
<% } else { %> ok() { [[ "$1" == "success" ]]; }
|
|
982
|
+
<% } %> if ! ok "${{ needs.gate.result }}"; then
|
|
983
|
+
echo "gate failed"
|
|
984
|
+
exit 1
|
|
985
|
+
fi
|
|
986
|
+
<% if (language === 'java' && buildTool === 'maven') { %>
|
|
987
|
+
if ! ok "${{ needs.build-reactor.result }}"; then
|
|
988
|
+
echo "build-reactor failed"
|
|
989
|
+
exit 1
|
|
990
|
+
fi
|
|
991
|
+
<% } if ((language === 'typescript' || language === 'java') && !locals.enableNativeBakeE2E) { %>
|
|
992
|
+
if ! ok "${{ needs.unit-tests.result }}"; then
|
|
993
|
+
echo "unit-tests failed"
|
|
994
|
+
exit 1
|
|
995
|
+
fi
|
|
996
|
+
<% } %><% if (language === 'typescript' && locals.enableNativeBakeE2E) { %>
|
|
997
|
+
if ! ok "${{ needs.generated-gate-min.result }}"; then
|
|
998
|
+
echo "generated-gate-min failed — the generated-project gate-thesis cell is red"
|
|
999
|
+
exit 1
|
|
1000
|
+
fi
|
|
1001
|
+
<% } %><% if (language === 'java' && governanceLevel !== 'L1') { %>
|
|
1002
|
+
if ! ok "${{ needs.archunit-tests.result }}"; then
|
|
1003
|
+
echo "archunit-tests failed"
|
|
1004
|
+
exit 1
|
|
1005
|
+
fi
|
|
1006
|
+
<% } %><% if (enableSecurityScanning) { %>
|
|
1007
|
+
if [[ "${{ needs.security-early-fail.result }}" != "success" ]]; then
|
|
1008
|
+
echo "security-early-fail failed"
|
|
1009
|
+
exit 1
|
|
1010
|
+
fi
|
|
1011
|
+
# dependency-review skips on push (PR-only) — only a real finding blocks.
|
|
1012
|
+
if [[ "${{ needs.dependency-review.result }}" == "failure" ]]; then
|
|
1013
|
+
echo "dependency-review failed — a newly-introduced dependency exceeds the severity floor"
|
|
1014
|
+
exit 1
|
|
1015
|
+
fi<% } %><% if (_hasClassify) { %>
|
|
1016
|
+
# iac-scan skips when no infra changed — only a real IaC finding blocks.
|
|
1017
|
+
if [[ "${{ needs.iac-scan.result }}" == "failure" ]]; then
|
|
1018
|
+
echo "iac-scan failed — an infrastructure-as-code misconfiguration was found"
|
|
1019
|
+
exit 1
|
|
1020
|
+
fi<% } %><% if (governanceLevel !== 'L1') { %>
|
|
1021
|
+
if [[ "${{ needs.docs-check.result }}" == "failure" ]]; then
|
|
1022
|
+
echo "docs-check failed"
|
|
1023
|
+
exit 1
|
|
1024
|
+
fi
|
|
1025
|
+
if [[ "${{ needs.sonar-scan.result }}" == "failure" ]]; then
|
|
1026
|
+
echo "sonar-scan failed"
|
|
1027
|
+
exit 1
|
|
1028
|
+
fi<% } %><% if (enableDebtGates) { %>
|
|
1029
|
+
if ! ok "${{ needs.debt-gates.result }}"; then
|
|
1030
|
+
echo "debt-gates failed"
|
|
1031
|
+
exit 1
|
|
1032
|
+
fi
|
|
1033
|
+
<% } %><% if (governanceLevel !== 'L1') { %>
|
|
1034
|
+
if [[ "${{ needs.gate-full.result }}" != "success" && "${{ needs.gate-full.result }}" != "skipped" ]]; then
|
|
1035
|
+
echo "gate-full (L2) failed or was cancelled"
|
|
1036
|
+
exit 1
|
|
1037
|
+
fi<% } %><% if (contractType && contractType !== 'none' && governanceLevel !== 'L1') { %>
|
|
1038
|
+
if ! ok "${{ needs.contract-verify.result }}"; then
|
|
1039
|
+
echo "contract-verify failed"
|
|
1040
|
+
exit 1
|
|
1041
|
+
fi<% } %><% if (_multiLane) { %>
|
|
1042
|
+
if [[ "${{ needs.cross-stack-guard.result }}" == "failure" ]]; then
|
|
1043
|
+
echo "cross-stack-guard failed"
|
|
1044
|
+
exit 1
|
|
1045
|
+
fi<% } %>
|
|
1046
|
+
<% if (_humanApproval) { %> if [[ "${{ needs.human-approval-required.result }}" == "failure" ]]; then
|
|
1047
|
+
echo "human-approval-required failed — PR needs approved-by-human label"
|
|
1048
|
+
exit 1
|
|
1049
|
+
fi
|
|
1050
|
+
<% } %>
|
|
1051
|
+
<% if (governanceLevel !== 'L1') { %>
|
|
1052
|
+
post-merge-gate:
|
|
1053
|
+
name: D4-LITE post-merge gate (main)
|
|
1054
|
+
needs: [classify-changes, gate-full]
|
|
1055
|
+
if: >
|
|
1056
|
+
always() &&
|
|
1057
|
+
github.event_name == 'push' &&
|
|
1058
|
+
github.ref == 'refs/heads/main' &&
|
|
1059
|
+
needs.classify-changes.result == 'success' &&
|
|
1060
|
+
needs.classify-changes.outputs.docs_only != 'true'
|
|
1061
|
+
runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
|
|
1062
|
+
timeout-minutes: 60
|
|
1063
|
+
steps:
|
|
1064
|
+
- name: Verify Full Gate outcome
|
|
1065
|
+
env:
|
|
1066
|
+
GATE_FULL_RESULT: ${{ needs.gate-full.result }}
|
|
1067
|
+
run: |
|
|
1068
|
+
if [[ "$GATE_FULL_RESULT" == "success" ]]; then
|
|
1069
|
+
exit 0
|
|
1070
|
+
fi
|
|
1071
|
+
echo "Full Gate result was $GATE_FULL_RESULT; D4 fails closed." >&2
|
|
1072
|
+
exit 1
|
|
1073
|
+
|
|
1074
|
+
post-merge-notify:
|
|
1075
|
+
name: D4-LITE notify on failure
|
|
1076
|
+
needs: [post-merge-gate]
|
|
1077
|
+
if: always() && needs.post-merge-gate.result == 'failure'
|
|
1078
|
+
permissions:
|
|
1079
|
+
issues: write
|
|
1080
|
+
uses: ./.github/workflows/_notify.yml
|
|
1081
|
+
with:
|
|
1082
|
+
workflow_name: D4-LITE post-merge gate
|
|
1083
|
+
area: ci
|
|
1084
|
+
severity: P1
|
|
1085
|
+
branch: main
|
|
1086
|
+
run_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
1087
|
+
failure_summary: Post-merge L2 gate failed on main — a change merged without full verification.
|
|
1088
|
+
status: failure
|
|
1089
|
+
<% } %><% } -%>
|