Skip to content

The pre-push hook refuses over a RETIRED line budget, and its verdict changes with the refspec form #1753

Description

@localai-bot

.githooks/pre-push (reached via core.hooksPath) refuses a push as "over the
budget" for one refspec form and permits the identical content under another,
and the budget it enforces was retired by policy.

Two defects, one file

1. It enforces a retired policy. AGENTS.md says, in ## Landing work:

The project has no line budget. It retired the per-class limits on 10 August
2026. Nine of the previous 22 merged pull requests exceeded the product limit.
Tests were one-third to one-half of each large change. The gate therefore
failed normal work [...] Size is a review decision.

git log -1 --format=%ad --date=short -- .githooks/pre-push reads 2026-08-09
— the day BEFORE the retirement. The hook was simply never revisited.

2. Its verdict depends on the refspec form. Observed on PR #1738 while
pushing head 2f573f1e3:

  • git push origin HEAD:row/SPEC-CUDA-DEGRADErefused, "refusing to push
    ... over the budget"
  • git push origin ${SHA}:refs/heads/row/SPEC-CUDA-DEGRADEpassed, with
    the hook running (no --no-verify)

Same commit, same content, opposite verdicts. The cause is the base: the hook
reads remote_sha from its stdin (:31, :36) and only falls back to
merge-base origin/main "$sha" (:60) when that is unusable. Git supplies a
different remote_sha for the abbreviated and fully-qualified forms, so the two
pushes are measured against different bases and therefore different diffs.

Why this matters beyond the annoyance

AGENTS.md asks for the exact-SHA push form, and that is the form that happens
to work — so the failure lands on whoever uses the ordinary form, which is most
people. A contributor who hits it has three options and two are wrong: use
--no-verify (which AGENTS.md's ## Landing work treats as bypassing
convenience, and which trains the habit of bypassing), split a change a retired
policy says needs no splitting, or re-spell the refspec — which only works by
accident and teaches a false lesson about what the gate measures.

AGENTS.md also says hooks are "bypassable convenience, not evidence", so this
is not a correctness gate. It is still an obstacle that fires on normal work,
which is the exact failure mode the 10 August retirement was reasoning about.

Suggested disposition

Either delete the budget check (matching the retirement, leaving the hook's
other checks intact) or, if some size signal is still wanted locally, make it a
warning that cannot refuse. Whichever is chosen, the base computation should be
made refspec-independent — derive it from merge-base origin/main "$sha"
unconditionally — so no gate in this tree can return two answers for one commit.

A red-before test should pin BOTH push forms to the same verdict, since the
divergence, not the threshold, is the part a future edit can silently
reintroduce. Note .githooks/README.md also mentions the budget and needs to
agree with whatever lands.

Found while repairing spec findings on PR #1738.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions