@@ -257,6 +257,37 @@ remapping this repo's `blob/main` URLs to the checkout.
257257
258258A repo with a docs site MUST have a `docs` job running `just docs-build` (`mkdocs build --strict`).
259259
260+ # ## CI9 · Shared ADR check { #CI9 }
261+
262+ The `lint` job MUST run `just adr-check` after `just install lint-ci`. The recipe MUST be this,
263+ byte for byte, and a repo MUST NOT keep a copy of `tests/test_adr_citations.py` :
264+
265+ ` ` ` just
266+ adr_check_source := "https://raw.githubusercontent.com/modern-python/.github/main/tests/test_adr_citations.py"
267+
268+ # Tracks main on purpose: the shared check is unpinned.
269+ adr-check:
270+ #!/usr/bin/env sh
271+ set -eu
272+ dir="$(mktemp -d .adr-check.XXXXXX)"
273+ trap 'rm -rf "$dir"' EXIT
274+ curl -fsSL "{{ adr_check_source }}" -o "$dir/test_adr_citations.py"
275+ uv run --no-sync pytest --rootdir=. --noconftest -o addopts= "$dir/test_adr_citations.py"
276+ ` ` `
277+
278+ The check asserts that every ADR cited anywhere in the repo, by `docs/adr/NNNN-slug.md` path or by
279+ bare `ADR-NNNN` number, exists in `docs/adr/` ([FL4](#FL4)).
280+
281+ *Why:* one rule, one file. Twenty-five byte-identical copies of this test drifted within a month
282+ of being written. The recipe tracks `main` unpinned on purpose : a change to the rule lands once,
283+ with no release and no bump across the org. The trade is that it reaches every repo's next run at
284+ once, so a change to the file in this repo is run against every repo's `main` before it merges,
285+ and a repo's own pull request sees the fix only once its branch carries it. `--rootdir=.` makes
286+ the repo the scanned root; `--noconftest` and `-o addopts=` keep the repo's conftests and
287+ coverage gate out of a one-file run; the temporary directory sits inside the repo because
288+ plugins such as `pytest-alembic` reject collected files outside the root. `adr_check_source` can
289+ be pointed at a `file://` path to run an unmerged version of the check.
290+
260291# # Release
261292
262293# ## RL1 · Tags { #RL1 }
0 commit comments