Loading...
Loading...
Respond to review comments on a PR after evaluation and fixes
npx skill4agent add existential-birds/beagle respond-pr-feedback/beagle-core:respond-pr-feedback [--pr <number>] [--no-resolve]--pr <number>--no-resolve/beagle-core:fetch-pr-feedback$ARGUMENTS--pr <number>--no-resolve# Get PR info (if --pr not specified, uses current branch)
gh pr view --json number,author --jq '{number, author: .author.login}'
# Get repo owner/name
gh repo view --json owner,name --jq '{owner: .owner.login, name: .name}'
# Get current authenticated user
gh api user --jq '.login'$PR_NUMBER$PR_AUTHOR$OWNER$REPO$CURRENT_USER$OWNER$REPO!=cat > /tmp/unreplied_comments.jq << 'JQEOF'
add // [] |
# Root comments from reviewers (not replies, not PR author, not current user)
[.[] | select(
.in_reply_to_id == null and
.user.login != $pr_author and
.user.login != $current_user
)] as $roots |
# IDs that current user has already replied to
[.[] | select(.user.login == $current_user) | .in_reply_to_id] as $replied |
# Filter to unreplied only
$roots | map(select(. as $c | $replied | index($c.id) == null)) |
# Dedup: group by path + line + reviewer, pick newest per group
group_by({
p: .path,
l: (.line // .original_line),
u: .user.login
}) |
map(sort_by(.created_at) | last) |
# Output needed fields
map({
id,
user: .user.login,
path,
line_display: (
.line as $end | .start_line as $start |
if $start and $start != $end then "\($start)-\($end)"
else "\($end // .original_line)" end
),
body
})
JQEOFgh api --paginate "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" | \
jq -s --arg pr_author "$PR_AUTHOR" --arg current_user "$CURRENT_USER" \
-f /tmp/unreplied_comments.jqgh api graphql -f query="
query {
repository(owner: \"$OWNER\", name: \"$REPO\") {
pullRequest(number: $PR_NUMBER) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 1) {
nodes { databaseId }
}
}
}
}
}
}
"databaseIdid| Evaluation Outcome | Response |
|---|---|
| Feedback was incorrect/unfounded | Explain why the current code is correct |
| Feedback lacked context | Explain the design decision |
| Feedback was valid and fixed | "Fixed in |
| Feedback was valid but won't fix | Explain the tradeoff/decision |
@@coderabbitai@gh api "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies" \
-X POST --raw-field body="$RESPONSE"--no-resolve$THREAD_ID$COMMENT_IDgh api graphql -f query="
mutation {
resolveReviewThread(input: {threadId: \"$THREAD_ID\"}) {
thread { isResolved }
}
}
"$COMMENT_ID### Reviewer: coderabbitai[bot]
| File:Line | Response Type | Thread |
|-----------|---------------|--------|
| `src/foo.ts:42` | Fixed in `abc1234` | Resolved |
| `src/bar.ts:15` | Explained design | Resolved |
### Reviewer: octocat
| File:Line | Response Type | Thread |
|-----------|---------------|--------|
| `src/baz.ts:7` | Won't fix | Resolved |**Threads resolved: 3/3**@# Respond to all reviewers on current PR (resolves threads)
/beagle-core:respond-pr-feedback
# Respond on a specific PR
/beagle-core:respond-pr-feedback --pr 123
# Respond without resolving threads
/beagle-core:respond-pr-feedback --no-resolve