用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/loomantix/claude-platform --skill copilot-review命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
PR-first adversarial review. Lean mode runs the highest-signal local Claude lenses; `deep` selects the full relevant matrix. Verified findings are posted inline before fixes, then replied to and resolved after a pushed fix.
PR-first refactor pass that runs /simplify once against an open draft PR, verifies and commits the surviving cleanups, pushes, and records them in the PR ledger. Runs at most once per PR for this engine.
High-fidelity PR-first review chain that opens or reuses a draft PR, posts verified findings inline before fixes, and runs /critique deep — preceded by /refactorpass on this engine's first pass only. Rounds 3+ run in convergence mode. Runs only when the review tier resolved to Deep; hands a Lean changeset back to /critique.
基于 SOC 职业分类
正在显示 SKILL.md
| name | copilot-review |
| description | Address GitHub Copilot code review comments on a PR systematically |
| argument-hint | PR number (e.g., 1206) |
You are helping a developer address GitHub Copilot code review comments on a pull request. Follow a systematic approach: fetch comments, create an isolated worktree, analyze each comment, address or defer appropriately, reply to confirm resolution, and iterate until complete.
Goal: Validate the PR and set up the working environment
Arguments: $ARGUMENTS (PR number)
Actions:
Validate PR number from arguments
Fetch PR details:
gh pr view <pr-number> --json number,title,headRefName,baseRefName,state
Verify PR is open and ready for review
Create todo list with all phases
Goal: Load and categorize all Copilot code review comments
IMPORTANT — jq quoting pitfalls:
--jq expressions passed directly to gh api are fragile because of shell/YAML quoting (especially with !=, embedded \n, and nested quotes)!= is a valid jq operator; the issues come from how the shell parses gh api --jq arguments, not from jq itself--jq filters (or none), save raw JSON to a temp file first, then run richer jq queries against that fileActions:
Fetch all PR comments to a temp file (single API call, reused for all queries):
gh api --paginate repos/{owner}/{repo}/pulls/<pr-number>/comments > /tmp/pr-<pr-number>-comments.json
Extract Copilot top-level comments (those without in_reply_to_id):
jq '[.[] | select((.user.login | test("copilot"; "i")) and (.in_reply_to_id == null or .in_reply_to_id == 0)) | {id, path, line, body: (.body | split("\n")[0][:120])}]' /tmp/pr-<pr-number>-comments.json
Extract reply target IDs (which comments already have human replies):
jq '[.[] | select(.in_reply_to_id > 0) | .in_reply_to_id] | unique' /tmp/pr-<pr-number>-comments.json
Compute unaddressed comments (Copilot comments whose ID is not in the replied set):
jq '[.[] | select((.user.login | test("copilot"; "i")) and (.in_reply_to_id == null or .in_reply_to_id == 0)) | {id, path, line, body: (.body | split("\n")[0][:120])}] as $all | [.[] | select(.in_reply_to_id > 0) | .in_reply_to_id] | unique as $replied | $all | map(select(.id as $cid | $replied | index($cid) | not))' /tmp/pr-<pr-number>-comments.json
Read full body of each unaddressed comment when needed:
jq '.[] | select(.id == <comment-id>) | .body' /tmp/pr-<pr-number>-comments.json
Categorize each unaddressed comment after reading the file:
Present summary to user:
Ask user for confirmation before proceeding
Goal: Create an isolated environment for making changes
Actions:
Get PR branch name from Phase 0 data (headRefName)
Check if worktree already exists:
git worktree list | grep "copilot-review-<pr-number>"
Create or reset worktree:
If worktree doesn't exist:
git fetch origin <branch-name>
git worktree add worktrees/copilot-review-<pr-number> origin/<branch-name>
If worktree exists:
git -C worktrees/copilot-review-<pr-number> fetch origin
git -C worktrees/copilot-review-<pr-number> checkout <branch-name>
git -C worktrees/copilot-review-<pr-number> reset --hard origin/<branch-name>
Verify worktree is ready:
git -C worktrees/copilot-review-<pr-number> status
git -C worktrees/copilot-review-<pr-number> log --oneline -3
Set worktree path for subsequent operations:
worktrees/copilot-review-<pr-number>/git -C worktrees/copilot-review-<pr-number>Goal: Address each unaddressed Copilot comment systematically
For each unaddressed comment, perform the following cycle:
Read the file at the path specified in the comment
Understand the context:
Classify the resolution approach:
If Fix:
just lint-fixIf Defer:
gh issue create --title "<issue-title>" \
--label "tech-debt,from-copilot-review" \
--body "## Context\n\nThis issue was identified during Copilot code review of PR #<pr-number>.\n\n## Original Comment\n\n<copilot-comment-body>\n\n## Recommendation\n\n<suggested-approach>\n\n## Related\n\n- PR #<pr-number>"
If Dismiss:
Do NOT post a reply here. The reply needs to reference the real commit SHA, which doesn't exist until after Phase 4's push. Posting now means the SHA is a placeholder the model substitutes with garbage (or skips the reply entirely). Replies are posted in Phase 4 step 6 using the real SHA.
Build a resolution row in memory for this comment:
{
"comment_id": <numeric id from GitHub>,
"path": "<file path>",
"line": <line number or null>,
"resolution": "fix" | "defer" | "dismiss",
"explanation": "<one-line: what changed / why deferred / why dismissed>",
"defer_issue_url": "<URL or null — only set on defer>"
}
Accumulate rows in an in-memory list as you iterate the comment loop. Do not try to append-write the JSON file row-by-row — naïve append produces invalid JSON. Phase 3 finishes by writing the full array once.
After the loop completes, write the accumulated array once:
Write(file_path="/tmp/copilot-review-<pr-number>-resolutions.json",
content=<json-array-of-all-resolution-rows>)
Phase 4 step 6 reads this file and posts one reply per row.
Goal: Save changes, push to the PR branch, verify the push landed, then post one reply per recorded resolution using the real commit SHA.
Actions:
Verify changes (in worktree):
git -C worktrees/copilot-review-<pr-number> status
git -C worktrees/copilot-review-<pr-number> diff
Run quality checks (in worktree):
cd worktrees/copilot-review-<pr-number> && just lint-fix
cd worktrees/copilot-review-<pr-number> && just typecheck
Commit changes (only if there are code changes from "fix" resolutions):
cd worktrees/copilot-review-<pr-number> && git add -A && git commit -m "fix(review): address copilot feedback"
Push to remote and capture the real SHA:
git -C worktrees/copilot-review-<pr-number> push origin <branch-name>
PUSHED_SHA=$(git -C worktrees/copilot-review-<pr-number> rev-parse HEAD)
PUSHED_SHA_SHORT=$(git -C worktrees/copilot-review-<pr-number> rev-parse --short=8 HEAD)
If push is rejected (remote has new commits):
git -C worktrees/copilot-review-<pr-number> pull --rebase origin <branch-name>
git -C worktrees/copilot-review-<pr-number> push origin <branch-name>
PUSHED_SHA=$(git -C worktrees/copilot-review-<pr-number> rev-parse HEAD)
PUSHED_SHA_SHORT=$(git -C worktrees/copilot-review-<pr-number> rev-parse --short=8 HEAD)
Verify the push landed on the PR head before posting replies — GitHub's PR API is eventually consistent, so headRefOid can lag the actual ref by a few seconds:
verify_pr_head() {
local attempt
for attempt in 1 2 3 4; do
local pr_head
pr_head=$(gh pr view <pr-number> --json headRefOid --jq '.headRefOid')
if [[ "$pr_head" == "$PUSHED_SHA" ]]; then
return 0
$(( attempt * ))
>&2
1
}
verify_pr_head || 1
Goal: Get fresh Copilot feedback on the updated code
Actions:
Check if Copilot auto-reviews on push
If no automatic review, trigger manually via GraphQL.
IMPORTANT: Copilot is a Bot, not a User — gh pr edit --add-reviewer and the REST requested_reviewers endpoint do not work for Copilot. Use the GraphQL requestReviews mutation with botIds:
PR_NODE=$(gh pr view <pr-number> --json id --jq '.id')
gh api graphql \
-f query='mutation($prId:ID!,$botIds:[ID!]){requestReviews(input:{pullRequestId:$prId,botIds:$botIds,union:true}){pullRequest{id}}}' \
-f prId="$PR_NODE" \
-f botIds='BOT_kgDOCnlnWA'
Copilot bot node id is BOT_kgDOCnlnWA (constant). Verify with gh api repos/{owner}/{repo}/pulls/<n>/requested_reviewers --jq '.users[].login' → expected Copilot. The mutation is idempotent — safe to call across iterations.
Wait for the new Copilot review to appear (filter by Copilot's login, then take the most recent):
gh api repos/{owner}/{repo}/pulls/<pr-number>/reviews \
--jq '[.[] | select(.user.login | test("copilot"; "i"))] | last | {id, submitted_at, user: .user.login}'
Fetch new comments and check for any new unaddressed items
Goal: Determine if another resolution cycle is needed
Actions:
Count new unaddressed comments from the latest Copilot review
If new comments exist:
If no new comments:
Goal: Summarize all work done and provide next steps
Actions:
Generate summary report:
Cleanup worktree (optional, ask user):
git worktree remove worktrees/copilot-review-<pr-number>
Provide next steps:
GitHub's PR comment API (POST repos/{owner}/{repo}/pulls/{pull_number}/comments) uses a oneOf schema. You must use exactly one of these patterns:
jq -n \
--arg body "$BODY" \
--arg commit_id "$HEAD_SHA" \
--arg path "$FILE_PATH" \
--argjson line $LINE_NUM \
--arg side "RIGHT" \
'{body: $body, commit_id: $commit_id, path: $path, line: $line, side: $side}' \
| gh api -X POST "repos/{owner}/{repo}/pulls/{pull_number}/comments" --input -
jq -n \
--arg body "$BODY" \
--arg commit_id "$HEAD_SHA" \
--arg path "$FILE_PATH" \
--argjson line $END_LINE \
--argjson start_line $START_LINE \
--arg side "RIGHT" \
'{body: $body, commit_id: $commit_id, path: $path, line: $line, start_line: $start_line, side: $side, start_side: "RIGHT"}' \
| gh api -X POST "repos/{owner}/{repo}/pulls/{pull_number}/comments" --input -
jq -n \
--arg body "$BODY" \
--arg commit_id "$HEAD_SHA" \
--arg path "$FILE_PATH" \
--arg subject_type "file" \
'{body: $body, commit_id: $commit_id, path: $path, subject_type: $subject_type}' \
| gh api -X POST "repos/{owner}/{repo}/pulls/{pull_number}/comments" --input -
line must be within the PR diff for that file. If the target line isn't in a diff hunk, the API returns 422. Fall back to subject_type: "file".commit_id must match the PR's current HEAD when creating or re-posting a review comment. After a force-push, existing inline comments become "Outdated" and remain anchored to the old commit SHA. You can still edit their body text via PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}, but you cannot change their diff anchor; to re-anchor to the new HEAD you must delete and recreate the comment.subject_type cannot be combined with line/start_line/side. The API uses oneOf — pick one pattern.position (deprecated) or include subject_type: "line" explicitly (not a valid creation param, only returned in responses).After a force-push, all existing inline comments become "outdated" (anchored to the old commit SHA). To re-anchor comments to the new commit:
gh api --paginate repos/{owner}/{repo}/pulls/{pull_number}/commentsuser.login or body pattern){path, body, original_line, original_start_line, subject_type} from eachgh api -X DELETE repos/{owner}/{repo}/pulls/comments/{id}grep -n on actual files to find correct line numbers for the new commitIf GitHub API fails:
If worktree creation fails:
git branch -r | grep <branch-name>git fetch origin <branch-name>If reply posting fails:
gh pr comment <pr-number> --body "Re: Copilot comment on <file>:<line>\n\n<reply-message>"
Post replies now that the real SHA is in hand. Read /tmp/copilot-review-<pr-number>-resolutions.json and post one reply per row, building each body with ${PUSHED_SHA_SHORT} substituted inline.
Reply body templates:
For Fix:
Fixed in `${PUSHED_SHA_SHORT}`.
<explanation from resolutions.json>
For Defer:
Deferred — tracking in <defer_issue_url>.
<explanation: why this is being deferred rather than fixed in this PR>
For Dismiss:
Dismissing — false positive.
<explanation: why the reviewer's reasoning doesn't apply>
Post each reply via:
gh api -X POST repos/{owner}/{repo}/pulls/<pr-number>/comments/<comment_id>/replies \
-f body="<assembled body>"
If any single reply POST fails, log it and continue with the rest — partial reply coverage is better than none. Surface the count of failed-reply POSTs in the Phase 7 completion summary.