Skip to content

feat(loop): reconcile in_review PRs to their real state (merged + closed)#13

Merged
mabry1985 merged 1 commit into
mainfrom
feat/pr-reconcile
Jun 13, 2026
Merged

feat(loop): reconcile in_review PRs to their real state (merged + closed)#13
mabry1985 merged 1 commit into
mainfrom
feat/pr-reconcile

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

What

The first P2 reconciliation port. 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 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 a gh failure → next poll retries).
  • _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; pr_is_mergedpr_state. Config is unchanged (merge_poll / merge_poll_interval_s).

Tests

116 total, all green: reconcile drives merged→done + closed→blocked + leaves open (reaps both terminal states); pr_state returns the state / "" on gh failure; reconcile rate-limit + disabled. ruff clean.

Remaining ports

  • P2: file-contention auto-deps at creation · capacity/forecast + cost surface · sitrep tool
  • P3: HITL escalation rung (host bus) · downstreamImpact tie-break

🤖 Generated with Claude Code

…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>
@protoquinn

protoquinn Bot commented Jun 13, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit a90c24b into main Jun 13, 2026
1 check passed
@mabry1985 mabry1985 deleted the feat/pr-reconcile branch June 13, 2026 06:37

@protoquinn protoquinn Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_mergedpr_state — clean rename, docs + config comments updated consistently across all 4 files.
  • New CLOSED branch calls store.flag_blocked(fid, reason) + reaps — correctly prevents silent re-dispatch of rejected work.
  • OPEN branch 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/reap failures too).
  • Test test_reconcile_drives_merged_to_done_and_closed_to_blocked covers all three states; reaps verified for both terminal states.

Observations

  • GAP: worktree.pr_state is 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

@protoquinn

protoquinn Bot commented Jun 13, 2026

Copy link
Copy Markdown

Submitted COMMENTED review on #13.

This was referenced Jun 13, 2026
mabry1985 added a commit that referenced this pull request Jun 13, 2026
Coding-orchestration hardening since v0.2.0 — resilience, parallel-correctness, and
PR reconciliation (#4#13). See the GitHub release notes for the full changelog.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant