Verify evidence digests against committed bytes, not the working tree - #1
Merged
Merged
Conversation
This gate reported PASSED on Windows while two artifacts under mcl-ap would
have failed for anyone else. The first release-gates run on a Linux runner,
minutes after the repositories became public, caught both immediately.
The gate was not wrong about the bytes it saw. It was looking at the wrong
bytes. `.gitattributes` says `* text=auto eol=lf`, and `text=auto` makes Git
compare NORMALISED content, so a file left over from before that rule can sit
in a Windows working tree with CRLF, hash to the CRLF value, and still be
reported by `git status` as perfectly clean. A digest recorded from that tree
then agrees with itself forever on that one machine.
That is the whole failure mode this gate exists to prevent, reappearing one
level up: nothing was checking that the bytes being checked were the published
ones. An external reviewer clones fresh and gets the committed bytes on every
platform, and that is the only thing a published digest can mean.
So each covered file's working-tree bytes are now compared against its
committed blob before any digest is verified, and a divergence is its own
distinct failure with its own instruction -- refresh the checkout, and do NOT
regenerate the digest from those bytes, because doing so is how a wrong digest
becomes permanent.
Three things this cost, all worth recording:
- Paths must be resolved before Git is asked about them. A digest file here
references ../../exp002_probe.wav, and `git rev-parse HEAD:` does not
normalise `..` the way `ls-files` does. Comparing the two answers without
resolving first reported a divergence that did not exist.
- The command substitutions need `|| true`. Under `set -e` a failing
substitution inside an assignment terminates the gate silently, which it
did on the first run -- printing its header and nothing else.
- Verified in both directions, not just observed to pass: a clean tree exits
0 with no failures, a file given CRLF in the working tree only is caught by
name and exits 1, and restoring it returns the gate to green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mcl-release-governor
Bot
requested review from
0j0bit and
sed-boi
as code owners
September 12, 2026 18:05
0j0bit
approved these changes
Sep 13, 2026
0j0bit
left a comment
Contributor
There was a problem hiding this comment.
Reviewed as 0j0bit: only tools/check-evidence-digests.sh changes; it now requires working-tree bytes to equal the committed blob before verifying a digest, resolves .. paths, and guards substitutions under set -e; verified in both directions; build (gcc) and build (clang) green.
This was referenced Sep 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Verify evidence digests against committed bytes, not the working tree
This gate reported PASSED on Windows while two artifacts under mcl-ap would
have failed for anyone else. The first release-gates run on a Linux runner,
minutes after the repositories became public, caught both immediately.
The gate was not wrong about the bytes it saw. It was looking at the wrong
bytes.
.gitattributessays* text=auto eol=lf, andtext=automakes Gitcompare NORMALISED content, so a file left over from before that rule can sit
in a Windows working tree with CRLF, hash to the CRLF value, and still be
reported by
git statusas perfectly clean. A digest recorded from that treethen agrees with itself forever on that one machine.
That is the whole failure mode this gate exists to prevent, reappearing one
level up: nothing was checking that the bytes being checked were the published
ones. An external reviewer clones fresh and gets the committed bytes on every
platform, and that is the only thing a published digest can mean.
So each covered file's working-tree bytes are now compared against its
committed blob before any digest is verified, and a divergence is its own
distinct failure with its own instruction -- refresh the checkout, and do NOT
regenerate the digest from those bytes, because doing so is how a wrong digest
becomes permanent.
Three things this cost, all worth recording:
Paths must be resolved before Git is asked about them. A digest file here
references ../../exp002_probe.wav, and
git rev-parse HEAD:does notnormalise
..the wayls-filesdoes. Comparing the two answers withoutresolving first reported a divergence that did not exist.
The command substitutions need
|| true. Underset -ea failingsubstitution inside an assignment terminates the gate silently, which it
did on the first run -- printing its header and nothing else.
Verified in both directions, not just observed to pass: a clean tree exits
0 with no failures, a file given CRLF in the working tree only is caught by
name and exits 1, and restoring it returns the gate to green.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com