Usage

What happens on every pull request: how a review is triggered and routed, what a PURA review looks like, and how re-reviews and skips behave.

The review lifecycle

PRs from any branch are eligible. When one opens or receives a push, PURA runs a deterministic pipeline — there is no LLM in the routing hot path:

PR opened / new commit pushed
        │
        ▼
1. Classify  → hydrate the pr.* context (paths, lines,
               CODEOWNERS, labels, author type) at the head SHA
        │
        ▼
2. Route     → Engine evaluates rules.yaml (CEL, no LLM) and picks
               (provider, model, thinking); org-cap overlay applies
        │
        ▼
3. Review    → Reviewer Agent reads the diff, uses read_file / glob /
               grep, and returns structured findings (your BYO key)
        │
        ▼
4. Post      → exactly ONE line-anchored GitHub review, as the PURA app

Deterministic by design.Two runs at the same head SHA route to the same model (budget permitting). The reviewer is agentic — it's handed the diff and tools and decides what to fetch — but routing is pure CEL evaluation.

Anatomy of a review

PURA posts exactly one Pull Request Review per run. It opens with a transparency header showing what was routed and why, then carries line-anchored inline comments.

The summary header:

**pura Review** • routed to `claude-opus` (high thinking) • matched rule `payments-critical`
3 findings: 1 P1, 2 P2 • estimated cost $0.34 • 2.1s

<summary prose from the agent>

Each finding is a line-anchored inline comment: severity tag, an imperative title, a short body that backticks every identifier, and an optional one-click suggestion block:

🟠 **P2 · Close popover before hiding Changes/Price pills**

Wrapping the Changes and Price pills behind `showAllFilters` introduces a
state mismatch: if `showAllFilters` is false and a user clears one of these
filters, the pill unmounts but `activeFilter` is not reset, leaving a
floating popover with no anchor pill.

```suggestion
{(filters.maxChanges !== null || showAllFilters) && (
```

Suggestion blocks are conditional.A one-click fix is emitted only when it is ≤ 25 lines, a single contiguous range matching the comment's line and side, and free of embedded triple-backticks. Otherwise the comment stays prose-only.

Severity tags & the review event

TagMeaningExamples
🔴 P1 — must fixCorrectness, security, breaking changeData loss, auth bypass
🟠 P2 — should fixRobustness, missing coverage, perfUnhandled edge case
🔵 P3 — suggestionPolish, alternative approachNaming, minor cleanup

The orchestrator derives the GitHub review event from the severity distribution — the agent never sets it:

  • Any P1 → REQUEST_CHANGES
  • Only P2 / P3 → COMMENT
  • No findings → APPROVE (the header is still posted)

Re-review on every push

A new commit re-runs the full pipeline against the new head SHA — re-classify, re-route (the budget may have shifted, so the model can differ), re-review. The prior PURA review is dismissed and superseded: the new review links back with Supersedes review #<id>.

Each re-review is a billable reviewed commit. The PR opening counts as 1, and every push that triggers a re-review counts as 1 more. A re-review happens even if the previous run ended in a manual-review-needed comment.

Drafts & skips

When the routing decision is skip, PURA posts nothing on the PR — the skip is recorded in the audit log with the matched rule name, and it is not counted as a reviewed commit.

  • Drafts are skipped by default. The Translator emits a synthetic skip-drafts rule when your pura.mddoesn't handle drafts; you can opt drafts in.
  • Explicit skips come from a rule with action: skip (e.g. skip docs-only PRs). When both a skip rule and a use rule match, the use rule wins.
  • Empty diffs skip the agent run entirely — no review, no comment.

Next