| name | resolve-pr-threads |
| description | Resolve settled review threads. |
| user-invocable | true |
| allowed-tools | ["Bash"] |
resolve-pr-threads
A narrow, standalone sweep: resolve inline review threads that are already
settled, without running a full ard/ardi pass. Useful when threads were
replied to in an earlier round but never resolved (a rebuttal the reviewer
stopped re-raising, a fix that landed after the reply), or before
re-requesting review so stale threads don't clutter the new round.
This skill does not invent dispositions. The settlement rules — what
counts as Address / Rebut / Defer / Acknowledge, and exactly when each is safe
to resolve — are defined once, in ard step 4b. This skill
only applies those existing rules to threads that already carry a reply.
When this fires
- "resolve pr threads", "clean up the threads", "resolve stale threads",
"sweep the review threads".
- At the start of a fresh
ardi round, to resolve any rebuttal threads the
latest review didn't re-raise (already covered inline by ard, but callable
standalone here too).
- Before re-requesting review, so the reviewer isn't looking at threads that
are already settled.
Procedure
1. List every inline review thread
GitHub — pull threads with their resolution state and last reply
(READ_PR_REVIEW_COMMENTS — abstract operation token; resolve to your
model's tool via tool-mappings.md):
gh api graphql -f query='query {
repository(owner:"<owner>", name:"<repo>") {
pullRequest(number:<N>) {
reviewThreads(first:100) {
totalCount
nodes {
id
isResolved
comments(last:5) { nodes { databaseId body author { login } } }
}
}
}
}
}'
If totalCount exceeds the returned node count, say so in the report instead
of silently sweeping a partial list (same cap caveat as pr-status).
GitLab:
glab api "projects/:id/merge_requests/<N>/discussions"
2. Classify each unresolved thread
For every thread where isResolved is false:
- No reply yet from this side (the last comment is the reviewer's, with no
Address/Rebut/Defer/Acknowledge response) — leave it open. This is a
fresh finding; it needs an
ard pass, not a resolve.
- Replied, and settled per
ard's resolve-only-when-settled rules:
- Address — the reply names a commit SHA, and that SHA (or a later one) is
on the branch.
- Defer — the reply links a tracked issue.
- Acknowledge — a reply exists at all.
- Rebut — a reply with falsifiable evidence exists, and the reviewer's
most recent review round did not re-raise the same point.
- -> resolve it.
- Replied, but not actually settled (an Address whose fix isn't pushed
yet, a Rebut the reviewer just re-raised, an ambiguous partial fix awaiting
reviewer confirmation) — leave it open.
Don't resolve a thread that has no reply on it — that skips straight past
ard's dispositioning step, and the reviewer never sees a response.
3. Resolve the settled ones
GitHub:
gh api graphql -f query='mutation {
resolveReviewThread(input:{threadId:"<thread_node_id>"}) { thread { isResolved } } }'
GitLab:
glab api -X PUT "projects/:id/merge_requests/<N>/discussions/<discussion_id>?resolved=true"
In a remote/web session without gh/glab, use
mcp__github__resolve_review_thread (see tool-mappings.md).
4. Report
State plainly, per thread: resolved (with the settlement reason) or left open
(with why — no reply / fix not pushed / re-raised / needs confirmation). If
any thread lacks a reply, note that a full ard pass is needed for those
before they can be swept.
Relationship to ard / ardi
ard step 4b already runs this exact sweep as part of every review round —
this skill exists so the sweep is callable on its own, without re-running the
whole Address/Rebut/Defer pass. The settlement criteria live in one place
(ard); this skill and ard both point to it rather than each keeping a
separate copy.