# .github-guard — declarations github-guard reads (see the github-guard skill:
# https://github.com/antimatter-studios/agent-skills/blob/main/.claude/skills/github-guard/README.md).
# git-config format: check with `git config -f .github-guard --list`, and
# double-quote any value containing # or ;.
# What must pass before main takes a merge. github-guard reads this from the
# default branch on the server and applies it to branch protection.
#
# ci-ok ci.yml: the one always-run gate. It `needs:` every other job in
# that workflow and fails when any of them failed, was cancelled or
# was SKIPPED -- the `test` matrix on ubuntu, macOS and Windows,
# fmt, and the coverage run that re-executes the suite under
# llvm-cov with a floor under it.
#
# WHY ONE NAME AND NOT FIVE (#154). This list used to name the five real
# check names: `fmt`, `coverage` and the three `test / <os>` matrix legs.
# Every one was correct when it was written, and that is the problem --
# nothing kept it correct. Adding a fourth runner to the matrix, renaming
# `coverage`, or splitting `fmt` into `fmt` + `clippy` each produce a check
# that reports on every pull request and gates nothing, and no test in this
# repository failed when that happened.
#
# The opposite spelling is worse. A required context that no job produces
# reads to GitHub as permanently pending, and with enforce_admins on nothing
# merges and there is no failure to point at. Both directions come from the
# required list naming individual jobs rather than one gate, and both have
# happened in this constellation.
#
# EVERY DRIVER IN THIS FAMILY DEPENDS ON THIS CRATE, so a job that quietly
# stopped gating here is a regression that reaches all of them. That is the
# reason to spend a file on it rather than trusting the settings page.
#
# THE NAME DOES NOT MOVE WHEN THE JOBS DO, which is what makes this safe to
# change. github-guard reads this file from the DEFAULT BRANCH, so a pull
# request that renames a gating job can never also be the one whose
# protection learns the new name -- it would leave the old name required and
# never reporting. Requiring the aggregate means the jobs behind it can be
# renamed, split or replaced wholesale in a single pull request that
# protection never notices.
#
# ONLY ci.yml CAN GATE, WHICH IS WHY ci-ok LIVES THERE AND NEEDS ONLY ITS
# JOBS. release.yml triggers on a `v*.*.*` tag, after the merge it would be
# gating has already happened. fuzz.yml is `workflow_dispatch` plus a nightly
# cron and never sees a pull request at all. Requiring anything from either
# would require a check that never reports on a pull request, which GitHub
# reads as pending forever -- a permanent block on every merge. They stay
# absent.
#
# NOT written to keep a third-party reviewer out of the required set. Greptile
# reports under app slug `greptile-apps`, and github-protect-main.sh filters
# `select(.app.slug=="github-actions")` on every one of its three queries, so
# it is excluded twice over before this file is read.
#
# `scripts/core.sh ci-gate` HOLDS BOTH HALVES TO THIS -- every job in ci.yml
# has to be in `ci-ok`'s `needs`, and this file has to require `ci-ok` and
# nothing else. Without that the aggregate drifts exactly as the named list
# did: a job added to ci.yml and not to `needs` is invisible again. It runs in
# the `fmt` job, and it reads this file with `git config`, as github-guard does.
#
# It used to be tests/ci_aggregate_gate.rs, and then a dev-dependency on the
# am-ci-guard crate (#156, #157). Neither belonged in a test suite: the rules
# exercise nothing this crate ships, and the `test` job enforces an
# executed-test floor that a meta-test inflates. The rules are
# antimatter-studios/chore's now, where twelve siblings share one copy nobody
# can locally edit.
#
# The name must match the check-run name GitHub reports, which is the job's
# `name:` rather than its key -- `ci-ok` for both.
[checks]
required = ci-ok