ikatkov/agent-skills · Archived

review-pr

Run an exact-HEAD GitHub PR review loop: trigger CodeRabbit if it is missing, wait without LLM polling, collect every review surface and unresolved thread, fix the findings that fall inside the PR's stated scope, decline the ones that don't, verify required checks, and return a machine-readable verdict.

First seen Jul 27, 2026

Installation

$ npx skills add ikatkov/agent-skills --skill review-pr

Summary

  • Run an exact-HEAD GitHub PR review loop: trigger CodeRabbit if it is missing, wait without LLM polling, collect every review surface and unresolved thread, fix the findings that fall inside the PR's stated scope, decline the ones that don't, verify required checks, and return a machine-readable verdict.
  • Use for bot-review requests, review cleanup, or GitHub review handling on the current branch PR.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from ikatkov/agent-skills · top by installs.

npx skills add ikatkov/agent-skills

Browse all from ikatkov/agent-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Default branch master
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 29,051 B
  • docs SUMMARY.md 418 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 23 installs

SKILL.md

Review PR

Review the current PR's exact HEAD, fix the findings that belong to it, and return a machine-readable verdict. Two rules run through the whole loop: keep polling deterministic — never spend model turns waiting for external state — and keep the diff inside the scope the PR description already claims.

This skill takes no flags. Its only input is the PR on the current branch (or a PR number the caller names).

Review gate

CodeRabbit (coderabbitai[bot]) is the only gating reviewer. It runs on push; the fallback trigger is a @coderabbitai review comment. The verdict waits on CodeRabbit and on the ruleset-required status checks — nothing else.

reviewDecision carries CodeRabbit's standing answer across cycles wherever the repository enables reviews.requestchangesworkflow. It holds CHANGES_REQUESTED while any of its comments is open, and turns APPROVED once they are resolved and the pre-merge checks pass. That approval is a real GitHub review object, submitted for a clean review with no unresolved CodeRabbit threads and no blocking pre-merge checks.

CodeRabbit approves a pull request once. The approval stands over every later commit, so reviewDecision keeps reading APPROVED for commits the reviewer has yet to see. It tracks the commit under review where branch protection dismisses stale approvals on push. Everywhere else, read it as a fact about the pull request, and take the exact-HEAD answer from Section 6.

Read which case applies from the snapshot Section 3 already fetches, and see Repository expectations below for what each costs the run.

Never post @coderabbitai approve. It submits an approving review on demand, with an empty body, whatever the state of the code — so it forges the exact signal this skill waits on. @coderabbitai review and @coderabbitai full review are the only commands this skill posts.

Unresolved human review threads block pass: triage every unresolved thread in Section 4 regardless of who opened it. The verdict itself waits on CodeRabbit.

Repository expectations

This skill runs against whatever configuration a repository already has and changes none of it. Three conditions decide how well the loop runs, and all three are read from evidence the run already produces. Name every one that is missing in the verdict, so the person reading it can decide whether to set it.

Condition What it buys the loop How this run detects it
reviews.requestchangesworkflow: true, with stale approvals dismissed on push reviewDecision becomes CodeRabbit's standing answer, so convergence is read from the decision reviewDecision is APPROVED or CHANGESREQUESTED. null with CodeRabbit reviews present means it is off. An APPROVED review whose commitid names an older commit means the dismissal half is missing
reviews.autoreview.autopauseafterreviewed_commits: 0 Automatic review survives a loop longer than five commits The default is 5. A reviewer that answered early cycles and goes quiet on a later one has likely reached it
A non-bot identity for the loop's own comments CodeRabbit reads the fix rationale, answers a declined finding, and resolves the thread itself The run knows who its token authenticates as, and a Skipped: comment is from another GitHub bot reply is the positive proof

None is required. With the first off, Section 6's acceptance rule carries the verdict alone and CodeRabbit's reviews land as COMMENTED. With the second at its default, the tag path in Section 2 recovers the paused reviewer. With the third missing, every review thread is a monologue and some cycles end needs-changes on a commit nothing reviewed. Each costs the run time or certainty, which is what the verdict line reports.

Set the first as a pair. The workflow enabled while stale approvals survive a push leaves a standing APPROVED over every later commit, which reads as convergence the loop has not earned. Report that shape by name.

