From 5b31aac97e8a713bce73bb9cc4e86048f70dade8 Mon Sep 17 00:00:00 2001 From: pr-relay Date: Sun, 16 Aug 2026 19:52:38 +0000 Subject: [PATCH] signals: ignore empty normalized duplicate titles --- src/signals/contributor-open-pr-monitor.ts | 1 + ...ibutor-open-pr-monitor-empty-title.test.ts | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/unit/contributor-open-pr-monitor-empty-title.test.ts diff --git a/src/signals/contributor-open-pr-monitor.ts b/src/signals/contributor-open-pr-monitor.ts index 4fd8cb3d37..62fa608b34 100644 --- a/src/signals/contributor-open-pr-monitor.ts +++ b/src/signals/contributor-open-pr-monitor.ts @@ -239,6 +239,7 @@ function duplicatePronePullNumbers(openPullRequests: PullRequestRecord[]): Set(); for (const pr of openPullRequests) { const key = normalizeTitle(pr.title); + if (!key) continue; const bucket = byNormalizedTitle.get(key) ?? []; bucket.push(pr); byNormalizedTitle.set(key, bucket); diff --git a/test/unit/contributor-open-pr-monitor-empty-title.test.ts b/test/unit/contributor-open-pr-monitor-empty-title.test.ts new file mode 100644 index 0000000000..bb19947737 --- /dev/null +++ b/test/unit/contributor-open-pr-monitor-empty-title.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { __contributorOpenPrMonitorInternals } from "../../src/signals/contributor-open-pr-monitor"; +import type { PullRequestRecord } from "../../src/types"; + +function pr(number: number, title: string, labels: string[] = []): PullRequestRecord { + return { + repoFullName: "acme/widgets", + number, + title, + state: "open", + authorLogin: "contributor", + labels, + linkedIssues: [], + } as PullRequestRecord; +} + +describe("duplicate-prone title grouping", () => { + it("does not group unrelated titles whose normalized form is empty", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(1, "..."), pr(2, "🎉🎉🎉")]); + expect([...flagged]).toEqual([]); + }); + + it("still groups matching non-empty normalized titles", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(3, "Fix bug"), pr(4, "fix bug!!")]); + expect([...flagged].sort((a, b) => a - b)).toEqual([3, 4]); + }); + + it("still flags explicit wip and duplicate labels", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(5, "...", ["wip"]), pr(6, "🎉", ["duplicate"])]); + expect([...flagged].sort((a, b) => a - b)).toEqual([5, 6]); + }); +});