Skip to content

fix(queue): elect the duplicate-winner from live sibling state, not the stale cache - #1406

Merged
JSONbored merged 1 commit into
mainfrom
claude/beautiful-margulis-cd0070
Jun 26, 2026
Merged

fix(queue): elect the duplicate-winner from live sibling state, not the stale cache#1406
JSONbored merged 1 commit into
mainfrom
claude/beautiful-margulis-cd0070

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

The duplicate-cluster winner (#dup-winner) was elected from the stored open-PR cache (listOtherOpenPullRequests), not live GitHub state. That cache lags GitHub, so a sibling that was closed/merged on GitHub but still cached open kept "winning" the cluster — the real lowest-OPEN PR was treated as a loser, given the duplicate_pr_risk blocker (default block), and one-shot auto-closed. This is a destructive race (audit #15).

The fix reconciles the cluster's open siblings against live GitHub state before the winner is elected, in reconcileLiveDuplicateSiblings:

  • Re-fetch the LIVE state of just the lower-numbered overlapping siblings (the only ones that can demote this PR from winner) via the new fetchLivePullRequestState (GET /pulls/{n}), and drop any no longer open, so isDuplicateClusterWinner sees ground truth.
  • Applied at both review entry points (reReviewStoredPullRequest and the pull_request webhook path) before buildPullRequestAdvisory, so the advisory's duplicate_pr_risk finding and the disposition agree.
  • Fail-open: a sibling is dropped only on a positive non-open confirmation — an unreadable live fetch keeps it, so a transient GitHub hiccup never newly spares a real loser.
  • Entirely gated behind GITTENSORY_DUPLICATE_WINNER; flag-off (default) is byte-identical with no extra API calls.

No GitHub issue — internal review-subsystem audit finding (#15). Self-contained behavioral fix to the live-merge / one-shot-close path.

Scope

  • Backend (src/) only — src/queue/processors.ts, src/github/backfill.ts
  • No API/schema change (no ui:openapi regen needed)
  • No DB/migration, no wrangler.jsonc binding/var, no UI change
  • Narrow, one coherent change

Validation

  • npm run test:ci — green (4454 passed | 4 skipped)
  • npm run test:coverage — every changed line and branch covered (verified against coverage/lcov.info), incl. the previously-uncovered linkedIssueDuplicatePullRequestsForGate non-overlap arm
  • npm audit --audit-level=moderate — 0 vulnerabilities
  • npm run typecheck / ui:typecheck — clean
  • New tests: reconcile-live-duplicate-siblings.test.ts (flag-off / no-issue / no-lower-sibling / cached-closed / live-closed-drop / live-open-keep / fail-open / multi-sibling / token-mint throws+succeeds), fetch-live-pr-state.test.ts, and added linkedIssueDuplicatePullRequestsForGate cases.

Safety

  • No secrets / wallets / hotkeys / coldkeys / trust scores / reward values added
  • Fail-open (drops a sibling only on positive non-open confirmation); flag-gated; flag-off byte-identical
  • No public-surface term leakage (no comment/check-output text changed)

…he stale cache

The duplicate-cluster winner (#dup-winner) was elected from the stored open-PR
cache (listOtherOpenPullRequests). That cache lags GitHub, so a sibling closed
or merged on GitHub but still cached `open` kept "winning" the cluster — the
real lowest-OPEN PR was treated as a loser, given the duplicate_pr_risk blocker,
and one-shot auto-closed.

Reconcile the cluster's open siblings against live GitHub state before the
winner is elected: re-fetch the LIVE state of just the lower-numbered
overlapping siblings (the only ones that can demote this PR) and drop any no
longer open, so isDuplicateClusterWinner sees ground truth. Fail-open — a
sibling is dropped only on a positive non-open confirmation, and the whole path
is gated behind GITTENSORY_DUPLICATE_WINNER, so flag-off is byte-identical with
no extra API calls.

Adds fetchLivePullRequestState; covers both reconcile arms, the new helper's
branches, and the previously-uncovered linkedIssueDuplicatePullRequestsForGate
non-overlap arm.
@dosubot dosubot Bot added the size:M label Jun 26, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.34%. Comparing base (c1db53a) to head (9ce90c2).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1406   +/-   ##
=======================================
  Coverage   95.34%   95.34%           
=======================================
  Files         192      192           
  Lines       20752    20770   +18     
  Branches     7501     7508    +7     
=======================================
+ Hits        19785    19804   +19     
  Misses        383      383           
+ Partials      584      583    -1     
Files with missing lines Coverage Δ
src/github/backfill.ts 92.93% <100.00%> (+0.01%) ⬆️
src/queue/processors.ts 87.87% <100.00%> (+0.24%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit fba397a into main Jun 26, 2026
18 checks passed
@JSONbored
JSONbored deleted the claude/beautiful-margulis-cd0070 branch June 26, 2026 00:52
@JSONbored JSONbored self-assigned this Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant