v1.20.0: report findings your change introduced
Diff mode kept only findings whose anchor line changed. Multiline rules report where a construct starts, so an edit could create a problem and have it dropped:
export function load() {
try {
return read();
} catch (err) { // <- finding reported here, line unchanged
console.error(err); // <- the only line you changed
}
}Full scan caught it. --diff exited 0. In the CI mode, that is a false clean.
What changed
The file is now scanned as it was before your change, and a finding is kept when its anchor changed, as before, or when the file did not already contain an equivalent one.
| change | result |
|---|---|
| catch body edited, anchor line unchanged | reported |
| function grows 80 → 81 lines | reported (its declaration never changed) |
build-time guard removed above an untouched console.log |
reported |
| one line edited inside an already-200-line function | quiet — that debt is not yours |
The alternative, matching a multiline finding whenever any line in its span changed, would have warned that a 200-line function is too long on every pull request that touched one line of it, forever, for code the author did not write.
Base content comes from the index for --diff and from HEAD for --staged, read with a single cat-file --batch. A 250-file --diff runs in 0.58s, level with v1.19.0.
One contract decision worth knowing
Identical findings carry nothing that tells them apart. When a file already has one and gains another, that group falls back to changed-line matching, so the new one may go unreported.
That is deliberate. Both heuristics I tried, encounter order and proximity to the change, ended up reporting the older copy — code the author never touched. A missed finding is recoverable; false blame is what gets a linter deleted. A group with nothing equivalent in the base is not ambiguous and is reported in full.
Known limitations
Documented in the README. A deletion-only change is invisible, since only added lines enter the diff map — this is unchanged from v1.19.0, not new. A staged move below git's rename-similarity threshold reads as a new file. An ambiguous duplicate group falls back to anchor matching, and a baseline can hide it for the same reason.
420 tests, up from 407. Three adversarial review rounds; rounds 2 and 3 each found real defects in the previous round, including a 13x slowdown and false blame on renamed files, all fixed before release.