From da7fa911b23777ed2317f9ef55f18317cecc7286 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Fri, 28 Aug 2026 15:26:12 +0200 Subject: [PATCH] An exception excuses the version it names, not the package `pinned:` is a required field precisely because an entry is an argument about ONE version. Matching on the package name alone turns a narrow, reasoned hold into a blanket exemption -- the fleet-wide typescript entry pins 6.0.3 for a reason specific to 6.0.3, and dufs-cloud/web sat on `~5.8.3`, two majors older for no stated reason, with the gate reporting it current. An entry that exists but does not cover the pin in front of it still counts as USED for the rot check. The hold is real; this repo is simply not on the held version, which is a stale pin to fix rather than an allowlist line to delete. 322 tests, 100% branch coverage. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CRykabMwPgDzFHcARoqpaK --- dep_freshness/check.py | 20 ++++++++++++++++++-- dep_freshness/tests/test_check_allowlist.py | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/dep_freshness/check.py b/dep_freshness/check.py index bd0b16a..e665349 100644 --- a/dep_freshness/check.py +++ b/dep_freshness/check.py @@ -72,10 +72,13 @@ def _excuse( excused: list[Finding] = [] for finding in findings: entry = by_label.get(finding.label) - if entry is None: + if entry is not None: + used.add(finding.label) # the entry applies here, even if it + # does not excuse this particular pin -- that is a stale pin to + # fix, not allowlist rot to delete. + if entry is None or not _covers(entry, finding): failing.append(finding) continue - used.add(finding.label) excused.append(Finding( finding.dep, finding.severity, finding.latest, finding.detail, excused=entry.reason, @@ -89,6 +92,19 @@ def _excuse( return failing, dead +def _covers(entry, finding: Finding) -> bool: + """Does this exception excuse THIS pin, or only the one it names? + + `pinned` is a required field: an entry is an argument about ONE version, + and excusing any version of the package turns a narrow, reasoned hold into + a blanket exemption. The fleet-wide typescript entry pins 6.0.3 for a + reason specific to 6.0.3, while dufs-cloud/web sat on `~5.8.3` -- two + majors older, for no stated reason -- and the gate called it current + because the package name matched. + """ + return entry.pinned in (finding.dep.pinned, finding.dep.constraint) + + def _unquarantine(finding: Finding) -> Finding | None: """Re-judge an npm finding against what pnpm will actually install. diff --git a/dep_freshness/tests/test_check_allowlist.py b/dep_freshness/tests/test_check_allowlist.py index a7e8570..586e7a6 100644 --- a/dep_freshness/tests/test_check_allowlist.py +++ b/dep_freshness/tests/test_check_allowlist.py @@ -129,3 +129,23 @@ exceptions: blocked_by: "transitive:x@1.0.0" """) assert run("--all") == 2 + + +def test_an_exception_excuses_only_the_version_it_names(repo, run, capsys): + """A held version is an argument about ONE version, not a blank cheque. + + The fleet-wide typescript entry pins 6.0.3 with a reason specific to it; + dufs-cloud/web sat on `~5.8.3`, two majors older for no stated reason, and + the gate reported it current because the label matched. + """ + write(repo, "pubspec.yaml", STALE_PUBSPEC.replace("1.5.0", "1.4.0")) + write(repo, ALLOWLIST, """\ +exceptions: + - ecosystem: pub + package: http + pinned: "1.5.0" + reason: "1.5.0 is held; 1.4.0 is not" + blocked_by: "transitive:some_pkg@1.0.0" +""") + assert run("--all") == 1 + assert "pub:http" in capsys.readouterr().err