Check two things before enabling the first. Where GitHub's Code Review Limits are on, only accounts with explicitly granted read access or higher may submit a review that approves or requests changes; ordinary comments still land. Under that restriction, requestchangesworkflow stops CodeRabbit posting review comments at all, with Failed to post review comments. Look at Settings → Access → Moderation options → Code review limits first, and either turn off "Limit to users explicitly granted read or higher access" or grant CodeRabbit read access.

Then turn on dismiss stale pull request approvals when new commits are pushed, in the branch rule protecting the base branch. It is what makes the approval arrive once per commit, and so what makes reviewDecision track the commit under review.

The third is a property of the token this skill runs with, and CodeRabbit exposes no setting for it — see [reviewer-edge-cases.md](references/reviewer-edge-cases.md). The remedy is a machine-user PAT for the commenting calls. An actions/create-github-app-token installation token authenticates as a Bot, which the skip applies to.

0. Preflight: pick one transport, or stop

This skill needs bash, jq, git, and exactly one working GitHub API transport. Probe in this order, before anything else:

for c in bash jq git; do command -v "$c" >/dev/null || echo "MISSING: $c"; done
# Transport A: gh — prove it END TO END with a real API call. In a macOS command
# sandbox, `gh auth status` can pass while every API call dies on TLS
# (`x509: OSStatus …`), because Go's platform verifier needs the keychain.
gh api rate_limit >/dev/null 2>&1 && echo "TRANSPORT: gh"
# Transport B: curl + token — a complete equivalent.
[ -n "${GH_TOKEN:-${GITHUB_TOKEN:-}}" ] && \
  curl -fsS -H "Authorization: Bearer ${GH_TOKEN:-$GITHUB_TOKEN}" \
    https://api.github.com/rate_limit >/dev/null 2>&1 && echo "TRANSPORT: curl"

Pick the first transport that works and use it for every call in this run — the same REST/GraphQL endpoints either way (the gh api commands below name the canonical paths; in curl mode hit the same paths with the token header). Never mix transports call-by-call within a cycle, and never downgrade to partial substitutes.

If bash/jq/git is missing, or neither transport works, stop the skill immediately. Report exactly what is unavailable and end the turn. A partial review produces a confident verdict from data it could not read. Do not work around it. Specifically, never:

  • install, download, or build gh, jq, or any other dependency;
  • parse command output with sed/awk/grep because jq is missing;
  • substitute local git log, the PR page's HTML, or your own reading of the diff

for the review surfaces in Section 3;

  • emit a verdict — including needs-changes — from an incomplete snapshot.

The stop message is the deliverable in that case. Say which tool is missing and what the operator needs to do (install it, run gh auth login, export GH_TOKEN, or run the skill outside the sandbox).

1. Anchor one cycle

Resolve the current branch PR with gh pr view --json number,headRefOid. With no PR on the branch, stop and tell the user to open one; this skill never creates a PR.

Refuse a dirty tree before reviewing. Push, then require PR headRefOid to equal local HEAD. Record:

  • HEAD_SHA and its short form.
  • REVIEW_START in Z UTC.
  • COMMIT_DATE from

gh api repos/$OWNER/$REPO/commits/$HEAD_SHA --jq .commit.committer.date.

  • The git status --porcelain baseline for later fix ownership.
  • SCOPE: the PR title and body from gh pr view --json title,body, plus the

changed-file list from gh pr diff --name-only. This is the scope contract for Section 4.

Use the API committer date; local git log can preserve a non-UTC zone. A finding belongs to this cycle when its commitid is HEADSHA, its timestamp is at or after either anchor, or its body cites the full/short SHA.

If an API call fails here — auth expired, repository not visible, network blocked — re-run the Section 0 probe once and switch to the other transport for the whole cycle if it passes; if neither transport works, stop as in Section 0.

2. Wait without model turns

Resolve scripts/wait-for-reviews.sh relative to this skill. Skill directories are often symlinks into a path the command sandbox cannot read (e.g. ~/.claude/skills/x -> ~/.agents/skills/x); if invoking the script fails with a permission error, copy it byte-for-byte to $TMPDIR with the harness file tools (Read → Write, which are not command-sandboxed) and run the copy — same arguments, same contract. Run it with the PR, HEAD, anchors, and base branch. It silently checks CodeRabbit's artifacts and the ruleset-required status checks, preserves the last good snapshot, and emits one terminal JSON object. Use its --once mode for a read-only diagnostic probe or validation. The normal bounded wait runs without it.

