`make setup` ran build_runner and reported success whether it produced the
39 files a fresh clone needs or almost nothing. `flutter test`'s only guard
checked a single sentinel file, which is why the 2026-08-09 4-of-46 gap
still read as 26 passed / 17 failed instead of a missing build step.
ci/check_codegen.sh walks every `part` directive under lib/ and confirms
the sibling file it names exists, then wires into both `setup` (fail loud
right after codegen if it under-produced) and `test` (fail loud, exit 69,
if nobody ran setup at all). Replaces the one-file guard, which would have
missed 44 of the 45 directives that exist today.
The hook carried ~50 lines of gitleaks logic and a comment explaining it was
self-contained because "this repo has no Makefile". It has one now, so the
reason is gone and the arrangement is backwards: a hook is a trigger, and
logic belongs where it can be read, run by hand, and changed under review.
.githooks/pre-push is now a byte-identical shim onto `make pre-push` in every
repo in the workspace. The scan itself moves to ci/secrets.sh unchanged, and
`make secrets` runs it on its own.
The call surface is identical everywhere; what it runs is not, and should not
be — each repo gates what it actually has. That is the point of standardising
the name rather than the contents: nobody has to read a repo to find out how
to check it.
secrets runs first, deliberately. It is the only failure here that cannot be
undone by fixing it afterwards — a failed lint costs another commit, a pushed
credential is cached and indexed whether or not it is later deleted.
Some of these gates fail today, on lint debt that predates them, and they are
left wired anyway. The board was measured once and written down in T-56
instead of being worked around here. Narrowing each gate to whatever already
passes would produce a gate that reports success for doing nothing, which is
the failure this workspace keeps rediscovering.
Co-Authored-By: Claude <noreply@anthropic.com>