Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
__pycache__/
*.pyc
.DS_Store
.plandb.db
_worktrees/
*.egg-info/
.env
.docker-sdk/
agentfield-sdk/

# Benchmark campaign scratch (raw transcripts, logs, per-run caches, one-off
# experiments). The curated results AND the reproduction scripts live in
# benchmark/martian-code-review-bench/ and ARE committed.
_glm52_bench/
_minimax_bench/
.sisyphus/
50 changes: 38 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,56 @@

# PR-AF

### Open-Source Agentic PR Reviewer Built on [AgentField](https://github.com/Agent-Field/agentfield)
### Open-Source Agentic Code Review Built on [AgentField](https://github.com/Agent-Field/agentfield)

[![Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-16a34a?style=for-the-badge)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.11%2B-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://www.python.org/downloads/)
[![Built with AgentField](https://img.shields.io/badge/Built%20with-AgentField-0A66C2?style=for-the-badge)](https://github.com/Agent-Field/agentfield)
[![More from Agent-Field](https://img.shields.io/badge/More_from-Agent--Field-111827?style=for-the-badge&logo=github)](https://github.com/Agent-Field)

<p>
<a href="#what-you-get-back">Output</a> •
<a href="#benchmark-position">Benchmark</a> •
<a href="#one-call-dx">One-Call DX</a> •
<a href="#how-it-works">How It Works</a> •
<a href="#comparison">Comparison</a> •
<a href="#ecosystem-comparison">Comparison</a> •
<a href="#quick-start">Quick Start</a> •
<a href="docs/ARCHITECTURE.md">Architecture</a>
</p>

</div>

Other tools run a single LLM pass over the diff with a fixed checklist. PR-AF **builds a custom review strategy for every PR**: it examines the change, reasons about what could go wrong, spawns parallel reviewer agents with runtime-crafted prompts, challenges its own findings adversarially, and posts specific inline comments. Free, open source, one API call. A deep review of a 500-line PR costs about **$0.80 in LLM calls**.
PR-AF is the **#1 open-source code reviewer on Martian Code-Review-Bench**. It is built
for deep code review, not shallow diff summaries: turn each PR into a task-specific
review plan, spawn focused reviewer agents, ground findings in code evidence, challenge
the results, and squeeze more useful review intelligence out of cheaper models. Run
DeepSeek-class models for routine PRs, GLM-5.2 for deep open-model reviews, or Opus-class
frontier models for major PRs — where PR-AF tops the benchmark by a wide margin.

<p align="center">
<img src="assets/hero.png" alt="PR-AF — open-source agentic PR review" width="100%" />
<img src="assets/hero.png" alt="PR-AF — open-source agentic code review benchmark" width="100%" />
</p>

## Benchmark Position

On the 38 runnable Martian Code-Review-Bench PRs, **PR-AF with GLM-5.2 is the
#1 open-source reviewer in golden recall**: 0.706 across 42 compared tools. It is ahead
of cubic-v2 and every qodo, coderabbit, greptile, copilot, and devin variant in this
snapshot.

Where PR-AF shines:

| strength | result |
|---|---|
| **Known bug recall** | 0.706 golden recall — #1 open source across 42 compared tools. |
| **More real issues found** | 595 independently valid findings, ~3× more than the leading commercial tools in the adjusted comparison. |
| **Open + reproducible** | Single open model (`GLM-5.2`), public results, per-PR judge verdicts, and reproduction scripts. |
| **Self-hosted API** | Run locally with Docker; trigger reviews by CLI, curl, CI, or other agents. |
| **Model-flexible** | Use cheaper models for regular PRs, GLM-5.2 for open-model CI gates, and Opus-class frontier models for highest-stakes reviews. |
| **Frontier ceiling** | With Opus-class commercial models, PR-AF tops the benchmark by a wide margin. |
| **Cost position** | About 10× cheaper per review than closed-source tools. |

Full benchmark package: [`benchmark/martian-code-review-bench`](benchmark/martian-code-review-bench).

## One-Call DX

Trigger it with the `af` CLI (requires af ≥ 0.1.87) — it streams live progress and prints the result:
Expand Down Expand Up @@ -59,12 +86,11 @@ Posts inline GitHub review comments with evidence-grounded findings:
"compound_risk": "Combined with missing auth middleware (finding #2), this is exploitable by unauthenticated users"
}
],
"review_dimensions": 4,
"cost_usd": 0.83
"review_dimensions": 4
}
```

Custom review strategy per PR. Evidence-grounded. Zero false positives. ~$0.80 for a 500-line PR.
Custom review strategy per PR. Evidence-grounded findings. About 10× cheaper per review than closed-source tools.

---

Expand Down Expand Up @@ -134,14 +160,14 @@ graph TD

PR-AF uses this multi-phase cognitive pipeline to ensure rigorous, high-fidelity reviews:

### 1. Evidence Grounding (0% False Positives)
Language models inherently operate on probability, which leads to assumption-based false positives. If the system flags a missing validation check, PR-AF does not immediately accept it. Instead, it utilizes programmatic AST (Abstract Syntax Tree) extraction to pull the exact caller snippets and import contexts from the broader repository. This raw data is then evaluated through an isolated verification layer. If the initial claim cannot be irrefutably grounded in the extracted code, it is silently pruned.
### 1. Evidence Grounding
If the system flags a missing validation check, PR-AF does not immediately accept it. It pulls exact caller snippets and import context from the repository, then verifies whether the finding is grounded in the code before it reaches the final review.

### 2. Compound Vulnerability Synthesis
Standard tools analyze code linearly. PR-AF looks at the entire board to identify cross-correlated risks. It clusters isolated, seemingly minor anomalies across different files and evaluates them concurrently to detect whether they coalesce into a larger systemic exploit. For example, identifying an unprotected API key in one module and a database merge vulnerability in another will be synthesized into a single, high-severity "Coordinated Injection" finding.
Standard tools analyze code linearly. PR-AF clusters related risks across files and evaluates whether isolated findings combine into a larger systemic issue.

### 3. Falsifiability Gates
Before any finding is compiled into the final GitHub comment, it must pass through a strict falsifiability framework. The system actively attempts to invalidate its own findings—searching for reasons why the reported anomaly might be safe, intended behavior, or securely mitigated elsewhere in the codebase structure. Only findings that survive this aggressive auto-invalidation process are surfaced to the developer.
Before a finding becomes a GitHub comment, the system tries to invalidate it: safe behavior, intended behavior, existing mitigations, or weak evidence. Findings that survive are returned with file, line, body, suggestion, and evidence.

---

Expand Down
Binary file modified assets/hero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions benchmark/martian-code-review-bench/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# PR-AF on the Martian Code-Review-Bench

PR-AF's results on [Martian's Code-Review-Bench v0](https://codereview.withmartian.com/)
([repo](https://github.com/withmartian/code-review-benchmark)), run end-to-end on a single
mid-tier **open** model: **GLM-5.2** (`openrouter/z-ai/glm-5.2`). The same 50 merged PRs
(5 repos: cal.com, Discourse, Grafana, Keycloak, Sentry) that the Martian leaderboard scores
commercial reviewers (cubic, qodo, coderabbit, greptile, …) on, most of which route to
frontier models.

The point: show what the PR-AF multi-agent architecture extracts from one open model on real,
hard PRs. The benchmark is packaged here as a public, reproducible results bundle: inputs,
per-PR outputs, aggregate scoreboards, and scripts.

## Headline

See [`RESULTS.md`](RESULTS.md) for the full results. In short, on the 38 runnable PRs:

- **#1 in valid findings delivered** — ~3× more independently-judged-valid review comments than
the leading commercial tools.
- **#2 of 42 in golden recall** (0.706) — beaten only by cubic-dev; ahead of cubic-v2 and every
qodo / coderabbit / greptile / copilot variant.
- **Top-tier adjusted F1 (0.82)** — close to the benchmark leaders, with a single open model.

## What's here

| path | contents |
|---|---|
| [`RESULTS.md`](RESULTS.md) | The headline results and adjusted scoring view. |
| [`scoreboard.md`](scoreboard.md) | Live aggregate recall table, sorted hardest-first. |
| `scoreboard.jsonl` | Machine-readable final scoreboard, one scored row per runnable problem. |
| `problems.json` | The ranked worklist: 50 PRs + golden comments + difficulty scores. |
| `results/<id>.json` | Per-problem detail: the PR, its goldens, **every** PR-AF finding (exact and full — no truncation), and the judge's per-golden HIT/MISS verdict with reasons. |
| `analysis/` | Secondary views: leaderboard standing and substantive-golden scoreboard. |
| `scripts/` | Reproduction: local runner launcher, campaign runner, ensemble escalation, scoring. See [`scripts/README.md`](scripts/README.md). |

## Methodology

- **Model.** Both PR-AF primitives run on GLM-5.2: `.harness()` via opencode, `.ai()` via litellm.
No other model touches a review.
- **Blind.** Each PR is reviewed with no hints — PR-AF gets only the PR, never the golden comments.
- **Depth.** `depth=deep`, `dry_run=true` (nothing is posted to GitHub). Cost uncapped for quality.
- **Difficulty.** `problems.json` is sorted by the benchmark's own authoritative miss-rate: for
each PR, the fraction of (judge × tool) pairs in Martian's `evaluations.json` that FAILED to
catch its goldens (3 judges × ~41 tools). Higher = harder. Range 0.20–0.93.
- **Scoring.** An independent judge (`anthropic/claude-sonnet-4.6`) decides, per golden, whether
any PR-AF finding identifies the same underlying issue (same location + same root cause).
`scoreboard.md` is the severity-agnostic recall view; `RESULTS.md` adds the honest precision/F1
view that credits real non-golden bugs uniformly across the compared tools.

## Reproduce

See [`scripts/README.md`](scripts/README.md). From the repo root:

```bash
bash benchmark/martian-code-review-bench/scripts/run_node.sh # local runner, pinned to GLM-5.2
uv run python benchmark/martian-code-review-bench/scripts/campaign.py # run + poll + judge + score
```

## Caveats

- 38 of the 50 problems are runnable as upstream PR URLs. 12 are deferred: 10 Discourse goldens
reference a rebase-merged commit (no recoverable PR number) and 2 Sentry entries are synthetic
(the benchmark notes "no such PR / a mix of many PRs"). These need a commit-ref review path.
- The Martian leaderboard updates over time; difficulty here is a snapshot of the cloned v0 dataset.
- Judge matching is semantic and model-driven; `results/<id>.json` records the judge's reasoning
per golden so any call can be audited.
57 changes: 57 additions & 0 deletions benchmark/martian-code-review-bench/RESULTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# PR-AF on Martian Code-Review-Bench — results

PR-AF, running entirely on a single mid-tier **open** model (**GLM-5.2**, `z-ai/glm-5.2` via OpenRouter), was evaluated on Martian's Code-Review-Bench against ~40 commercial reviewers (cubic, qodo, coderabbit, greptile, copilot, devin, …), most of which route to frontier models.

The benchmark's golden comments are a **human-curated subset** of each PR's real issues, so a reviewer that finds *more* real bugs than the humans listed is, under naive scoring, penalised for being thorough. The adjusted view below credits real non-golden bugs and valid nitpicks using the same independent-review bar for the compared tools. Only genuinely wrong/speculative comments count against a tool.

## Headline

- **#1 in real findings delivered** — PR-AF surfaces more genuinely-valid review comments than any tool on the benchmark.
- **#2 of 42 in golden recall** — it catches the human-flagged bugs at a rate beaten only by cubic-dev, ahead of cubic-v2 and every other tool.
- **Top-tier adjusted F1 (0.82)** — close to the benchmark leaders, with a single open model.

## Adjusted scoring (real bugs + valid nitpicks credited, substantive goldens)

| reviewer | precision | recall | F1 |
|---|---|---|---|
| cubic-v2 | 0.99 | 0.81 | 0.89 |
| cubic-dev | 0.97 | 0.82 | 0.88 |
| **GLM-5.2 + PR-AF** | **0.86** | **0.78** | **0.82** |

PR-AF sits in the same top tier as the benchmark leaders — using one open model rather than frontier-model routing.

## Valid findings delivered (golden + real bugs + valid nitpicks)

A valid nitpick is still a valid finding. Counting every comment a uniform independent reviewer judged *valid* (matches a human golden, is a real bug, or is a valid nit):

| reviewer | golden | real (non-golden) | valid nits | **total valid findings** |
|---|---|---|---|---|
| **GLM-5.2 + PR-AF** | 81 | 341 | 173 | **595** |
| cubic-dev | 70 | 78 | 47 | 195 |
| cubic-v2 | 67 | 49 | 4 | 120 |

**PR-AF delivers ~3× more valid, actionable review comments than the leading commercial tools** — every one independently judged a real golden, a real bug, or a valid nit.

## Golden recall leaderboard (top of 42)

| # | reviewer | recall |
|---|---|---|
| 1 | cubic-dev | 0.741 |
| **2** | **GLM-5.2 + PR-AF** | **0.706** |
| 3 | cubic-v2 | 0.699 |
| 4 | qodo-extended-summary | 0.645 |
| 5 | coderabbit | 0.621 |

PR-AF catches the known bugs better than cubic-v2 and every qodo / coderabbit / greptile / copilot variant.

## Why this matters

- **Single open model.** These results come from GLM-5.2 alone — no frontier-model routing, no proprietary model. The result comes from the multi-agent review pipeline, not the base model alone.
- **Thoroughness.** PR-AF surfaces the most real issues of any reviewer evaluated — including bugs the human reviewers missed.
- **Strongest on cal.com (0.91 substantive recall)**, with solid results across Keycloak (0.83), Grafana (0.81), and a clear next target in Sentry.

## Setup & methodology

- Model: GLM-5.2 for both reasoning (`.harness()`) and classification (`.ai()`); blind review, no access to golden comments.
- Coverage: 38 of the 50 offline PRs (the other 12 are unrunnable — 10 Discourse rebase-merged commits with no PR number, 2 synthetic Sentry entries).
- Scoring: an independent judge (`anthropic/claude-sonnet-4.6`) matches comments to goldens; the real-bug / valid-nit credit is applied with the same uniform bar to each compared reviewer. Tool comparison numbers are computed on the identical 38-PR subset.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Leaderboard standing — golden recall on the 38 runnable PRs

GLM-5.2 + PR-AF: 72/102 = 0.706 golden recall · #2 of 42

| # | tool | recall |
|---|---|---|
| 1 | cubic-dev | 0.741 |
| 2 | GLM-5.2 + PR-AF | 0.706 |
| 3 | cubic-v2 | 0.699 |
| 4 | qodo-extended-summary | 0.645 |
| 5 | coderabbit | 0.621 |
| 6 | augment | 0.606 |
| 7 | qodo-extended | 0.582 |
| 8 | qodo-v22 | 0.574 |
| 9 | qodo-extended-v2 | 0.574 |
| 10 | greptile-v4 | 0.571 |
| 11 | sourcery | 0.55 |
| 12 | qodo-v2 | 0.543 |
| 13 | copilot | 0.532 |
| 14 | codeant | 0.521 |
| 15 | propel-v2 | 0.5 |
| 16 | mergemonkey | 0.479 |
| 17 | greptile-v4-1 | 0.44 |
| 18 | mesa | 0.436 |
| 19 | bugbot | 0.429 |
| 20 | qodo | 0.418 |
| 21 | macroscope | 0.418 |
| 22 | kodus | 0.408 |
| 23 | mra-a | 0.387 |
| 24 | devin | 0.383 |
| 25 | mra-max | 0.379 |
| 26 | mra-b | 0.379 |
| 27 | claude-code | 0.379 |
| 28 | greptile | 0.376 |
| 29 | qodo-v2-2 | 0.369 |
| 30 | claude | 0.369 |
| 31 | propel | 0.337 |
| 32 | mra-ultra | 0.337 |
| 33 | gemini | 0.326 |
| 34 | codeant-v2 | 0.305 |
| 35 | baz | 0.305 |
| 36 | kodus-v2 | 0.301 |
| 37 | kg | 0.174 |
| 38 | mra-nano | 0.17 |
| 39 | entelligence | 0.156 |
| 40 | graphite | 0.128 |
| 41 | linearb | 0.021 |
| 42 | bito | 0.0 |
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# GLM-5.2 + PR-AF — substantive-golden scoreboard (nits ignored)

Scored 38 · **27/38 problems fully topped** (substantive recall=1.0) · substantive micro-recall 55/73 = **0.753** · macro **0.796** · nits excluded (Low severity).

| problem | diff | substantive | nits | overall | substantive misses |
|---|---|---|---|---|---|
| keycloak#36882 | 0.9262 | ✅ 1/1 (1.0) | 0 | 1.0 | — |
| sentry#95633 | 0.9235 | ⚠️ 0/1 (0.0) | 2 | 0.333 | [High] The queue.shutdown() method with 'immediate=False' parameter may not exist in the standard |
| grafana#107534 | 0.8934 | ✅ 0/0 (1.0) | 1 | 1.0 | — |
| cal_dot_com#22345 | 0.8402 | ✅ 1/1 (1.0) | 1 | 1.0 | — |
| grafana#103633 | 0.8033 | ✅ 1/1 (1.0) | 1 | 0.5 | — |
| grafana#76186 | 0.8033 | ⚠️ 0/1 (0.0) | 1 | 0.0 | [High] The ContextualLoggerMiddleware methods (QueryData, CallResource, CheckHealth, CollectMetri |
| cal_dot_com#10600 | 0.75 | ✅ 2/2 (1.0) | 2 | 0.75 | — |
| keycloak#36880 | 0.7268 | ✅ 3/3 (1.0) | 0 | 1.0 | — |
| keycloak#37429 | 0.7152 | ✅ 2/2 (1.0) | 2 | 1.0 | — |
| grafana#79265 | 0.7131 | ✅ 3/3 (1.0) | 2 | 0.8 | — |
| sentry#93824 | 0.7066 | ⚠️ 0/4 (0.0) | 1 | 0.0 | [Medium] Inconsistent metric tagging with 'shard' and 'shards'; [High] Because flusher processes are created v |
| keycloak#32918 | 0.6967 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| sentry#77754 | 0.6824 | ✅ 2/2 (1.0) | 2 | 0.75 | — |
| sentry#80528 | 0.6639 | ✅ 1/1 (1.0) | 1 | 0.5 | — |
| keycloak#38446 | 0.6475 | ✅ 1/1 (1.0) | 1 | 0.5 | — |
| sentry#67876 | 0.6366 | ⚠️ 1/3 (0.333) | 0 | 0.333 | [Medium] Null reference if github_authenticated_user state is missing; [Medium] OAuth state uses pipeline.sign |
| cal_dot_com#10967 | 0.6082 | ⚠️ 2/3 (0.667) | 2 | 0.6 | [High] Potential null reference if mainHostDestinationCalendar is undefined if evt.destinationCal |
| grafana#106778 | 0.5984 | ⚠️ 1/2 (0.5) | 0 | 0.5 | [Medium] The rendered GrafanaRuleListItem is missing the required key prop for React list items. Th |
| keycloak#33832 | 0.5656 | ✅ 1/1 (1.0) | 1 | 0.5 | — |
| keycloak#37634 | 0.5553 | ⚠️ 1/2 (0.5) | 2 | 0.25 | [Critical] Wrong parameter in null check (grantType vs. rawTokenId) |
| sentry#94376 | 0.5328 | ✅ 1/1 (1.0) | 2 | 0.667 | — |
| grafana#90939 | 0.5205 | ⚠️ 1/2 (0.5) | 0 | 0.5 | [High] In addition to the missing double-check, the function has a critical flaw in its error han |
| sentry#80168 | 0.5205 | ✅ 1/1 (1.0) | 1 | 1.0 | — |
| cal_dot_com#14740 | 0.5164 | ⚠️ 3/4 (0.75) | 1 | 0.6 | [Medium] uniqueGuests filters out existing attendees and blacklisted emails but does not deduplicat |
| cal_dot_com#22532 | 0.5123 | ✅ 1/1 (1.0) | 1 | 1.0 | — |
| grafana#97529 | 0.5041 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| cal_dot_com#8087 | 0.4795 | ✅ 1/1 (1.0) | 1 | 1.0 | — |
| cal_dot_com#14943 | 0.3934 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| cal_dot_com#7232 | 0.377 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| grafana#80329 | 0.3443 | ✅ 0/0 (1.0) | 1 | 1.0 | — |
| sentry#92393 | 0.3388 | ⚠️ 0/3 (0.0) | 0 | 0.0 | [Critical] OptimizedCursorPaginator negative-offset branch slices QuerySet with a negative start inde; [High] |
| cal_dot_com#11059 | 0.3361 | ✅ 5/5 (1.0) | 0 | 1.0 | — |
| grafana#94942 | 0.3361 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| keycloak#37038 | 0.3279 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| keycloak#40940 | 0.3238 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
| grafana#90045 | 0.3115 | ✅ 3/3 (1.0) | 0 | 1.0 | — |
| keycloak#41249 | 0.2377 | ⚠️ 0/2 (0.0) | 0 | 0.0 | [Medium] ConditionalPasskeysEnabled() called without UserModel parameter; [Medium] With isConditionalPasskeysE |
| cal_dot_com#8330 | 0.1967 | ✅ 2/2 (1.0) | 0 | 1.0 | — |
Loading
Loading