一键导入
respond-to-comments
Read PR review comments, fix the code issues they raise, and resolve the conversations on GitHub. Handles the full respond-to-feedback cycle.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Read PR review comments, fix the code issues they raise, and resolve the conversations on GitHub. Handles the full respond-to-feedback cycle.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Distill the current conversation into one self-contained work-item — context, decisions, remaining work, acceptance criteria — for a downstream agent with zero context from this session.
Audit the codebase for hardening opportunities — dependency CVEs, container CVEs (Scout + Trivy), code-level robustness — read-only, and emit execution-ready plans as my-work items. Never edits source.
Initialize Hero for a project. Investigates the repo, auto-detects the stack, confirms findings with smart questions, and creates HERO.md that all skills use.
Drive a small task end-to-end — plan, implement, simplify, push (tests included), self-review, mark ready, await review, respond, ship. No args: resume the current goal (gated). Small, low-risk PRs only.
Test (verify + smoke), commit, push, and open a draft PR with a CI report. Pass test to run only the test phase, ready for a non-draft PR, or a target branch to merge into.
Review a PR with the pr-review-toolkit agents plus a security pass. No argument reviews your own draft PR and applies fixes. A PR number reviews the author's code via inline comments, no edits.
| name | respond-to-comments |
| description | Read PR review comments, fix the code issues they raise, and resolve the conversations on GitHub. Handles the full respond-to-feedback cycle. |
| argument-hint | ["pr-number"] |
Read review comments on your pull request, update the code to address them, and resolve the conversations on GitHub.
$ARGUMENTS - PR number or URL (optional)
gh CLI installed and authenticatedROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
cat "$ROOT/HERO.md" 2>/dev/null || echo "NO_HERO_CONFIG"
Read HERO.md if it exists. This skill uses:
If HERO.md is missing, suggest hero-skills:init-hero but proceed with defaults.
If no argument provided, detect from current branch:
BRANCH=$(git branch --show-current)
gh pr list --head "$BRANCH" --json number,title,url,headRefName --jq '.[0]'
If argument provided:
gh pr view $PR_ARG --json number,title,url,headRefName,baseRefName,state
If PR is merged or closed: Report status and stop.
CURRENT=$(git branch --show-current)
PR_BRANCH=$(gh pr view $PR_NUMBER --json headRefName --jq '.headRefName')
If not on the PR branch, first check for uncommitted changes:
git status --porcelain
If uncommitted changes exist, STOP and show:
You have uncommitted changes on '$CURRENT':
(list changed files from git status)
Need to switch to '$PR_BRANCH' to address PR comments.
Options:
1. Stash changes (saved as "respond-to-comments: WIP on $CURRENT") — will NOT auto-restore since you're moving to a different branch
2. Cancel — go back and commit or handle changes first
STOP and wait for user to choose. Do NOT switch branches without explicit confirmation.
If user chooses option 1 (stash):
git stash push -m "respond-to-comments: WIP on $CURRENT"
Report: Stashed as: stash@{0} — "respond-to-comments: WIP on $CURRENT". Restore later with: git checkout $CURRENT && git stash pop
Note: Since the user is switching to a different branch to do PR work, do NOT auto-pop the stash. Remind the user in the final summary how to restore.
Then switch to the PR branch:
git fetch origin $PR_BRANCH
git checkout $PR_BRANCH
git pull origin $PR_BRANCH
# Get pending (unresolved) review comments
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/comments \
--jq '.[] | {
id: .id,
node_id: .node_id,
path: .path,
line: .line,
original_line: .original_line,
body: .body,
user: .user.login,
in_reply_to_id: .in_reply_to_id,
created_at: .created_at
}'
# Get review threads to check which are resolved
gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 10) {
nodes {
id
databaseId
body
path
line
author { login }
}
}
}
}
}
}
}
' -f owner="$OWNER" -f repo="$REPO" -F pr=$PR_NUMBER
Group comments into:
Skip already-resolved threads. Focus on unresolved ones.
Present the categorized list to the user:
PR #123 Review Comments
=======================
Unresolved: N comments in M threads
Actionable (will fix):
1. [file.ts:42] @reviewer - "Handle the null case here"
2. [api.ts:15] @reviewer - "This should validate input before..."
Questions (need your input):
3. [utils.ts:88] @reviewer - "Why not use the existing helper?"
Acknowledged (no code change needed):
4. [README.md:5] @reviewer - "Nice docs 👍"
Already resolved: K threads
Ask the user to confirm the plan before proceeding. The user may:
For each confirmed actionable comment:
# Read the file context around the commented line
# (Use Read tool for the file, centered on the line number)
Apply fixes one at a time. After each fix, verify the change makes sense in context.
If a comment is ambiguous: Ask the user for clarification rather than guessing.
After all fixes are applied:
# Run pre-commit if available
if command -v pre-commit > /dev/null 2>&1; then
pre-commit run --all-files
else
echo "NO_PRECOMMIT"
fi
# Run tests if configured in HERO.md
# Use the test command from HERO.md projects section
If checks fail, fix the issues before committing.
git add CHANGED_FILES
git commit -m "$(cat <<'EOF'
fix: address PR review feedback
- [Summary of fix 1]
- [Summary of fix 2]
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EOF
)"
Group related fixes into a single commit. If fixes are logically independent and touch different areas, use separate commits.
git push origin $(git branch --show-current)
For each addressed comment, reply with what was done and resolve the thread:
# Reply to the comment explaining the fix
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/comments \
-f body="Fixed — [brief description of what changed]" \
-F in_reply_to=$COMMENT_ID
# Resolve the thread via GraphQL
gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread { isResolved }
}
}
' -f threadId="$THREAD_NODE_ID"
For question comments where the user provided an answer:
gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/comments \
-f body="[User's explanation or rationale]" \
-F in_reply_to=$COMMENT_ID
For acknowledged comments (praise, FYI):
# Just resolve, no reply needed unless user wants to respond
gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread { isResolved }
}
}
' -f threadId="$THREAD_NODE_ID"
Per-thread replies (Step 9) explain each fix in isolation. They do not, on their own, give a reviewer a single place to see what changed across the whole respond cycle. Always post one consolidated improvements comment, in addition to (never instead of) the per-thread replies from Step 9. Even when no code changes were made (e.g., all comments were questions or were declined), still post the comment — silence on a no-fix cycle hides the fact that the cycle ran.
Group by category. For each fix, name the file:line, the original feedback, and the change in one sentence. For each declined item, give the reason — "low impact", "out of scope", "would conflict with X" — so reviewers can tell whether to re-raise it.
Rendering rules (apply before posting, not as part of the template):
- none inline. Do not post empty section bodies.FILE:LINE, REVIEWER_FEEDBACK, FIX_DESCRIPTION, SHA1, etc. placeholder with the real value before invoking gh pr comment. The literal placeholder strings must never appear in the posted comment.COMMENT_BODY=$(cat <<'EOF'
## Respond-to-Comments Improvements
**Code changes (X applied):**
- FILE:LINE — REVIEWER_FEEDBACK — FIX_DESCRIPTION
**Questions answered (Y):**
- FILE:LINE — QUESTION — ANSWER_OR_RATIONALE
**Declined (Z, with rationale):**
- FILE:LINE — REVIEWER_FEEDBACK — REASON_FOR_DECLINING
Commits: SHA1, SHA2
Remaining unresolved threads: N (LIST_OR_NONE)
---
_Generated using hero-skills._
EOF
)
# Substitute the placeholders, drop empty sections, then post.
# If the post fails (network, gh auth), surface the rendered body so
# the user can paste it manually — do NOT swallow the error and
# pretend the comment was posted.
if ! gh pr comment $PR_NUMBER --body "$COMMENT_BODY"; then
echo "ERROR: Failed to post improvements comment. Body follows — paste manually:"
printf '%s\n' "$COMMENT_BODY"
exit 1
fi
If nothing was applied or replied to (rare — the cycle should not run otherwise), still post the comment stating "No changes this cycle" and explaining why. Do not fall silent.
Reviewer feedback often expands a PR's scope — adding new files, hardening a code path, removing an option. When that happens, the PR title and body must reflect the new shape. Reviewers should not have to dig through commits to find what the PR now claims to do.
Decide whether to update by checking each:
hero-skills:review-pr's.When an update is warranted:
gh pr view $PR_NUMBER --json title,body --jq '{title, body}'
Draft the full new body (preserving the existing structure — Summary, Changesets, Test Plan — and appending entries for this iteration's work), ending with _Generated using hero-skills._ as the final line. Do not paste the heredoc literally — gh pr edit --body fully replaces the body, so the heredoc must contain the entire drafted Markdown:
gh pr edit $PR_NUMBER --title "NEW_TITLE_UNDER_70_CHARS" --body "$(cat <<'EOF'
DRAFTED_FULL_BODY_HERE
EOF
)"
Substitute DRAFTED_FULL_BODY_HERE with the actual drafted Markdown before running — the drafted body must end with _Generated using hero-skills._. Never run the snippet with the placeholder still in place — it would overwrite the PR description with the literal string DRAFTED_FULL_BODY_HERE.
Rules:
If no description update is needed, note it in the Step 10 summary as "PR description left as-is — fixes were limited to surface tweaks, no scope change."
Substitute the {...} placeholders before printing. Concrete examples for the PR description: line:
PR description: updated (added entry for "fail-closed on API error" to Changesets, refreshed Test Plan)PR description: left as-is (typo and comment fixes only, no scope change)Respond Summary
=======================
PR: #{number} - {pr-title}
Branch: {pr-branch}
Comments Addressed:
Fixed: X (code changes made)
Replied: Y (questions answered)
Acknowledged: Z (resolved without changes)
Skipped: W (user chose to skip)
Commits: N new commits pushed
Threads Resolved: M of T
PR description: {updated | left as-is} ({one-line reason})
Remaining unresolved: {list any, if applicable}
URL: {pr-url}
Next step: (pick exactly one)
package.json, pyproject.toml, lockfiles, .github/workflows/*.yml version pins, or Dockerfile* — same definition as push-pr's equivalent bullet): Next step: hero-skills:harden (print only — model-invocation-restricted, cannot auto-run).Next step: hero-skills:ship-pr — @auto-approve, merge, reset to default branch (blocks if any threads remain unresolved) (offer to auto-run: ask "Run it now? [y/N]", invoke via Skill tool on yes).If changes were stashed in Step 2, remind the user:
Note: You have stashed changes from {original-branch}.
To restore: git checkout {original-branch} && git stash pop
After completing the initial respond cycle (Steps 3-10), check if HERO.md has a Code Review Agent configured (agent is not none). If so, and the user passed --loop or confirms they want to loop, enter the iterative review loop.
Skip this step entirely if:
ITERATION=1
MAX_ITERATIONS=5
REVIEW_AGENT=$(grep '^\- agent:' "$ROOT/HERO.md" | sed 's/- agent: //' | head -1)
TRIGGER=$(grep '^\- trigger:' "$ROOT/HERO.md" | sed 's/- trigger: //' | head -1)
POLL_METHOD=$(grep '^\- poll-method:' "$ROOT/HERO.md" | sed 's/- poll-method: //' | head -1)
Report to user:
Review Loop enabled (agent: REVIEW_AGENT, max iterations: 5)
Starting iteration 1...
11a. Trigger external review
Trigger depends on the configured method:
Comment trigger (e.g., Greptile): Post a comment on the PR
gh pr comment $PR_NUMBER --body "TRIGGER_TEXT"
Label trigger (e.g., some CodeRabbit setups): Add a label
gh pr edit $PR_NUMBER --add-label "TRIGGER_LABEL"
Auto on push: No action needed — the push from Step 8 already triggers it
11b. Poll for review completion
Poll every 30 seconds based on configured poll-method:
check-runs: Wait for the review agent's check run to complete
gh api repos/OWNER/REPO/commits/HEAD_SHA/check-runs \
--jq '.check_runs[] | select(.app.slug == "AGENT_SLUG") | {status: .status, conclusion: .conclusion}'
comments: Wait for a new comment from the review agent bot
gh api repos/OWNER/REPO/pulls/$PR_NUMBER/comments \
--jq '[.[] | select(.user.login == "AGENT_BOT_USERNAME")] | last | {id: .id, created_at: .created_at, body: .body}'
pipeline-status: Wait for pipeline job to finish
gh api repos/OWNER/REPO/actions/runs?head_sha=HEAD_SHA \
--jq '.workflow_runs[] | select(.name | contains("AGENT_NAME")) | {status: .status, conclusion: .conclusion}'
Timeout: If no result after 5 minutes of polling, report timeout and ask user whether to retry or exit the loop.
11c. Parse results
After the external review completes:
# Count unresolved review threads from the agent
gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 10) {
nodes {
body
author { login }
}
}
}
}
}
}
}
' -f owner="$OWNER" -f repo="$REPO" -F pr=$PR_NUMBER
Filter for threads authored by the review agent bot that are unresolved. Count them.
If the agent provides a confidence score (e.g., 5/5 in PR description or comment), extract it.
11d. Check exit conditions
Exit the loop if ANY of these are true:
5/5)If exiting due to max iterations with remaining issues, warn the user:
Review loop reached maximum iterations (5).
Remaining unresolved comments: N
Manual review may be needed for the remaining items.
11e. Fix, commit, push, resolve
If not exiting, repeat the respond cycle for the new comments. The mandatory improvements comment and PR-description decision apply on every iteration — silently skipping them inside the loop would defeat the always-post contract.
Increment iteration counter and loop back to 11a.
11f. Loop summary
After exiting the loop, report:
Review Loop Complete
====================
Agent: REVIEW_AGENT
Iterations: N of MAX_ITERATIONS
Total comments addressed: X
Total commits: Y
Per-iteration breakdown:
Iteration 1: A comments fixed, B resolved
Iteration 2: C comments fixed, D resolved
...
Final status: [Clean / N unresolved comments remain]
URL: PR_URL