The hook’s old value
Git’s reference-transaction hook receives lines with an old object, a new object, and a reference name. It is tempting to read the old field as a snapshot of what the reference currently contains.
Spice’s checked-out-branch guard cannot make that assumption. A caller can update a ref without declaring the old value. The hook input can then contain the zero object ID, even though the ref already exists. A rewind can look like creation if the guard trusts that field.
During the prepared stage, the reference still holds its pre-transaction value. The guard resolves it from the repository before deciding whether the proposed value would abandon commits already shared with the branch’s upstream.
The parsed update deliberately retains only new and ref. It still requires the three-field input grammar, but does not carry the misleading old value farther into the decision.
The upstream also needs an exact source. Spice’s per-process Git configuration can redirect apparent tracking information, so this guard reads the branch’s pairing from local repository configuration instead of trusting a shadowed @{upstream}. It does not assume the remote is named origin or the branch is named main.
This is a guard for the current checked-out branch, not a universal policy for every reference transaction. Appends that retain the old tip can proceed; a rewind requiring an upstream judgment cannot silently pass when the declared upstream cannot be resolved.
The repair made those evidence sources explicit. The hook input describes the requested transaction. The repository supplies the state against which this particular guard has to judge it.