Skip to content

feat(reviewer-report): clearer scorecard — count review events (Total PRs · Reviews · Rate-limited · No response) - #1236

Merged
don-petry merged 3 commits into
mainfrom
claude/reviewer-scorecard-buckets
Jul 14, 2026
Merged

don-petry merged 3 commits into
mainfrom
claude/reviewer-scorecard-buckets

Conversation

@don-petry

Copy link
Copy Markdown
Collaborator

What & why

Follow-up to #1196. The Participation % and Resolved % columns were confusing, so the scorecard now reports the metric you actually want: a per-reviewer partition of the eligible (non-draft) PRs into three buckets that always sum to the eligible count.

Bucket Meaning
Reviewed the bot delivered a real review/comment
Rate-limited the bot's sole action was to decline (out of quota) — it refused to review
No response the bot never appeared on the PR

Correctness fix (the important part)

Previously a PR was flagged "rate-limited" if the bot posted any rate-limit text — even when it also gave a real review. That massively overstated refusals. New logic classifies a PR as a refusal only when the bot's real_responses == 0.

On live 30-day data for .github-private:

Reviewer Reviewed Rate-limited (old → new) No response
Gemini 70 1 4
Copilot 62 1 12
SonarCloud 69 0 6
Codex 6 63 6
CodeRabbit 56 147 → 16 3

CodeRabbit's refusals drop from a misleading 147 to a true 16 (it reviews most PRs despite occasional limits), while Codex's genuine 63/75 refusal rate is now isolated cleanly.

Changes

  • Normalization tags each submission as a refusal vs real response; a rate-limit-only touch is a refusal, a real review alongside a rate-limit comment still counts as Reviewed.
  • Latency is now measured to the first real response, so quota notices don't pollute the p50/p95.
  • Dropped the redundant "Reliability & no-shows" section (folded into the buckets) and removed Resolved/reactions from the headline (still computed into the snapshot).
  • Docs updated to the new metric model.

Validation

  • shellcheck --severity=warning -x clean
  • tests/reviewer_report.bats — 24/24 (added: three-bucket sum invariant, refusal-vs-review classification, and "real review + rate-limit comment ⇒ reviewed")
  • Re-ran end-to-end on live org data — output above.

🤖 Generated with Claude Code

…imited / No response

Replaces the confusing "Participation %" and "Resolved %" columns with a clear
per-reviewer partition of the eligible (non-draft) PRs into three buckets that
always sum to the eligible count:

- Reviewed        — the bot delivered a real review/comment
- Rate-limited    — the bot's SOLE action was to decline (out of quota)
- No response     — the bot never appeared

Correctness fix: previously a PR was flagged "rate-limited" if the bot posted
ANY rate-limit text, even when it also gave a real review — massively
overstating refusals (e.g. CodeRabbit showed 147 "rate-limited" while actually
reviewing most of them). Now a PR is a refusal only when the bot's real_responses
== 0. On live data this corrects CodeRabbit from 147 → 16 refusals and isolates
Codex's genuine 63/75 refusal rate.

Normalization now tags each submission as a refusal vs real response; latency is
measured to the first REAL response so quota notices no longer pollute the
percentiles. Thread-resolution and reactions are still computed into the snapshot
but dropped from the headline table for legibility. Dropped the now-redundant
"Reliability & no-shows" section (folded into the buckets).

Tests: 24/24 (added bucket-sum invariant, refusal-vs-review classification, and
"real review alongside a rate-limit comment still counts as reviewed").

Follow-up to #1196.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@don-petry
don-petry requested a review from a team as a code owner July 14, 2026 20:51
Copilot AI review requested due to automatic review settings July 14, 2026 20:51
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@don-petry, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 56bd5942-10be-40e2-af08-ef30003ecc06

📥 Commits

Reviewing files that changed from the base of the PR and between bfa57ea and afac2c2.

