feat(review): capture per-reviewer AI votes with swap-proof attribution#8265
Conversation
…on (#8229) Block-mode dual review now attaches one vote per reviewer leg at production time (a.review <-> primary.model, b.review <-> secondary.model), immune to the tie-break judge's order swap. Ok results expose reviewerVotes; orchestration persists each as a best-effort reviewer_vote audit event (actor = model id, stance in metadata) for the later per-provider track-record stages. Advisory runs and unparseable legs cast no votes.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Logic backtestReplayed 0 historical case(s) for Backtest comparison:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8265 +/- ##
==========================================
- Coverage 92.15% 91.62% -0.53%
==========================================
Files 786 786
Lines 78814 78823 +9
Branches 23790 23796 +6
==========================================
- Hits 72630 72224 -406
- Misses 5062 5524 +462
+ Partials 1122 1075 -47
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Warning ⏸️ LoopOver review result - manual review recommendedReview updated: 2026-07-23 17:06:25 UTC
Review summary Nits — 4 non-blocking
Concerns raised — review before merging
📋 Copy for AI agents — paste into your coding agentDecision drivers
Context & advisory signals — never blocks the verdict
Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
orb-v3.3.0 shipped stable, so the beta cutter is idle until the manifest's declared target moves forward. The calibration-expansion epic's merges since (per-repo loosening #8264, reviewer votes #8265, tightening #8267, AMS loop #8270, counterfactual replay #8271) are feats — the inferred bump is minor, so the next automated snapshot targets orb-v3.4.0-beta.1.
Summary
Advances #8229 (stage 0 of 3 — the capture substrate; the would-have-routed report and flag-gated weighting follow once votes accumulate).
The dual-AI combiner never persisted which provider voted which way, and its disagreement tie-break judge re-runs the pair order-swapped — so any capture at slot-interpretation time would misattribute votes. This PR attaches votes where slot↔model is unambiguous by construction:
LoopOverAiReviewResultok-branch gainsreviewerVotes: { reviewer, votedFail }[], populated at leg production time (a.review↔primary.model,b.review↔secondary.model) in the dual path and on the single-reviewer block path. Advisory-only runs and unparseable legs cast no votes — never a fabricated stance.reviewer_voteaudit event (actor = model id, target =owner/repo#N, stance in metadata) after an ok result; a rejecting write is swallowed and never touches the review outcome.computeProviderTrackRecords(calibration: per-provider reviewer track records from the consensus corpus #8228) directly in stage 1.Validation
npm run test:cigreen (TEST_CI_EXIT=0) on a branch rebased onto current main, plusnpm audit --audit-level=moderate.src/services/ai-review.tsandsrc/queue/ai-review-orchestration.ts(verified via lcov against the exact diff hunks): split-case attribution, unparseable-leg no-vote, advisory-empty, persistence rows, and the swallowed-rejection arm each have both sides exercised.test/unit/reviewer-vote-capture.test.tspins the persistence contract; runner-side invariants live beside the existing combiner tests intest/unit/ai-review.test.ts.