SKILL.md
$27
gh pr view <number> --json \
number,state,isDraft,mergeable,mergeStateStatus,reviewDecision,headRefOid,statusCheckRollup,url
Resolve the repository owner/name before using GraphQL:
repo_json=$(gh repo view --json owner,name)
owner=$(jq -r '.owner.login // .owner.name' <<<"$repo_json")
repo=$(jq -r '.name' <<<"$repo_json")
Use GraphQL for unresolved review threads. Include pageInfo; omit cursor on the first page, then pass the previous endCursor with -f cursor="$cursor" while hasNextPage is true.
gh api graphql \
-f query='query($owner:String!,$repo:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewThreads(first:100,after:$cursor){pageInfo{hasNextPage endCursor}nodes{id,isResolved,isOutdated,path,line,comments(last:1){nodes{author{login},body,createdAt,url}}}}}}}' \
-f owner="$owner" -f repo="$repo" -F number=<number>
Use this loop when a PR may have many review threads:
thread_query='query($owner:String!,$repo:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewThreads(first:100,after:$cursor){pageInfo{hasNextPage endCursor}nodes{id,isResolved,isOutdated,path,line,comments(last:1){nodes{author{login},body,createdAt,url}}}}}}}'
cursor_args=()
while :; do
page=$(gh api graphql -f query="$thread_query" -f owner="$owner" -f repo="$repo" -F number=<number> "${cursor_args[@]}")
printf '%s\n' "$page" | jq -r '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved==false)
| [.id,.path,(.line//""),(.isOutdated|tostring),(.comments.nodes[-1].author.login//""),(.comments.nodes[-1].body|gsub("\n";" ")|.[0:240])]
| @tsv'
jq -e '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage' >/dev/null <<<"$page" || break
cursor=$(jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor' <<<"$page")
cursor_args=(-f cursor="$cursor")
done
Filter unresolved threads with jq:
jq -r '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved==false)
| [.id,.path,(.line//""),(.isOutdated|tostring),(.comments.nodes[-1].author.login//""),(.comments.nodes[-1].body|gsub("\n";" ")|.[0:240])]
| @tsv'
Resolve a stale thread only when the fix is verified:
gh api graphql \
-f query='mutation($threadId:ID!){resolveReviewThread(input:{threadId:$threadId}){thread{id,isResolved}}}' \
-f threadId=<thread-id>
Operating Rules
- Keep the watcher running while long checks are pending.
- If a generated file is part of the distribution, verify the source and generated artifact agree before resolving comments.
- If a bot reports an issue against stale code, confirm whether the thread is outdated or addressed in the latest head.
- Before final reporting, do one fresh sweep of PR status, unresolved threads, recent comments, and local
git status.
- Report concrete evidence: latest commit SHA, check names and results, unresolved thread count, tests run, and any dirty local files left untouched.