What 295 Agentic PRs Taught Us About Code Review

Building AI-native team · · Yi Zhang (CEO & Founder)

Letting coding agents take over meaningful, large software projects sounds fascinating. The pitch is everywhere: give agents docs on what you want to build, let them branch, implement, fix, and hand back working software. On social media, the claims are easy to find. The operational details are shared less often.

We were especially inspired by OpenAI’s Symphony, which frames Linear issues as a control plane where each task can be assigned to an agent and humans review the result. That is the right direction. At the same time, our day-to-day workflow was still very direct: engineers were talking to Claude Code and Codex, shaping tasks, inspecting patches, and deciding when a change was ready.

So we kept the direct coding-agent loop, then moved classic code review into an agent-carried workflow.

That is why we built Crosscheck: an open-source assistant workflow that watches pull requests, runs an independent AI review, applies targeted fixes when configured, re-checks the result, and keeps pushing the PR toward a mergeable form when the automated path is safe. The preferred pattern is cross-vendor: let one setup create or fix, then let another setup review so the workflow catches blind spots that a single vendor loop may miss.

Crosscheck logo

Crosscheck is open source. Install @humanbased/crosscheck from npm, connect GitHub plus Codex or Claude Code, and run review loops from your own machine or server.

The product choice is deliberately pragmatic. Crosscheck drives Codex and Claude Code directly for review, fix, re-check, and conflict-resolution steps. That gives us two useful properties. First, Claude Code and Codex can work in sequence and help each other: one agent creates or fixes, another reviews, and the loop exposes blind spots. Second, teams can keep using the coding-agent subscriptions they already pay for instead of converting every review loop into a new per-token API bill.

This analysis asks a practical question: which workflow choices protect quality without slowing the team down?

The short version:

What we analyzed

We joined GitHub PR metadata for humanbased-ai/monorepo with retained local Crosscheck logs. The repository was created on 2026-04-27T10:08:41Z; the first PR in the dataset was opened on April 30; the analysis window runs through June 5, 2026.

The full PR population covers 295 pull requests. The retained Crosscheck logs cover May 24 to June 5, giving us a smaller workflow-observed subset of 96 PRs.

Cumulative PRs from monorepo creation to June 5, 2026
Cumulative PRs since monorepo creation. The repo went from zero to 295 PRs in 40 calendar days.

The core measurements:

MeasureValue
PRs since repo creation295
Non-doc PRs286
PRs in retained Crosscheck logs96
Recorded workflow minutes2,948.8
Recorded review hours49.1
24-hour days of workflow2.0
Unique ticket refs157

We separate the goal from the implementation:

Problem complexity vs. solution complexity
Each dot is a Crosscheck-observed non-doc PR. Hover for the PR, verdict, ticket count, and recorded workflow time.
completed workflow error observed/no workflow fitted trend outlier
Crosscheck PR problem complexity versus solution complexity Interactive scatter plot of observed pull requests. X axis is problem complexity from the goal. Y axis is solution or code complexity. Dot color is workflow state and dot size is recorded workflow time.
Color indicates workflow state. Dot size increases with recorded workflow minutes. Click a dot to open the GitHub pull request.

The scatterplot is useful precisely because it separates the demand from the implementation. If every solution were proportionate to the problem, the dots would hug a straight upward line: harder goals should usually require broader code. A fitted line over the observed PRs points in that direction, but only moderately (r = 0.52, R^2 = 0.27). In other words, problem complexity explains some solution size, but the solution can easily become more complex than the goal required.

The most important outliers are the simple-goal, complex-solution PRs above the fitted line:

PRWhy it is an outlierLikely cause
#233 blog systemLow goal score, very high solution scoreA small stated goal hid a full subsystem: Astro blog, content model, assets, and deploy surface
#226 badge MVPTrivial problem bucket, high-risk solutionTen ticket refs were bundled into one PR, so the review story became much larger than the issue shape
#258 shared upload routingFix-shaped goal, broad implementation”Route uploads” crossed shared storage, campaign cover images, form assets, and data recording
#267 and #291 UI layeringSimple product-polish goals, broad UI changesVisual refresh work tends to fan out across routes, state, assets, and layout conventions

These are not necessarily bad PRs. They are warning labels. They usually come from under-specified goals, hidden platform work, bundled tickets, or a refactor/migration disguised as a small fix. The prevention pattern is simple: require a short implementation plan before large generated diffs, enrich issues with acceptance boundaries, split scaffolding from product behavior, and ask Crosscheck to flag PRs whose solution score is far above the fitted expectation for the goal.

