IonWarp logoIonWarp
Get started
IonWarp Docs
API

Reviews

One review pass over a pull request: launch it, read the per-reviewer telemetry, and see the outcome stamped on the PR.

A review is one pass over a pull request. IonWarp reads the diff, picks a reviewer lineup, runs each reviewer, merges and dedupes what they found, and posts the result back to GitHub as PR comments. It runs automatically on every watched PR, and you can start one yourself from the PR page, from a task, or from the API.

Where a review got to is recorded on the pull request itself — review_status, last_reviewed_at, last_review_run_id — so the PR row is what you query:

List pull requestsGET /api/v1/pull-requests

curl "https://ionwarp.com/api/v1/pull-requests?state=open" \
  -H "Authorization: Bearer $DASH_API_KEY" \
  -H "Project-ID: pr_acme"
Which pull requests are still waiting on changes?
data_query {
  "collection": "pull_requests",
  "where": {
    "state": "open"
  }
}

{
  "object": "list",
  "data": [
    {
      "object": "pull-request",
      "id": "obj_123",
      "number": 630,
      "title": "Collapse the review dispatch fast path",
      "state": "open",
      "created_at": "2026-07-25T12:00:00.000Z",
      "updated_at": "2026-07-25T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Every field, filter and sort is in the pull-requests reference, and the PR objects reviews hang off are documented in Repositories & PRs.

What to know before you call it

One ionwarp-review task runs per pull request, and three project settings shape it: ionwarp.review.enabled turns automatic review on or off, ionwarp.review.guidance adds project-specific instruction to every reviewer, and ionwarp.review.budget_usd (default 1) tells the planner how wide a lineup to buy — a scale signal, not a ceiling.

Read per-reviewer results from reviewers_telemetry, never from the PR comment. GET /api/v1/tasks/{task_id}/status returns one row per reviewer carrying the model that actually ran, its grade and verdict, findings count, real cost, and phase timings. The comment is a rendering of that table; the table is the record. A reviewer that timed out or delivered nothing appears there as a named row rather than as silence.

A review that cannot run says so by name on the run — read it with Debugging a Run. The project-level brakes that stop one before it starts (pause, approval window, spend cap) are on Control Plane, and PR-level skips are recorded on the pull request itself.

The review lifecycle & the GitHub check

Every review moves through ONE named lifecycle, persisted on the pull request (review_status) and mirrored 1:1 by the status pill and the GitHub check run IonWarp / Review:

push ──▶ TRIGGER ──▶ REVIEW                      GITHUB CHECK "IonWarp / Review"
         (filters,    planning                    queued
          dedupe)     skipped/errored ──────────▶ skipped · reason in title
                      reviewing                   in_progress
                      reviews_available           in_progress (findings post inline)
                      summarizing                 in_progress
                      reviewed ─────────────────▶ P0 → action_required
                                                  P1 → neutral · clean → success
                      ⏱ deadline (≤10m) ────────▶ neutral "still reviewing"
                                                  → PATCHed to verdict when done

The terminal success state is Reviewed. If the review outlives its deadline (auto: the p75 latency for the PR's size bucket, hard cap 10 min), the check completes neutral — "Review still running — findings will post as comments" — and is updated to the real verdict when the review lands. A slow review never blocks a merge.

Check conclusions

Review outcomeGitHub check conclusionMerge button, if you made the check required
P0 openaction_required❌ blocked — the only blocking state
P1 onlyneutral✅ mergeable
Clean / P2 onlysuccess✅ mergeable
Not reviewed — filteredskipped · title: "Skipped: draft / release PR / no reviewable diff"✅ mergeable
Not reviewed — erroredskipped · title: "Skipped: review failed to run — @ionwarp review now to retry"✅ mergeable

With the check not required — the default — every row is mergeable and the conclusion is purely informational. The per-severity conclusions are workspace settings (ionwarp.checks.p0_conclusion / p1 / p2); "not reviewed → skipped" is fixed — a no-show must never block. Blocking = you mark the check required in GitHub branch protection; there is no separate IonWarp "hard block" switch. The structured fix prompt rides check output.text, so a coding agent reads it from the Checks API without comment parsing.

Findings survive re-runs: the conclusion derives from the per-PR open-findings ledger (the union of findings across runs, keyed by the inline thread markers). A finding leaves "open" only by being fixed (its anchor outdated by a push and not re-found) or dispositioned — reply wontfix: <reason> on the finding thread (or resolve it) and the check re-computes without a new review run.

PR commands

GitHub has no typeahead for app commands — a bare @ionwarp comment replies with this list:

  • @ionwarp review off [reason] — disable automatic review for this PR
  • @ionwarp review on — re-enable and review now
  • @ionwarp review now — one review without changing the setting
  • @ionwarp review force — re-review even on an unchanged head SHA
  • @ionwarp review status — the PR's current review state
  • @ionwarp help — the command list

Replying to a finding thread: wontfix: <reason> dismisses it (the check re-computes), fix this opens a fix task.

Autofix contract (for coding agents)

The AGENTS.md block IonWarp installs (see the enablement PR from Settings → Coding Agents) tells your coding agent, after pushing to a PR:

wait for the "IonWarp / Review" check to finish (findings + summary) or its deadline:
  finished → triage each finding with the summary as context:
    helpful → reply "✔ fixing", fix it · wrong → reply "wontfix: <reason>"
    then post ONE "⚡🛸 IonWarp autofix round 1" comment (✅ fixed / 🚫 wontfix
    lines + a "✅ Verified:" line naming what was run) and push all fixes as
    ONE fixpack commit (re-review resolves the ledger, tagged autofix)
  deadline passed → proceed without IonWarp (never block on it) · max 2 rounds

Let the agent do it

Reviews start themselves on every watched PR; this is how you ask for one by hand — the same ionwarp-review task either way.

tasks_create { "project_id": "pr_acme", "skill_id": "ionwarp-review", "run": true,
               "input": { "pr_number": 128 } }
tasks_status { "task_id": "ts_…" }     // → per-reviewer telemetry, findings count, cost

Next: Reviewers & Models to choose who reviews and with which model, Repositories & PRs for the PR objects reviews hang off, Scorecards for repo-wide rubrics instead of per-PR passes.