On Claude Code, invoke the helper through one main-session Monitor call with timeout_ms slightly above the helper's 900-second budget. Do not delegate to an Agent subagent. After Monitor started, end the assistant turn; the task notification resumes the main session.

On another harness, run the helper in one long-lived execution and use that harness's process-wait primitive. Never implement an LLM polling loop.

The helper selects its own transport the same way Section 0 does: gh when a real API call works, otherwise curl with GHTOKEN/GITHUBTOKEN. In a sandbox where only direct gh invocations are exempted, the helper's nested gh calls are still confined — export the token so its curl path engages:

WATCHER=skills/review-pr/scripts/wait-for-reviews.sh
GH_TOKEN="$GH_TOKEN" "$WATCHER" \
  --owner "$OWNER" --repo "$REPO" --pr "$PR" --base "$BASE" \
  --head "$HEAD_SHA" --review-start "$REVIEW_START" \
  --commit-date "$COMMIT_DATE" \
  --interval 50 --timeout 900

On every cycle after the first — the wait that follows pushing fixes for findings from an exact-HEAD review at the previous anchor — add --re-review-cycle. Automatic incremental review picks up every push, so on a re-review cycle the wait is the mechanism: post nothing, and let it run. The flag changes only what happens when the wait runs dry, because a clean incremental review can emit no artifact at all — see needsfullreview below.

A review takes minutes. Measure the repository's own push-to-review latency before shortening any delay: --tag-after and --full-review-after default to values that sit above a several-minute review, and a command posted inside that window interrupts the automatic review it was meant to provoke.

At this decision point, enforce all of these:

  • Do not call sleep directly; sleeping is inside the helper/Monitor.
  • Do not call true, date, echo waiting, tail a watcher log, manually poll,

start a second monitor, or narrate heartbeats while the helper runs.

  • Keep the monitor silent. Only its terminal JSON should wake the model.
  • If state is needs_tag — cycle 1 only — post one @coderabbitai review

comment, then restart the helper once with --tagged-coderabbit. Never retag. If you filter comments by time afterwards, derive since= from the posted tag comment's created_at in the API response. CodeRabbit can reply within seconds, and a window derived from your own clock misses it.

  • If state is needsfullreview, post one @coderabbitai full review comment,

then restart the helper once with --forced-full-review. Never escalate twice. Use full review here; review is itself incremental and returns an acknowledgement while automatic review is un-paused. This state also arrives on a first cycle whose rate-limit window has run out: the refused request was dropped, so asking again ends the wait.

  • If state is failed, timeout, or snapshotfetchfailing, read

[reviewer-edge-cases.md](references/reviewer-edge-cases.md) before judging it.

  • If the helper exits 2 with no JSON, a dependency is missing or both

transports failed. Stop as in Section 0 — do not retry it and do not review by hand.

ready means waiting is complete. The final snapshot and triage decide whether the PR passes, and the acceptance rule in Section 6 says what counts as CodeRabbit's exact-HEAD response.

unresolvedcoderabbitthreads in the helper's JSON is reported and never gated on. Section 4 resolves those threads itself, so a zero count describes this run's own actions.

3. Fetch one final snapshot

After the waiter stops, fetch the full bodies once from all three REST surfaces:

{ gh api --paginate repos/$OWNER/$REPO/issues/$PR/comments --jq '.[] | {surface:"issue",login:.user.login,id,ts:.created_at,commit:"",path:null,line:null,url:.html_url,body}'
  gh api --paginate repos/$OWNER/$REPO/pulls/$PR/reviews --jq '.[] | {surface:"review",login:.user.login,id,ts:.submitted_at,commit:.commit_id,path:null,line:null,url:.html_url,body}'
  gh api --paginate repos/$OWNER/$REPO/pulls/$PR/comments --jq '.[] | {surface:"inline",login:.user.login,id,ts:.created_at,commit:(.original_commit_id // .commit_id),path,line,url:.html_url,body}'
} | jq -s 'sort_by(.ts // "")'

If the issue-comments REST call fails, fetch the same full top-level comment bodies through the paginated GraphQL pull-request comments connection. A successful equivalent fallback is a valid surface. An empty response caused by a failed command fails closed.

