fix(agents): add two-phase claim protocol to prevent duplicate PR reviews #1326

Merged
freemo merged 1 commits from improvement/pr-reviewer-double-claim-prevention into master 2026-04-03 03:41:30 +00:00
+34 -6
View File
@@ -196,17 +196,37 @@ LOOP FOREVER:
# Take up to N work items
batch = work_items[:N]
# Claim all PRs in the batch BEFORE dispatching (distributed lock)
# Claim all PRs in the batch using two-phase locking protocol
claimed_items = []
for item in batch:
if item.type in ("review", "re_review"):
token = f"{INSTANCE_ID}-{item.pr.number}-{timestamp}"
post comment on PR:
"Review claimed by reviewer pool instance <INSTANCE_ID>.
Dispatching independent code review.
"🔒 Review claimed by <INSTANCE_ID> [claim-token: <token>]
---
**Automated by CleverAgents Bot**
Supervisor: PR Review | Agent: ca-continuous-pr-reviewer"
# Phase 2: Wait 5 seconds, then verify claims
wait 5 seconds
for item in batch:
if item.type in ("review", "re_review"):
comments = re-fetch PR comments
competing_claims = [c for c in comments if "claim-token:" in c.body
and c.user == our_user
and c.body does not contain our token]
if competing_claims exist:
their_token = extract claim-token from competing_claims[0]
our_token = f"{INSTANCE_ID}-{item.pr.number}-{timestamp}"
if our_token > their_token:
# We lose — delete our claim and skip
delete our claim comment
continue
claimed_items.append(item)
batch = claimed_items # Only dispatch for PRs we successfully claimed
# Dispatch N parallel ca-pr-self-reviewer sessions (fire-and-forget)
active_reviews = {} # pr_number -> session_id
for item in batch:
@@ -313,12 +333,20 @@ Multiple reviewer pools or standalone reviewers may run simultaneously. To
prevent duplicate reviews:
1. **Claim via comment.** Before dispatching a reviewer for a PR, post a
comment: `"Review claimed by reviewer pool instance <INSTANCE_ID>."`
comment: `"🔒 Review claimed by <INSTANCE_ID> [claim-token: <UNIQUE_TOKEN>]"`
where `<UNIQUE_TOKEN>` is a unique value like `<INSTANCE_ID>-<PR_NUMBER>-<TIMESTAMP>`.
2. **Check before claiming.** Always fetch fresh comments and check for
existing claims before posting your own.
3. **Race condition tolerance.** If a dispatched reviewer finds the PR was
3. **Verify after claiming (double-check protocol).** After posting your
claim comment, wait 5 seconds, then re-fetch the PR comments. If another
claim comment appeared from a different instance within the same window,
the instance with the **lexicographically smaller claim-token wins**. The
losing instance must delete its claim comment and skip that PR. This
two-phase protocol eliminates the race condition where two pools claim
the same PR within seconds of each other.
4. **Race condition tolerance.** If a dispatched reviewer finds the PR was
already reviewed by someone else, it should yield gracefully.
4. **Stale claims.** If a claim comment is older than 30 minutes with no
5. **Stale claims.** If a claim comment is older than 30 minutes with no
subsequent review activity, consider the claim stale and proceed with
a new claim.