Files
nanny/crates/nanny-cli/src
grenadeandClaude Opus 5 467c8d35ad feat: severity depends on where a finding is, and judgements are remembered
Two mechanisms for the same complaint: nanny's own test fixtures were being
reported as critical, and dismissing them was per-row work that came back on
the next sweep.

Severity was purely a property of the rule — an Anthropic key is critical
because Anthropic keys are critical. That answers "what kind of credential"
and not the question an operator asks, which is what a leak at this location
costs them. A finding now carries the rule's severity, the effective one,
and the context that separates them; filters, sorts and alerts use the
effective one, and every demotion can state what it was and why. Contexts
are tests, benchmarks, fixtures, examples, documentation and .example
configs.

Demote, never drop. crates/nanny-core/src/scan.rs:271 should read
"medium - test fixture", not vanish: a tool that hides things is one you
cannot reason about, and nanny's silence is only worth something if it means
something. Demotion moves a finding below alert.min_severity, which stops
the interruption without losing the record.

Only in working trees. A .md in a repo is documentation; a .md in
~/.claude/projects/*/memory/ is an agent memory, which is exactly where a
real credential ends up. In a harness store there is no way to distinguish a
transcript quoting a test file from one that printed a live key, so nothing
there is demoted.

Rust needs more than a path rule, because its convention puts a
#[cfg(test)] mod tests inside the production source file — which is the
literal case that prompted this. Matches after that attribute in a .rs file
are classified as fixtures. Deliberately Rust-only: every other language
here keeps tests in their own files, which the path rules already catch.

The second mechanism is suppression. Marking a finding ignored settles one
row, but "that is an invented token" is true of the value wherever it turns
up next, transcripts included. Suppressions are keyed by fingerprint and
optionally scoped to a path prefix, so the table holds the same one-way
salted hashes as the findings table and no values — remembering a judgement
risks nothing the database did not already. Suppressed findings are still
recorded, as ignored, so the counts do not lie about what is on disk, and
each suppression tracks what it caught so one that stopped earning its place
is visible.

  nanny ignore 849 --everywhere
  nanny ignore --under ~/git/upstream --everywhere --note "their fixtures"
  nanny suppressions / nanny unsuppress <id>
  I in the triage screen, next to i

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqHWfdMAsYu1o36tgeima
2026-09-02 16:21:22 +03:00
..