This data can answer operating questions: which PR shapes are expensive, where review loops repeat, when stronger models are worth considering, and what Crosscheck should instrument next.

It cannot yet answer the final quality question by itself. Crosscheck verdicts are a useful review-risk proxy, but production code quality needs post-merge joins: reverts, follow-up fixes, CI failures, incident links, bug tickets, and customer-visible regressions.

Finding 1: make review routing proactive

The strongest product lesson is not “which telemetry field explains cost afterward.” The useful question is: which setup choices make a PR likely to need more review before we spend the review budget?

In this sample, ticket bundling was the clearest controllable cost signal. Problem complexity and solution complexity also mattered, but they describe different layers. The issue brings demand complexity. The coding agent creates one solution shape.

Crosscheck should route review strength from both.

Directional correlations between actionable workflow levers, CR cost, and review risk
Directional correlations from the retained Crosscheck window. These are routing signals, not causal estimates.

The routing inputs should be things a team can act on:

FactorWhat it tells usCrosscheck action
Issue or goal complexityHow ambiguous or broad the demand is before code existsSingle-vendor review uses thorough for high ambiguity; cross-vendor review can stay balanced until risk signals appear
Ticket bundle sizeWhether one PR is carrying one review story or severalDefault to one ticket; allow 2-3 related tickets only in rush mode or one shared rollout; block or split 4+ tickets
PR solution shapeWhether the implementation is broad, risky, or cross-domainIf solution complexity is far above the fitted expectation, require an implementation-plan check and targeted tests
Coding agent and model provenanceWhether the original patch came from a known setupPrefer cross-vendor review when the coding agent and reviewer would otherwise be the same setup
Workflow length and errorsWhether the run is becoming unstableStop after repeated errors, retry from a clean state, or hand off with context instead of extending the loop

A practical router should classify the issue, estimate PR shape, capture coding-agent and model provenance, then choose a review lane:

Crosscheck already has workflow tiers such as balanced and thorough. The next product step is to make review strength an automatic routing decision, not a manual habit.

The most practical process question is simple: should we ship a larger PR covering multiple tickets, or keep PRs small and run more review loops?

The default answer is one ticket per PR. It gives the fastest single-PR turnaround, keeps review context small, and makes approval easier to reason about.

The exception is rush mode. When the team needs highly parallel execution and the tickets are genuinely related, a 2-3 ticket bundle is worth trying. In the retained Crosscheck window, those PRs looked comparable to one-ticket PRs on median computer time and CR rounds, while preserving approve rate. That is a useful bundle size when the tickets form one coherent unit.

The stop sign is 4+ tickets. Those PRs became a different operating mode: higher median computer time, more review/fix time, more rounds, and a much lower approve rate. At that point, any theoretical throughput gain gets outrun by the prolonged code-review workflow required to reach APPROVE.

Ticket bundling trade-off across workflow minutes, approve rate, and risk proxy
Bundling can reduce coordination overhead up to a point. Past that point, the workflow becomes harder to stabilize.

Median per-PR comparison:

BundleSampleProblem / solutionWorkflow / PRReview + fix / PRCR rounds / PRWall-clock / PRApprove
1 ticket19 PRs / 19 tickets28.5 / 43.334.6m19.2m + 1.6m927.4h63%
2-3 tickets10 PRs / 20 tickets32.3 / 43.538.7m11.6m + 1.1m957.1h60%
4+ tickets11 PRs / 69 tickets52.6 / 82.086.4m46.5m + 10.7m1341.5h18%

The per-ticket view explains why bundling is tempting:

BundleAvg workflow / PRTickets per review hourApproveRisk proxy
1 ticket43.1m1.3260%0.55
2-3 tickets38.8m2.8155%0.36
4+ tickets124.1m3.0318%1.18

The bad trade is visible only when cost and quality sit together. A 4+ ticket bundle can look efficient per ticket, but the approve rate collapses and the risk proxy more than doubles versus the 2-3 ticket bucket.

The operating rule we took from this:

Prefer one ticket when approval speed matters.

Bundle 2-3 tickets only when they are one evidence unit: same domain, same rollout, shared migration, or one acceptance flow.

Never treat 4+ tickets as a normal bundle. Split them before implementation, or require a human plan plus thorough cross-vendor review.

Finding 3: do not rank coding agents without provenance

The observed agent comparison is useful, but not fair enough to crown a winner.

Codex-origin PRs in this sample were mostly smaller site and product-polish changes. Claude-origin PRs carried more ticket refs, higher problem scores, and more backend/domain-risk work. The measured outcomes reflect task assignment as much as agent ability.