📒 Files selected for processing (5)
  • docs/reviewer-report.md
  • scripts/reviewer_report.sh
  • tests/fixtures/reviewer_jsonl/repo1.jsonl
  • tests/fixtures/reviewer_jsonl/repo2.jsonl
  • tests/reviewer_report.bats
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/reviewer-scorecard-buckets

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) July 14, 2026 20:52

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the reviewer report generation to partition eligible pull requests into three distinct buckets per reviewer: Reviewed, Rate-limited, and No response. This improves the accuracy of the metrics by separating out-of-quota refusals from absent work. The review feedback highlights two valuable improvement opportunities: optimizing the JQ aggregation logic from $O(N \times M)$ to $O(N + M)$ using a lookup map, and ensuring temporary files in BATS tests are created within $BATS_TEST_TMPDIR for automatic cleanup.

Comment thread scripts/reviewer_report.sh Outdated
Comment thread tests/reviewer_report.bats Outdated
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-14T21:53:14Z.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the deterministic third-party reviewer scorecard to report a clearer three-bucket partition of eligible PRs per reviewer (Reviewed / Rate-limited / No response), fixing the prior over-counting of “rate-limited” when a real review was also present.

Changes:

  • Reworked normalization to split bot activity into real_responses vs refusals, and measure latency only to the first real response.
  • Updated snapshot aggregation + rendering to output the three-bucket scorecard (and WoW deltas on Reviewed/Rate-limited).
  • Updated fixtures, bats tests, and documentation to reflect the new metric model and invariants.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/reviewer_report.sh Implements the new refusal-vs-real-response normalization, three-bucket aggregation, and updated scorecard rendering.
tests/reviewer_report.bats Adds/updates unit tests for refusal classification, bucket-sum invariant, and updated rendered headers/snapshot keys.
tests/fixtures/reviewer_jsonl/repo1.jsonl Updates normalized fixture records to the new real_responses/refusals + latency semantics.
tests/fixtures/reviewer_jsonl/repo2.jsonl Same as repo1 fixture update for the new normalized schema.
docs/reviewer-report.md Updates the design doc to describe the three-bucket model and updated latency definition.

Comment thread scripts/reviewer_report.sh Outdated
…ommit reviews)

A PR with multiple commits gets re-reviewed on each push, producing multiple
review submissions by the same reviewer. The bucket model collapsed these to
one "reviewed" PR, hiding real activity — on live data CodeRabbit shows 193
review events across 97 PRs (up to 11 on a single PR), and Codex shows 121
rate-limit refusals vs 11 real reviews.

Scorecard columns are now: Total PRs · Reviews · ✅/🔄 · Rate-limited · No response.
  - Reviews       = count of real review submissions, EACH occurrence
  - Rate-limited  = count of refusal events, EACH occurrence
  - No response   = eligible PRs the bot never engaged with at all
The per-PR bucket fields (reviewed_prs / refused_prs / no_response_prs) remain in
the snapshot for the sum-to-eligible invariant and history; the headline now
surfaces event counts. SonarCloud posts status-check comments rather than reviews,
so its Reviews reads 0 by design (noted in the report).

WoW deltas now track Reviews and Rate-limited event counts. Tests: 26/26 (added
event-count aggregation + a "PR reviewed twice = 2 review events" case).
@don-petry don-petry changed the title refactor(reviewer-report): three-bucket scorecard — Reviewed / Rate-limited / No response feat(reviewer-report): clearer scorecard — count review events (Total PRs · Reviews · Rate-limited · No response) Jul 14, 2026
@don-petry

Copy link
Copy Markdown
Collaborator Author

Update: count review events, not distinct PRs

Per follow-up feedback — a PR with multiple commits is re-reviewed on each push, so a reviewer submits many reviews on one PR. The scorecard now counts each event.

Columns: Total PRs · Reviews · ✅/🔄 · Rate-limited · No response

Live 30-day data (.github-private) — note how event-counting surfaces activity the per-PR view hid:

Reviewer Total PRs Reviews ✅/🔄 Rate-limited No response
Gemini 100 78 0/0 10 3
Copilot 100 84 0/0 13 11
SonarCloud 100 0 0/0 0 5
Codex 100 11 0/0 121 7
CodeRabbit 100 193 54/25 82 3
  • CodeRabbit submits 193 reviews across ~97 PRs (up to 11 on one PR) — the per-PR bucket showed only ~97.
  • Codex refuses (121) ~11× more than it reviews (11).
  • SonarCloud posts status-check comments, not GitHub reviews → Reviews reads 0 by design (footnoted).

reviewed_prs/refused_prs/no_response_prs still live in the snapshot (sum-to-eligible invariant preserved). Tests now 26/26.

@don-petry
don-petry disabled auto-merge July 14, 2026 21:05
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) July 14, 2026 21:10
@sonarqubecloud

Copy link
Copy Markdown

@don-petry
don-petry disabled auto-merge July 14, 2026 21:10
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: fix-reviews)

PR: #1236
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-07-14T21:41:31Z

@don-petry
don-petry enabled auto-merge (squash) July 14, 2026 21:11
@don-petry
don-petry disabled auto-merge July 14, 2026 21:15

@donpetry-bot donpetry-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: afac2c2a187b73ccc37a32e173b3fb52778031a7
Review mode: triage-approved (single reviewer)

Summary

Refactors the deterministic reviewer scorecard to partition eligible PRs into Reviewed / Rate-limited / No response buckets, fixing over-counting of rate-limited PRs (a real review alongside a quota notice now counts as Reviewed; only refusal-only touches count as rate-limited). Latency now measures time to first real response. Docs, fixtures, and bats tests updated in step; all advisory-reviewer findings were addressed and threads resolved.

Linked issue analysis

No linked issues. The PR is a follow-up to #1196 with a thorough description including live 30-day validation data showing the correctness fix (CodeRabbit refusals corrected from 147 to 16; Codex's genuine 63/75 refusal rate isolated).

Findings

No blocking findings.

  • Correctness: refusal classification (real_responses == 0) is the right fix for the prior over-counting; the three-bucket partition invariant (reviewed + refused + no_response == eligible) is enforced by construction and covered by a dedicated test. Latency correctly excludes refusal-only touches (latency_s: null).
  • Reviewer feedback resolved: the O(N×M) $elig_urls | index() scan was replaced with a reduce-built O(1) lookup map, and the bare mktemp was moved into $BATS_TEST_TMPDIR — all 3 review threads are resolved. CodeRabbit approved.
  • Tests: 6 new/updated bats tests cover refusal-only classification, real-review-beside-quota-notice, bucket-sum invariant, event counts, multi-commit re-review counting, and render columns.
  • Security: pure jq/awk/bash reporting logic; values passed via --arg/--argjson; no new dependencies, no workflow changes. Secret-scanning MCP tool unavailable in this run; the gitleaks CI check passed.

CI status

All checks green: shellcheck, ShellCheck, Lint, bats, unit-tests, CodeQL, Secret scan (gitleaks), SonarCloud (quality gate passed), AgentShield, guard, holdout-guard, template-drift, and all validators passed. Two cancelled dev-lead runs (dispatch, ci-relay) were superseded seconds later by successful/skipped re-runs on the same SHA — concurrency cancellation, not failures. Dependency-audit jobs skipped (no matching ecosystems).


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-reviews (no-changes)

Agent reasoning
Addressed 0 threads:
  (no open threads)
Test verification: skipped — no code changes were made
Files changed: none
```
The PR is in a clean state: all CI checks pass, CodeRabbit has approved, and there are no open review threads requiring fixes.

@don-petry
don-petry merged commit 559c945 into main Jul 14, 2026
34 of 38 checks passed
@don-petry
don-petry deleted the claude/reviewer-scorecard-buckets branch July 14, 2026 21:15
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.

3 participants