The gate hardcoded HEAD as its diff tip, but pre-commit exports
PRE_COMMIT_TO_REF for exactly this. Pushing "somebranch:main" from another
checkout diffed the wrong tip — a false negative when HEAD is older, a false
positive when newer. Fixing only the diff tip leaves a second bug: git describe
took the tag baseline from HEAD too, so a tag reachable only from HEAD becomes
a baseline the pushed ref never saw. Both now resolve from the pushed ref, and
an all-zeros ref (branch deletion) short-circuits before any rev resolution
rather than surfacing as "could not diff".
PRE_COMMIT_FROM_REF is deliberately not used: it is the remote's current tip,
so diffing from it would let an untagged release-relevant commit already on
main excuse the next push from cutting a tag — the drift this gate exists to
catch. The baseline must stay the last release tag.
collect_release_paths took tokens[0] as a path unconditionally. ADR-0014 makes
bare single-path entries a binding constraint, but nothing enforced it, and the
sibling .pre-commit-config.yaml already ships "entry: bash <script>". Under
that shape add_release_path takes "bash", git diff accepts the non-matching
pathspec silently, bundle_root becomes "." and is skipped — the hook's whole
surface leaves the gate with no error, the same shape as the --config
regression in LESSONS.md. Multi-token entries now fail loudly naming the hook
and the ADR, and tokens[0] must resolve at HEAD or at the tag (the union is
load-bearing: a per-scope check would reject the deletion cases).
Six mutations verified, each restored. One correction worth recording: the
first multi-token test passed with its guard removed, because the existence
guard caught "bash" and printed a similar message. It now requires the verbatim
entry text that only the multi-token diagnostic emits.
Refs: #85
ADR: 0014