Agent loop: auto-resolve merge failures instead of asking for manual merge #253

Closed
opened 2026-05-25 17:25:51 +00:00 by guettlibot · 0 comments
guettlibot commented 2026-05-25 17:25:51 +00:00 (Migrated from codeberg.org)

Context

When fgj pr merge exits 0 but the PR is still open, the loop currently posts
"Automatic merge of PR #NNN failed (PR is still open after the merge command). Please merge manually."
and sets State/Question (see agent_loop.py lines 678–686 and 744–758).

The comment in the code already explains the root cause: "fgj can exit 0 without merging (e.g. branch-protection rules not satisfied)".
The most common cause in practice is merge conflicts (the PR branch has diverged from main).

Plan

When _find_pr_for_branch(branch) still returns the PR after _merge_pr() succeeds without exception:

Step 1 — Query mergeability via API

Call _tea_get(f"repos/{REPO}/pulls/{pr_number}") and inspect the mergeable field.

Step 2a — Merge conflicts (mergeable == false)

Spawn a new agent (same pattern as the ci-fix agent) whose sole task is to rebase the PR branch onto main:

Rebase branch `issue-NNN-fix` onto main to resolve merge conflicts, then push.
Do not change any logic — only resolve conflicts and push.

Write state as pending-ci for the issue so the next loop iteration waits for CI
to pass on the rebased branch, then retries the merge normally.

Step 2b — No conflicts (mergeable == true or null)

The merge may have failed due to a transient API glitch or timing issue.
Retry _merge_pr(pr_number) up to 2 more times with a time.sleep(5) between attempts.
After each retry, re-check _find_pr_for_branch(branch).
If the PR is merged after any retry, proceed to _close_issue as normal.

Step 3 — Fallback

If after all retries the PR is still open, fall back to the existing behaviour:
set State/Question and post "Please merge manually.".

Tests to add

  • test_merge_fails_open_with_conflicts_spawns_rebase_agentmergeable=false → agent spawned, state written as pending-ci
  • test_merge_fails_open_no_conflicts_retries_and_succeedsmergeable=true, second attempt succeeds → issue closed
  • test_merge_fails_open_no_conflicts_all_retries_exhausted → falls through to State/Question
## Context When `fgj pr merge` exits 0 but the PR is still open, the loop currently posts \"Automatic merge of PR #NNN failed (PR is still open after the merge command). Please merge manually.\" and sets State/Question (see `agent_loop.py` lines 678–686 and 744–758). The comment in the code already explains the root cause: *\"fgj can exit 0 without merging (e.g. branch-protection rules not satisfied)\"*. The most common cause in practice is merge conflicts (the PR branch has diverged from main). ## Plan When `_find_pr_for_branch(branch)` still returns the PR after `_merge_pr()` succeeds without exception: ### Step 1 — Query mergeability via API Call `_tea_get(f"repos/{REPO}/pulls/{pr_number}")` and inspect the `mergeable` field. ### Step 2a — Merge conflicts (`mergeable == false`) Spawn a new agent (same pattern as the ci-fix agent) whose sole task is to rebase the PR branch onto main: ``` Rebase branch `issue-NNN-fix` onto main to resolve merge conflicts, then push. Do not change any logic — only resolve conflicts and push. ``` Write state as `pending-ci` for the issue so the next loop iteration waits for CI to pass on the rebased branch, then retries the merge normally. ### Step 2b — No conflicts (`mergeable == true` or `null`) The merge may have failed due to a transient API glitch or timing issue. Retry `_merge_pr(pr_number)` up to **2 more times** with a `time.sleep(5)` between attempts. After each retry, re-check `_find_pr_for_branch(branch)`. If the PR is merged after any retry, proceed to `_close_issue` as normal. ### Step 3 — Fallback If after all retries the PR is still open, fall back to the existing behaviour: set State/Question and post \"Please merge manually.\". ## Tests to add - `test_merge_fails_open_with_conflicts_spawns_rebase_agent` — `mergeable=false` → agent spawned, state written as pending-ci - `test_merge_fails_open_no_conflicts_retries_and_succeeds` — `mergeable=true`, second attempt succeeds → issue closed - `test_merge_fails_open_no_conflicts_all_retries_exhausted` → falls through to State/Question
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: guettli/sharedinbox#253