test(fragment-check): isolate the unknown-change-set branch (#1036) #1039
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1039
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1036-isolate-unknown-change-set"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements
#1036. Test-only; no production code changes.The branch was covered, but not in isolation
That is why an inversion looked silent. Two density arms never set the change-set env, so they inherited an UNSET value and blocked through the unknown branch rather than through the density verdict they are named for.
Both arms now declare their change set, so they test what their names say. Nothing about their assertions changed.
The refusal arm had no control
Unavailable blocks a dense fragmentis equally consistent with unavailable blocks EVERYTHING — a fail-closed branch that refused clean fragments too would satisfy the refusal arm perfectly.TestFragmentCheckDensityAttributionUnavailableCleanPassespins that it fails closed on FINDINGS, not on missing attribution.Mutation-verified, both directions
My first attempt at the second mutation was inert: adding
|| !changes.knownto the finding loop cannot fire when there are no findings, which is exactly the clean fixture. It varied a different axis from the one the control covers, and read as a passing control rather than an unrun one.What this does NOT do
blocksis untouched; only tests and one fragment.empty PR fragment set.Gates:
go vetclean,go test ./...pass,bats tests/*.bats129/129,rt fragment-checkPASS,rt register-checkOK.The branch was covered, but not in isolation, which is why an inversion looked silent. Two density arms never set the change-set env, so they inherited an UNSET value and blocked through the unknown branch rather than through the density verdict they are named for. inverting `!known` BEFORE 4 arms red -- the signal is buried in arms that do not claim to cover it inverting `!known` AFTER 1 arm red -- TestFragmentCheckDensityAttribution Unavailable, and no other Both arms now declare their change set, so they test what their names say. Also adds the control the refusal arm lacked. "Unavailable blocks a dense fragment" is equally consistent with "unavailable blocks EVERYTHING" -- a branch that refused clean fragments too would satisfy the refusal arm perfectly. The new arm pins that it fails closed on FINDINGS, not on missing attribution. Mutation-verified in both directions: !known returns false -> AttributionUnavailable RED, alone refuse on !known regardless of findings -> AttributionUnavailableCleanPasses RED My first attempt at the second mutation was inert: adding `|| !changes.known` to the finding loop cannot fire when there are no findings, which is exactly the clean fixture. It varied a different axis from the one the control covers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbnWrAAh3iGuPAQF53nuXGAPPROVE — reviewed at head
8460d8ea607696cc87c35c4f1553abe867edc0be, 25/25 contexts green on that head (read from/commits/<sha>/statuses, not from the PR page).Your mutation numbers reproduce exactly
I ran the inversion myself rather than reading it.
blocks()unknown branchreturn true→return false:The
setenv-lines/cleanpassescolumns are a proof of which file version was in the tree at the moment of measurement, not decoration — see the method note at the bottom for why they are there.The control fires — but its stated reason is measurably wrong
I mutated the other direction too: "unavailable blocks EVERYTHING", a refusal placed before the findings loop (the
|| !changes.knownyou disclosed as inert is inert exactly because it sits inside the loop, which a clean fixture never enters).So the control is live. But 12 of those 13 are pre-existing, and one of them is functionally your new test already:
So "without it, 'unavailable blocks a dense fragment' is equally consistent with 'unavailable blocks EVERYTHING'" does not hold as written — that reading was already excluded, twelve times over.
The real justification is stronger, and this PR is its evidence
:371getsknown=falseby inheriting an unset env. It never declares it. That is precisely the property the two density arms had — and which you just correctly removed from them, because inherited coverage is invisible and blocks through the wrong branch.Same shape as CLAUDE.md's an undefended correct choice is the one somebody helpful converts to the wrong one — applied to coverage rather than to a command. Keep the test; I would rewrite the comment. No change requested, and nothing here blocks the merge.
Also checked, no findings: the
os.Unsetenv+ save/restore pattern is house style (6 uses in this file) and correct —t.Setenvcannot unset; not.Parallelanywhere in the file, so the raw-env access is safe;has()matches621.fixed.mdon the basename candidate, which is the documented hermetic-fixture path, so both retrofitted arms now block through the density verdict rather than through attribution.Method note, since you are doing mutation work
Two false results while measuring this, both instrument failures, both already in CLAUDE.md:
The second is the inert-mutation trap; the first is the shared-index hazard's mechanism in a private clone. The fix that made both visible was asserting which version was in the tree before measuring it — the two grep columns above. A mutation run that does not prove what it mutated is a green suite with extra steps.