Skip to content

test(audit): pin the suppressed_count zero guard and list_attachments - #89

Merged
plusky merged 1 commit into
mainfrom
test/audit-counter-coverage
Aug 12, 2026
Merged

test(audit): pin the suppressed_count zero guard and list_attachments#89
plusky merged 1 commit into
mainfrom
test/audit-counter-coverage

Conversation

@plusky

@plusky plusky commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes #87.

Two paths in the audit suppression counter had no coverage. Deleting note_suppressed_count's if n == 0 { return; } early return, or deleting the counter call in list_attachments, each left the whole suite green.

That guard is what stops a suppression-free call from merging ServedFiltered. Every call site passes total - filtered.len(), which is 0 on the common path — so without it, every bug_comments, summarize_bug and list_attachments record would claim the response was filtered whether or not anything was withheld. verdict is the field an operator filters on to find calls where the guard actually did something; collapsing it is the same silent-but-valid defect class as #68.

No production code changes. Tests and the DESIGN.md test inventory only.

The three tests

Test Pins
bug_comments_with_nothing_filtered_stays_served_and_counts_zero a clean call stays served at count 0
list_attachments_counts_the_private_metadata_it_dropped dropped private metadata is counted over an empty suppressed_ids — the shape only this tool produces
list_attachments_with_nothing_private_stays_served_and_counts_zero a clean call over two public attachments stays served at count 0

The third serves real rows rather than an empty list deliberately: total == filtered.len() == 2, so the recorded zero means nothing was withheld, not nothing existed to withhold. An empty-list fixture would sleep through a note_suppressed_count(total) mutation.

It also covers the call site rather than the guard, which a guard-only test cannot do — see the review section.

Mutation evidence

"Fails if the guard is removed" is precisely what a green CI run cannot demonstrate, so every test here was mutation-proven rather than assumed:

Mutation Result
zero guard deleted both zero tests fail on the verdict
list_attachments counter call deleted private-metadata test fails, Served vs ServedFiltered
total instead of total - filtered.len() both attachment tests fail — 3 vs 2, and ServedFiltered vs Served
note_redacted("attachment.is_private") added public-attachment test fails
note_verdict(ServedFiltered) added same
note_suppressed(empty) added same
guard relocated to a bug_comments-only call-site condition only the list_attachments test fails

Adversarial review before opening

Three reviewers attacked the uncommitted diff — test-validity, invariants, and convention lenses. All three returned MERGE-SAFE; the test-validity lens also ran a pre-diff control, confirming the first three mutations were green at HEAD, so this genuinely adds six kills rather than restating existing coverage.

The substantive finding overturned my own call. I had omitted a list_attachments zero-path test as redundant, reasoning the zero guard is a single shared early return already killed by test 1. That was half right: anything inside note_suppressed_count is covered, but adding one plausible line to the list_attachments audit block — note_redacted("attachment.is_private"), an edit someone would make for good reasons — makes every call of that tool record served_filtered with all 423 tests green. A second reviewer found the mirror image: relocating the zero guard to a call-site condition around bug_comments only, also green. Both are exactly #87's failure mode at the exact tool #87 named as uncovered, so the test landed here rather than as a follow-up.

Also applied: a DESIGN.md wording fix (the clause claimed no record assertion had reached list_attachments, but every_routed_tool_writes_exactly_one_record_per_call does — the true statement is that none had reached its guard fields), a missing entry in DESIGN.md's list of causes for an absent guard.rule, and an audit-file canary assertion to match the envelope one.

Verified under refutation and left alone: both original tests pass for the right reason, rule == Some("default") is a documented contract literal and not brittle, the new mocks are load-bearing without .expect(1) (breaking either matcher turns the test red), and four adjacent mutations I asked about all die on pre-existing tests. 25 consecutive runs, zero flakes.

On the guard.rule clearing this PR's fixture exhibits — a list_attachments call that drops private metadata records rule: None though the default granted the bug — the invariants lens argued it is correct by design: rule names what decided the record's verdict, and the filtering was decided by a global plus an absent request flag, not by a rule. Writing "default" beside served_filtered would assert that rule did the filtering. Separate slots for "what decided access" and "what decided filtering" is a schema change already deferred to #34.

Verification

cargo fmt --check, both clippy invocations, cargo test --workspace --all-targets --locked (424 passed, 0 failed) and cargo deny check all pass — re-run independently, not taken on report. cargo doc --no-deps --workspace emits the same 4 pre-existing warnings as main.

Follow-up filed

#88summarize_bug's if !hidden.is_empty() guard can be deleted with the suite green, the twin of the bug_comments hole this PR closes as a side effect.

Two paths in the audit suppression counter had no coverage: deleting
note_suppressed_count's `if n == 0 { return; }` early return, or deleting
the counter call in list_attachments, each left the whole suite green.
That guard is what stops a suppression-free call from merging
ServedFiltered, so without it every bug_comments, summarize_bug and
list_attachments record would claim the response was filtered whether or
not anything was withheld — and verdict is the field an operator filters
on to find the calls where the guard actually did something.

Add three record-level tests. A clean bug_comments call stays served
with a zero count; a list_attachments call whose private metadata the I5
gate dropped records that count over an EMPTY id list, the shape only
that tool produces; and a list_attachments call over two PUBLIC
attachments stays served at zero. The third serves real rows rather than
an empty list on purpose: total == filtered.len() == 2 means the
recorded zero says nothing was withheld, not that nothing existed to
withhold.

The third test covers the call site rather than the guard, which a
guard-only test cannot do. Adding any single unconditional note to the
list_attachments audit block — note_redacted, note_verdict, or
note_suppressed over an empty iterator — makes every call of that tool
record served_filtered, and each of those left the full suite green
before this commit.

Every test here was mutation-proven rather than assumed, since "fails if
the guard is removed" is exactly what a green CI run cannot show:

  zero guard deleted        -> both zero tests fail on the verdict
  counter call deleted      -> the private-metadata test fails, served
                               vs served_filtered
  total, not total-filtered -> both attachment tests fail, 3 vs 2 and
                               served_filtered vs served
  note_redacted added       -> the public-attachment test fails
  note_verdict added        -> same
  note_suppressed(empty)    -> same
  guard moved to a bug_comments-only call-site condition -> only the
                               list_attachments test fails

No production code changes.

Closes #87
@plusky
plusky merged commit 8b1fae9 into main Aug 12, 2026
11 checks passed
@plusky
plusky deleted the test/audit-counter-coverage branch August 12, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

note_suppressed_count's zero guard is untested: nothing pins that a clean call stays served

1 participant