Skip to content

fix(ci): two gates that could not fail, and the arithmetic that says so (#829, #559) - #882

Merged
stephrobert merged 1 commit into
mainfrom
fix/two-gates-that-could-not-fail
Nov 11, 2026
Merged

stephrobert merged 1 commit into
mainfrom
fix/two-gates-that-could-not-fail

Conversation

@stephrobert

Copy link
Copy Markdown
Owner

Both report a verdict they did not measure.

The gofmt hook reported Passed when gofmt could not run. The entry was test -z \"$(gofmt -l .)\", which discards the exit code: gofmt -l writes its errors to stderr, so any failure produced an empty substitution and the hook exited 0. Not skipped, not red — green, asserting it looked. Its window is a fresh clone before mise trust, which is a new contributor first commit, and it is the only hook in that file with the shape: go vet and golangci-lint propagate their own status and both reddened at the same instant on the same cause, which is the only reason the gofmt green was noticed.

A balancer verdict drawn from six coin flips. The Outscale dataplane suite asked six connections whether a balancer reaches both machines; a balancer that works sends every connection to one side with probability 2 x 0.5^6 = 3.1 percent. One run in thirty-two, red on a subject that was behaving, on the suite whose subject is this project own differentiator. The same arithmetic runs the other way after an unlink: six probes that avoid a machine the unlink never reached is 1.6 percent, a false green over a real defect — and that site comment already named it. 24 probes puts both tails at 1.2e-7 and 6.0e-8, for about ten seconds on a leg that measures in minutes. The liveness probe keeps six, and says why.

Both tests run the thing rather than reading it: the hook test executes the entry: line taken out of the YAML, with a PATH holding no gofmt. Both assert the ACCEPTING half too, because a guard that refuses everything passes its own attack test and teaches --no-verify.

/falsify: 2 mutations per spec, all biting, each spec mutating the over-correction as well as the defect.

mise run prepush green. The testplan prescribes falsify:lint and the specs it names for this diff.

Closes #829. Closes #559.

🤖 Generated with Claude Code

…so (#829, #559)

Both report a verdict they did not measure. They are the same family as "un
commentaire n'est pas un contrôle", one level up: a control that cannot fail is
not a control, and a control that fails on a healthy subject is worse than none
because it teaches the reflex of re-running it.

## The gofmt hook reported Passed when gofmt could not run

`.pre-commit-config.yaml` read `test -z "$(gofmt -l .)" || …`. `gofmt -l`
writes the offending files to stdout and its own errors to stderr, and the
verdict was `test -z` over the captured stdout alone — the exit code was never
read. Any failure of gofmt produced an empty substitution, `test -z ""` was
true, and the hook exited 0.

Not skipped, not red: **Passed, asserting it looked.** Its window is a fresh
clone before `mise trust`, which is a new contributor's first commit, and it is
the only hook in that file with the shape — `go vet` and `golangci-lint`
propagate their own status, and both reddened at the same instant on the same
cause, which is the only reason the gofmt green was ever noticed.

The test runs the hook's own `entry:` line, read out of the YAML rather than
copied into Go: a test asserting the entry *contains* `||` would pass on any
rewrite that kept the characters and lost the property. Both directions are
asserted in the same file, because a hook that always failed would satisfy the
refusing test and reject every commit.

## A balancer verdict drawn from six coin flips

The Outscale dataplane suite asked **six** connections whether a balancer
reaches both of its machines. A balancer that works sends every connection to
one side with probability 2 × 0.5⁶ = **3.1 %**, so the gate reddened about one
run in thirty-two on a subject that was behaving — on the suite whose subject
is this project's own differentiator.

The same arithmetic runs the other way after an unlink: six probes that happen
to avoid a machine the unlink never reached is 0.5⁶ = 1.6 %, a false **green**
over a real defect. That site's comment already named it "#559's defect with a
different number" and left the number.

`DISTRIBUTION_PROBES=24` puts both tails at 1.2e-7 and 6.0e-8, for about ten
seconds on a leg that measures in minutes. The liveness probe keeps six and
says why: "did every connection get an answer" has no false negative that more
probes would remove, so a bigger sample there buys wall-clock and nothing else.

What the suite still does not prove is written beside the constant rather than
left to be assumed: that the distribution is **fair**. Both machines being
reached says the balancer has more than one backend, nothing about the ratio.

The control reads the script, because the subject *is* the sample size — but it
checks a property, not a value: every probe whose verdict names a machine draws
from the declared constant, and that constant supports the claim. Changing the
number stays free; going back to a literal does not.

/falsify: 2 mutations on a-hook-that-cannot-measure-fails.json and 2 on
a-verdict-drawn-from-six-coin-flips.json, all biting. Each spec mutates the
over-correction as well as the defect, because a guard that refuses everything
passes its own attack test.

mise run prepush green.

Assisted-by: Claude Code (claude-opus-5)
@stephrobert
stephrobert merged commit e23b49b into main Nov 11, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant