Skip to content

Commit f326dc3

Browse files
justin808claude
andcommitted
Add jq -s (slurp) to paginated gh api commands
gh api --paginate outputs separate JSON documents per page. Without jq -s, each page is processed independently, fragmenting the output. This adds -s to all four paginated jq commands so results are aggregated into a single array before projection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 292ab7d commit f326dc3

1 file changed

Lines changed: 18 additions & 13 deletions

File tree

commands/address-review.md

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ If this command fails, ensure `gh` CLI is installed and authenticated (`gh auth
1616

1717
## Step 2: Parse User Input
1818

19-
Extract the PR number and optional review/comment ID from the user's message:
19+
The user's input is: $ARGUMENTS
20+
21+
Extract the PR number and optional review/comment ID from the input above:
2022

2123
**Supported formats:**
2224

@@ -46,7 +48,7 @@ gh api repos/${REPO}/issues/comments/{COMMENT_ID} | jq '{body: .body, user: .use
4648
gh api repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID} | jq '{id: .id, body: .body, state: .state, user: .user.login, html_url: .html_url}'
4749

4850
# Inline comments for this review
49-
gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}/comments | jq '[.[] | {id: .id, node_id: .node_id, path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
51+
gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
5052
```
5153

5254
Include the review body as a general comment when it contains actionable feedback.
@@ -55,26 +57,27 @@ Include the review body as a general comment when it contains actionable feedbac
5557

5658
```bash
5759
# Inline code review comments
58-
gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/comments | jq '[.[] | {id: .id, node_id: .node_id, type: "review", path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
60+
gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, type: "review", path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
5961

6062
# General PR discussion comments (not tied to specific lines)
61-
gh api --paginate repos/${REPO}/issues/{PR_NUMBER}/comments | jq '[.[] | {id: .id, node_id: .node_id, type: "issue", body: .body, user: .user.login, html_url: .html_url}]'
63+
gh api --paginate repos/${REPO}/issues/{PR_NUMBER}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, type: "issue", body: .body, user: .user.login, html_url: .html_url}]'
6264
```
6365

6466
For review comments, fetch review thread metadata and attach `thread_id` by matching each review comment's `node_id`:
6567

6668
```bash
6769
OWNER=${REPO%/*}
6870
NAME=${REPO#*/}
69-
gh api graphql --paginate -f owner="${OWNER}" -f name="${NAME}" -F pr={PR_NUMBER} -f query='query($owner:String!, $name:String!, $pr:Int!, $endCursor:String) { repository(owner:$owner, name:$name) { pullRequest(number:$pr) { reviewThreads(first:100, after:$endCursor) { nodes { id isResolved comments(first:100) { nodes { id databaseId } } } pageInfo { hasNextPage endCursor } } } } }' | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | {thread_id: .id, is_resolved: .isResolved, comments: [.comments.nodes[] | {node_id: .id, id: .databaseId}]}]'
71+
gh api graphql --paginate -f owner="${OWNER}" -f name="${NAME}" -F pr={PR_NUMBER} -f query='query($owner:String!, $name:String!, $pr:Int!, $endCursor:String) { repository(owner:$owner, name:$name) { pullRequest(number:$pr) { reviewThreads(first:100, after:$endCursor) { nodes { id isResolved comments(first:100) { nodes { id databaseId } } } pageInfo { hasNextPage endCursor } } } } }' | jq -s '[.[].data.repository.pullRequest.reviewThreads.nodes[] | {thread_id: .id, is_resolved: .isResolved, comments: [.comments.nodes[] | {node_id: .id, id: .databaseId}]}]'
7072
```
7173

7274
**Filtering comments:**
7375

76+
- Skip comments belonging to already-resolved threads (match via `thread_id` and `is_resolved` from the GraphQL response)
7477
- Skip comments where `in_reply_to_id` is set (these are replies, not top-level comments)
7578
- Do not skip bot-generated comments by default. Many actionable review comments in this repository come from bots.
7679
- Deduplicate repeated bot comments and skip bot status posts, summaries, and acknowledgments that do not require a code or documentation change
77-
- Treat as actionable by default only: correctness bugs, regressions, missing tests, and clear inconsistencies with adjacent code
80+
- Treat as actionable by default only: correctness bugs, regressions, security issues, missing tests, and clear inconsistencies with adjacent code
7881
- Treat as non-actionable by default: style nits, speculative suggestions, changelog wording, duplicate bot comments, and "could consider" feedback unless the user explicitly asks for polish work
7982
- Focus on actionable feedback, not acknowledgments or thank-you messages
8083

@@ -101,13 +104,13 @@ Triage rules:
101104

102105
## Step 5: Create Todo List
103106

104-
Create a todo list with TodoWrite containing **only the `MUST-FIX` items**:
107+
Create a task list with TaskCreate containing **only the `MUST-FIX` items**:
105108

106-
- One todo per must-fix comment or deduplicated issue
107-
- For file-specific comments: `"{file}:{line} - {comment_summary} (@{username})"` (content)
108-
- For general comments: Parse the comment body and extract the must-fix action
109-
- Format activeForm: `"Addressing {brief description}"`
110-
- All todos should start with status: `"pending"`
109+
- One task per must-fix comment or deduplicated issue
110+
- Subject: `"{file}:{line} - {comment_summary} (@{username})"`
111+
- For general comments: Parse the comment body and extract the must-fix action as the subject
112+
- Description: Include the full review comment text and any relevant context
113+
- All tasks should start with status: `"pending"`
111114

112115
## Step 6: Present Triage to User
113116

@@ -126,7 +129,8 @@ Present the triage to the user - **DO NOT automatically start addressing items**
126129

127130
## Step 7: Address Items, Reply, and Resolve
128131

129-
When addressing items, after completing each selected todo item, reply to the original review comment explaining how it was addressed.
132+
When addressing items, after completing each selected item (whether `MUST-FIX` or `DISCUSS`), reply to the original review comment explaining how it was addressed.
133+
If the user selects `DISCUSS` items to address, treat them the same as `MUST-FIX`: make the code change, reply, and resolve the thread.
130134
If the user selects skipped/declined items for rationale replies, post those replies too.
131135

132136
**For issue comments (general PR comments):**
@@ -219,3 +223,4 @@ Note: Only show the "Optional: rationale replies" line when there are `SKIPPED`
219223

220224
- Rate limiting: GitHub API has rate limits; if you hit them, wait a few minutes
221225
- Private repos: Requires appropriate `gh` authentication scope
226+
- GraphQL inner pagination: The `comments(first:100)` inside each review thread is hardcoded. Threads with >100 comments (rare) will have older comments truncated. The outer `reviewThreads` pagination is handled by `--paginate`.

0 commit comments

Comments
 (0)