diff --git a/CHANGELOG.md b/CHANGELOG.md index 81b6292..ee28569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 2026-08-02 — `--fast` for the pre-push hook (no version: this repo carries none) + +**`scripts/catalog_gates.py --fast`** selects only gates that touch no network and no container +runtime. Today that is gate 1, `check-image-pins.py`. `check-image-resolvable.py` (network) and +`check-volume-persistence.py` (Docker, minutes per app) are **not** in it, and the skip is +**announced**, with the reason and with what still owes a periodic run — a silently narrowed run +reads as "covered everything" when it did not. Default behaviour with no flag is unchanged. + +**Why the runtime gates are never in a hook.** A push that pulls images and starts containers gets +bypassed within a week, and the bypass becomes the habit. They stay deliberate periodic runs: the +start of a catalog campaign, before a publish train that vouches the catalog, and whenever a +template's `volumes:` block or image tag changes — on a scratch host, never a customer box. + +**`.githooks/pre-push` (new)** runs `catalog_gates.py --fast` and refuses the push. It is per-clone +(`git config core.hooksPath .githooks`) and `git push --no-verify` bypasses it on purpose; both +limits are written into the hook. This is R-161's convention half made automatic-ish; the +unbypassable half is CI, now tracked as `felhom.eu` `OPEN-ITEMS.md` **R-168**. + +**`scripts/test_catalog_gates.py` (new, 5 tests)** pins `--fast`'s CONTENT, not just its exit code: +the static gate's own stdout must appear (an inert runner prints the summary while calling nothing), +the runtime gates' must not, the skip must be announced, and the no-flag path must still select all +three. Red-proofed with an inert `run_gate`. + ## 2026-08-02 — one entry point for the catalog's gates (R-161 ruling) `scripts/catalog_gates.py` runs all three gates — image-pins, image-resolvable, volume-persistence —