PR #44 reached CI with govet fieldalignment findings that no local
gate had ever checked. This PR wires the repository's existing lint configuration into the
commit path, so the verdict arrives before the push rather than after it.
The same linter, the same pinned version and the same .golangci.yml in both rows.
Only the moment of the verdict moves. Hover or focus any node to trace its edges.
A shell hook, a version pin, and the two commands a new clone has to run. Each card expands.
gofmt -l runs first because it is cheap: a formatting problem is
rejected before the expensive linter is ever started.golangci-lint run ./... — the same command the CI
lint job runs, against the same .golangci.yml.golangci-lint binary fails closed rather than
silently skipping. An uninstalled linter would otherwise reintroduce exactly the
CI-only failure mode the hook exists to remove.bypass for a genuine emergency: git commit --no-verify
GOLANGCI_LINT_VERSION := v2.12.2 — a single pin, kept beside a
comment tying it to .github/workflows/ci.yml.make lint-tools installs exactly the CI version, so a local verdict
and a CI verdict cannot diverge on linter version.make hooks sets core.hooksPath to .githooks
— one command, once per clone. The hooks themselves stay committed, so they
stay in review.make lint-tools and make hooks
immediately after the build and test commands, where a new clone will actually read
them.A clean tree passes the whole hook in roughly 8s wall time with a warm cache.
An induced fieldalignment violation blocked a real git commit:
exit 1, no commit created.
A misformatted file was stopped at the gofmt stage, before the linter ran.
This PR's own commit was created through the hook.