Skip to content

CI gates

Implemented

Source: scripts/ci/*.sh · doc/governance/CI_Enforcement_Checklist.md · doc/governance/Pipeline_Blueprint.md

Why CI gates exist

Every "rule we always follow" in Coding_Standards.md is paired with a CI gate. Reviewers and agents are fallible; CI is not.

flowchart LR
    A[Coding standard rule] --> B[scripts/ci/*.sh gate]
    B --> C[PR fails on violation]
    C --> D[Author fixes root cause]
    D --> E[Rule sticks across<br/>contributors and time]

Gate inventory

Script Enforces
bootstrap_ci_toolchain.sh Install toolchain (Go, Node, oapi-codegen, openapi-typescript)
backend_build_and_tests.sh go build ./..., go vet, golangci-lint, make test, make test-integration
frontend_build_and_tests.sh pnpm typecheck, pnpm build, vitest
frontend_e2e*.sh Playwright E2E suites
contracts_validate.sh Spectral lint + OpenAPI/AsyncAPI structural validation
contracts_breaking_change.sh Diff vs main — block unannotated breakage
contracts_schemathesis_report.sh Property-based contract tests against running server
audit_mandatory_guard.sh Privileged mutation handlers write audit_logs rows
audit_presence_guard.sh Integration tests assert audit rows present
canonical_error_guard.sh All error returns use codes from the catalog
observability_trace_gate.sh Every binary initializes OTel; every router wraps tracing middleware
agent_queue_validate.sh Multi-agent work queue schema valid
agent_queue_git_consistency.sh Queue is in sync with branch state
frontend_smoke.sh Smoke test for web build artifact
ci_script_smoke.sh Smoke that scripts/ci/ work locally

Gate flow per PR

flowchart TB
    PR[PR opened] --> S1[Toolchain bootstrap]
    S1 --> S2[Lint: golangci-lint + spectral]
    S2 --> S3[Contracts validate]
    S3 --> S4[Contracts breaking-change diff]
    S4 --> S5[Backend build + unit]
    S5 --> S6[Backend integration]
    S6 --> S7[Audit guards]
    S7 --> S8[Canonical error guard]
    S8 --> S9[Observability trace gate]
    S9 --> S10[Frontend build + tests]
    S10 --> S11[Frontend E2E]
    S11 --> S12[Schemathesis contract test]
    S12 --> OK([All gates pass])

    S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9 & S10 & S11 & S12 -.fail.-> BLOCK[PR blocked]

Portability principle

From Coding_Standards.md §11:

Keep gate logic in scripts/ci/*.sh; CI workflow files (.gitlab-ci.yml / GitHub Actions) are orchestration wrappers only. If CI host changes, reuse scripts and only adapt runner/secrets wiring.

Both doc/governance/ci_workflow_github_actions.yaml and ci_workflow_gitlab_ci.yaml exist as reference orchestration; they invoke the same scripts.

Spectral policy

doc/governance/openapi.spectral.yaml lints OpenAPI. Examples of rules:

  • operation-operationId-camelCase
  • operation-tag-required
  • operation-success-response
  • path-parameter-pattern (kebab-case)
  • error-response-uses-ErrorResponse

ReviewGuard policy

doc/governance/reviewguard_policy_draft.yaml enforces PR-level governance:

  • Title format
  • Required reviewers per touched domain
  • Required labels for breaking changes
  • Auto-block of PRs touching governance/agent_policy.yaml without explicit approval

Source: reviewguard_adoption_plan.md.

Agent policy

doc/governance/agent_policy.yaml is the highest-priority governance artifact — it constrains what coding agents are allowed to do automatically:

  • Allowed file globs per task class
  • Required cross-references for design changes
  • Forbidden file patterns
  • Required test layers per change class

Source: agent_policy.yaml.

Where to look next