diff --git a/src/drift/__tests__/path-false-positives.test.ts b/src/drift/__tests__/path-false-positives.test.ts index 6dd8713d..bb3f39d2 100644 --- a/src/drift/__tests__/path-false-positives.test.ts +++ b/src/drift/__tests__/path-false-positives.test.ts @@ -60,15 +60,20 @@ describe("MISSING_PATH false positives", () => { ).toEqual([]); }); - // Not part of #143. A trailing version number reads as a file extension to - // the guard above, so `release/2.1.0` never reaches the unrooted check and is - // reported as a missing path. Tracked separately; unskip with the fix. - it.skip("does not claim a version-shaped branch name", () => { + it("does not claim a version-shaped branch name", () => { expect( - missingPaths("# Release\n\n- Work landed on `release/2.1.0` and `python/3.11`\n") + missingPaths( + "# Release\n\n- Work landed on `release/2.1.0`, `python/3.11`, and `node/20.11`\n" + ) ).toEqual([]); }); + it("still claims a missing file with an alphabetic extension", () => { + // Tightening the extension check must not treat `docs/foo.bar` as unrooted + // prose: `.bar` is a file type, so the claim stays a missing path. + expect(missingPaths("# Docs\n\n- See `docs/foo.bar`\n")).toEqual(["docs/foo.bar"]); + }); + it("does not claim a pseudo-path pair such as overall/overall", () => { expect(missingPaths("# Stats\n\n- Rating shown as `overall/overall`\n")).toEqual([]); }); diff --git a/src/drift/checkers/path.ts b/src/drift/checkers/path.ts index 1d862daf..4903feb9 100644 --- a/src/drift/checkers/path.ts +++ b/src/drift/checkers/path.ts @@ -94,7 +94,10 @@ function isUnrootedReference( const trimmed = value.replace(/\/+$/, ""); const isDirectoryRef = trimmed !== value; if (!trimmed.includes("/") && !isDirectoryRef) return false; - if (/\.[A-Za-z0-9]+$/.test(trimmed)) return false; + // A trailing numeric-only segment is a version (`release/2.1.0`, + // `python/3.11`), not a file type. Require an alphabetic character so + // `.ts` still counts as an extension and those tokens reach the prose check. + if (/\.[A-Za-z0-9]*[A-Za-z][A-Za-z0-9]*$/.test(trimmed)) return false; const first = trimmed.split("/")[0]; if (!first || first.startsWith("@") || first === "." || first === "..") return false;