Skip to content

Route PR reviews by code ownership

Codeowners review gives each part of a codebase its own review. A CODEOWNERS-style table maps changed paths to review areas; each area has a markdown playbook with the team's rules for that domain; and one area-reviewer subagent runs per routed area, in parallel. A billing change gets the billing review, a migration gets the migration review, and an author's personal style rides along as advisory notes. The lead aggregates: approve only when every area approves.

Use this project when review quality depends on domain-specific values instead of one generic checklist.

Browse the codeowners review source.

Keep routing in code and judgment in playbooks

The pipeline separates three concerns:

  • reviews/REVIEWERS routes. Host code matches every changed path against the table; every matching rule applies, and unmatched paths fall back to the general playbook. Routing is glob code with unit tests, not model judgment.
  • reviews/<area>.md judges. Each playbook is a severity-ordered rule list the team owns: billing mandates integer cents and idempotent webhooks, migrations forbid destructive DDL beside code changes, background jobs demand idempotency and dead-letter paths.
  • Subagents review. The lead reads nothing but the manifest and routes; each area-reviewer reads one playbook plus its files' diff hunks and returns a mechanical verdict: request changes on any High finding or two Mediums.

Personal styles extend the same mechanism. reviews/people/<login>.md attaches automatically, as advisory notes, whenever that person authors the PR. Adding an area or a style is a markdown file plus at most one routing line.

Follow a review

  1. A PR arrives: a GitHub pull_request event, a chat message, or a bundled fixture reference.
  2. prepare_review fetches metadata and the diff with the host gh CLI, routes every changed file, and writes the pr/ evidence tree: MANIFEST.md, ROUTES.md, diff.patch, and a copy of each matched playbook.
  3. The lead follows the review-process skill and issues one area-reviewer delegation per routed area, plus one per personal style, all in one step so they run in parallel.
  4. Each reviewer reads its playbook, reviews only its files, and returns a verdict line with at most three findings.
  5. The lead aggregates per-area sections and the overall verdict: APPROVE only when every non-advisory area approved.

Nothing posts to GitHub. Verdicts live in the session; the Approval Buddy guide shows how to wire a real APPROVE and commit statuses on top of the same shape.

Map the review files

FilePurpose
reviews/REVIEWERSRoutes path patterns to review areas.
reviews/Holds the area playbooks and people/<login>.md styles.
agent/lib/routing.tsParses the table, matches globs, and unions areas per file.
agent/lib/prepare-review.tsFetches PRs or fixtures and builds the evidence tree.
agent/tools/prepare_review.tsExposes host preparation as a typed server tool.
agent/tools/list_review_areas.tsAnswers routing questions deterministically.
agent/skills/review-process.mdFixes the fan-out procedure and the verdict rule.
agent/subagents/area-reviewer/Defines the one-area, one-playbook reviewer contract.
agent/channels/github.tsReviews opened, reopened, synchronized, and undrafted PRs.
fixtures/Ships two reviewable PRs with known planted findings.
agent/storage.tsPersists sessions and events with cursorHostedStorage.
evals/evals.config.tsCaps eval run concurrency.
evals/review.eval.tsGates routing, fan-out, planted bugs, and verdicts.

There is no MCP connection, schedule, hook, A/B experiment, or custom storage.

Prepare credentials and services

You need:

  • Node 22.13 or newer.
  • An agent-runtime credential for model turns.
  • gh on PATH with read access to real PRs you review. The bundled fixtures need no network at all.

The channel verifies webhook signatures when GITHUB_WEBHOOK_SECRET is set and narrows repositories with CODEOWNERS_REVIEW_REPOS=owner/repo,owner/other. Pushes re-review in the same session through the pr:<label> continuation token.

Validate the surface

bash
agent-sdk validate --dir examples/codeowners-review
agent-sdk info --dir examples/codeowners-review --json

The manifest should report two server tools, one skill, one subagent, and the authored GitHub channel.

Inspect routing without a model turn

bash
agent-sdk call list_review_areas --dir examples/codeowners-review --input '{}'

agent-sdk call prepare_review \
  --dir examples/codeowners-review \
  --input '{"pr":"fixture:multi-area"}'

The fixture routes to billing, database-migrations, and frontend, attaches people/alice because alice authored it, and returns the full evidence map. Point the same tool at a real PR URL and the routing runs against the live file list. The example table maps a hypothetical src/ layout, so most real repositories route to general until you adapt reviews/REVIEWERS.

Review the planted fixture

bash
agent-sdk dev examples/codeowners-review

In the playground:

Review fixture:multi-area

The fixture plants one violation per area: float dollar math in src/billing/invoice.ts, a DROP COLUMN plus a non-concurrent index in the migration, and a clickable div without loading states in the UI. The trace shows prepare_review, the evidence reads, four parallel area-reviewer cards, and an aggregated CHANGES REQUESTED verdict with each planted bug filed under its own area. The second fixture, fixture:jobs-clean, routes to background-jobs alone and ends in APPROVE.

Review a real PR the same way:

Review https://github.com/owner/repo/pull/123

Or replay one as a webhook delivery:

bash
agent-sdk github replay https://github.com/owner/repo/pull/123 \
  --dir examples/codeowners-review --action opened

See how the verdict stays mechanical

The reviewer contract computes verdicts from findings instead of letting the model pick a mood: findings first, then request-changes if any High exists or two Mediums do, otherwise approve. Pre-existing issues visible in context are scoped out, at most one advisory Low. The lead applies one rule on top: the PR is APPROVE only when every non-advisory area approved.

Run the evals

bash
agent-sdk eval --dir examples/codeowners-review --list
agent-sdk eval --dir examples/codeowners-review review/multi-area

review/multi-area gates the whole pipeline: prepare_review runs, at least three subagent delegations happen, the reply carries every area section plus alice's advisory notes, the planted billing and migration bugs surface, and the verdict requests changes. review/clean-approve proves the approval path on the clean fixture, and review/routing-question gates that routing answers come from list_review_areas.

Reuse the ownership-routing pattern

Copy this shape when different code deserves different judgment:

  • Route with data and code, not prompt instructions. Tables and globs are testable.
  • Write one playbook per domain and keep each reviewer blind to the others.
  • Make verdicts mechanical so aggregation is arithmetic, not negotiation.
  • Ship fixtures with planted findings so the review quality itself is testable offline.

Where to go next