From b485965e40d1c15af7f55a27873b81e229e21220 Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman Date: Thu, 2 Apr 2026 16:49:32 +0000 Subject: [PATCH] fix(agents): prevent backlog groomer from closing PRs as duplicates of their tracking issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent evolver identified a critical systematic pattern: - Pattern: The backlog groomer was closing PRs as 'duplicates' of their linked tracking issues. A PR containing 'Closes #N' was being treated as a duplicate of issue #N, when it is actually the implementation delivery vehicle for that issue. - Evidence: At least 12 PRs were incorrectly closed (#1219, #1236, #1247, #1269, #1267, #953, #1198, #1220, #1237, #1238, #1246, #1248) — all with the same 'Duplicate Detected' comment pattern from groomer-1. - Fix: Added explicit instructions to skip PRs during duplicate detection, added a guard in the analysis loop pseudocode, and added a rule in the Important Rules section. This change requires human approval before taking effect. ISSUES CLOSED: #2180 --- .opencode/agents/ca-backlog-groomer.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.opencode/agents/ca-backlog-groomer.md b/.opencode/agents/ca-backlog-groomer.md index 5cf8b0f64..4d6fa858e 100644 --- a/.opencode/agents/ca-backlog-groomer.md +++ b/.opencode/agents/ca-backlog-groomer.md @@ -87,8 +87,13 @@ LOOP FOREVER: all_prs = query Forgejo for all open and recently closed PRs # ── Step 2: Run all analysis passes ────────────────────────── + # IMPORTANT: Filter out pull requests before duplicate detection. + # PRs are NOT issues — they deliver code for issues. A PR that + # "Closes #N" is the implementation of #N, NOT a duplicate. + issues_only = [i for i in all_issues if i.pull_request is None] + findings = [] - findings += check_duplicates(all_issues) + findings += check_duplicates(issues_only) # Issues only, never PRs findings += check_orphans(all_issues) findings += check_stale_issues(all_issues) findings += check_label_quality(all_issues) @@ -153,14 +158,25 @@ LOOP FOREVER: ### 1. Duplicate Detection -Compare every pair of open issues for similarity: +Compare every pair of open **issues** for similarity: - **Title similarity** — issues with very similar titles (>80% word overlap) - **Description similarity** — issues describing the same work - **Same branch name** — two issues with the same branch in metadata +**CRITICAL: Pull Requests are NOT duplicates of their linked issues.** +A PR that contains `Closes #N` in its body is the **implementation delivery +vehicle** for issue #N — it is NOT a duplicate. Never close a PR because it +references or implements a tracking issue. Duplicate detection applies ONLY +to issue-vs-issue comparisons, never to PR-vs-issue comparisons. + +When scanning for duplicates, **skip all pull requests entirely**. Only +compare issues (items where `pull_request` is null in the Forgejo API +response) against other issues. PRs have a different lifecycle and purpose +than issues — they deliver code, while issues track work. + **Action:** Post a comment on the newer issue noting the potential duplicate. If confidence is very high (same branch name, near-identical title), close -the newer issue as duplicate. +the newer issue as duplicate. **Never close a pull request as a duplicate.** ### 2. Orphan Detection @@ -403,6 +419,10 @@ No exceptions — every comment, every issue body, every PR description. - **Be conservative with closes.** Only close issues when you are CERTAIN the work is done or it is clearly a duplicate. When in doubt, comment instead of closing. +- **NEVER close pull requests as duplicates of their tracking issues.** + A PR that says `Closes #N` is the implementation of issue #N, not a + duplicate. PRs and issues serve fundamentally different purposes. Only + apply duplicate detection to issue-vs-issue comparisons. - **Be helpful, not noisy.** Don't post comments on every issue every cycle. Only post when you find an actionable problem. - **Respect human decisions.** If an issue has a comment from a human -- 2.52.0