# The review pipeline

# The review pipeline

Every review is one trip through the same pipeline. A webhook enqueues a job; the worker claims it; the pipeline loads the PR, decides how much to spend, runs the review, filters the output, and posts. This page walks the whole path in order.

## The shape of it

```text
GitHub PR opened / updated
   │  signed webhook (verified)
   ▼
inline webhook endpoint ──► review job queued
                              │  picked up by the worker
                              ▼
   ┌─ the review pipeline ──────────────────────────────────────┐
   │ 1. guard / skip checks (repo enabled? PR open? head fresh?) │
   │ 2. incremental base (diff only since last reviewed head)    │
   │ 3. path filters + diff compression                          │
   │ 4. project-type detection → guideline pack                  │
   │ 5. triage — a fast model (trivial vs substantive)           │
   │ 6. budget gate                                              │
   │ 7. deep review — a frontier model, agentic loop             │
   │ 8. validation gate (confidence, severity, dedup, anchoring) │
   │ 9. post GitHub review: summary + inline comments            │
   │ 10. persist review + findings + cost, absorb repo memory    │
   └────────────────────────────────────────────────────────────┘
```

The webhook path does almost nothing — it verifies the signature and queues a job. GitHub gives webhooks only a few seconds to respond, so all model work happens later in the worker. Reviewable PR actions are **opened**, **synchronize**, **ready for review**, and **reopened**; drafts are skipped; a **closed** PR triggers the [feedback harvest](./feedback-loop.html).

## 1. Guards and skips

Before spending anything, the pipeline bails early when there's nothing to do:

- **Repo disabled** — no review.
- **PR no longer open**, or the **head moved** since the job was queued — skip as stale (a newer push already queued a fresher job).
- **Bot authors** (e.g. Dependabot) — skip the review, but still sync the merge gate so a required check never gets stuck.

## 2. Incremental base

inline reviews **only what's new**. It finds the last completed review for this PR and uses that review's head as the comparison base, so a third push reviews only the third push's changes — deduped against everything already flagged.

Commenting `@inline full review` on the PR forces a full re-review from scratch. A force-push that breaks the compare API falls back to a full diff automatically.

## 3. Path filters and diff compression

Two cost levers run here before a single token reaches a model:

- **Path filters** drop files that never deserve a review — lockfiles, build output, dependencies, generated code, minified JS, migrations, snapshots, images, fixtures. This is the cheapest lever: filtered files cost nothing. Defaults are combined with per-repo and per-workspace globs you set in [review config](./review-config.html).
- **Diff compression** ranks the surviving files by change volume, de-prioritizes enormous files, and clips the diff sent to the model. Anything omitted is noted so the review agent can pull it in later with its file-reading tools.

See **[Cost & two-tier models](./review-cost.html)** for the full lever list.

## 4. Project-type detection

inline detects whether the PR is TypeScript, React, React Native, C#, and so on, and selects the matching **guideline pack** — a language-specific set of review rules folded into the review.

## 5. Triage — a fast model

The first model call is cheap on purpose. A fast model reads the diff and returns a structured verdict:

```json
{ "verdict": "substantive", "summary": "...", "riskAreas": ["auth", "db"] }
```

- **trivial** — no deep review. inline records the verdict, notes a low-risk line on the walkthrough, syncs the gate, and stops. This is where most of the cost savings come from.
- **substantive** — proceed to the deep review. When in doubt, triage chooses substantive.

## 6. The budget gate

Between triage and the expensive deep review, inline checks the workspace's monthly budget. At 80% of the cap it fires a one-time alert. Past the cap, if **budget-degrade** is on, it stops at triage and records the review as incomplete — which excludes it from the incremental base, so the PR gets a real review next month instead of being silently skipped.

## 7. Deep review — a frontier model

The substantive review is an **agentic loop** on a frontier model. The model doesn't just see a diff — it can act:

| Tool | What it does |
| --- | --- |
| `read_file` | Read any file at the PR head, with path-alias and extension resolution. |
| `search_code` | Grep file *contents* at the head commit — sees symbols the PR just added. |
| `find_files` / `list_directory` | Locate and browse files at the head. |
| `dispatch_explorers` | Fan out cheap subagents to map a large PR breadth-first. |
| `graph_*` | Traverse a [code graph](./codegraph.html) — definitions, references, importers, call traces — when an index exists. |
| `load_skill` | Pull in a [skill](./learnings.html) whose description matches the PR. |
| `web_search` / `web_fetch` | Research external context (when web research is enabled). |
| `submit_review` | The required terminal tool that returns the findings. |

The loop is bounded by a step ceiling and a per-turn output cap. The **explorer subagents** run on a fast model at a fraction of the deep model's price, carrying the token-heavy breadth work while the frontier model does the judgment. If the loop hits the step ceiling without submitting a review, the review is recorded incomplete and the incremental base is held so nothing is lost.

The model is told, emphatically, that **a review with no findings is a success** — never comment on style, formatting, naming, docs, or coverage, and refute your own finding before flagging it.

## 8. The validation gate

Everything the model submits passes through a validation gate before anything is posted. Findings are suppressed (never dropped — they're stored with a reason and visible in the portal) when they are low-confidence, below the repo's severity threshold, duplicates, un-anchorable to the diff, or beyond the comment cap. This is the machinery that keeps inline quiet — it has its own page: **[Noise control](./review-noise.html)**.

## 9. Post

inline posts a single GitHub review: a summary comment (the walkthrough sticky comment, finalized here) plus inline comments anchored to changed lines. If GitHub rejects the inline anchors, it falls back to a body-only review so the findings still land.

## 10. Persist and learn

Finally the pipeline records the review and its findings with full cost accounting, reopens any re-confirmed findings, auto-resolves threads for findings that are now addressed, syncs the merge gate, optionally enqueues a [walkthrough page](./walkthrough.html), [sandbox tests](./sandbox.html), or an [auto-fix PR](./auto-fix.html) — and folds this review's summary and findings into the repo's [memory](./repo-memory.html) with a cheap model call.

## The worker

Jobs are drained by an in-process worker. It claims jobs atomically, serializes work per-PR so two jobs on the same PR never double-post, dispatches each job to the right handler by type, and continuously recovers stale jobs. Failed jobs retry with exponential backoff up to a bounded attempt count.
