Drive an open PR to mergeable without process gaps. claude-review
(/claude-review, claude[bot]) is the sole AI reviewer. Rebase before EVERY
push, no exceptions. The repo owner runs the final gh pr merge; AI agents
never do (bash-guard blocks it).
-
Rebase first, always. git fetch && git rebase origin/main before EVERY
push without exception. Resolve conflicts before continuing.
-
Push, then verify it landed. gh api repos/erikunha/portfolio/pulls/<N> --jq '.head.sha'
must equal git rev-parse HEAD. If not, re-push before continuing.
-
Do NOT re-request after a push — the push already triggers a review.
The pull_request trigger fires on every synchronize, and the concurrency
group is per-PR with cancel-in-progress: true, so a /claude-review comment
posted seconds after a push CANCELS the auto-run that was already reviewing
that SHA. Both runs leave a "Claude Code is working…" comment, the cancelled
one may already have posted findings against the pre-push SHA, and the cycle
count doubles. Observed on #229: two pull_request runs cancelled, three
issue_comment runs skipped, and a finding posted quoting a comment the push
had just deleted.
Re-request ONLY when no review will otherwise run:
- the PR edits
.github/workflows/claude-review.yml (the action refuses when
the workflow differs from the default branch, so the auto path cannot run)
- a completed run posted no parsable verdict
- the verdict on record is stale against a HEAD no run is currently reviewing
pnpm review:converge reports which of those applies; check it before
commenting rather than commenting by reflex.
-
Poll CI until green.
-
Check for new threads — claude[bot] inline comments via gh api graphql
reviewThreads(first:100) and gh api .../pulls/<N>/comments.
-
EVERY comment goes in a review THREAD. Never a timeline comment.
gh pr comment <N> posts an unanchored timeline comment (#issuecomment-…) —
it is attached to no code, cannot be resolved, and never appears in
reviewThreads, so it is invisible to the resolve-thread ground truth in
pr-merge-gate. Do not use it to report a finding, a fix, or a status.
- Finding already has a thread (claude[bot] inline comment): reply in that
thread —
gh api repos/erikunha/portfolio/pulls/<N>/comments/<comment_id>/replies -f body=…
(or GitHub MCP add_reply_to_pull_request_comment), then resolve.
- Finding has NO thread (e.g. one your own review battery raised): CREATE a
thread on the relevant file+line, do not fall back to a timeline comment —
gh api repos/erikunha/portfolio/pulls/<N>/comments -f body=… -f commit_id=<HEAD_sha> -f path=<file> -F line=<n>
Then reply/resolve it like any other. A self-raised finding that never became a
thread is an unrecorded finding: it is not in reviewThreads, so nothing gates
on it and the PR's conversation is an incomplete record of what was found.
- The ONLY acceptable timeline comment is the
/claude-review re-request trigger
itself (it is a command, not a comment).
-
Resolve each thread; never resolve silently (a thread with 1 comment is a
process failure):
- Real finding: fix, commit, stamp, push, verify SHA, reply citing the
fix SHA, resolve. The reply MUST come after push+verify so it cites the
actual remote SHA.
- Stale / already-fixed: reply citing the fix SHA and why it is stale,
then resolve — before the next push.
-
Wait for claude-review to complete the new review.
-
After any push, verify every thread has >= 2 comments. comments=1 is a
silent resolve; add the missing reply (GitHub MCP add_reply_to_pull_request_comment,
not gh api .../replies, which 404s on resolved threads).
-
Repeat 4-8 until CI is green AND 0 unresolved threads AND pnpm ready-to-merge
exits OK (it gates on a claude[bot] Approve verdict that is non-stale —
reviewed SHA == HEAD). Only then tell the repo owner to run gh pr merge.