Docs

PR review

PR review reads the PR diff in full context and reasons about it — this is a code review, not a second CI: it never re-runs the build, the linter or the test suite, because CI already answered those. The harness enforces that per phase with a command policy that blocks test runs (and, when the evidence pipeline is on, installs) in the reviewing phases, and keeps every phase inside the checkout — no scanning the machine or borrowing a globally installed package, so a probe only ever tests the versions the PR pins. Only a small, targeted probe may execute code. It runs in two phases: an agent phase judges the diff and records its findings, then a deterministic phase posts one formal review with each finding as an inline comment anchored to its diff line (with an applyable suggestion where a concrete fix fits). A finding whose line isn't in the diff is folded into the review summary instead. With the review evidence pipeline on, the agent phase is replaced: a per-unit survey records where defects might be, five investigators each examine one of the most-pointed-at stretches of code, and one selection pass decides what is worth posting.

The review is precision-first: only high-signal Critical and Important findings are posted — each with a concrete impact (what breaks, for which input) and put through a self-refutation confidence gate — while lower-value suggestions and nits are dropped, because a noisy reviewer gets muted. A clean PR is approved with few or no comments — unless a finding from an earlier review is still open or a maintainer has requested changes, when the review is a comment instead. Asking the bot on a PR to review it, or to approve it, runs a fresh review.

Permission profile: review-write — can read the repo and post review comments, but cannot push code.

Pipeline

Review judge the diff Post inline comments

What it checks

  • Implementation correctness against the PR description
  • Test coverage for changed code
  • Security vulnerabilities (OWASP top 10)
  • Code style and naming consistency
  • Error handling and edge cases

Triggers

When a review runs is an operator (and per-repo) decision — review.trigger, which ships after-checks. Every route below crosses the same gate, so the mode has one meaning everywhere.

  • GitHub webhook: pr.opened / pr.synchronize / pr.reopened, and Ready for review on a draft — under eager. Under after-checks these defer and the review instead runs once the head SHA's checks settle, either colour
  • By request: the review.requestLabel label, an @last-light review comment, a review requested from the bot, or Re-run on the last-light/review check. An explicit request always runs — it overrides the mode, the draft skip and the "already reviewed this commit" check
  • Cron sweep: every 30 minutes, including when webhooks are configured. It is the only route that reaches a PR whose fix chain stopped without pushing a commit, since no further check-suite event will fire for it
  • Slack: review cliftonc/repo
  • CLI: npm run cli -- review owner/repo

Skipped without a run: draft PRs (review.skipDraft, matching what the sweep has always done), a commit we already reviewed, and a PR another Last Light run is currently working on — reviewing a tree a fix run is rewriting produces a review that is stale before it lands. All three are read off one resolved snapshot of the pull request, and the last-light/review check each decision leaves behind differs; see the PR state model.

How much review a re-review is owed

A second review of the same pull request is priced by how much the change actually moved, not by the fact that the commit did. Three tiers, and the first two ship on:

  • No review. A push whose own diff against the base is byte-identical to the one we already reviewed — a merge from main, a rebase that preserves the tree, an empty force-push — is skipped, and the standing verdict is repeated on the new commit. So is a push that touched only generated files. See review.skipUnchangedDiff and review.generatedPaths.
  • A light review. For a real but small delta, one cheap pass decides the rest of the run is not worth re-deriving, and the reviewer makes a single focused pass over what changed since the last review — a new defect, a flagged point the delta claims to fix but does not, and one it genuinely fixed. See review.triage.
  • The full review. Everything else, and every uncertain case: a large or spread-out delta, anything touching an interface, a schema, auth or error handling, and any answer the triage pass was unsure about.

With the review.analysis evidence pipeline on, re-reviews converge instead of starting from scratch. Last Light keeps a review memory for each pull request — which code each review covered, every finding it made (posted or held back), and what became of each one — and uses it three ways:

  • It looks only where the code moved. Functions unchanged since the last review, and not calling into or called from changed code, are not investigated again. A small push is a small, cheap review; a push that changed nothing the last review saw plans no investigation at all. (The light pass above is not used with the pipeline on.)
  • It does not raise new points on old code. A finding on lines the last review already had is held back — recorded, not posted — unless it is must-fix outside low-risk code, in which case it posts, labelled as missed in an earlier review.
  • It reports on what it said before. The review opens with what was addressed since the last round and what is still open, never posts the same point twice, and only says "good to merge" when nothing it raised is still open.

Each changed area also gets a risk tier — docs, tests and generated files low; migrations, schemas, auth and CI high — which decides where investigators go first. A repository can set its own tiers in .lastlight/lastlight.yml under review.risk.rules; see configuration. The dashboard's Review tab on each run shows how much of the change was surveyed and investigated, weighted by risk, and the review memory.

A first review of a pull request is never affected by any of this, and an explicit @last-light review always buys the full one.