# Branch protection for `main` CI defines the checks; **branch protection is a repo setting** (Settings → Branches → Add rule) and has to be configured once by an admin. This file records the intended policy so it can be re-applied or audited. ## Rule: `main` - **Require a pull request before merging.** No direct pushes. - **Require status checks to pass before merging**, and require branches to be up to date first. Required checks: | Check (job name in `ci.yml`) | Required from | |---|---| | `clang-format` | now | | `testserver` | now | | `bootstrap-script` | now (validates package names against the 24.04 runner archive) | | `bootstrap-script-2604` | now — real `--with-clang` install in a 26.04 container; the release the project ships on | | `build (gcc)` / `build (clang)` | now — core, daemon and gui have merged | | `sanitizers (dev)` / `sanitizers (tsan)` | now — core, daemon and gui have merged | | `conformance` | **now — `tests/conformance/` has landed; this is the M0 exit gate.** Includes the live-`veloxd` runner (step 3b of `run.sh`), unconditional in the script — see `docs/adr/0019-live-veloxd-conformance-is-required.md`. | | `extension-lint` | now — `extension/` has merged (MV3 manifest + esbuild build) | | `gui-dod` | now — `gui/tests/dod/` has landed (GUI M1 DoD gates R3: `scroll-60fps`, `unhappy-path`); see `tests/integration/README.md#gui-m1-definition-of-done-gates-r3`. `gui-dod-nightly` (`rss-flat`) is schedule-only and cannot be a required PR check. | `clang-tidy` is intentionally **not** required through M1 (`continue-on-error: true`, `.clang-tidy` has `WarningsAsErrors: ''`). Make it required at M2. - **Require linear history** (matches CLAUDE.md §6: rebase onto `main`, no merge commits). - **Require conversation resolution before merging.** - Do **not** allow force pushes or deletions. - Apply the rule to administrators too, except for the initial scaffolding period. ## Note on the "skipped" job steps `extension-lint` and `clang-tidy` short-circuit to a "skipped" echo when their lane hasn't landed. They still report **success**, so they can be marked required now without blocking — they start doing real work automatically on the commit that adds the lane. Their guards fail **loudly** (non-zero) once the lane is half-present — e.g. an `extension/manifest.json` with no lintable `package.json`. A guard keyed to a single filename is how a required check ends up green over nothing; the skip branch is only for a lane that is genuinely absent. `conformance` has no skip branch. It runs `ctest -L conformance` (see `docs/adr/0014-conformance-runs-through-ctest.md`); the `dev` test preset's `noTestsAction: error` fails the job if that label ever matches nothing, so a deleted or renamed registration goes red instead of passing vacuously.