Most AI review comments
should survive shouldn’t.

mergejury fans your pull request out to several AI reviewers, each with one lens: security, correctness, contracts, tests, performance. Then it makes every finding fight for its life. What survives gets posted: one review, a handful of comments, each one defensible.

$ mergejury review 4127 --dry-run
claude-code security · 6 findings
cursor correctness · 8 findings
antigravity api-contract · 5 findings
api-baseline test-gap · 4 findings
api-perf perf · 4 findings
27 findings enter the gauntlet. Follow them down.

01 validate

No model involved. An anchor must land on a commentable line. Every cited line must exist. Deterministic, and merciless about invention.

Session token logged in plaintext dropped: bad_evidence · cites auth/session.go:400; the file has 210 lines

02 cluster

Plain code groups findings that hit the same lines. Three reviewers flagging one comparison is agreement: a signal, not three comments.

Non-constant-time token comparison 3 supporters: claude-code, cursor, api-baseline

03 challenge

A model that did not write the finding gets one instruction: argue that it is a false positive. Adversarial framing produces real dissent where peer review produces rubber stamps.

Unvalidated redirect in OAuth callback challenger: the target is allowlisted upstream at router.go:52 · judge agreed

04 verify

Mechanical checks outrank every opinion in the pipeline. Claimed test gap? Look for the test. Claimed breaking change? Count the call sites. Lint-class complaint the linter doesn’t flag? Evidence against.

Retry path has no test coverage refuted: client/retry_test.go exists and exercises the branch

05 judge

One model, one cluster at a time, default verdict drop. Publishing requires specific, anchored, and falsifiable from the code in front of it. “This could be a problem” is a drop. What survives is rewritten into one voice.

Consider adding more robust error handling here dropped: not falsifiable · no concrete consequence stated

Twenty-seven walked in. Three walk out.

One review per run, never a notification storm. Comments are capped, severity-sorted, and anchored to lines the API will actually accept. Every one traces back through cluster, challenge, verification, and verdict to the reviewers that raised it.

◆ blocker · auth/session.go:142

Session token compared with == instead of constant-time compare

expected is []byte and tok is string, so this comparison is both type-confused and non-constant-time. An attacker who can measure response timing can recover the token byte by byte. Validate is reachable straight from handler.go:88 with attacker-controlled input.

suggested change
- if string(expected) == tok {
+ if hmac.Equal(expected, []byte(tok)) {
flagged by claude-code, cursor · disputed by challenger · verified: handler.go call site confirmed

The verdict is computed. No model ever states it.

Any published blocker, even when other reviewers failed REQUEST_CHANGES
Complete run, every gate passed, not a fork, zero findings APPROVE
A reviewer timed out, was denied, or crashed, and found nothing COMMENT · silence only counts when everyone was heard
Pull request from a fork COMMENT · never auto-approved

A degraded run can request changes. It can never approve. That is not configurable.

One binary. Console included.

No runtime, no database to provision, no service to stand up. The reviewers are the CLIs you already have; everything else is compiled in.

macOS, Linux
no Go needed
$ curl -fsSL mergejury.etornam.dev/install | sh

Detects your platform, verifies the SHA-256 against the release checksums, and installs to /usr/local/bin. Override with PREFIX, pin with VERSION.

With Go
1.25 or newer
$ go install github.com/iamEtornam/mergejury/cmd/mergejury@latest

Builds from source at the latest release tag.

From source
to hack on it
$ git clone https://github.com/iamEtornam/mergejury.git && cd mergejury && go build -o bin/mergejury ./cmd/mergejury

Windows: download the .zip from the releases page.

Then, in order

01
$ mergejury init

Finds the reviewers you already have, tells you what is missing and how to fix it, and writes a config wired to the tools on your machine. Nothing missing is fatal: it degrades to whatever is available, down to the API reviewer alone. Credentials stay in your environment, never in the file.

02
$ mergejury adapters check

Names every reviewer that is missing, unauthenticated, or running with flags this build does not expect, each with the exact fix. Start here; a run that fails at the adapter layer is the most confusing way to meet this tool.

03
$ mergejury review --local

Reviews your working tree against a base ref. No pull request, no posting, nothing leaves your machine except the diff you are reviewing.

04
$ mergejury review 4127 --dry-run

Renders the exact review it would post, comment for comment, and posts nothing. Read it before you let it near a real pull request.

05
$ mergejury serve

The operator console on localhost: every finding, every drop and its reason, every verdict, traceable end to end.

What it needs

git
on PATH. Worktrees and diffs go through the real binary, not a library.
ANTHROPIC_API_KEY
for the judge, the challenger, and the API reviewer.
GITHUB_TOKEN
only for posting, and only in the posting step. The GitHub API is called straight from the binary, so there is no gh CLI to install. Use a machine user or an App installation: GitHub rejects self-approval, and the reviewing identity should never be the authoring one.
Agent CLIs
optional. claude, cursor-agent, agy: whichever you configure. Configure none and the API reviewer runs alone.

Built to be operated,
not believed.

$ mergejury review --localreview the working tree before you push. No PR, no posting
$ mergejury adapters checkwhich reviewer is broken, and the exact fix
$ mergejury runs replay 7re-judge a stored run for cents; tune prompts against real findings
$ mergejury statscost per published comment, per reviewer: the number that decides who stays
$ mergejury servethe operator console: every drop, every verdict, traceable in under a minute