$npx -y skills add NeoLabHQ/context-engineering-kit --skill load-pr-commentsUse to load open/unresolved PR review comments then aggregate them as tasks in .specs/comments/*.md for parallel agents to fix.
| 1 | # Load Unresolved PR Review Comments as Parallel Tasks |
| 2 | |
| 3 | Load ONLY open/UNRESOLVED PR review threads and rewrite them into grouped markdown task files under `.specs/comments/*.md`, each safe for a separate parallel agent to implement with no overlap. |
| 4 | |
| 5 | ## Critical Guidelines |
| 6 | |
| 7 | - You MUST load ONLY threads where the resolved state is false. Skip resolved threads. |
| 8 | - You MUST rewrite each comment as an actionable TASK requirement, not a summary. Preserve substance (code suggestions, exact instructions) verbatim. |
| 9 | - You MUST NOT post, reply to, or modify anything on GitHub. This skill is read-only against the API. |
| 10 | - You MUST group comments so each file is independently implementable with NO duplication across files. |
| 11 | |
| 12 | ## Step 0: Verify what tools are available |
| 13 | |
| 14 | 1. Check if GitHub CLI is installed and authenticated: |
| 15 | |
| 16 | ```bash |
| 17 | gh auth status |
| 18 | ``` |
| 19 | |
| 20 | 2. Check if the GitHub MCP server is available: |
| 21 | |
| 22 | ```bash |
| 23 | mcp__MCP_DOCKER__pull_request_read |
| 24 | ``` |
| 25 | or simular command without `MCP_DOCKER` prefix, if installed directly. |
| 26 | |
| 27 | - if both are available, use any that have enough accesses to the repository. |
| 28 | - if github mcp server avaiable but have different structure, adjust in order to fit the expected structure. |
| 29 | - if none is available, try to load directly through curl in case if it is public repository. If it is private, ask user to install GitHub CLI or GitHub MCP server. |
| 30 | - if MCP server not installed, but github cli is installed, but not authenticated, ask user to run `gh auth login` to authenticate. |
| 31 | |
| 32 | ## Step 1: Resolve the Target PR |
| 33 | |
| 34 | - An explicit PR argument ALWAYS takes precedence over current-branch resolution. If a PR number or URL was passed, use it (a URL like `https://github.com/{owner}/{repo}/pull/{n}` → number `{n}`) and do NOT consult the current branch. |
| 35 | - Otherwise default to the PR of the CURRENT branch: |
| 36 | |
| 37 | ```bash |
| 38 | gh pr view --json number,url,headRefName # current branch's PR |
| 39 | ``` |
| 40 | |
| 41 | - Resolve repo owner/name: `gh repo view --json owner,name`. |
| 42 | - If no PR exists for the branch, `gh pr view` errors with "no pull requests found" — STOP and report that no PR is associated with the branch (ask for a PR number/URL). |
| 43 | |
| 44 | ## Step 2: Retrieve UNRESOLVED Comments |
| 45 | |
| 46 | Resolved/unresolved is a GraphQL `reviewThreads { isResolved }` concept — the REST `/pulls/{n}/comments` endpoint does NOT expose it. Use one of the two approaches below; if the primary is unavailable, fall back to the other. |
| 47 | |
| 48 | ### Primary: gh CLI (GraphQL) |
| 49 | |
| 50 | Filter `isResolved == false` directly in the jq: |
| 51 | |
| 52 | ```bash |
| 53 | gh api graphql -f query=' |
| 54 | query($owner:String!,$repo:String!,$pr:Int!){ |
| 55 | repository(owner:$owner,name:$repo){ |
| 56 | pullRequest(number:$pr){ |
| 57 | reviewThreads(first:100){ |
| 58 | nodes { |
| 59 | isResolved |
| 60 | isOutdated |
| 61 | path |
| 62 | line |
| 63 | startLine |
| 64 | originalLine |
| 65 | comments(first:50){ |
| 66 | nodes { author{login} body diffHunk url } |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | }' -F owner=OWNER -F repo=REPO -F pr=PR_NUMBER \ |
| 73 | --jq '[.data.repository.pullRequest.reviewThreads.nodes[] |
| 74 | | select(.isResolved==false) |
| 75 | | {path, isOutdated, |
| 76 | line: (.line // .startLine // .originalLine), |
| 77 | comments: [.comments.nodes[] |
| 78 | | {author: .author.login, url, body, diffHunk}]}]' |
| 79 | ``` |
| 80 | |
| 81 | This returns each unresolved thread with its file `path`, an `isOutdated` flag, a usable `line`, and ordered comments (author, body, permalink `url`, `diffHunk`). |
| 82 | |
| 83 | IMPORTANT: For OUTDATED threads `line` is `null` (the diff moved). The jq above already falls back `line // startLine // originalLine`, so `line` is never null when any anchor exists. When ALL three are null, omit the `:<line>` segment entirely in the template — never render `path:null`. |
| 84 | |
| 85 | ### Fallback: GitHub MCP |
| 86 | |
| 87 | If the GitHub MCP server (`MCP_DOCKER`) is available, use the `mcp__MCP_DOCKER__pull_request_read` tool with `method: "get_review_comments"`: |
| 88 | |
| 89 | ``` |
| 90 | mcp__MCP_DOCKER__pull_request_read |
| 91 | method: "get_review_comments" |
| 92 | owner: "OWNER" |
| 93 | repo: "REPO" |
| 94 | pullNumber: PR_NUMBER |
| 95 | perPage: 100 |
| 96 | ``` |
| 97 | |
| 98 | It returns `review_threads[]`, each with `is_resolved`, `is_outdated`, `is_collapsed` (all snake_case — verified against this tool's response) and `comments[]` (`body`, `path`, `author`, `html_url`). Keep only threads where `is_resolved` is `false`. Note the MCP comment objects expose `path` but NOT a line number, so use the `html_url` as the location anchor. Paginate with `after: <endCursor>` while `pageInfo.hasNextPage` is true. |
| 99 | |
| 100 | ## Step 3: Group and Rewrite as Tasks |
| 101 | |
| 102 | Convert unresolved threads into focused task files for parallel agents. |
| 103 | |
| 104 | Deduplicate FIRST (before grouping): if two or more threads request the same change at the same `path` (and same/overlapping line), or car |