cpflow 4.2.0 → 5.0.0.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.agents/workflows/address-review.md +216 -0
- data/.claude/commands/address-review.md +547 -0
- data/.claude/commands/update-changelog.md +367 -0
- data/.github/workflows/claude.yml +5 -0
- data/.overcommit.yml +43 -3
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +28 -4
- data/CONTRIBUTING.md +28 -0
- data/Gemfile +8 -7
- data/Gemfile.lock +92 -72
- data/README.md +55 -20
- data/cpflow.gemspec +5 -5
- data/docs/ai-github-flow-prompt.md +61 -0
- data/docs/ci-automation.md +335 -28
- data/docs/commands.md +67 -4
- data/docs/migrating-heroku-to-control-plane.md +12 -0
- data/docs/postgres.md +5 -0
- data/docs/redis.md +6 -0
- data/docs/releasing.md +153 -0
- data/lib/command/ai_github_flow_prompt.rb +47 -0
- data/lib/command/base.rb +25 -0
- data/lib/command/cleanup_images.rb +1 -1
- data/lib/command/cleanup_stale_apps.rb +1 -1
- data/lib/command/copy_image_from_upstream.rb +14 -3
- data/lib/command/deploy_image.rb +40 -9
- data/lib/command/exists.rb +13 -2
- data/lib/command/generate.rb +153 -4
- data/lib/command/generate_github_actions.rb +170 -0
- data/lib/command/generator_helpers.rb +31 -0
- data/lib/command/github_flow_readiness.rb +37 -0
- data/lib/command/promote_app_from_upstream.rb +13 -2
- data/lib/command/run.rb +1 -1
- data/lib/command/terraform/generate.rb +1 -0
- data/lib/command/version.rb +1 -0
- data/lib/constants/exit_code.rb +1 -0
- data/lib/core/config.rb +8 -0
- data/lib/core/controlplane.rb +9 -7
- data/lib/core/controlplane_api_direct.rb +3 -3
- data/lib/core/github_flow_readiness/checks.rb +143 -0
- data/lib/core/github_flow_readiness_service.rb +453 -0
- data/lib/core/repo_introspection.rb +118 -0
- data/lib/core/terraform_config/dsl.rb +1 -1
- data/lib/core/terraform_config/local_variable.rb +1 -1
- data/lib/cpflow/version.rb +1 -1
- data/lib/cpflow.rb +65 -3
- data/lib/generator_templates/Dockerfile +59 -3
- data/lib/generator_templates/controlplane.yml +27 -39
- data/lib/generator_templates/entrypoint.sh +1 -1
- data/lib/generator_templates/release_script.sh +23 -0
- data/lib/generator_templates/templates/app.yml +5 -8
- data/lib/generator_templates/templates/rails.yml +2 -11
- data/lib/generator_templates_sqlite/controlplane.yml +46 -0
- data/lib/generator_templates_sqlite/release_script.sh +25 -0
- data/lib/generator_templates_sqlite/templates/app.yml +15 -0
- data/lib/generator_templates_sqlite/templates/db.yml +6 -0
- data/lib/generator_templates_sqlite/templates/rails.yml +32 -0
- data/lib/generator_templates_sqlite/templates/storage.yml +6 -0
- data/lib/github_flow_templates/.github/actions/cpflow-build-docker-image/action.yml +131 -0
- data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/action.yml +24 -0
- data/lib/github_flow_templates/.github/actions/cpflow-delete-control-plane-app/delete-app.sh +50 -0
- data/lib/github_flow_templates/.github/actions/cpflow-detect-release-phase/action.yml +62 -0
- data/lib/github_flow_templates/.github/actions/cpflow-setup-environment/action.yml +98 -0
- data/lib/github_flow_templates/.github/actions/cpflow-validate-config/action.yml +85 -0
- data/lib/github_flow_templates/.github/actions/cpflow-wait-for-health/action.yml +92 -0
- data/lib/github_flow_templates/.github/cpflow-help.md +73 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-cleanup-stale-review-apps.yml +56 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-delete-review-app.yml +142 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-review-app.yml +445 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-staging.yml +140 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-help-command.yml +58 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +490 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-review-app-help.yml +45 -0
- data/rakelib/create_release.rake +662 -37
- data/script/check_command_docs +4 -2
- data/script/check_cpln_links +25 -11
- data/script/precommit/check_command_docs +22 -0
- data/script/precommit/check_cpln_links +21 -0
- data/script/precommit/check_trailing_newlines +68 -0
- data/script/precommit/get_changed_files +49 -0
- data/script/precommit/ruby_autofix +52 -0
- data/script/precommit/ruby_lint +33 -0
- metadata +54 -14
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Fetch GitHub PR review comments, triage them, post summary checkpoints, and resolve addressed threads
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Fetch review comments from a GitHub PR in this repository, triage them, and create a todo list only for items worth addressing.
|
|
6
|
+
|
|
7
|
+
# Instructions
|
|
8
|
+
|
|
9
|
+
## Step 1: Parse User Input
|
|
10
|
+
|
|
11
|
+
The user's input is: $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
First, detect whether the request includes the phrase `check all reviews` (case-insensitive, trailing position only — match it as the final tokens of the input, after the PR reference).
|
|
14
|
+
|
|
15
|
+
- If it does, set a `CHECK_ALL_REVIEWS` flag and remove only that phrase before parsing the PR reference.
|
|
16
|
+
- If the phrase appears in any other position (leading, embedded), do not treat it as an override; warn the user and ask them to retry with the trailing form.
|
|
17
|
+
- Mention that override in the eventual PR summary comment so future runs have clear history.
|
|
18
|
+
|
|
19
|
+
Then extract the PR number and optional review/comment ID from the remaining input:
|
|
20
|
+
|
|
21
|
+
**Supported formats:**
|
|
22
|
+
|
|
23
|
+
- PR number only: `12345`
|
|
24
|
+
- PR number with override: `12345 check all reviews`
|
|
25
|
+
- PR URL: `https://github.com/org/repo/pull/12345`
|
|
26
|
+
- PR URL with override: `https://github.com/org/repo/pull/12345 check all reviews`
|
|
27
|
+
- Specific PR review: `https://github.com/org/repo/pull/12345#pullrequestreview-123456789`
|
|
28
|
+
- Specific issue comment: `https://github.com/org/repo/pull/12345#issuecomment-123456789`
|
|
29
|
+
|
|
30
|
+
**URL parsing:**
|
|
31
|
+
|
|
32
|
+
- Extract org/repo from URL path: `github.com/{org}/{repo}/pull/{PR_NUMBER}`
|
|
33
|
+
- Extract fragment ID after `#` (e.g., `pullrequestreview-123456789` → `123456789`)
|
|
34
|
+
- If a full GitHub URL is provided, capture the URL's `org/repo` now so Step 2 can use it without calling `gh repo view`.
|
|
35
|
+
|
|
36
|
+
## Step 2: Set Repository and PR Number
|
|
37
|
+
|
|
38
|
+
- If Step 1 extracted `org/repo` from a full GitHub URL, use that as `REPO`.
|
|
39
|
+
- Otherwise, detect the repository from the current checkout.
|
|
40
|
+
- Set `PR_NUMBER` to the number parsed in Step 1.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) # or the org/repo extracted from the PR URL in Step 1
|
|
44
|
+
PR_NUMBER=<the PR number parsed in Step 1>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Every subsequent snippet uses `${REPO}` and `${PR_NUMBER}` as shell variables; setting them once here means no manual substitution is required later. If `gh repo view` fails (and no URL was supplied), ensure `gh` CLI is installed and authenticated (`gh auth status`).
|
|
48
|
+
|
|
49
|
+
## Step 3: Determine Scan Window and Summary Cutoff
|
|
50
|
+
|
|
51
|
+
For full-PR scans (plain PR number or PR URL with no specific review/comment anchor), default to reviewing only feedback posted after the latest PR summary comment created by this workflow.
|
|
52
|
+
|
|
53
|
+
- The summary marker is a PR issue comment whose body starts with `<!-- address-review-summary -->` on its very first line. Requiring `startswith` (not `contains`) means a human comment that quotes or embeds the marker in prose is not mistaken for a checkpoint and cannot silently advance the cutoff.
|
|
54
|
+
- If the user explicitly said `check all reviews`, ignore the cutoff and scan the full PR history.
|
|
55
|
+
- If the input is a specific review URL or specific issue-comment URL, fetch that exact target even if it predates the latest summary comment.
|
|
56
|
+
|
|
57
|
+
Fetch the latest summary comment before collecting review data. Extract only the timestamp, guarding against the empty-array case (`jq ... | last` emits JSON `null` when nothing matches):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
REVIEW_CUTOFF_AT=$(
|
|
61
|
+
gh api --paginate repos/${REPO}/issues/${PR_NUMBER}/comments \
|
|
62
|
+
| jq -rs '[.[].[] | select((.body // "") | startswith("<!-- address-review-summary -->")) | {id: .id, created_at: .created_at, html_url: .html_url}] | sort_by(.created_at) | last | if . == null then "" else .created_at end'
|
|
63
|
+
)
|
|
64
|
+
# Empty string → no prior summary comment; scan full PR history.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Cutoff rules:
|
|
68
|
+
|
|
69
|
+
- `REVIEW_CUTOFF_AT` is empty when no summary comment exists; treat that as "scan full PR history" and do not filter by timestamp.
|
|
70
|
+
- If `REVIEW_CUTOFF_AT` is non-empty and `CHECK_ALL_REVIEWS` is false, use it as the cutoff.
|
|
71
|
+
- Use exact timestamps in user-facing status updates, for example: "Scanning review activity after 2026-04-01T20:14:33Z."
|
|
72
|
+
- When a cutoff is active, keep enough older thread context to understand new replies, but only triage items whose own timestamp or latest thread activity is after `REVIEW_CUTOFF_AT`.
|
|
73
|
+
- If no items survive the cutoff, say that no new review feedback was found since the last summary comment and remind the user they can say `check all reviews` to rescan the full PR.
|
|
74
|
+
|
|
75
|
+
## Step 4: Fetch Review Comments
|
|
76
|
+
|
|
77
|
+
Before fetching, wait for any in-progress `claude-review` CI run on this PR so the triage reflects the latest posted feedback. Skip the wait if the user provided a specific review URL or specific issue-comment URL — fetch that exact target immediately. If `gh pr checks` is unavailable or returns an error, log a warning and continue without blocking.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Block while a claude-review check is still queued/running (bucket == "pending").
|
|
81
|
+
# Pass --repo so cross-repo PR URLs target the parsed REPO, not the current checkout.
|
|
82
|
+
# The fallback `|| echo 0` makes the loop exit gracefully if `gh pr checks` errors.
|
|
83
|
+
# `MAX_WAIT` caps the total wait so a stalled runner cannot block triage indefinitely.
|
|
84
|
+
MAX_WAIT=180
|
|
85
|
+
WAITED=0
|
|
86
|
+
while [ "$(gh pr checks "${PR_NUMBER}" --repo "${REPO}" --json name,bucket 2>/dev/null \
|
|
87
|
+
| jq '[.[] | select((.name | test("claude.?review"; "i")) and (.bucket == "pending"))] | length' 2>/dev/null || echo 0)" -gt 0 ]; do
|
|
88
|
+
if [ "${WAITED}" -ge "${MAX_WAIT}" ]; then
|
|
89
|
+
echo "Warning: claude-review CI still pending after ${MAX_WAIT}s — proceeding with triage anyway."
|
|
90
|
+
break
|
|
91
|
+
fi
|
|
92
|
+
echo "Waiting for in-progress claude-review CI to finish before triaging... (${WAITED}s elapsed)"
|
|
93
|
+
sleep 15
|
|
94
|
+
WAITED=$((WAITED + 15))
|
|
95
|
+
done
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**If a specific issue comment ID is provided (`#issuecomment-...`):**
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
gh api repos/${REPO}/issues/comments/{COMMENT_ID} | jq '{body: .body, user: .user.login, created_at: .created_at, html_url: .html_url}'
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**If a specific review ID is provided (`#pullrequestreview-...`):**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Review body (often contains summary feedback)
|
|
108
|
+
gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews/{REVIEW_ID} | jq '{id: .id, body: .body, state: .state, user: .user.login, created_at: .submitted_at, html_url: .html_url}'
|
|
109
|
+
|
|
110
|
+
# Inline comments for this review
|
|
111
|
+
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, created_at: .created_at, html_url: .html_url}]'
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Include the review body as a general comment when it contains actionable feedback. When the review body contains actionable feedback, note that it cannot be replied to via the `/replies` endpoint — responses to review summary bodies must be posted as general PR comments (see Step 8).
|
|
115
|
+
|
|
116
|
+
**If only PR number is provided (fetch all PR comments):**
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Review summary bodies (can contain actionable feedback even without inline comments)
|
|
120
|
+
gh api --paginate repos/${REPO}/pulls/${PR_NUMBER}/reviews | jq -s '[.[].[] | select((.body // "") != "") | {id: .id, type: "review_summary", body: .body, state: .state, user: .user.login, created_at: .submitted_at, html_url: .html_url}]'
|
|
121
|
+
|
|
122
|
+
# Inline code review comments
|
|
123
|
+
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, created_at: .created_at, html_url: .html_url}]'
|
|
124
|
+
|
|
125
|
+
# General PR discussion comments (not tied to specific lines)
|
|
126
|
+
gh api --paginate repos/${REPO}/issues/${PR_NUMBER}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, type: "issue", body: .body, user: .user.login, created_at: .created_at, html_url: .html_url}]'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Include actionable review summary bodies from `/pulls/{PR_NUMBER}/reviews` as additional general comments. Like specific review bodies, they cannot be replied to via the `/replies` endpoint and must be answered as general PR comments (see Step 8).
|
|
130
|
+
|
|
131
|
+
When `REVIEW_CUTOFF_AT` is set for a full-PR scan:
|
|
132
|
+
|
|
133
|
+
- Fetch the full datasets above so you keep older context for unresolved threads.
|
|
134
|
+
- Filter issue comments and review summaries to items created after `REVIEW_CUTOFF_AT`.
|
|
135
|
+
- For inline review threads, keep an unresolved thread only when at least one comment in that thread has `created_at > REVIEW_CUTOFF_AT`.
|
|
136
|
+
- Use the thread's top-level comment as the triage item, and use newer replies in that thread as the latest context.
|
|
137
|
+
- Do not let older comments with no new activity re-enter triage unless the user asked for `check all reviews`.
|
|
138
|
+
|
|
139
|
+
**For all paths that fetch review comments (both specific review and full PR), fetch review thread metadata and attach `thread_id` by matching each review comment's `node_id`:**
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
OWNER=${REPO%/*}
|
|
143
|
+
NAME=${REPO#*/}
|
|
144
|
+
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}]}]'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Filtering comments:**
|
|
148
|
+
|
|
149
|
+
- Never triage a prior summary checkpoint comment. Skip any issue comment whose body starts with `<!-- address-review-summary -->`.
|
|
150
|
+
- Skip comments belonging to already-resolved threads (match via `thread_id` and `is_resolved` from the GraphQL response)
|
|
151
|
+
- Do not create standalone triage items from comments where `in_reply_to_id` is set, but use reply text as the latest thread context when it updates or narrows the unresolved concern
|
|
152
|
+
- When `REVIEW_CUTOFF_AT` is set, evaluate unresolved review threads by their latest activity timestamp, not only by the top-level comment timestamp
|
|
153
|
+
- Do not skip bot-generated comments by default. Many actionable review comments in this repository come from bots.
|
|
154
|
+
- Deduplicate repeated bot comments and skip bot status posts, summaries, and acknowledgments that do not require a code or documentation change
|
|
155
|
+
- Treat as actionable by default only: correctness bugs, regressions, security issues, missing tests, and clear inconsistencies with adjacent code
|
|
156
|
+
- 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
|
|
157
|
+
- Focus on actionable feedback, not acknowledgments or thank-you messages
|
|
158
|
+
|
|
159
|
+
**Error handling:**
|
|
160
|
+
|
|
161
|
+
- If the API returns 404, the PR/comment doesn't exist - inform the user
|
|
162
|
+
- If the API returns 403, check authentication with `gh auth status`
|
|
163
|
+
- If the response is empty after cutoff filtering, inform the user no new review comments were found since the last summary comment and mention `check all reviews`
|
|
164
|
+
- If the response is empty without a cutoff, inform the user no review comments were found
|
|
165
|
+
|
|
166
|
+
## Step 5: Triage Comments
|
|
167
|
+
|
|
168
|
+
Before creating any todos, classify every review comment into one of three categories:
|
|
169
|
+
|
|
170
|
+
- `MUST-FIX`: correctness bugs, regressions, security issues, missing tests that could hide a real bug, and clear inconsistencies with adjacent code that would likely block merge
|
|
171
|
+
- `DISCUSS`: reasonable suggestions that expand scope, architectural opinions that are not clearly right or wrong, and comments where the reviewer claim may be correct but needs a user decision
|
|
172
|
+
- `SKIPPED`: style preferences, documentation nits, comment requests, test-shape preferences, speculative suggestions, changelog wording, duplicate comments, status posts, non-actionable summaries, and factually incorrect suggestions
|
|
173
|
+
|
|
174
|
+
Triage rules:
|
|
175
|
+
|
|
176
|
+
- Deduplicate overlapping comments before classifying them. Keep one representative item for the underlying issue.
|
|
177
|
+
- Verify factual claims locally before classifying a comment as `MUST-FIX`.
|
|
178
|
+
- If a claim appears wrong, classify it as `SKIPPED` and note briefly why.
|
|
179
|
+
- Preserve the original review comment ID and thread ID when available so the command can reply to the correct place and resolve the correct thread later.
|
|
180
|
+
- Treat actionable review summary bodies as normal feedback to classify (`MUST-FIX`/`DISCUSS` as appropriate); skip only boilerplate or status-only summaries.
|
|
181
|
+
|
|
182
|
+
## Step 6: Create Todo List
|
|
183
|
+
|
|
184
|
+
Create a task list with TodoWrite containing **only the `MUST-FIX` items**:
|
|
185
|
+
|
|
186
|
+
- One task per must-fix comment or deduplicated issue
|
|
187
|
+
- Subject: `"{file}:{line} - {comment_summary} (@{username})"`
|
|
188
|
+
- For general comments: Parse the comment body and extract the must-fix action as the subject
|
|
189
|
+
- Description: Include the full review comment text and any relevant context
|
|
190
|
+
- All tasks should start with status: `"pending"`
|
|
191
|
+
|
|
192
|
+
## Step 7: Present Triage and Quick-Action Menu
|
|
193
|
+
|
|
194
|
+
Present the triage to the user - **DO NOT automatically start addressing items**:
|
|
195
|
+
|
|
196
|
+
- Use a single sequential numbering across all categories (1, 2, 3, ...) so every item has a unique number the user can reference. Do not restart numbering at 1 for each category.
|
|
197
|
+
- `MUST-FIX ({count})`: list the todos created
|
|
198
|
+
- `DISCUSS ({count})`: list items needing user choice, with a short reason
|
|
199
|
+
- `SKIPPED ({count})`: list skipped comments with a short reason, including duplicates and factually incorrect suggestions
|
|
200
|
+
|
|
201
|
+
After the triage list, present a **quick-action menu**:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
Quick actions:
|
|
205
|
+
f — Fix must-fix items, then confirm whether to reply/resolve skipped items before deciding discuss items
|
|
206
|
+
f+i — Fix must-fix + create follow-up issue for discuss/non-trivial skipped items
|
|
207
|
+
d — Discuss specific items before deciding (e.g., "d2,4"). Bare "d" presents all DISCUSS items.
|
|
208
|
+
r — Reply with rationale to items (e.g., "r3,5", "r7-9", "r all skipped", "r all discuss"); add `+ resolve` to also resolve those threads
|
|
209
|
+
m — Skip code changes + create follow-up issue for must-fix/discuss/non-trivial skipped items
|
|
210
|
+
|
|
211
|
+
Or pick items by number: "1,2", "all must-fix", "1,3-5"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Range syntax**: Support `N-M` to expand into individual item numbers (e.g., `3-5` becomes `3,4,5`). Ranges work everywhere: item selection, `d`, and `r`.
|
|
215
|
+
If a range is malformed, reversed, or out of bounds, show a validation message and ask the user to retry (do not silently coerce it).
|
|
216
|
+
|
|
217
|
+
**Dynamic menu**: Generate `f` and `f+i` descriptions dynamically using actual item numbers and deferred targets from the current triage set (e.g., "Fix #1, #3" instead of "Fix must-fix items"). When there are no `DISCUSS` or `SKIPPED` items, only show `f` and direct item selection.
|
|
218
|
+
|
|
219
|
+
Wait for the user to choose an action before proceeding.
|
|
220
|
+
|
|
221
|
+
Do not post the PR summary checkpoint during this triage-only phase. Post it only after a chosen action reaches a stable stopping point so the summary reflects the new baseline.
|
|
222
|
+
|
|
223
|
+
## Step 8: Execute the Chosen Action
|
|
224
|
+
|
|
225
|
+
### Action `f` — Fix and merge-ready
|
|
226
|
+
|
|
227
|
+
1. Address all `MUST-FIX` items (make code changes, run checks). If there are no `MUST-FIX` items, skip directly to discuss/skipped handling.
|
|
228
|
+
2. If local changes exist, commit and then ask for push confirmation before pushing. If there are no local changes, skip commit/push and continue decision flow.
|
|
229
|
+
3. Reply to each addressed comment explaining the fix.
|
|
230
|
+
4. Resolve the corresponding review threads.
|
|
231
|
+
5. If `SKIPPED` items exist, ask for explicit confirmation before posting rationale replies and resolving those threads (for example: "Reply/resolve 3 skipped items? y/n").
|
|
232
|
+
6. Do **not** auto-resolve `DISCUSS` items in `f`; after must-fix work, re-present discuss items and prompt the user to choose `d` (discuss), `f+i` (create follow-up issue), or `r all discuss + resolve`. If `f` starts with zero `MUST-FIX` items, show this discuss decision menu immediately.
|
|
233
|
+
7. Tell the user the PR is merge-ready only after `DISCUSS` items are resolved or explicitly deferred.
|
|
234
|
+
8. If any `DISCUSS` items remain, explicitly prompt with the next action (for example: "DISCUSS items remain - use `d` to review, `f+i` to defer to a follow-up issue, or `r all discuss + resolve` to decline and close.").
|
|
235
|
+
|
|
236
|
+
### Action `f+i` — Fix, follow-up issue, and merge-ready
|
|
237
|
+
|
|
238
|
+
1. Do everything in `f` for `MUST-FIX` items. If there are no `MUST-FIX` items, skip the fix phase and continue with deferred-item handling.
|
|
239
|
+
2. Create a **follow-up GitHub issue** (see Step 9) bundling all `DISCUSS` and non-trivial `SKIPPED` items.
|
|
240
|
+
3. For each deferred item in the follow-up issue, post a reply in the original location referencing the issue (use review-comment replies for inline comments and issue comments for review summaries/general comments), and resolve the thread when one exists. For general PR comments and review summary bodies (which have no thread), the reply alone is sufficient.
|
|
241
|
+
4. For trivial `SKIPPED` items that are not included in the follow-up issue (duplicates, factually incorrect suggestions, status noise), still post rationale replies and resolve those threads.
|
|
242
|
+
5. If there are zero deferred items, skip issue creation and behave like `f`.
|
|
243
|
+
6. No additional commit is required unless later steps introduce local changes; if they do, commit and ask for push confirmation before pushing.
|
|
244
|
+
7. Tell the user the PR is merge-ready.
|
|
245
|
+
|
|
246
|
+
### Action `d` — Discuss items
|
|
247
|
+
|
|
248
|
+
Present the requested items with full context and ask the user for a decision on each. If the user enters bare `d` with no item numbers, present all `DISCUSS` items. After the user decides, treat approved items as `MUST-FIX` (fix, reply, resolve) and declined items as `SKIPPED` (optionally reply with rationale if the user asks). For approved items that produce local changes, use the same commit/push-before-reply ordering as action `f`. After handling requested `d` items, re-offer the quick-action menu for remaining unaddressed items.
|
|
249
|
+
|
|
250
|
+
### Action `r` — Reply with rationale
|
|
251
|
+
|
|
252
|
+
Post rationale replies to the specified items explaining why they are being deferred or skipped. By default, do not resolve threads in `r` unless the user explicitly asks to resolve them (for example, `r3,5 + resolve`). Accept only `SKIPPED`/`DISCUSS` item numbers, ranges, `r all skipped`, or `r all discuss`. If the selection includes any `MUST-FIX` item (including `r all must-fix`), do not post replies; direct the user to `f` or explicit deferral (`f+i` / `m`).
|
|
253
|
+
|
|
254
|
+
- Bare `r` (with no items and no `all` qualifier) is ambiguous. Do not reply to anything. Prompt the user to specify item numbers or ranges, or one of `r all skipped` / `r all discuss`.
|
|
255
|
+
- Bare `r all` (without `skipped` or `discuss`) is also ambiguous. Do not reply to anything. Respond with: `"r all" is ambiguous — use "r all skipped", "r all discuss", or run both: "r all skipped" then "r all discuss"`.
|
|
256
|
+
|
|
257
|
+
### Action `m` — Merge as-is
|
|
258
|
+
|
|
259
|
+
1. Create a follow-up GitHub issue (see Step 9) bundling `MUST-FIX`, `DISCUSS`, and non-trivial `SKIPPED` items.
|
|
260
|
+
2. Post replies in the original location for each deferred item: use review-comment replies for inline comments and issue comments for review summaries/general comments.
|
|
261
|
+
3. Resolve `DISCUSS` and `SKIPPED` review threads after replying (resolve only when a thread exists).
|
|
262
|
+
4. If any `MUST-FIX` items were deferred, keep those review threads open by default unless the user explicitly asks to close them.
|
|
263
|
+
5. If any `MUST-FIX` items were deferred, explicitly tell the user the PR is **not merge-ready** without an override decision.
|
|
264
|
+
6. Only signal merge-ready with no code changes when there are zero deferred `MUST-FIX` items.
|
|
265
|
+
|
|
266
|
+
### Direct item selection (e.g., "1,2", "all must-fix", "1,3-5")
|
|
267
|
+
|
|
268
|
+
Address only the selected items. After completing them:
|
|
269
|
+
|
|
270
|
+
1. If selected items produced local changes, commit and ask for push confirmation before pushing (skip this step when there are no local changes).
|
|
271
|
+
2. Reply and resolve threads for addressed items.
|
|
272
|
+
3. Ask whether remaining items should receive rationale replies, a follow-up issue, or be left as-is.
|
|
273
|
+
|
|
274
|
+
### Combination actions
|
|
275
|
+
|
|
276
|
+
Users can chain actions: e.g., `f+i` then `r7-9`. After the first action completes, check if there are remaining un-replied items and offer the next logical action.
|
|
277
|
+
|
|
278
|
+
### General rules for all actions
|
|
279
|
+
|
|
280
|
+
When addressing items, after completing each selected item (whether `MUST-FIX` or `DISCUSS`), reply to the original review comment explaining how it was addressed.
|
|
281
|
+
If the user selects `DISCUSS` items to address, treat them the same as `MUST-FIX`: make the code change, reply, and resolve the thread.
|
|
282
|
+
If the user selects skipped/declined items for rationale replies, post those replies too.
|
|
283
|
+
|
|
284
|
+
**For issue comments (general PR comments):**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
gh api repos/${REPO}/issues/${PR_NUMBER}/comments -X POST -f body="<response>"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**For PR review comments (file-specific, replying to a thread):**
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
gh api repos/${REPO}/pulls/${PR_NUMBER}/comments/{COMMENT_ID}/replies -X POST -f body="<response>"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Use the `/replies` endpoint for all existing review comments, including standalone top-level comments.
|
|
297
|
+
|
|
298
|
+
**For review summary bodies (from `/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}`):**
|
|
299
|
+
|
|
300
|
+
Review summary bodies do not have a `comment_id` and cannot be replied to via the `/replies` endpoint. Instead, post a general PR comment referencing the review:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
gh api repos/${REPO}/issues/${PR_NUMBER}/comments -X POST -f body="<response>"
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The response should briefly explain:
|
|
307
|
+
|
|
308
|
+
- What was changed
|
|
309
|
+
- Which commit(s) contain the fix
|
|
310
|
+
- Any relevant details or decisions made
|
|
311
|
+
|
|
312
|
+
After posting the reply, resolve the review thread when all of the following are true:
|
|
313
|
+
|
|
314
|
+
- The comment belongs to a review thread and you have the thread ID
|
|
315
|
+
- The concern was actually addressed in code, tests, or documentation, or it was explicitly declined with a clear explanation approved by the user
|
|
316
|
+
- The thread is not already resolved
|
|
317
|
+
|
|
318
|
+
Use GitHub GraphQL to resolve the thread:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
gh api graphql -f query='mutation($threadId:ID!) { resolveReviewThread(input:{threadId:$threadId}) { thread { id isResolved } } }' -f threadId="<THREAD_ID>"
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Do not resolve a thread if the fix is still pending, if you are unsure whether the reviewer concern is satisfied, or if the user asked to leave the thread open.
|
|
325
|
+
|
|
326
|
+
If the user explicitly asks to close out a `DISCUSS` or `SKIPPED` item, reply with the rationale and resolve the thread only when the conversation is actually complete.
|
|
327
|
+
|
|
328
|
+
## Step 9: Create Follow-Up Issue (when requested)
|
|
329
|
+
|
|
330
|
+
When the user chooses `f+i`, `m`, or explicitly asks for a follow-up issue, create a GitHub issue that bundles deferred items.
|
|
331
|
+
|
|
332
|
+
**Run Steps 9 and 10 in a single shell call.** They share state — `${FOLLOW_UP_URL}` set in Step 9 is consumed by Step 10's summary template, `${issue_body_file}` and `${summary_body_file}` share an EXIT trap, and the `_cleanup_addr_review` function is defined once. Agents that execute each Bash tool call in a fresh subshell (the default in Claude Code and similar harnesses) will lose `${FOLLOW_UP_URL}` between calls and trigger Step 9's cleanup trap before Step 10 runs. Combine both steps into one heredoc/chained invocation, or capture Step 9's `FOLLOW_UP_URL` from stdout and pass it explicitly into Step 10's invocation.
|
|
333
|
+
|
|
334
|
+
The cleanup trap below is a named `_cleanup_addr_review` function rather than an inline `trap '...' EXIT` so Step 10's standalone path can redefine the same function without divergence. Installing the trap up front (rather than letting Step 10 replace it) closes the race window where an early exit between Step 9 and Step 10 would skip cleanup of the second temp file.
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# Template inputs: replace each <...> placeholder before running this snippet.
|
|
338
|
+
# Use single-quoted heredocs so pasted review text is treated as literal content.
|
|
339
|
+
DISCUSS_ITEMS="$(cat <<'EOF'
|
|
340
|
+
<DISCUSS_ITEMS_BULLETS_OR_EMPTY>
|
|
341
|
+
EOF
|
|
342
|
+
)"
|
|
343
|
+
SKIPPED_ITEMS="$(cat <<'EOF'
|
|
344
|
+
<SKIPPED_ITEMS_BULLETS_OR_EMPTY>
|
|
345
|
+
EOF
|
|
346
|
+
)"
|
|
347
|
+
|
|
348
|
+
# For `f+i`, keep this empty. For `m`, include a heading and deferred must-fix bullets.
|
|
349
|
+
MUST_FIX_SECTION="$(cat <<'EOF'
|
|
350
|
+
<MUST_FIX_SECTION_OR_EMPTY>
|
|
351
|
+
EOF
|
|
352
|
+
)"
|
|
353
|
+
|
|
354
|
+
DISCUSS_SECTION=""
|
|
355
|
+
if [ -n "${DISCUSS_ITEMS}" ]; then
|
|
356
|
+
DISCUSS_SECTION="### Discuss items
|
|
357
|
+
${DISCUSS_ITEMS}
|
|
358
|
+
"
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
SKIPPED_SECTION=""
|
|
362
|
+
if [ -n "${SKIPPED_ITEMS}" ]; then
|
|
363
|
+
SKIPPED_SECTION="### Skipped items (non-trivial)
|
|
364
|
+
${SKIPPED_ITEMS}
|
|
365
|
+
"
|
|
366
|
+
fi
|
|
367
|
+
|
|
368
|
+
if [ -z "${MUST_FIX_SECTION}${DISCUSS_SECTION}${SKIPPED_SECTION}" ]; then
|
|
369
|
+
echo "No deferred items found; skip follow-up issue creation."
|
|
370
|
+
else
|
|
371
|
+
issue_body_file="$(mktemp)"
|
|
372
|
+
# Cleanup covers both temp files; Step 10 redefines _cleanup_addr_review for its standalone path.
|
|
373
|
+
_cleanup_addr_review() {
|
|
374
|
+
[ -n "${issue_body_file:-}" ] && rm -f "${issue_body_file}"
|
|
375
|
+
[ -n "${summary_body_file:-}" ] && rm -f "${summary_body_file}"
|
|
376
|
+
}
|
|
377
|
+
trap _cleanup_addr_review EXIT
|
|
378
|
+
# Build the issue body with printf only — avoids bash-only ANSI-C quoting
|
|
379
|
+
# (e.g., $'\n\n') which expands to a literal "$\n\n" under POSIX sh (dash).
|
|
380
|
+
{
|
|
381
|
+
printf '## Deferred review feedback from PR #%s\n\n' "${PR_NUMBER}"
|
|
382
|
+
printf 'These items were triaged during review and deferred for follow-up.\n\n'
|
|
383
|
+
printed_first=0
|
|
384
|
+
for section in "${MUST_FIX_SECTION}" "${DISCUSS_SECTION}" "${SKIPPED_SECTION}"; do
|
|
385
|
+
[ -z "${section}" ] && continue
|
|
386
|
+
if [ "${printed_first}" -eq 1 ]; then
|
|
387
|
+
printf '\n\n'
|
|
388
|
+
fi
|
|
389
|
+
printf '%s' "${section}"
|
|
390
|
+
printed_first=1
|
|
391
|
+
done
|
|
392
|
+
printf '\n\n'
|
|
393
|
+
printf -- '---\n'
|
|
394
|
+
printf 'Original PR: https://github.com/%s/pull/%s\n' "${REPO}" "${PR_NUMBER}"
|
|
395
|
+
} > "${issue_body_file}"
|
|
396
|
+
|
|
397
|
+
FOLLOW_UP_URL=$(gh issue create --repo "${REPO}" --title "Follow-up: Review feedback from PR #${PR_NUMBER}" --body-file "${issue_body_file}" --json url -q .url)
|
|
398
|
+
fi
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Rules for follow-up issues:
|
|
402
|
+
|
|
403
|
+
- Only include non-trivial `SKIPPED` items (skip pure duplicates and factually incorrect suggestions)
|
|
404
|
+
- For `f+i`, omit the must-fix section because must-fix items were addressed in the current PR
|
|
405
|
+
- For `m`, include a must-fix section with heading `### Must-fix items (deferred)` and deferred blockers
|
|
406
|
+
- Omit any section heading when its corresponding item list is empty
|
|
407
|
+
- Include the original reviewer username and comment link for each item
|
|
408
|
+
- Include enough context that someone can act on the issue without re-reading the full PR review
|
|
409
|
+
- After creating the issue, reference it in thread replies (e.g., "Tracked in #NNN for follow-up")
|
|
410
|
+
- Capture the `gh issue create` output into `FOLLOW_UP_URL` (as shown above) so Step 10's summary comment can include the link
|
|
411
|
+
- Return the issue URL to the user
|
|
412
|
+
|
|
413
|
+
## Step 10: Post PR Summary Comment
|
|
414
|
+
|
|
415
|
+
After any chosen action or completed action chain (`f`, `f+i`, `d`, `r`, `m`, or direct item selection), post a consolidated PR comment that becomes the next default review cutoff.
|
|
416
|
+
|
|
417
|
+
Rules for the summary comment:
|
|
418
|
+
|
|
419
|
+
- Always post it as a general PR issue comment, never as a review-thread reply.
|
|
420
|
+
- Include the exact marker `<!-- address-review-summary -->` on its own line near the top.
|
|
421
|
+
- Summarize `MUST-FIX` and `DISCUSS` items under a `Mattered` section, including whether each item was addressed, deferred, or left pending by user choice.
|
|
422
|
+
- Summarize `SKIPPED` items under a `Skipped` section with short reasons.
|
|
423
|
+
- Mention any follow-up issue URL that was created.
|
|
424
|
+
- Mention whether the run used the default cutoff or the explicit `check all reviews` override.
|
|
425
|
+
- End with a note that future full-PR scans should start after this comment unless the user says `check all reviews`.
|
|
426
|
+
|
|
427
|
+
Suggested structure. As called out in Step 9, run Steps 9 and 10 in the same shell call so `${FOLLOW_UP_URL}` and the EXIT trap persist; otherwise capture `FOLLOW_UP_URL` from Step 9's stdout and pass it in explicitly. `_cleanup_addr_review` is redefined here to cover the standalone-Step-10 path (when Step 9 was skipped and `issue_body_file` is unset). Redefining the same function is harmless if Step 9 already defined it; the `[ -n ... ]` guards keep `rm -f ""` out of the picture on shells that reject empty path arguments.
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
summary_body_file="$(mktemp)"
|
|
431
|
+
# Cleanup mirrors Step 9's definition for the standalone-Step-10 path.
|
|
432
|
+
_cleanup_addr_review() {
|
|
433
|
+
[ -n "${issue_body_file:-}" ] && rm -f "${issue_body_file}"
|
|
434
|
+
[ -n "${summary_body_file:-}" ] && rm -f "${summary_body_file}"
|
|
435
|
+
}
|
|
436
|
+
trap _cleanup_addr_review EXIT
|
|
437
|
+
# Set SCAN_SCOPE before this block, e.g.:
|
|
438
|
+
# SCAN_SCOPE="since previous summary at ${REVIEW_CUTOFF_AT}" # cutoff active
|
|
439
|
+
# SCAN_SCOPE="full history via check all reviews" # CHECK_ALL_REVIEWS set
|
|
440
|
+
{
|
|
441
|
+
printf '<!-- address-review-summary -->\n'
|
|
442
|
+
printf '## Address-review summary\n\n'
|
|
443
|
+
printf 'Scan scope: %s\n\n' "${SCAN_SCOPE}"
|
|
444
|
+
printf '### Mattered\n'
|
|
445
|
+
printf '%s\n\n' "<bullets for must-fix/discuss outcomes, or - None.>"
|
|
446
|
+
printf '### Skipped\n'
|
|
447
|
+
printf '%s\n\n' "<bullets for skipped items, or - None.>"
|
|
448
|
+
if [ -n "${FOLLOW_UP_URL:-}" ]; then
|
|
449
|
+
printf 'Follow-up issue: %s\n\n' "${FOLLOW_UP_URL}"
|
|
450
|
+
fi
|
|
451
|
+
printf 'Next default scan starts after this comment. Say `check all reviews` to rescan the full PR.\n'
|
|
452
|
+
} > "${summary_body_file}"
|
|
453
|
+
|
|
454
|
+
gh api repos/${REPO}/issues/${PR_NUMBER}/comments -X POST -f body=@"${summary_body_file}"
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Use exact dates/timestamps in this comment when referring to the cutoff or scan window.
|
|
458
|
+
|
|
459
|
+
## Step 11: Merge-Ready Signal
|
|
460
|
+
|
|
461
|
+
After completing the chosen action (`f`, `f+i`, `d`, `r`, `m`, or direct item selection) and posting the PR summary comment, report merge readiness status:
|
|
462
|
+
|
|
463
|
+
```text
|
|
464
|
+
All review threads resolved. PR is merge-ready.
|
|
465
|
+
Follow-up issue: https://github.com/org/repo/issues/NNN (if created)
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
If `m` deferred any `MUST-FIX` items, report:
|
|
469
|
+
|
|
470
|
+
```text
|
|
471
|
+
Deferred review feedback tracked in follow-up issue: https://github.com/org/repo/issues/NNN
|
|
472
|
+
Deferred MUST-FIX threads remain open by default.
|
|
473
|
+
PR is NOT merge-ready because must-fix items were deferred.
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
If the action was direct item selection and unresolved `MUST-FIX`/`DISCUSS` items remain, do not signal merge-ready. Re-offer the quick-action menu and ask whether to continue with `f`, `f+i`, `d`, `r`, or `m`.
|
|
477
|
+
If the action was `d` or `r` and unresolved `MUST-FIX`/`DISCUSS` items remain, do not signal merge-ready; re-offer the quick-action menu and ask whether to continue with `f`, `f+i`, `d`, `r`, or `m`.
|
|
478
|
+
|
|
479
|
+
Do not automatically merge. Signal readiness (or non-readiness) and let the user decide.
|
|
480
|
+
|
|
481
|
+
# Example Usage
|
|
482
|
+
|
|
483
|
+
```text
|
|
484
|
+
/address-review https://github.com/org/repo/pull/12345#pullrequestreview-123456789
|
|
485
|
+
/address-review https://github.com/org/repo/pull/12345#issuecomment-123456789
|
|
486
|
+
/address-review 12345
|
|
487
|
+
/address-review https://github.com/org/repo/pull/12345
|
|
488
|
+
/address-review 12345 check all reviews
|
|
489
|
+
/address-review https://github.com/org/repo/pull/12345 check all reviews
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
# Example Output
|
|
493
|
+
|
|
494
|
+
After fetching and triaging comments, present them like this:
|
|
495
|
+
|
|
496
|
+
```text
|
|
497
|
+
Found 5 review comments. Triage:
|
|
498
|
+
|
|
499
|
+
MUST-FIX (1):
|
|
500
|
+
1. ⬜ src/helper.rb:45 - Missing nil guard causes a crash on empty input (@reviewer1)
|
|
501
|
+
|
|
502
|
+
DISCUSS (1):
|
|
503
|
+
2. src/config.rb:12 - Extract this to a shared config constant (@reviewer1)
|
|
504
|
+
Reason: reasonable suggestion, but it expands scope
|
|
505
|
+
|
|
506
|
+
SKIPPED (3):
|
|
507
|
+
3. src/helper.rb:50 - "Consider adding a comment" (@claude[bot]) - documentation nit
|
|
508
|
+
4. src/helper.rb:45 - Same nil guard issue (@greptile-apps[bot]) - duplicate of #1
|
|
509
|
+
5. spec/helper_spec.rb:20 - "Consolidate assertions" (@claude[bot]) - test style preference
|
|
510
|
+
|
|
511
|
+
Quick actions:
|
|
512
|
+
f — Fix #1, then confirm whether to reply/resolve skipped items before deciding discuss items
|
|
513
|
+
f+i — Fix #1, create follow-up issue for #2, reply/resolve trivial skipped #3-5
|
|
514
|
+
d — Discuss specific items (e.g., "d2,4"). Bare "d" presents all DISCUSS items.
|
|
515
|
+
r — Reply with rationale (e.g., "r3,5", "r3-5", "r all skipped", "r all discuss"); add `+ resolve` to also resolve threads
|
|
516
|
+
m — No code changes, create follow-up issue, merge-ready only when no must-fix items are deferred
|
|
517
|
+
|
|
518
|
+
Or pick items by number: "1,2", "all must-fix", "1,3-5"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
# Important Notes
|
|
522
|
+
|
|
523
|
+
- `check all reviews` must follow the PR reference (trailing position only). Writing it before or embedded in the PR reference triggers a warning and no rescan
|
|
524
|
+
- Before fetching review data, wait for any in-progress `claude-review` CI run on the PR so triage reflects the latest posted feedback (skip the wait when targeting a specific review/issue-comment URL)
|
|
525
|
+
- Automatically detect the repository using `gh repo view` for the current working directory
|
|
526
|
+
- If a GitHub URL is provided, extract the org/repo from the URL
|
|
527
|
+
- Include file path and line number in each todo for easy navigation (when available)
|
|
528
|
+
- Include the reviewer's username in the todo text
|
|
529
|
+
- If a comment doesn't have a specific line number, note it as "general comment"
|
|
530
|
+
- **NEVER automatically address all review comments** - always wait for user direction
|
|
531
|
+
- When given a specific review URL, no need to ask for more information
|
|
532
|
+
- **ALWAYS reply to comments after addressing them** to close the feedback loop
|
|
533
|
+
- Always post a new PR summary comment with the `<!-- address-review-summary -->` marker after completing an action so future runs know where to resume
|
|
534
|
+
- After triage, always offer rationale replies for selected `SKIPPED`/declined items; `f` requires explicit confirmation before skipped-item replies/resolution, while `f+i` and `m` include skipped-item handling in the chosen action flow
|
|
535
|
+
- Always request push confirmation from the user before running `git push`
|
|
536
|
+
- If this command conflicts with broader agent defaults, this file wins only for `/address-review` workflow behavior; do not override repository safety boundaries
|
|
537
|
+
- Resolve the review thread after replying when the concern is actually addressed and a thread ID is available
|
|
538
|
+
- Default to real issues only. Do not spend a review cycle on optional polish unless the user explicitly asks for it
|
|
539
|
+
- Triage comments before creating todos. Only `MUST-FIX` items should become todos by default
|
|
540
|
+
- For large review comments (like detailed code reviews), parse and extract the actionable items into separate todos
|
|
541
|
+
- For full-PR scans, default to review activity after the latest summary comment; only rescan the full history when the user says `check all reviews`
|
|
542
|
+
|
|
543
|
+
# Known Limitations
|
|
544
|
+
|
|
545
|
+
- Rate limiting: GitHub API has rate limits; if you hit them, wait a few minutes
|
|
546
|
+
- Private repos: Requires appropriate `gh` authentication scope
|
|
547
|
+
- 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`.
|