--- name: review-pr-threads description: Resolve the currently-unresolved review threads on the current branch's PR in one sweep — assess each, fix it (test-first, verified) or reply-only, then reply and resolve — and return a summary. Use standalone to address PR review feedback, or as the thread-handling step invoked by /watch-pr. Repo is adamayoung/TMDb. --- # Review PR Threads Handle the open **review conversations** on a pull request: for each unresolved thread, decide whether it warrants a code change, make and verify the fix (or explain why not), reply, and resolve it. This is a **single sweep** over the threads that are unresolved *right now* — it does not wait for new reviews to arrive. The caller (you, or `/watch-pr`) decides whether to run it again after a push triggers a fresh review. Repo is `adamayoung/TMDb`. GitHub reads (find the PR, fetch threads), the **reply**, and the **resolve** all use the **GitHub MCP** (`mcp__github__*`): `get_review_comments` exposes each comment's numeric REST id in its `html_url` (the `#discussion_r` anchor — verified 2026-08-07), which is exactly the id `add_reply_to_pull_request_comment` takes. `gh` is authenticated and kept as the reply **fallback** (`gh api graphql` with the thread node id) on a 401/403 or if the anchor is ever absent. ## Principles 1. **One sweep, then return.** Process every thread that is unresolved at invocation, then stop and report. Do not loop waiting for re-reviews — pushing a fix re-triggers the `claude-review` bot and CI, and that convergence loop belongs to the caller. 2. **Fix test-first and verify before you reply.** A code change in response to a thread follows the project's discipline: reproduce/capture with a test where applicable, then fix, then verify with the delegated skills. Never claim a fix you haven't verified. 3. **Don't change code you disagree with — reply instead.** Out-of-scope, incorrect, already-handled, or question-only threads get a reasoned reply and a resolve, not an edit. 4. **Dedup via the run ledger.** Keep (or reuse the caller's) ledger of handled thread IDs and a topic signature (`path:line` + gist) per thread. If a thread repeats a topic you already fixed this run, reply pointing at the earlier commit SHA and resolve — do **not** re-edit. 5. **The `claude-review` bot's summary comment is advisory.** It posts inline threads only for Critical/High; its Medium/Low summary bullets are not threads and are not work items — don't turn them into code changes. ## 0. Find the PR Find the open PR for the current branch with `mcp__github__list_pull_requests` (owner/repo from the `origin` remote, `head: :`, `state: open`), or read a specific one with `mcp__github__pull_request_read` method `get` (`pullNumber: `). Take `number`/`html_url`/`state`/`head.ref` from the result. - An explicit PR number in the skill arguments overrides the current branch. - No PR for the current branch → stop and tell the user (suggest `/pr`). - State not `open` → stop and report. ## 1. Fetch unresolved threads Use `mcp__github__pull_request_read` method `get_review_comments` (owner/repo from `origin`, `pullNumber: `). It returns review **threads**, each with metadata (`isResolved`, `isOutdated`, `isCollapsed`), the thread **node id** (`PRRT_…`, used to resolve in §2), `path`/`line`, and the grouped comments — each comment carrying an `html_url` whose `#discussion_r` anchor is the numeric comment id §2's reply needs. Paginate with `perPage`/`after` (the `endCursor` from the previous page's `pageInfo`) if needed. Process each thread where `isResolved` is `false` and whose thread id is not already in the ledger. ## 2. Handle each thread For each unresolved thread: 1. **Assess** the comment(s) and decide whether a code change is warranted, in scope, and clearly correct. 2. **Needs a fix** → edit the code, then verify with the delegated skills — `/lint`, `/build`, `/test` (and `/integration-test` if it could affect live-API behaviour); those run in Haiku subagents so logs stay out of context. Commit with a gitmoji message and record the commit SHA. **Batch the sweep's pushes:** commit per fix, but `git push` **once** after all threads are handled (§3), so one review/CI cycle is triggered per sweep, not one per thread. 3. **No fix warranted** (disagree / out of scope / a question / already done) → make no code change; you'll say why in the reply. When the reason is *out of scope* and the reviewer's point is sound, file it per [`.github/ISSUE_FILING.md`](../../../.github/ISSUE_FILING.md) and reply with the issue number. "Out of scope" with nothing behind it is how a valid review comment gets closed forever; a link is what makes it a deferral rather than a dismissal. 4. **Reply** on the thread — what you assessed and whether you fixed it (include the commit SHA when you did). Use `mcp__github__add_reply_to_pull_request_comment` (owner/repo from `origin`, `pullNumber: `, `body`, and `commentId` — the number from the thread's first comment's `html_url` anchor, `…#discussion_r`; the number only, never the `PRRT_…` node id). On a **401/403**, or if no comment in the thread carries the anchor, fall back to the GraphQL reply with the thread node id we already have from §1: ```bash gh api graphql -f query='mutation($id:ID!,$body:String!){ addPullRequestReviewThreadReply(input:{pullRequestReviewThreadId:$id,body:$body}){ comment{ id } } }' -f id= -f body='' ``` 5. **Resolve** the thread with `mcp__github__pull_request_review_write` method `resolve_thread` (`threadId: `; `owner`/`repo`/`pullNumber` are ignored for this method). Resolving an already-resolved thread is a no-op. 6. Record the thread ID and topic signature in the ledger. > Reply and resolve **after** the single push (§3) for threads you fixed, so the > SHA you cite is on the remote. Reply/resolve reply-only threads immediately. ## 3. Push once, then finish After every thread is handled, if you committed any fixes, `git push` once (it re-triggers CI and the `claude-review` bot — expected). Then post the deferred replies + resolves for the fixed threads. **There is no pre-commit hook** (`.git/hooks/` holds only `*.sample`), so nothing lints on your behalf — run `/lint` before committing. ## Guardrails - Never edit `.github/workflows/*` or other CI/config to silence a reviewer, and never force-push, without surfacing to the user first. - If a requested change is ambiguous or risky, reply with your assessment and leave it for the user (note it in the summary) rather than guessing. - Stay in scope: address the thread, don't opportunistically refactor around it. ## Return: sweep summary Report, concisely: - **Fixed** — thread topic → commit SHA, per fixed thread. - **Replied-only** — thread topic → one-line reason (disagreed / out of scope / already done / question answered). - **Left for the user** — ambiguous/risky threads you replied on but did not act on, and why. - **Counts** — threads handled this sweep, and any that remain unresolved (e.g. a thread you intentionally left open for a human decision). Whether anything was pushed (and the resulting CI/review re-trigger) so the caller can decide whether to sweep again. Arguments: $ARGUMENTS