From a6bf6145cbea3236136a7880154b8d189b8ccff6 Mon Sep 17 00:00:00 2001 From: pr-relay Date: Tue, 18 Aug 2026 09:17:12 +0000 Subject: [PATCH] Ignore inline-code closing PR references --- .../loopover-miner/lib/self-review-context.ts | 7 +++++ test/unit/miner-self-review-context.test.ts | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/packages/loopover-miner/lib/self-review-context.ts b/packages/loopover-miner/lib/self-review-context.ts index 847643dfa3..6701c9a346 100644 --- a/packages/loopover-miner/lib/self-review-context.ts +++ b/packages/loopover-miner/lib/self-review-context.ts @@ -264,8 +264,15 @@ async function fetchRepositoryRecord(target: any, resolved: any) { // miner skipped an available issue (the host's own #issue-body-pr-mention-pollution fix, never ported here). const LINKED_PR_PATTERN = /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+(?:PR|pull request)\s+#(\d+)\b/gi; function extractLinkedPrNumbers(body: any) { + const inlineCodeSpanRanges = [...body.matchAll(/`[^`\n]*`/g)].map((match: any) => ({ + start: match.index, + end: match.index + match[0].length, + })); const numbers = []; for (const match of body.matchAll(LINKED_PR_PATTERN)) { + const matchStart = match.index; + const matchEnd = matchStart + match[0].length; + if (inlineCodeSpanRanges.some((range: { start: number; end: number }) => matchStart < range.end && matchEnd > range.start)) continue; const number = Number(match[1]); if (Number.isInteger(number) && number > 0) numbers.push(number); } diff --git a/test/unit/miner-self-review-context.test.ts b/test/unit/miner-self-review-context.test.ts index 834188d4c0..b7f4458150 100644 --- a/test/unit/miner-self-review-context.test.ts +++ b/test/unit/miner-self-review-context.test.ts @@ -1058,6 +1058,36 @@ describe("live gate thresholds probe (#6487)", () => { }); }); +describe("extractLinkedPrNumbers — inline-code exclusion (#10339)", () => { + it("REGRESSION (#10339): a backtick-quoted closing PR reference is excluded", async () => { + const fetchImpl = routedFetch({ + "/repos/acme/widgets/issues": () => + jsonResponse([issuePayload({ body: "See the template example `Closes PR #501` before submitting." })]), + "/repos/acme/widgets/pulls": () => jsonResponse([]), + "/repos/acme/widgets": () => jsonResponse(REPO_PAYLOAD), + "raw.githubusercontent.com": () => jsonResponse(null, 404), + "api.gittensor.io/miners": () => jsonResponse([]), + }); + + const result = await fetchSelfReviewContext("acme/widgets", { fetchImpl: fetchImpl as never, loopoverAuth: null }); + expect(result.issues[0]?.linkedPrs).toEqual([]); + }); + + it("REGRESSION (#10339): a genuine closing PR reference outside inline code still counts", async () => { + const fetchImpl = routedFetch({ + "/repos/acme/widgets/issues": () => + jsonResponse([issuePayload({ body: "Closes PR #501 (template example: `Closes PR #999`)" })]), + "/repos/acme/widgets/pulls": () => jsonResponse([]), + "/repos/acme/widgets": () => jsonResponse(REPO_PAYLOAD), + "raw.githubusercontent.com": () => jsonResponse(null, 404), + "api.gittensor.io/miners": () => jsonResponse([]), + }); + + const result = await fetchSelfReviewContext("acme/widgets", { fetchImpl: fetchImpl as never, loopoverAuth: null }); + expect(result.issues[0]?.linkedPrs).toEqual([501]); + }); +}); + describe("extractLinkedIssueNumbers — parity with the host's byte-range exclusion + URL form (#7527)", () => { it("counts the bare #N and same-repo qualified owner/repo#N forms, rejecting a different-repo qualified ref", () => { expect(extractLinkedIssueNumbers("Closes #7", "acme/widgets")).toEqual([7]);