Average problem and solution complexity by inferred PR origin
Origin is inferred, not authoritative. The product opportunity is to make this metadata first-class.

The origin proxy table shows the bias:

Origin proxyPRsTicket refsAvg problemAvg solutionAvg workflowAvg roundsApprove
Claude308933.455.772.2m11.633%
Codex28813.835.912.2m4.579%
Human111127.840.737.2m8.782%
Unknown20421.140.40.0m0.00%

The conclusion is not “Codex is better” or “Claude is worse.” The conclusion is that Crosscheck needs first-class provenance for:

Without that, task assignment bias overwhelms model choice.

What model comparison can tell us today

Reviewer model routing is more actionable than original coding-agent ranking because Crosscheck owns that part of the workflow.

In retained review-call logs, Claude Sonnet review calls were much faster than Claude Opus calls. Opus appeared on somewhat harder PRs, so this is not a quality ranking. It is a routing hint.

Reviewer setupCallsPRsAvg problemAvg durationApproveNeeds workBlock
Claude / Sonnet 4.6613017.063.2s62%36%2%
Claude / Opus 4.7141324.4162.4s50%36%14%

The practical policy: use smaller/faster models by default, then escalate to stronger models for high-risk PRs, reviewer disagreement, or repeated fix loops.

That gives Crosscheck a concrete routing policy:

LaneGood fitDefault reviewer setupEscalation trigger
FastSmall, single-domain, low ambiguitySmaller/faster model, one passAny blocking finding, missing tests, or changed risk surface
BalancedNormal feature or bugfix PRStandard review plus targeted re-checkRepeated fix loop, broad diff, auth/data/migration code
ThoroughComplex goal, cross-domain PR, or 4+ ticket bundleStronger model and stricter reviewHuman plan check or domain-owner gate
RecoveryFailed, conflicted, or unstable workflowDiagnose environment and state before more reviewStop looping and preserve context for handoff

What this means for Crosscheck

Crosscheck does not need to magically make generated code good. Its leverage is more practical: make review reliable, observable, cheap enough to run often, and smart enough to spend effort where risk is highest.

The next product opportunities are clear:

  1. Issue-ticket enrichment. Join Linear/GitHub issue fields so problem complexity is measured from the goal, not inferred from the PR.
  2. Agent/model provenance. Record coding agent, model, effort, context strategy, and verification behavior for the original PR attempt.
  3. Complexity-aware workflow lanes. Route low-risk PRs through fast review, complex PRs through review plus targeted fix, and high-risk PRs through human-plan or domain-owner gates.
  4. Reliability preflight. Check GitHub auth, vendor CLI auth, repo access, and tunnel state before accepting PR work.
  5. Original vs. fixed state tracking. Separate original PR quality from Crosscheck-applied fix deltas.
  6. Real cost accounting. Persist provider, model, duration, retry count, and computed USD per reviewer/fixer call.
  7. Post-merge quality joins. Track reverts, follow-up fixes, bug issues, incidents, and CI failures after merge.

The product should turn these into defaults, not dashboards alone. A useful Crosscheck run should end with an answer like: “This PR is a good candidate for fast review”, “This PR is carrying three independent review stories”, or “This PR needs thorough review because the goal is high-ambiguity and the diff crosses data boundaries.”

The practice we want

AI-native engineering should not mean “let agents ship whatever they produce.” It should mean faster loops with better instrumentation.

Small goals should move quickly. Risky goals should get stronger gates. PRs should stay shaped for review. Models should be routed by expected risk, not habit. Every run should leave data behind so the workflow gets easier to improve.

For teams adopting agentic coding, the practice is not traditional review versus AI automation. It is traditional engineering discipline, made cheaper to run on every PR.

Crosscheck is our attempt to make that discipline operational: independent review, fix, re-check, conflict handling, cost visibility, and eventually quality feedback from production back into the next review.

That is how agentic teams can improve cadence and quality together.

Method notes

This is a retrospective of available data, not a controlled experiment. PR origin is inferred from titles, branches, and workflow artifacts. Ticket count is based on detected issue references, so unlinked work is undercounted. Wall-clock time is PR open to merge or close, so human scheduling and batching can dominate that metric.

The next analysis should join the issue tracker directly, record coding-agent and model provenance at PR creation time, and connect merged PRs to post-merge quality outcomes. That is the path from “review workflow telemetry” to a real model of code quality.

Try Crosscheck on GitHub at humanbased-ai/crosscheck, or install it from npm as @humanbased/crosscheck.