AI code review

Three reviewers. One verdict.

Every AI reviewer generates findings it cannot stand behind. Dicast puts each one in front of three independent models that argue it out — and posts only what survives.

Start free See how it works Installs on a repo in about two minutes
#482  feat: retry failed payment webhooks  ·  +214 −38
12 generated  ·  3 posted  ·  9 struck
payment.ts:47
Retry path reuses the original request without an idempotency key — a timed-out charge can settle twice.
Block
queue.ts:112
Retry loop has no ceiling; a poisoned message can hold a worker indefinitely.
Warn
webhook.ts:23
Signature is verified after the body is parsed, so malformed payloads reach the parser unauthenticated.
Warn
index.ts:31
Possible null dereference on config.retries. Struck — guarded on line 28. All three jurors refuted.
 
utils.ts:8
Consider extracting this into a helper function. Struck — style preference, not a defect. 1 of 3 affirmed.
 
client.ts:96
Unhandled promise rejection. Struck — already caught by the linter rule in your CI.
 
types.ts:14
This type should be narrowed. Struck — plus 5 more findings that failed to reach two votes.
 
juror affirmed juror refuted two votes required to post · three to block
Works with
GitHubGitLabBitbucket GitHub ActionsAnthropicOpenAIGoogle
The problem

Nobody reads the twelfth comment.

Independent audits of AI review tools put 15–30% of their comments at low value or outright wrong. Teams don't filter that selectively — they mute the whole bot. The finding that mattered was in there somewhere.

A single model has no way to know which of its own findings it should have kept to itself. It is the author, the advocate and the judge at once. So it ships everything, and the filtering becomes your job.


How it works

Findings have to survive cross-examination.

Dicast splits the two jobs a reviewer does badly at once: finding things, and deciding which of them are worth your attention.

STEP 01

Scan wide

One fast model reads the full diff with your repository as context and proposes everything it suspects. Recall first — precision is not its job.

STEP 02

Cross-examine

Each finding goes to three jurors drawn from three different model vendors, blind to one another. Each is asked to refute it, not to confirm it.

STEP 03

Return a verdict

Two affirming votes to post a comment, three to block the merge. Everything struck stays on the record with the reason it was struck.

Configuration

You set the burden of proof.

Panel size, vote threshold and what blocks a merge are yours to tune. Commit one file and the whole team inherits it.

.dicast.ymlcommitted to your repo
# the panel that hears every finding
panel:
  jurors: [anthropic, openai, google]
  threshold: 2        # votes required to post
  block_at: 3         # unanimous verdict blocks merge

scan:
  paths: ["src/**", "!**/*.generated.ts"]
  max_diff: 3000      # larger PRs are split and heard in parts

# house rules the jury must weigh
rules:
  - "Money paths must be idempotent."
  - "No network calls inside a request handler."

suppress:
  - style             # the linter already owns this
  - test_coverage
Checks on pull request #4822 checks
dicast / review 3 posted, 9 struck Details
dicast / merge-gate 1 unanimous finding Details

The gate is a normal status check. Make it required in branch protection, or leave it advisory — Dicast never pushes commits and never merges on your behalf.


Features

Built for repositories that outgrew the diff.

Whole-repository context

Jurors read the call sites, the types and the tests around a change, not just the lines that moved.

The struck record

Every rejected finding is kept with its votes and the reason. When the panel is wrong, you can see exactly where.

Learns from dismissals

Resolve a comment as "not useful" and that pattern carries a lower prior on every future hearing in the repo.

House rules

Write your invariants in plain language. They become evidence the jury has to weigh, not regex to maintain.

Monorepo aware

Per-package panels and thresholds. Payment code can demand unanimity while the docs site stays advisory.

Your own keys

Point the panel at your own vendor accounts on Scale, so inference runs under your contracts and your retention terms.

Comparison

Same models. Different burden of proof.

Single-model reviewerDicast
Who decides what you see The model that wrote the finding Three jurors from three vendors, none of which wrote it
Comments per pull request Everything generated Only findings that reach the vote threshold
When it is wrong You find out by reading it Usually caught by a juror before it is posted
Rejected findings Never existed as far as you know Kept on the record, with votes and reasons
Blocking a merge Severity label from one model Unanimous verdict, configurable per path

Pricing

Per developer. No charge for the noise you never see.

Struck findings don't count against your quota — you are billed for pull requests heard, not comments generated.

Solo
Free
  • 10 pull requests per month
  • One repository
  • Full three-juror panel
  • Community support
Start free
Scale
$39 / developer / month
  • Everything in Team
  • Bring your own model keys
  • SSO and SCIM
  • Audit export of every verdict
  • Self-hosted runner option
Start 14-day trial

Open source repositories are free. Public repos get the full panel with no pull request limit — no application, no logo on our site required.

Questions

The objections we'd raise too.

Why three models instead of one better model?

Because the failure mode isn't capability, it's calibration. A model that generates a finding is a poor judge of whether that finding is worth your time — it has already committed to it. A juror that did not write the finding, and is asked to refute rather than confirm it, has no such commitment. Vendor diversity matters for the same reason: models trained on overlapping data make correlated mistakes, so a panel of three from one vendor agrees with itself far more often than it should.

Doesn't this triple the cost and the latency?

No, because the panel doesn't review your code — it reviews the findings. One inexpensive pass reads the diff, and only the candidates it produces go to the jury, where each hearing is short and the three run in parallel. In practice a review lands in the same window you'd expect from a single-model reviewer.

What happens to our code?

Diffs and the context needed to review them are sent to the model vendors configured for your panel, held for the duration of the review, and not retained afterwards. We never train on customer code. On Scale you can point the panel at your own vendor accounts, which keeps inference under your own contracts and retention terms.

Which languages do you support?

The panel is language-agnostic — it reasons over your diff and the surrounding code rather than a parser. Repository context is strongest where the ecosystem gives us a dependency graph to walk: TypeScript, JavaScript, Python, Go, Ruby, Java, Kotlin, Swift, Rust, C# and PHP.

How is this different from turning down my current tool's verbosity?

A verbosity setting drops findings by severity label, which the same model assigned. You lose real bugs it ranked low and keep noise it ranked high. A vote threshold drops findings by whether independent reviewers could refute them, which is a different axis — and you keep the record of what was dropped, so the filter is auditable rather than a dial you guess at.

Can Dicast block a merge?

Only if you make it required. Dicast publishes a normal status check; branch protection is yours to configure. It never pushes commits, never merges, and never requests changes on behalf of a human reviewer.

Put your next pull request to the panel.

Install on one repository, keep your current reviewer running beside it, and compare what each of them thought was worth saying.