Skip to content

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2)#159

Merged
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-96-comment-fix
Jul 18, 2026
Merged

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2)#159
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-96-comment-fix

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

What this does

Part 2 of #96: gives the autonomous PR loop a fourth reaction to a
loop-authored, open PR — an unresolved, qualifying inline review-comment
thread now gets an automated fix attempt instead of sitting open forever
waiting on a human to notice.

  • pr-comment-fix.sh (new): detects open, bot-authored PRs with an
    UNRESOLVED review-comment thread (GraphQL reviewThreads, since REST has
    no "resolved" concept for these) that has at least one comment from the
    repo owner or an allowlisted bot commenter, excluding: PRs that are ALSO a
    pr-feedback.sh candidate (precedence); PRs labeled needs-human or
    claude-comment-fixing (in-flight guard, mirroring pr-ci-fix.sh's
    claude-ci-fixing); and threads whose fix was already posted for the
    thread's CURRENT state (a <!-- claude-comment-addressed:<thread_id>:<attempt> -->
    marker cursor, keyed to the thread id + attempt number, so a genuinely NEW
    comment reopening the same thread still re-triggers).
  • Anti-livelock: fix-attempt count is tracked PER THREAD, derived
    directly from the marker's own embedded attempt number (no new state
    file). A thread that reopens after 2 completed fix attempts is escalated
    to needs-human instead of retried again.
  • loop-census.sh: surfaces the count as comment_fix_prs=N, folded
    into the existing cadence=FAST trigger alongside feedback_prs/ci_fix_prs.
  • loop-tick.sh: wires pr-comment-fix.sh in as step 5/6 (between
    pr-feedback.sh and pr-ci-fix.sh), parses its TSV, and emits
    action=comment-fix pr=N at the documented precedence.
  • loop-event.sh: builds the COMMENT-FIX driver prompt — label
    claude-comment-fixing first (in-flight guard), fix on the same branch
    (no new branch), push, resolve ONLY the threads actually addressed, then
    post the claude-comment-addressed marker(s) with the real thread id(s)
    and attempt number(s). Never merges, never force-pushes.
  • loop-daemon.sh: gives comment-fix drivers their own transient
    systemd unit shape (pr-loop-driver-commentfix-pr<N>, distinct from both
    pr-loop-driver-pr<N> for feedback and pr-loop-driver-cifix-pr<N> for
    ci-fix) so drivers for the same PR number can never collide in naming or
    reattach.
  • pr-ci-fix.sh: now ALSO excludes comment-fix candidates from its own
    detection (mirroring its existing feedback exclusion), enforcing the
    ci-fix < comment-fix precedence twice (belt and suspenders).
  • gates.json / self/gates.json: new commentFix.botAllowlist config
    surface (empty array = disabled, same empty-means-skip convention as
    notify) — the repo owner's own review threads always qualify regardless
    of this list; fill it in to let a specific bot reviewer's threads
    auto-trigger comment-fix too.
  • .claude/commands/pr-loop.md / .claude/self/pr-loop-self.md: STEP 0
    tick contract updated to mention the new step and verdict.

Decision: verdict precedence

feedback > comment-fix > ci-fix > advance. Owner CHANGES_REQUESTED
always outranks everything else. An unresolved qualifying review-comment
thread outranks a CI fix (the reopened conversation is addressed before
chasing a possibly-unrelated CI failure) and a fresh advance dispatch. Merge
still requires a fresh owner approval regardless of any of this —
merge-ready.sh is untouched.

Bounded attempts

Comment-fix dispatches reuse the same per-issue attempt-budget counter
introduced in #95 (loop-issue-attempts.json) for the overall
dispatch-count ceiling — no new state file for that. The PER-THREAD retry
budget (2 attempts before escalating that specific thread) is a
separate, finer-grained bound, derived entirely from the marker comments
already posted to the PR (see pr-comment-fix.sh's header doc).

Out of scope

Part 3 of #96 (conflict-after-sibling-merge rebase) is not included
here — still open, tracked separately.

🤖 Generated with Claude Code

…ed PR review threads (issue #96, part 2)

Adds pr-comment-fix.sh (issue #96 capability #2): detects open, bot-authored
PRs with an unresolved, qualifying (owner or allowlisted-bot) review-comment
thread, excluding feedback candidates, needs-human/claude-comment-fixing
labeled PRs, and threads already addressed for their current state. Bounds
retries to 2 attempts per thread (derived from the claude-comment-addressed
marker itself, no new state file) before escalating to needs-human.

Wires the new comment-fix reaction into the loop at the documented
precedence (feedback > comment-fix > ci-fix > advance > resume): census
surfaces comment_fix_prs=N, loop-tick.sh adds it as step 5/6 and emits
action=comment-fix pr=N, loop-event.sh builds its driver prompt, and
loop-daemon.sh gives comment-fix drivers their own transient unit naming
(pr-loop-driver-commentfix-pr<N>). pr-ci-fix.sh now also excludes comment-fix
candidates from its own detection (mirroring its existing feedback
exclusion). Adds the commentFix.botAllowlist config surface to gates.json
(empty by default — only the owner's threads qualify).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t empty allowlist

TESTS reviewer rejection on PR #159 (issue #96 part 2): the anti-livelock
escalation scenario had no positive assertion that PR 17's budget-exhausted
thread actually triggers `gh pr edit 17 --add-label needs-human` -- "PR 17
not emitted" alone can't distinguish correct escalation from a silent drop.
Mirror pr-feedback.test.sh's gh-call-log convention: the fixture's fake
bot-gh.sh now appends every invocation to a log file, and the test greps it
directly (PR 17 labeled, PR 16 -- attempt 2, not yet exhausted -- is not).

Also add a fixture2 scenario with commentFix.botAllowlist: [] (the shipped
DEFAULT), previously never exercised since fixture1 hardcodes a non-empty
allowlist everywhere: a bot-only commenter does not qualify, while an owner
comment in the same run still does, proving the owner always qualifies
independent of the allowlist.

Test-only change; no production logic touched.
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

25 similar comments
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

9 similar comments
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

feat(loop): comment-fix — automated bounded fix attempts for unresolved PR review threads (issue #96, part 2) (not yet reviewed)

@robercano-ghbot
robercano-ghbot merged commit e361c09 into main Jul 18, 2026
9 checks passed
@robercano-ghbot
robercano-ghbot deleted the feat/issue-96-comment-fix branch July 18, 2026 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants