You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: make a resumed PR read its comments, not only its reviews (#631)
Reviews and conversation comments are two different feeds, and
`gh pr view --json reviews` returns only the first. Step 0's rehydration list
said "the diff itself, and any inline review comments" and never mentioned the
conversation, so a session that followed it exactly still missed the thing that
mattered most.
That is not hypothetical. On #620 the maintainer posted "this PR should shrink"
with a four-step plan: branch protection now rejects pushes to `main`
server-side, so the protected-ref enumeration should be DELETED rather than
extended. A later session read the reviews, did not read the comments, and
spent a full rework ADDING protected-ref patterns — the exact opposite of a
standing instruction sitting in the PR's own thread. Two further holes the
maintainer had found by hand (`git push origin refs/tags/v1.2.3`,
`git push origin HEAD`) were in that same comment and stayed open.
The asymmetry is structural, not incidental: a review must attach to a diff, so
direction — "do this differently", "this whole approach changed" — can only be
expressed in a comment. That makes the feed the skill ignored the one carrying
the highest-authority input.
So: `comments` joins `reviews` in the Step 0 query; the rehydration list names
the conversation explicitly and gives both commands; and a maintainer comment
is stated to outrank every bot review on the PR, including later ones. Step 11
re-checks comments each round rather than only at Step 0, because a direction
posted mid-loop is invisible to the verdict feed — the bot will keep approving
a diff the maintainer has already asked you to redo. The CI-mode table gets the
same note, where it matters more: Stage 3's re-trigger IS a comment, so the
reason is usually in the same thread.
Two Rationalizations rows and two Red Flags name the failure directly, since
"I read the reviews, so I know what this PR needs" is exactly how it reads from
the inside.
No CHANGELOG entry: agent tooling, no user-visible effect.
Claude-Session: https://claude.ai/code/session_012LExo6fcbup75vtc9NfoAR
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .claude/skills/implement-issue/SKILL.md
+58-2Lines changed: 58 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,7 +58,7 @@ runners — only repo-level `.claude/skills/` and `.claude/agents/` exist there.
58
58
59
59
| Step | CI mode |
60
60
|---|---|
61
-
| 0. Resume check | Applies, and matters more here: Stage 3 is re-triggered by hand, so a second `@claude-bot fix` on an issue that already has a `has-fix-pr` PR is a resume, not a restart. Detect the existing PR and continue it — never open a second PR for one issue. The CI checkout has no worktrees, so branch existence on `origin` is the only signal available. |
61
+
| 0. Resume check | Applies, and matters more here: Stage 3 is re-triggered by hand, so a second `@claude-bot fix` on an issue that already has a `has-fix-pr` PR is a resume, not a restart. Detect the existing PR and continue it — never open a second PR for one issue. The CI checkout has no worktrees, so branch existence on `origin` is the only signal available. Reading the PR's **conversation comments** matters more here too, not less: the re-trigger is itself a comment, so the maintainer has very often said *why* in the same thread. |
62
62
| 2. Diagnose | Stage 2 comment absent → STOP. Post "No deep analysis found. Run `@claude-bot analyze` first" and exit — never self-diagnose in CI; the analyze/fix split *is* the human gate. |
63
63
| 3. Confirm gate | The owner's `@claude-bot fix` comment is the go-ahead. Still perform the workaround check and scope assessment — put them in a `## Scope assessment` section of the PR body instead of chat. Escalation path (can't confidently pass the workaround check) still applies: dispatch a fresh general-purpose `Agent` to critique the design before implementing. |
64
64
| 4. Worktree | Skip — the CI checkout is already isolated. Create the branch directly (naming per Step 1). |
@@ -85,10 +85,14 @@ for `TODO.md` items and for refactors that never had an issue, so a PR with no
85
85
linked issue is the normal shape for that work, not a defect.
**A maintainer conversation comment OUTRANKS every bot review on the PR**,
146
+
including ones submitted after it. The bot reviews the diff; the maintainer
147
+
decides the direction, and they change direction in comments — that is the
148
+
only place they can, since a review has to attach to a diff.
149
+
150
+
This is not hypothetical. On #620 the maintainer posted "**this PR should
151
+
shrink**" with a four-step plan: branch protection now rejects pushes to `main`
152
+
server-side, so the protected-ref *enumeration* should be **deleted** rather
153
+
than extended. A later session read the reviews, did not read the comments,
154
+
and spent a full rework **adding** protected-ref patterns — the exact opposite
155
+
of the standing instruction, on a PR whose own thread already said so. Two
156
+
further holes the maintainer had found by hand (`git push origin
157
+
refs/tags/v1.2.3`, `git push origin HEAD`) were in that comment too, and stayed
158
+
open because nobody read it.
159
+
160
+
So: **before touching code on a resumed PR, read the human comments first, and
161
+
newest-first.** If one sets a direction the diff contradicts, that is a
162
+
STOP-and-confirm, not something to reconcile silently — the maintainer may have
163
+
changed their mind since, and asking costs one message where guessing costs a
164
+
rework.
165
+
132
166
**If those sources do not reconstruct a coherent diagnosis, STOP and report
133
167
it.** Do not re-diagnose from scratch on top of someone else's half-finished
134
168
branch: you would be building on a design you cannot see, and the commits
@@ -674,6 +708,20 @@ On the verdict:
674
708
silently ignore it either.
675
709
-**A review from the maintainer rather than the bot** (the `<author>` field):
676
710
treat it as authoritative and stop the loop — a human has taken over.
711
+
-**A maintainer CONVERSATION comment, which is not a review at all**, is
712
+
equally authoritative and arrives on a feed the verdict never touches. Check
713
+
it each round, not only at Step 0 — a direction posted mid-loop is invisible
714
+
to `gh pr view --json reviews`, and to the bot, which will keep reviewing the
715
+
diff as if nothing had been said:
716
+
717
+
```bash
718
+
gh pr view <n> --json comments \
719
+
--jq '.comments[] | select(.createdAt > "<submittedAt from the round before>") | "\(.author.login)\n\(.body)"'
720
+
```
721
+
722
+
If one lands, stop the loop and act on it before the next round. A bot
723
+
APPROVED on a diff the maintainer has already asked you to redo is worth
724
+
nothing.
677
725
678
726
Fix the blockers, park genuine nits in `TODO.md`, run
679
727
`./scripts/quality-check.sh`, commit, and push. Step 9's frontend rule carries
@@ -756,6 +804,8 @@ net is upstream, not this section.
756
804
| "the old branch is a mess, cleaner to redo it" | Its commits are the only copy of a diagnosis you no longer have. If you genuinely cannot reconstruct the approach, that is a STOP-and-report, not a licence to reset. |
757
805
| "that worktree's session shows dead, so it's mine to take" | Check unsandboxed. A sandboxed `claude agents --json` returned 1 session where the real answer was 17, because `~/.claude/jobs` is sandbox-denied — every other session read as dead. |
758
806
| "the review said CHANGES_REQUESTED but nobody assigned it to me" | Nothing else will pick it up. Once the opening session exits, an orphaned PR has no owner at all — `sweep-prs` refuses the job by design. Resuming is how it gets one. |
807
+
| "I read the reviews, so I know what this PR needs" | Reviews and conversation comments are separate feeds and `--json reviews` returns only one. The maintainer sets *direction* in comments, because a review can only attach to a diff. On #620 that cost a full rework in the opposite direction. |
808
+
| "the bot approved it, so the direction must be fine" | The bot reviews the diff against a checklist; it has no idea what the maintainer asked for in the thread. An approval on a diff you were told to redo is worth nothing. |
759
809
| "I can see the assertion is right, no need to run it red" | Assertions that look right have repeatedly bounded only one side, or compared a quantity a second varying term swamped. Seeing it fail is the cheap part. |
760
810
| "quality-check.sh passed, that's enough" | Green tests prove the suite is satisfied, not that the fix behaves correctly against the real scenario. Step 8 requires observed output, every time. |
761
811
| "the diagnosis is obviously right, skip the confirm gate" | Wrong diagnoses are exactly when confidence is highest. One message, cheap insurance. |
@@ -787,6 +837,12 @@ net is upstream, not this section.
787
837
- About to re-diagnose from scratch on top of someone else's half-finished
788
838
branch because the Stage 2 comment and PR body didn't reconstruct the
789
839
approach. That is a STOP-and-report.
840
+
-**About to change code on a resumed PR without having read its conversation
841
+
comments** — not just its reviews. They are separate feeds, and the
842
+
maintainer's direction lives in the one `--json reviews` does not return.
843
+
- About to implement a diff that contradicts a maintainer comment already on
844
+
the thread. Stop and confirm; they may have moved on, but guessing costs a
845
+
rework and asking costs one message.
790
846
- About to open a second PR for an issue that already has one.
791
847
- About to relaunch an issue that has already died twice without saying so.
792
848
- About to commit or open the PR without having actually run/observed the
0 commit comments