REST review payloads have no severity field. Read CodeRabbit's severity label from its body. Only inline findings carry path:line. Scope inline findings with originalcommitid; GitHub may rewrite commit_id as the diff moves, which can make stale feedback look current.

Fetch every unresolved thread, whoever opened it. Keep the thread node ID for resolution and fullDatabaseId for replies:

gh api graphql --paginate -f query='
  query($owner:String!,$repo:String!,$pr:Int!,$endCursor:String){
    repository(owner:$owner,name:$repo){ pullRequest(number:$pr){
      reviewThreads(first:100,after:$endCursor){
        nodes{id isResolved isOutdated path line
          comments(first:50){nodes{fullDatabaseId body createdAt url author{login}}}}
        pageInfo{hasNextPage endCursor}}}}}
' -f owner=$OWNER -f repo=$REPO -F pr=$PR \
  --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)'

Also fetch the base ruleset and gh pr view --json isDraft,mergeStateStatus,mergeable,reviewDecision,statusCheckRollup. A failed snapshot or ruleset lookup fails closed; never interpret an empty payload as clean.

Take the verdict from comment and review bodies. CodeRabbit's own review-progress check is bound to the head commit and reports that the run finished; reviews.failcommitstatus defaults to false, so it goes green with findings open, and no acceptance rule below rests on it. Where the repository enables it, read it once for completion: a run that finished and said nothing is the silence needsfullreview answers.

A review in progress note counts as engagement. So does a green CodeRabbit check with no review body and no inline finding. A review whose state is APPROVED or CHANGESREQUESTED at HEADSHA is a verdict at any body length, and so is a walkthrough comment reporting no actionable comments over a range ending at HEAD_SHA, which on a clean pull request is routinely the only artifact present. A walkthrough carrying neither is engagement. Section 6's acceptance rule holds on every cycle.

4. Triage against the scope contract, then fix

Dedupe by thread/URL. If an inline finding is an unresolved thread, handle it once as the thread.

Classify every finding against SCOPE before deciding how to answer it. A finding is in scope only when it is one of:

  • a defect in the diff — the code this PR added or changed is wrong, unsafe, or

breaks a caller;

  • a gap the PR description itself promises to close;
  • a required-check failure this PR causes.

Everything else is out of scope, however reasonable it sounds: adjacent pre-existing bugs, refactors of code the PR merely touched, new abstractions, extra features, wider test coverage than the change needs, renames, and style rewrites beyond the changed lines. Reviewers and bots suggest these constantly. Do not implement them in this PR. Reply with one sentence naming the reason (out of scope for this PR), then resolve. Carry every declined finding into the Section 6 verdict so the user sees what was turned down and can decide whether it deserves its own PR.

When a finding's scope is genuinely unclear, or a reviewer argues the PR's approach is architecturally wrong, read docs/architecture/INTENT.md and docs/architecture/adr/* before answering. If a recorded decision already settles it, reply citing that document by path and decline the change. If those files do not settle it, ask the user — never widen the diff to end an argument.

Then, for the findings that survive triage:

  • Fix in-scope bugs, correctness/security issues, and CodeRabbit

⚠️/🔴/🟠 at the root. Still triage low-severity findings even when the overall verdict says the patch is correct.

  • Apply cheap, correct CodeRabbit 🧹/🔵 suggestions that land inside the

changed lines; otherwise explain the skip. Ignore 🤖 Prompt for AI Agents and 🧩 Analysis scaffolding.

  • Ask the user on a design judgment call. Reply to a false positive with

evidence.

  • For consistency findings, trace the real resolver and make both paths read the

same runtime source.

Never edit a file outside the PR's changed-file list to satisfy a finding. If a correct fix genuinely requires touching a new file, say so and get the user's agreement first. That is a scope change.

Always reply before resolving. Resolve only a finding you fixed or explicitly declined as out of scope; anything still open or awaiting the user stays unresolved. Reply inline through pulls/$PR/comments/{id}/replies, top-level through issues/$PR/comments, and resolve with:

gh api graphql -f query='mutation($t:ID!){resolveReviewThread(input:{threadId:$t}){thread{isResolved}}}' -f t=$THREAD_ID

For an outdated thread, reply and resolve only when the current diff already covers it; otherwise leave it unresolved and tell the user.

5. Verify, push, and repeat

Every ruleset-required check must be SUCCESS/SKIPPED; a missing required context is pending. A ruleset lookup failure is needs-changes — with one carve-out: HTTP 403 with "Upgrade to GitHub Pro or make this repository public" means the rules feature is unavailable on this plan, so no rules can exist. Read that as an empty ruleset with no required checks. A required pull_request approval gate only evaluates once the PR is ready for review; on a draft PR, report it as deferred. BLOCKED/DIRTY/UNKNOWN blocks unless only that ready-only gate remains with zero pending checks and unresolved threads.

Commit only files introduced relative to the cycle baseline. Stop if unrelated edits appear. Before pushing, diff the new changed-file list against the SCOPE list from Section 1: a file that review fixes added to the PR is a scope change the user has not seen — stop and confirm it. Run the repo's own lint/format/typecheck entry point on the changed files, reading CONTRIBUTING.md, AGENTS.md, CLAUDE.md, or the package/Makefile scripts to find the command.

If the accepted fixes made the PR description inaccurate, update the description to match what the PR now does. Never let the diff drift ahead of its stated scope.

Push fixes, re-anchor the new HEAD, and run another deterministic wait with --re-review-cycle set (Section 2). Cap at five cycles; each cycle must make a concrete fix. Stop on repeated or non-actionable churn.

Every cycle spends a review. Automatic incremental review of a pushed fix counts against the hourly allowance exactly as a first review does, and so does each @coderabbitai review or full review this skill posts. Five cycles are therefore five reviews before either escalation, against ten an hour on Pro+ and five on Pro — the accounting behind the rate limits in Section 5a. A cycle that pushes a one-character fix costs the same as one that pushes a rewrite, so batch a cycle's fixes into a single push.

The approval trails the resolution that triggers it, so a wait can return while reviewDecision still reads CHANGES_REQUESTED from the review you just answered. With every finding fixed and the decision still standing, let it settle through the same turn-free mechanism as Section 2, and judge afterwards. Never hand-roll a while loop around gh api, including when the helper returns something you doubt. Report a waiter that stops too early as a bug.

5a. Re-arm on only-waiting

Before returning needs-changes, check whether the only blocker is external progress — CodeRabbit still in-progress, a rate limit with time left to run, or a required check still pending-not-failed — with zero actionable findings/threads, zero failed checks, and zero pending local fixes. Any actionable finding or failed check returns needs-changes immediately; never mask a real problem behind "still waiting".

A rate limit belongs here because it expires on its own. The quota is per-developer and charged to whichever identity pushed, so a loop running as a bot spends a different allowance than the repository owner. When the helper reports coderabbit: unavailable, coderabbitretryafter carries the seconds still left on the window CodeRabbit published — re-arm on that number. Published windows run from seconds to tens of minutes, so any fixed delay misses. failed never re-arms: CodeRabbit has stopped, and the cause it prints (most often a pull request closed under the review) persists through any wait.

unavailable means a live notice: CodeRabbit's own refusal, with time still on its window and nothing said since. Once that window runs out the helper stops reporting it, and the next wait escalates through needsfullreview, because a refused request is dropped. Read a refusal only from CodeRabbit's own notice wording. It summarises every diff in its own words, so a pull request about rate limits earns a walkthrough containing "rate limit" while the review proceeds normally.

On that only-waiting state, re-arm, so the operator never re-runs the helper by hand:

  • Claude Code / dynamic-loop harness: schedule a self-paced wake-up

(ScheduleWakeup, dynamic-mode loop) with a long fallback interval (~20–30 min) re-arming this skill for the same PR, then end the turn. Idle must cost nothing — no assistant turns between wakes, never a short busy poll. This re-arm is outer only: never wrap the Section 2 turn-free watcher wait in a recurring loop.

  • Each wake: re-resolve the PR HEAD and re-run Section 1 exact-HEAD

anchoring before judging — a human may have pushed between wakes — then re-enter from Section 2.

  • Always terminate. Stop on a real verdict (pass or real needs-changes),

on operator interrupt, or after a few consecutive wakes with no reviewer/check movement — then return the last needs-changes (still waiting). Never re-arm forever.

  • Other harness with no self-paced-loop primitive: emit needs-changes

(still waiting) and tell the operator to re-arm with /loop /review-pr <PR#> (dynamic mode, long fallback).

6. Return the verdict

GITHUB_REVIEW_RESULT:
- PR: <url or number>
- CodeRabbit: <responded/in-progress/unavailable/failed; reason. On unavailable,
  name the account whose quota ran out and the published retry delay>
- Review cycles: <count>
- Issues found / fixed in scope / declined out of scope: <n> / <n> / <n>
- Declined as out of scope: <one line each: finding, thread URL, reason; or none>
- Files added to the PR by review fixes: <list or none>
- Unresolved actionable threads: <count>
- Review decision: <APPROVED/CHANGES_REQUESTED/null; null where the
  request-changes workflow is off. On APPROVED, name the commit the approving
  review carries>
- Repository configuration to set: <each setting from Repository expectations
  this run found missing, with what it cost; or none>
- Pending required checks: <list or none; include mergeStateStatus>
- Ready-only deferred gates: <list or none>
- Verdict: <pass/needs-changes>
- Summary: <1-2 sentences>

Return pass only when CodeRabbit delivered an exact-HEAD response, every in-scope finding is fixed, every out-of-scope one is answered and listed in the verdict, all threads are resolved, reviewDecision reads APPROVED wherever the request-changes workflow is enabled, and every required check is SUCCESS/SKIPPED.

reviewDecision is necessary and never sufficient. Auto-approval fires once CodeRabbit's comments are resolved, and Section 4 puts resolution in this skill's own hands, so the flag confirms that CodeRabbit agrees with what the skill already did — which is why Section 4 resolves only what it fixed or declined. The field also carries no commit: CodeRabbit approves a pull request once, so an APPROVED read on cycle two can be the approval earned on cycle one. Take the exact-HEAD response from the acceptance rule below. Check the approving review's own commitid against HEADSHA before reading the decision as this cycle's answer, and where it names an older commit, report the missing dismissal under Repository configuration. The substantive conditions above are what make the resolution honest. Read the decision as the last check on a case built elsewhere. A PR that ships exactly what its description promised is the goal, and declining scope creep is a pass.

CodeRabbit's exact-HEAD response is a substantive response at HEADSHA, which is any one of a nonzero-body review, inline findings, a review carrying the state APPROVED or CHANGESREQUESTED on that exact commit, or the walkthrough comment carrying No actionable comments were generated in the recent review over a reviewed range ending at HEAD_SHA. The state counts on its own: CodeRabbit approves with an empty body when it has nothing to say, which is the shape of every clean review.

The walkthrough counts because a clean review can produce no review object and no inline comment at all — that one sentence, edited into the walkthrough comment, is the entire verdict. Require both halves on the same comment. The sentence alone names no commit, and CodeRabbit rewrites the comment in place on each review, so the anchor is the end of the range it reports. A range that starts at HEAD_SHA describes a review of the commit after it.

The rule is the same on every cycle. Automatic incremental review covers each new push, so a fix commit earns the same artifact a first commit does. These count as engagement on any cycle:

  • an empty-body COMMENTED review — CodeRabbit wraps its thread replies in one,

so it marks a conversation;

  • Review finished or Action performed — the acknowledgement of a command,

emitted within seconds of the command itself;

  • No new commits to review — a statement about CodeRabbit's own bookkeeping;
  • zero unresolved CodeRabbit threads — Section 4 resolves those threads itself.

Silence is the hard case. Read the walkthrough comment before concluding a review is silent; a clean review usually lives there. Where even that is absent, needsfullreview exists: one @coderabbitai full review, and if that still yields no artifact bound to HEAD_SHA, the verdict is needs-changes naming the commit as unreviewed. Asked to redo a review already reported in the walkthrough, that escalation answers Action performed / Full review finished within seconds and produces nothing.

pass means reviewed and ready to merge. Its scope ends there: building, deploying, and working live all sit outside it. Never merge from this skill; hand back to the operator.

Return needs-changes for an unresolved finding/thread, a failed or pending required check, an engaged-but-incomplete CodeRabbit review, CodeRabbit being unavailable (quota/rate limit), or snapshotfetchfailing. When the only remaining blocker is a still-in-progress CodeRabbit review or a pending-not-failed required check with nothing actionable left, route through 5a and re-arm.