diff --git a/.opencode/agents/ca-continuous-pr-reviewer.md b/.opencode/agents/ca-continuous-pr-reviewer.md index 572ffa09e..d453eb014 100644 --- a/.opencode/agents/ca-continuous-pr-reviewer.md +++ b/.opencode/agents/ca-continuous-pr-reviewer.md @@ -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 . - Dispatching independent code review. + "🔒 Review claimed by [claim-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 ."` + comment: `"🔒 Review claimed by [claim-token: ]"` + where `` is a unique value like `--`. 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.