Skip to content

feat(refresh-reviewers): recompute the reviewer expertise map from git history and open a drift PR (BE-4116)#63

Open
mattmillerai wants to merge 2 commits into
mainfrom
matt/be-4116-refresh-reviewers
Open

feat(refresh-reviewers): recompute the reviewer expertise map from git history and open a drift PR (BE-4116)#63
mattmillerai wants to merge 2 commits into
mainfrom
matt/be-4116-refresh-reviewers

Conversation

@mattmillerai

Copy link
Copy Markdown
Contributor

ELI-5

When someone opens a PR, assign-reviewers.yml picks owners from a hand-written map (.github/reviewers.yml) of "who knows which part of the code." That map goes stale as people join, leave, or change focus. This PR adds a sibling reusable workflow, refresh-reviewers.yml, that a repo can run on a schedule: it re-reads the repo's git history, re-scores who actually works where (recent commits count more; bots, lockfiles, and generated code don't count), and — only when the map has drifted — opens ONE small PR proposing the updated lists, with the scores shown so a human can sanity-check and merge. It never assigns anyone and never merges anything itself.

What's here

  • .github/workflows/refresh-reviewers.yml — the reusable workflow_call engine, following assign-reviewers.yml's conventions: app-token auth (vars.APP_ID + CLOUD_CODE_BOT_PRIVATE_KEY), caller-side config, never-fail defensive handling. The workflow's own permissions: stay contents: read; the branch push + PR open go through the app token. Generator script is loaded from a pinned workflows_ref of this repo (tamper-proofing convention), never the caller's checkout.
  • .github/refresh-reviewers/generate.py — the engine, ported from the validated BE-4114 prototype (not redesigned): decayed commit-touch scoring (0.5^(age/half_life), line counts intentionally unused), bot-author + generated/churn-path + rename-syntax filtering, noreply-email decoding (incl. digits+login@) with per-run-cached commits-API fallback, collaborator (not org-member) eligibility, per-rule threshold/floor/backfill selection with the under-floor leave-unchanged cold-start fallback, default_pool = top-5 overall minus ≥2-rule anchors minus map_exclude, a surgical rewrite that touches only the reviewers:/default_pool: sequences (flow AND block) and preserves every comment byte-for-byte, plus the report-only taxonomy-gap section.
  • Drift gate + idempotent PR: no drift → quiet exit. Drift → reset bot/refresh-reviewers from the default branch, commit the single file, force-push, and create the PR or edit the existing open one's body — duplicates never stack.
  • .github/refresh-reviewers/tests/test_generate.py — 38 pure-python tests (repo .github/<tool>/tests/ pattern): glob parity with globToRegExp (**/inference/** vs services/ingest/** cases), decay math, threshold/floor/backfill/under-floor selection, bot/path/rename filtering, noreply decoding, byte-preserving rewrite (flow + block + scalar), PR-body content. Plus test-refresh-reviewers.yml (path-filtered CI, mirrors test-cursor-review-scripts.yml).
  • Docs: .github/refresh-reviewers/README.md (contract, knob defaults + BE-4114 rationale, map_exclude guidance), root README table row, AGENTS.md entries (137/200 lines, integrity checker passes).

Verification

  • python3 -m unittest discover -s .github/refresh-reviewers/tests — 38/38 pass; all other suites (cursor-review, agents-md-integrity, groom, bump-callers) still green; actionlint clean on both new workflows.
  • End-to-end smoke against a synthetic git repo with a stubbed API: correct drift detection, comment-preserving rewrite, under-floor rule left unchanged, bot/unresolved counts right, idempotent outputs.

Judgment calls

  • workflows_ref input added (not in the ticket contract): required by this repo's "scripts are the single source of truth, loaded from a pinned ref" convention — same shape as agents-md-integrity.yml/pr-size.yml.
  • Never-fail scope: environmental failures (missing config, unreachable collaborators API, no history) exit 0 with a ::warning::; genuine bugs still raise so they're visible. Collaborator-API-down aborts quietly rather than emitting a map with unvalidated eligibility.
  • Login-case canonicalization: noreply decode preserves email casing and membership matching is case-insensitive against the collaborator list's canonical casing — without this, mixed-case logins (e.g. DrJKL-style) would be silently dropped. Regression-tested.
  • Whole-path rename form (old => new without braces) is normalized too, not just the ticket's brace form — git emits both.
  • Force-push on bot/refresh-reviewers is per the ticket's reset-branch idempotency spec; the branch is bot-owned by contract. No concurrency: group (siblings don't set one; weekly-schedule overlap is negligible).
  • No consumer wiring here — the cloud caller is the separate blocked follow-up, per the ticket.

…xpertise map from git history, open a drift PR (BE-4116)
@mattmillerai mattmillerai added cursor-review Multi-model cursor review agent-coded Authored by the agent-work loop labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 38 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 Plus

Run ID: a9e58107-5846-42cb-b129-766293f123b7

📥 Commits

Reviewing files that changed from the base of the PR and between cc325ca and 0b3c716.

📒 Files selected for processing (7)
  • .github/refresh-reviewers/README.md
  • .github/refresh-reviewers/generate.py
  • .github/refresh-reviewers/tests/test_generate.py
  • .github/workflows/refresh-reviewers.yml
  • .github/workflows/test-refresh-reviewers.yml
  • AGENTS.md
  • README.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-4116-refresh-reviewers
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch matt/be-4116-refresh-reviewers

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

@github-actions github-actions 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.

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

Found 10 finding(s).

Severity Count
🟡 Medium 5
🟢 Low 5

Panel: 8/8 reviewers contributed findings.

Comment thread .github/refresh-reviewers/generate.py
Comment thread .github/workflows/refresh-reviewers.yml
Comment thread .github/refresh-reviewers/generate.py Outdated
Comment thread .github/workflows/refresh-reviewers.yml
Comment thread .github/workflows/refresh-reviewers.yml Outdated
Comment thread .github/refresh-reviewers/generate.py Outdated
Comment thread .github/refresh-reviewers/generate.py Outdated
Comment thread .github/refresh-reviewers/generate.py
Comment thread .github/refresh-reviewers/generate.py
Comment thread .github/refresh-reviewers/generate.py
…I-failure no-op, branch guards, stale-PR reconcile, md escaping (BE-4116)

Addresses the cursor-review panel findings on #63:
- validate HALF_LIFE_DAYS strictly positive (zero divided by zero, negative
  inverted the decay) — falls back to the default with a warning
- distinguish API failure from "no linked account" via an API_ERROR
  sentinel; any failed email->login lookup downgrades the run to the
  documented clean no-op instead of silently dropping contributors
- workflow: refuse pr_branch == default branch, add a per-repo concurrency
  group, and never force-reset an open drift PR whose tip a human authored
- workflow: a genuine no-drift run (report present) closes a stale
  still-bot-authored drift PR so an obsolete proposal can't linger mergeable
- workflows_ref is now required (defaulting to mutable main defeated the
  pin-by-SHA rule); no consumers exist yet so nothing breaks
- gap report: accumulate once per commit per key (parity with rule scores)
  and key by top-two-level DIRECTORY, never the filename
- decode git's C-style path quoting properly (tabs, quotes, octal)
- escape | and backticks in repo-derived text in the PR-body tables
- document the accepted trust boundary (forgeable author metadata, bounded
  by human review) and the caller-trusted EXTRA_EXCLUDE_PATHS regexes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded Authored by the agent-work loop cursor-review Multi-model cursor review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant