From 38fec26826bc1d5f95fe1ececc2eb11870a601af Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Thu, 16 Jul 2026 00:36:35 -0700 Subject: [PATCH] fix(engine): stop unscoped issue.linkedPrs from inflating collision risk buildCollisionReport's issue-cluster risk escalation ORed in the raw, unverified issue.linkedPrs field (parsed from contributor-controlled issue body text mentions) alongside the genuinely-scoped linkedPrs (real open PRs whose body actually closes the issue). An issue with exactly one real competing PR but multiple unrelated "PR #N" mentions in its body text was incorrectly escalated to high risk, producing a false-positive duplicate-overlap warning annotation on the PR and inflating the reported high-risk-collision count. Risk now derives only from the scoped linkedPrs list. Add a regression test covering the exact scenario: a single real linked PR plus a multi-entry issue.linkedPrs text-mention field, asserting the cluster stays medium risk. --- .../loopover-engine/src/signals/engine.ts | 2 +- test/unit/signals.test.ts | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/loopover-engine/src/signals/engine.ts b/packages/loopover-engine/src/signals/engine.ts index e7c10e8683..2d2634fbdf 100644 --- a/packages/loopover-engine/src/signals/engine.ts +++ b/packages/loopover-engine/src/signals/engine.ts @@ -845,7 +845,7 @@ export function buildCollisionReport( const items = [issueItem(issue), ...linkedPrs.map(prItem)]; clusters.set(`issue-${issue.number}`, { id: `issue-${issue.number}`, - risk: linkedPrs.length > 1 || issue.linkedPrs.length > 1 ? "high" : "medium", + risk: linkedPrs.length > 1 ? "high" : "medium", reason: `Open PR work references issue #${issue.number}.`, items, }); diff --git a/test/unit/signals.test.ts b/test/unit/signals.test.ts index aaf15b4c41..d186de36ed 100644 --- a/test/unit/signals.test.ts +++ b/test/unit/signals.test.ts @@ -123,6 +123,36 @@ describe("world-class backend signals", () => { expect(report.clusters[0]?.items.map((item) => item.number)).toContain(7); }); + it("does not escalate a single-real-PR issue cluster to high risk from unscoped issue.linkedPrs text mentions (regression)", () => { + // Issue #40 has exactly ONE real open PR (#12) that closes it via `linkedIssues`, but the issue's own + // cached `linkedPrs` (parsed from contributor-controlled issue body text, e.g. "see PR #8 and PR #9 for + // earlier discussion") mentions two PR numbers that are not actually competing work. The cluster's risk + // must be driven only by the genuinely-scoped `linkedPrs` (real open PRs), not this raw text-mention field. + const soloIssue: IssueRecord = { + repoFullName: repo.fullName, + number: 40, + title: "Solo-linked issue with unrelated body mentions", + state: "open", + authorLogin: "reporter", + labels: ["bug"], + linkedPrs: [8, 9], + }; + const solePr: PullRequestRecord = { + repoFullName: repo.fullName, + number: 12, + title: "Fix solo-linked issue", + state: "open", + authorLogin: "oktofeesh1", + authorAssociation: "NONE", + labels: ["bug"], + linkedIssues: [40], + updatedAt: "2026-04-01T00:00:00.000Z", + }; + const report = buildCollisionReport(repo.fullName, [soloIssue], [solePr]); + const cluster = report.clusters.find((entry) => entry.id === "issue-40"); + expect(cluster?.risk).toBe("medium"); + }); + it("builds maintainer burden from queue hygiene signals", () => { const collisions = buildCollisionReport(repo.fullName, issues, pullRequests); const health = buildQueueHealth(repo, issues, pullRequests, collisions);