Code review

Three files changed
Forty-seven call paths touched

Niro reviews every changed line against the call graph behind it - the callers it breaks, the tests that never cover it, the repos it reaches. What lands on your PR looks exactly like this.

Put it on a PR Read one finding
3
comments posted
5
withdrawn, with reasons
41s
push to posted
payments-core · PR #447 · fix: retry policy from config review complete
niro-reviewbotcommented on retry-policy.tsblocking
graph-impact

maxRetries now comes from config. 47 call paths reach this line across 6 repos - 43 of them have no covering test. The nearest is checkout-api, which retries on the user's card.

PaymentProcessor.execute ↳ StripeClient.charge payments-core ↳ CheckoutService.submit checkout-api ✗ no test ↳ RefundWorker.retry billing-jobs ✗ no test
Confidence: 96%survived the verify pass
5 findings withdrawn by the verify passhidden from humans
Anatomy

Every finding carries
its own evidence

Four parts, always the same four. A claim without them is withdrawn before you see it.

01 · the pass
Which reader found it

Every comment names its pass - graph-impact, security, patch-drift - so you can turn off the ones that waste your time, per repo.

02 · the claim
One sentence, one risk

What breaks, stated flatly. No severity theatre, no paragraph of hedging - the claim is falsifiable or it does not post.

03 · the trace
The call paths, verbatim

Read from CodeGraph, not inferred from the diff. Caller by caller, repo by repo, with the untested paths marked ✗.

04 · the survival
Proof it was argued with

Confidence and the verifier’s verdict, on the comment itself. A finding that could not defend itself never reached you.

The noise math

A reviewer who flags everything
gets ignored

The same diff, reviewed twice. On the left, every comment a diff-only linter bot posted. On the right, the ones that survived Niro’s verify pass - where each finding has to justify itself against the graph before it reaches you.

diff-only tooling14
styleLine exceeds 120 characters.
stylePrefer const over let.
lintUnused import java.util.Optional.
lintMethod exceeds 40 lines.
nitConsider renaming tmp2 for clarity.
maybePossible null dereference on customer.
infoTODO found; consider filing a ticket.
+ 7 more nobody read
niro, after the verifier3
graph-impactPaymentProcessor.execute
47 callers across 6 repos, 43 with no covering test.
securityAuthFilter.java:88
Token compared with equals - timing attack, reachable from a public endpoint.
patch-driftapplication.yml
Config changed without the code that reads it - the reader lives in another repo.
3 posted · 5 withdrawn with reasons · 0 repeated advice
Why the graph

Diffs show what moved. Graphs show what breaks.

CodeGraph holds every call path across your repositories. Review reads it before commenting - so "three files changed" becomes forty-seven call paths, each checked for a covering test.

6
repos reached
47
call paths read
blast radius · retry-policy.ts:L47
RetryPolicy.of(config.maxRetries()) ↳ PaymentProcessor.execute payments-core ↳ StripeClient.charge payments-core ↳ CheckoutService.submit checkout-api ↳ CartController.pay checkout-api ↳ RefundWorker.retry billing-jobs ↳ InvoiceRetrier.run billing-jobs ↳ SubscriptionRenewal.charge subscriptions ↳ DunningJob.retryFailed subscriptions 41 further paths · expand in console
Fig. 1 - read from CodeGraph · 11ms · nothing inferred from the diff
The manifest

Ten passes.
Each one a flag you own.

Every pass is one capability with one prompt behind it, off by default. This is the full list - nothing runs that is not on it.

security
static-code
code-redundancy
use-case
guidelines
graph-impact
compliance
history
infra-level
patch-drift
verify
refutes before you see it
✓ 3 stand
posted to the PR
✗ 5 refuted
withdrawn · reasons logged
How it runs

In your PRs,
on your terms

01
A GitHub App, not a bot account

Installed against the repos you choose. Reviews arrive as PR comments where the conversation already is.

02
One egress point for every model call

Nothing calls a provider directly. What leaves is auditable in one place.

03
Your diff is not in the logs

No source, no diff content, no prompts. Paths and counts only - written into the service principles, not bolted on.

04
Off until you turn it on

Every pass is flag-gated and defaults off. Adoption is a decision, not a surprise.

FAQ

Before you point
it at a repo

Which platforms does PR review support?

GitHub today, as a GitHub App installed against the repositories you choose rather than a bot account holding a seat. GitLab, Bitbucket and Gitea are indexed over an access token, but do not yet receive review comments.

Will it flood our pull requests?

Ten passes read the diff in parallel, then a verifier tries to refute every finding before delivery - when it is uncertain it leans refuted, because a false alarm costs more than a dropped maybe. Dispute a finding on the PR and it is re-checked against your doubt without folding to it. Every capability is also flag-gated and defaults off, so adoption is a decision rather than a surprise - you turn on the passes that earn their place.

Does this replace human review?

No. It reads the graph behind the diff and reports the call paths a diff view cannot show you, including which of them no test covers. Deciding what to do about them is still a reviewer's job.

Does our diff reach your logs, or a model provider directly?

Neither. No source, no diff content and no prompts are written to logs - paths and counts only, written into the service principles rather than bolted on afterwards. Every model call goes through one gateway, so what leaves is auditable in a single place.

Next

Point it at
one noisy repo

The one where review comments are ignored. Compare what gets posted with what your current tooling posts.

Get set up Measure the difference