Show the gate's hash in -Status, because the version label had already lied - #46
Merged
Conversation
…el had already lied
Rules 1a, 3c and 3d shipped without bumping $GateVersion, so after the merge `-Status`
printed the SAME version on both lines directly above a *** STALE *** verdict:
installed : ... v2026.07.29.1
source : ... v2026.07.29.1
parity : *** STALE ***
The SHA-256 comparison caught the drift correctly -- that check was never in doubt. But a
hand-bumped label that contradicts the verdict beside it is precisely the ambiguity this
whole audit set out to remove, and it took one merge to appear.
Two changes. $GateVersion is bumped, and -Status now prints the hash prefix next to each
version, so agreement is VISIBLE rather than asserted and the label can never again be the
only thing a reader compares. Lowercased, because Get-FileHash returns uppercase while
every other digest a reader meets here is lowercase, and two spellings of one hash invite a
false "these differ".
Also closes a gap the audit recorded as open: nothing exercised `-Status` at all. It is now
tested for exit 0 and for a hash on the source line, which always resolves. The test runs
with CLAUDECODE=1 on purpose -- `-Status` sits above the refusal precisely so a session can
audit but not install, and that ordering is now covered too.
192 gate tests pass, 4 skipped.
wshallwshall
enabled auto-merge (squash)
July 29, 2026 17:09
… it the way Claude Code does Every test in this suite passes -ReposFile so it can point at a temp allowlist. That is right for isolation, and it left a hole the size of the whole product: a PowerShell parameter default is NOT evaluated when a value is supplied, so the default expression was never once executed by 192 passing tests. It shipped broken in the previous commit. `Join-Path ( if ... )` opens a COMMAND-INVOCATION group, so PowerShell parses the `if` as a command name and the hook dies with "The term 'if' is not recognized" before its first line. A PreToolUse hook that exits non-zero-but-not-2 lets the tool call through, so the gate was OFF for every real tool call on this machine for the length of one install -- while `install-gate.ps1 -Status` cheerfully reported IN SYNC, because parity compares the installed copy to source and both were equally broken. Caught only because the end-to-end probe invokes the hook the way production does, with no arguments: 0/13 expected, every case CRASH(1). The unit suite was green throughout. Two lessons worth more than the one-character fix, both now encoded: Parity is not validity. `-Status` answers "is the installed copy the same as source", which is silent about whether either RUNS. Those are different properties and I conflated them. An isolation seam that every test uses is a seam no test exercises. -ReposFile exists so tests can be hermetic; that made the production default untested by construction. tests/test_worktree_gate_default_reposfile.py now invokes the hook with NO arguments and asserts three things nothing else could: that it runs at all, that an absent allowlist is a SILENT allow (no stderr), and that an allowlist placed where the default expression should look actually produces a deny. Reverting the fix fails all three. This is also, exactly, the failure mode reported upstream this morning as anthropics/claude-code#82323 -- a hook inert with no signal anywhere. I filed it and then shipped it.
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.
A one-merge-old follow-up to #40.
Rules 1a, 3c and 3d shipped without bumping
$GateVersion, so-Statusprinted the same version on both lines directly above a*** STALE ***verdict:The SHA-256 comparison caught the drift correctly — that check was never in doubt. But a hand-bumped label contradicting the verdict beside it is exactly the ambiguity #40 set out to remove, and it took one merge to appear.
Changes
$GateVersionbumped, and its comment now says plainly that it is a human label while the hash is authoritative.-Statusprints the hash prefix next to each version, so agreement is visible rather than asserted. Lowercased —Get-FileHashreturns uppercase while every other digest a reader meets here is lowercase, and two spellings of one hash invite a false "these differ".-Statusat all. Now tested for exit 0 and for a hash on the source line, which always resolves. The test runs withCLAUDECODE=1deliberately —-Statussits above the refusal precisely so a session can audit but not install, and that ordering is now covered too.192 gate tests pass, 4 skipped.
🤖 Generated with Claude Code