test: make the safe assertion the easy one, and measure guard coverage - #124
Open
dlovell wants to merge 1 commit into
Open
test: make the safe assertion the easy one, and measure guard coverage#124dlovell wants to merge 1 commit into
dlovell wants to merge 1 commit into
Conversation
Three review rounds this week produced nine findings. Two had a structural cause with a mechanical fix; this is those two. The other seven needed a reader, and nothing here pretends otherwise. 1. Fail-open assertions. `assert_contains` matches a needle that is a PREFIX of a longer line, so an assertion about `<owner> /a/b` is satisfied by an unrelated `-R <owner> /a/b/c` and passes while the behaviour it names has stopped. That shipped in tests/test-volume-chown-guard.sh (caught in review on #113) in a file that already documented the trap in a comment — the knowledge was present and the affordance was not. Suites needing line anchoring were wrapping `grep -qxF` in assert_true/assert_false, which works but loses the expected/got diagnostic and leaves each author to rediscover the problem. assert_line/assert_no_line make the safe form the ergonomic one. tests/test-harness-assertions.sh pins the DIFFERENCE between the two families, since that difference is the only reason the safe pair exists. 2. Mutation records prove the suite has teeth, not the assertions. Measured on tests/test-volume-chown-guard.sh with its five recorded mutations: 9 of 46 assertions ever went red — and the one that was fail-open sat in the other 37 with nothing pointing at it. tests/mutation-coverage runs mutations in throwaway copies and reports the never-red set as a worklist. It also reports NO-OP mutations, which matters more than it sounds: a silently non-matching sed otherwise reads as a passing mutation run that tested nothing — it caught one of mine while writing this. The pr-reviewer agent gains the three rubrics that produced the highest-value findings in those rounds and were, every time, typed ad hoc into the invoking prompt: treat the PR's own claims as unverified assertions (over- AND under-claims are findings); sweep new assertions for vacuity, with the shapes that have actually shipped here; and check whether a new guard reads all CHANNELS and FIELDS of the substrate it claims to cover, reporting only when it claims coverage it lacks. Leaving those in prompts made review quality depend on the invoker remembering — the "convention only its author knows" failure this repo already documents, applied to review itself. CLAUDE.md gets two lines and no more. The session's central finding is that prose without a reader drifts, so the response to it should not be mostly prose: agent definitions are read at the moment they are relevant, and a harness function cannot be forgotten. tests/test-nix-user-sync.sh migrates its one hand-rolled site. The remaining `grep -qxF` uses in test-dockerignore-lib-allowlist and test-image-fingerprint are plain loop conditions, not assertions, and want no migration. tests/test-volume-chown-guard.sh is NOT migrated here: it is in flight on #113. It should move once that lands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMRkcVZwXpwBqjMY4bSehH
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.
Meta-work from three review rounds this week (#113 ×2, #120 ×1) that produced nine findings. Two had a structural cause with a mechanical fix — this is those two. The other seven needed a reader, and nothing here pretends otherwise.
1. Fail-open assertions → make the safe form ergonomic
assert_containsmatches a needle that is a prefix of a longer line, so an assertion about<owner> /a/bis satisfied by an unrelated-R <owner> /a/b/c— and passes while the behaviour it names has stopped happening.That shipped in
tests/test-volume-chown-guard.sh(caught in review on #113) in a file that already documented the trap in a comment. The knowledge was present; the affordance was not. Suites needing line anchoring were wrappinggrep -qxFinassert_true/assert_false— workable, but it loses the expected/got diagnostic and leaves each author to rediscover the problem.assert_line/assert_no_linemake the safe form the ergonomic one.tests/test-harness-assertions.shpins the difference between the two families, since that difference is the only reason the safe pair exists — ifassert_lineever degraded to substring matching, every migrated call site would silently go fail-open again.2. Mutation records prove the suite has teeth, not the assertions
ADR-0005 §2 requires showing a guard fail once. Measured on
tests/test-volume-chown-guard.shwith its five recorded mutations: 9 of 46 assertions ever went red — and the one that turned out to be fail-open sat in the other 37 with nothing pointing at it.tests/mutation-coverage <suite> '<cmd>'...runs mutations in throwaway copies and reports the never-red set as a worklist, not a verdict — most never-red assertions are fine, they pin things the mutations don't touch. It also reports no-op mutations, which matters more than it sounds: a silently non-matchingsedotherwise reads as a passing mutation run that tested nothing. It caught one of mine while I was writing this.3.
pr-reviewergains the rubrics that actually workedThree instructions produced the highest-value findings across those rounds, and every time I typed them ad hoc into the invoking prompt:
Leaving those in prompts made review quality depend on the invoker remembering — the "convention only its author knows" failure this repo already documents, applied to review itself.
Why CLAUDE.md gets only two lines
The session's central finding is that prose without a reader drifts. The response to that should not be mostly prose. Agent definitions are read at the moment they're relevant; a harness function cannot be forgotten. CLAUDE.md competes with ~330 lines for attention, so it gets the two facts that are genuinely authoring-time rules and nothing else.
Scope notes
tests/test-nix-user-sync.shmigrates its one hand-rolled site. The remaininggrep -qxFuses intest-dockerignore-lib-allowlistandtest-image-fingerprintare plain loop conditions, not assertions, and want no migration. (My first draft of the harness comment claimed "four suites worked around it" — that was an over-claim, corrected before commit.)tests/test-volume-chown-guard.shis not migrated here: it is in flight on fix(devcontainer): repair bind mount points' daemon-created parents #113. It should move once that lands.tests/mutation-coverageis extensionless sotests/*.shdoes not pick it up as a suite, matching thedev/convention.Verification
bash tests/run-all→ all suites green, exit 0pre-commit run --all-files→ cleantests/mutation-coverageitself🤖 Generated with Claude Code
https://claude.ai/code/session_01MMRkcVZwXpwBqjMY4bSehH