Uh oh!
There was an error while loading. Please reload this page.
docs(bugbot): encode the three shapes of a vacuous test (backend#2265) - #776
Merged
Conversation
Three PRs merged on 2026-08-20 — #762, #763 and tracebloc/release-train#94 — shipped ELEVEN tests that asserted the right property and proved nothing. Every one was written deliberately, reviewed, and green. That is the most frequent finding of the three PRs by a wide margin, more than every production defect in them combined, and the guide said nothing about it. The convention is that a finding recurring across PRs becomes a rule here, so: - the three shapes, ascending in subtlety — unreachable fixture, redundant mechanisms (two paths, one observable), and the inert mutation, where the MUTATION fails to express the defect. The third is the dangerous one: an anchor-resolution check cannot see it, because the anchor resolves perfectly. - a surviving mutation is a defect in the test, never a nuisance to annotate; and a green mutation log is evidence only if the run asserts the mutation APPLIED (backend#1729 rule 5). - a derived vocabulary must fail closed. Deriving beats restating, but a derivation that silently falls through returns the WRONG vocabulary and then agrees with itself — check-style.bats's `_brand_rgbs` fell back to the hex list when rule 1's RGB arm was deleted, so "every RGB triple is caught" passed with the RGB half gone. - the early-close hazard now has a CI gate, with diagnose.sh as the worked example of an instance that is correct AS a pipe. - a corollary on the `scripts/lib/*.sh` non-issue: they set no options but they RUN under both, so errexit/pipefail rules apply to them in full. A guard that asks only "does this file set the options" reads the whole lib tree as safe — the bug #763 fixed. - never resolve a review thread on "the reported case now passes": a fix for one spelling routinely leaves its sibling broken, and a resolved thread reads as handled to the next person. backend#1729 already required mutation-proving, deriving the input domain, and never testing a copy of the rule. All three were FOLLOWED in these PRs and the tests were still vacuous eleven times — the existing rules say to mutation-test but not what a surviving mutation means, nor that a fixture can be too thin for the property to be observable. That is the gap. Every claim verified against the tree before committing; two drafting errors caught that way (diagnose.sh carries no marker — the guard reads `set +e` — and `mutation-markers` is a release-train target, not a client one). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
aptracebloc
approved these changes
Aug 21, 2026
aptracebloc
left a comment
Contributor
There was a problem hiding this comment.
Reviewed. Docs-only addition to .cursor/BUGBOT.md encoding the three shapes of a vacuous guard test, plus the surviving-mutation / fail-closed-vocabulary / early-close corollaries.
Spot-checked every concrete claim against the tree and they hold: scripts/lib/diagnose.sh keeps df -h | head -20 under run_diagnose's set +e (line 96 / 42), # pipefail-guard: allow has no live usages, and scripts/tests/pipefail-early-close.sh + _brand_rgbs in check-style.bats both exist on develop with the fail-closed behavior the doc describes. Accurate and internally consistent.
— drafted with Claude Code
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Fixes tracebloc/backend#2265
Why
Three PRs merged on 2026-08-20 — #762, #763 and
tracebloc/release-train#94— shipped eleven tests that asserted the right property and proved nothing. Every one was written deliberately, reviewed, and green. That is the most frequent finding across those PRs by a wide margin — more than every production defect in them combined — and.cursor/BUGBOT.mdsaid nothing about it.The repo convention is that a finding recurring across PRs becomes a rule here.
What's added
Three shapes, ascending in subtlety — only the first is widely understood:
reland the basename are the same string, so mutating one of two redundant arms leaves the other matching.Shape 3 is the one worth internalising: an anchor-resolution check cannot detect it. The anchor resolves perfectly and the log is indistinguishable from real coverage. Only a surviving mutation reveals it.
Plus:
_brand_rgbscase: deleting rule 1's whole RGB arm left its test green, because the extractor fell through to the hex list)diagnose.shas the worked example of an instance that is correct as a pipescripts/lib/*.shnon-issue: they set no options but they run under both, so errexit/pipefail rules apply in fullRelationship to backend#1729
#1729 already requires mutation-proving, deriving the input domain, and never testing a copy of the rule. All three were followed in these PRs and the tests were still vacuous eleven times. The existing rules say to mutation-test; they don't say what a surviving mutation means, or that a fixture can be too thin for the property to be observable. That's the gap.
Verification
Docs-only, but every factual claim was checked against the tree — which caught two errors in my own draft before commit:
diagnose.shcarries a# pipefail-guard: allowmarker. It doesn't — I removed it once the guard learned to readset +e. Reworded to describe what the file actually does.make mutation-markers, which is a release-train target, not a client one. Replaced with a repo-neutral phrasing.Writing a rule about prose that contradicts code, and nearly shipping exactly that, is not lost on me.
check-style.sh,gen-manifest --check,check-drift.shand the early-close gate all clean. No customer or internal detail (public repo).🤖 Generated with Claude Code
Note
Low Risk
Docs-only change to the Bugbot review guide; no runtime, security, or installer behavior is modified.
Overview
Updates
.cursor/BUGBOT.mdso reviewers treat vacuous guard tests as the default suspicion: fixtures that never hit the named path, inputs that cannot distinguish two mechanisms, and mutations that do not actually express the defect.Also tells Bugbot to flag surviving mutations as test defects (not nuisances), derived vocabularies that fail open, and unexplained
# pipefail-guard: allowmarkers. Clarifies that sourcedscripts/lib/*.shstill run undererrexit/pipefail, and that a finding must not be resolved just because the reported case now passes.Reviewed by Cursor Bugbot for commit f7d2196. Bugbot is set up for automated code reviews on this repo. Configure here.