feat(loop): reconcile in_review PRs to their real state (merged + closed)#13
Merged
Conversation
…sed) The merge poll only handled MERGED, so a feature whose PR was CLOSED without merging sat in_review forever (the same stuck-forever class the poll was meant to kill). The poll is now a full PR reconcile: worktree.pr_state returns MERGED/CLOSED/OPEN, and _reconcile_prs drives the terminal edges — MERGED → done (+reap, the existing idempotent edge), CLOSED-unmerged → Blocked for triage (+reap; the work was rejected, don't silently re-dispatch and fight whoever closed it), OPEN → leave in review. Renamed _poll_merges → _reconcile_prs and _maybe_poll_merges → _maybe_reconcile; config (merge_poll / merge_poll_interval_s) is unchanged. pr_is_merged → pr_state. First of the P2 reconciliation/observability ports; the active half of the closed edge (the merge webhook only fires on merge, never on a manual close). Tests: reconcile drives merged→done + closed→blocked + leaves open (one case each, reaps both terminal states); pr_state returns the state string / "" on gh failure; reconcile rate-limit + disabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow. |
There was a problem hiding this comment.
QA Audit — PR #13 | feat(loop): reconcile in_review PRs to their real state (merged + closed)
VERDICT: WARN
CI Status
- test: in_progress ⏳
Diff Review
- Renames
_poll_merges→_reconcile_prs,pr_is_merged→pr_state— clean rename, docs + config comments updated consistently across all 4 files. - New
CLOSEDbranch callsstore.flag_blocked(fid, reason)+ reaps — correctly prevents silent re-dispatch of rejected work. OPENbranch is a deliberate no-op (leave in_review) — correct.- Error handling widened to catch the whole per-feature block — safer than before (catches
record_merge/flag_blocked/reapfailures too). - Test
test_reconcile_drives_merged_to_done_and_closed_to_blockedcovers all three states; reaps verified for both terminal states.
Observations
- GAP:
worktree.pr_stateis called but not visible in this diff (diff truncated at 200/290 lines — remaining 90 may contain worktree.py changes). Cannot verify the function exists on this branch. - GAP:
store.flag_blocked(fid, reason)is called on the real store — cannot verify this method exists on the production store class (test mock defines it, but that doesn't prove the real store has it). - LOW: clawpatch structural review unavailable for this repo (not in project registry) — proceeding with diff-only review.
- LOW: CI still in_progress — formal PASS/FAIL deferred to re-dispatch once checks settle.
— Quinn, QA Engineer
|
Submitted COMMENTED review on #13. |
mabry1985
added a commit
that referenced
this pull request
Jun 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The first P2 reconciliation port. The merge poll only handled
MERGED, so a feature whose PR was closed without merging satin_reviewforever — the same stuck-forever class the poll was meant to kill (the merge webhook fires on merge, never on a manual close).The poll is now a full PR reconcile:
worktree.pr_state(pr_url)→MERGED/CLOSED/OPEN(""on aghfailure → next poll retries)._reconcile_prsdrives the terminal edges:MERGED→ done (+reap; the existing idempotent edge),CLOSED-unmerged → Blocked for triage (+reap; the work was rejected — don't silently re-dispatch and fight whoever closed it),OPEN→ leave in review.Renamed
_poll_merges→_reconcile_prsand_maybe_poll_merges→_maybe_reconcile;pr_is_merged→pr_state. Config is unchanged (merge_poll/merge_poll_interval_s).Tests
116 total, all green: reconcile drives
merged→done+closed→blocked+ leavesopen(reaps both terminal states);pr_statereturns the state /""onghfailure; reconcile rate-limit + disabled.ruffclean.Remaining ports
downstreamImpacttie-break🤖 Generated with Claude Code