⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
src/signals/contributor-open-pr-monitor.ts's duplicatePronePullNumbers groups a repo's open PRs by
a normalized version of their title, and flags every PR in any group of 2+ as duplicate_prone:
function duplicatePronePullNumbers(openPullRequests: PullRequestRecord[]): Set<number> {
const flagged = new Set<number>();
const byNormalizedTitle = new Map<string, PullRequestRecord[]>();
for (const pr of openPullRequests) {
const key = normalizeTitle(pr.title);
const bucket = byNormalizedTitle.get(key) ?? [];
bucket.push(pr);
byNormalizedTitle.set(key, bucket);
}
for (const bucket of byNormalizedTitle.values()) {
if (bucket.length < 2) continue;
for (const pr of bucket) flagged.add(pr.number);
}
// ...
}
function normalizeTitle(title: string): string {
return title
.toLowerCase()
.replace(DRAFT_TITLE_PATTERN, "")
.replace(/^wip:\s*/i, "")
.replace(/[^a-z0-9]+/g, " ")
.trim();
}
normalizeTitle strips every character that isn't [a-z0-9] down to a single space, then trims. A PR
title made up entirely of punctuation, emoji, or other non-alphanumeric characters — e.g. "...",
"!!!", "---", "🎉🎉🎉" — normalizes to the empty string "". Any two (or more) open PRs on the
same repo whose titles both happen to normalize to "" collide into the same map bucket and get
flagged as duplicate_prone, even though their real titles have nothing in common and the PRs may be
about completely unrelated changes.
This flag is not cosmetic-only: duplicatePronePullNumbers's output feeds
mapPendingClassToWorkClassification → nextStepsForClassification (same file), which tells the
contributor to check the flagged PRs for overlap and "close or consolidate duplicates" — a misleading
and potentially harmful suggestion for two genuinely unrelated PRs that only coincidentally share an
empty normalized title.
No existing test in test/unit/contributor-open-pr-monitor.test.ts covers this case — the file's
duplicate-detection tests only exercise real-word title collisions and the draft-marker-stripping
regression.
Requirements
duplicatePronePullNumbers must never flag two PRs as duplicate-prone solely because both of their
titles normalize to the empty string. A normalized title of "" must be excluded from the
duplicate-grouping logic entirely (it must not be treated as a valid grouping key that two or more PRs
can collide into).
- This must not change behavior for any pair of PRs whose titles normalize to the same NON-EMPTY string
— that is the intended, working case and must continue to flag as duplicate_prone exactly as today.
- The separate
wip/duplicate-label-based flagging in the same function (the wip block below the
title-grouping loop) must be unchanged.
Deliverables
Both Deliverables are required in the same PR.
Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ patch coverage on every changed line and branch under
src/**. src/signals/contributor-open-pr-monitor.ts is inside src/**. Both new/updated tests above
must exercise the actual empty-normalized-title collision (not just assert on normalizeTitle's return
value in isolation) so the fix is verified end-to-end through duplicatePronePullNumbers's real return
value.
Expected Outcome
Two open PRs whose titles both happen to normalize to an empty string (all-punctuation, all-emoji, or
otherwise entirely non-alphanumeric titles) are never flagged as duplicate-prone of each other. A
contributor working on such a PR no longer sees a misleading "check overlap / close or consolidate
duplicates" suggestion generated purely from an empty-string coincidence.
Links & Resources
src/signals/contributor-open-pr-monitor.ts — duplicatePronePullNumbers and normalizeTitle
(around lines 237-262).
test/unit/contributor-open-pr-monitor.test.ts — the existing duplicate-title test suite to extend.
Context
src/signals/contributor-open-pr-monitor.ts'sduplicatePronePullNumbersgroups a repo's open PRs bya normalized version of their title, and flags every PR in any group of 2+ as
duplicate_prone:normalizeTitlestrips every character that isn't[a-z0-9]down to a single space, then trims. A PRtitle made up entirely of punctuation, emoji, or other non-alphanumeric characters — e.g.
"...","!!!","---","🎉🎉🎉"— normalizes to the empty string"". Any two (or more) open PRs on thesame repo whose titles both happen to normalize to
""collide into the same map bucket and getflagged as
duplicate_prone, even though their real titles have nothing in common and the PRs may beabout completely unrelated changes.
This flag is not cosmetic-only:
duplicatePronePullNumbers's output feedsmapPendingClassToWorkClassification→nextStepsForClassification(same file), which tells thecontributor to check the flagged PRs for overlap and "close or consolidate duplicates" — a misleading
and potentially harmful suggestion for two genuinely unrelated PRs that only coincidentally share an
empty normalized title.
No existing test in
test/unit/contributor-open-pr-monitor.test.tscovers this case — the file'sduplicate-detection tests only exercise real-word title collisions and the draft-marker-stripping
regression.
Requirements
duplicatePronePullNumbersmust never flag two PRs as duplicate-prone solely because both of theirtitles normalize to the empty string. A normalized title of
""must be excluded from theduplicate-grouping logic entirely (it must not be treated as a valid grouping key that two or more PRs
can collide into).
— that is the intended, working case and must continue to flag as
duplicate_proneexactly as today.wip/duplicate-label-based flagging in the same function (thewipblock below thetitle-grouping loop) must be unchanged.
Deliverables
duplicatePronePullNumbers(ornormalizeTitle's caller) skips the empty-string normalized-titlebucket when deciding which PRs to flag, verified by a new test asserting that two open PRs titled
"..."and"🎉🎉🎉"(or any two punctuation/emoji-only titles that both normalize to"") areNOT included in the returned
Set<number>.(e.g. both titled
"Fix bug"and"fix bug!!", which normalize to the same non-empty string)are still correctly flagged as duplicate-prone after this fix — the fix must not weaken the real
detection case.
Both Deliverables are required in the same PR.
Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ patch coverage on every changed line and branch under
src/**.src/signals/contributor-open-pr-monitor.tsis insidesrc/**. Both new/updated tests abovemust exercise the actual empty-normalized-title collision (not just assert on
normalizeTitle's returnvalue in isolation) so the fix is verified end-to-end through
duplicatePronePullNumbers's real returnvalue.
Expected Outcome
Two open PRs whose titles both happen to normalize to an empty string (all-punctuation, all-emoji, or
otherwise entirely non-alphanumeric titles) are never flagged as duplicate-prone of each other. A
contributor working on such a PR no longer sees a misleading "check overlap / close or consolidate
duplicates" suggestion generated purely from an empty-string coincidence.
Links & Resources
src/signals/contributor-open-pr-monitor.ts—duplicatePronePullNumbersandnormalizeTitle(around lines 237-262).
test/unit/contributor-open-pr-monitor.test.ts— the existing duplicate-title test suite to extend.