Skip to content

A Merge run reports "review required" without trying a merge it knows will be refused #707

Closed

Description

@JacobStephens2

Problem

When the Base branch requires an approving review, a Merge run spends a whole Run before it finds out it can't merge. Then it takes a Repair round that can't help, and it ends with a generic failed.

Example: Educational-Travel-Adventures/tourbot#1438 (from issue 1437). CI passed on 79f6bfe, then gh pr merge was refused with "the base branch policy prohibits the merge". thirdshift went round the Repair loop once more: it merged an unchanged Base branch, pushed the same head and waited for CI that was already green. Then it reported:

Result:       failed
Cause:        the merge was refused with nothing left to fix, so the PR stays ready for review: ...

ADR-0004 already says this is a policy refusal and that "a repository that requires reviews can't be used with a Merge run". This issue keeps that decision and makes the outcome faster and clearer.

Idea

Before the Self-merge, read the pull request's reviewDecision. If it says a review still blocks the merge, skip the merge attempt and the no-op Repair round, and end the run as a named Review required outcome. It stays a policy refusal: exit 1, the PR left ready for review. This reads a structured field, not GitHub's error text, so it fits ADR-0004.

GitHub auto-merge (--auto) stays out of scope. ADR-0004 rejected it.

Triage: see the agent brief comment below.

Related

ADR-0004, #93, #26, #586

Activity

  1. changed the title [-]Report a review-required PR as awaiting review, not a Failed run, and optionally enable auto-merge[/-] [+]A Merge run reports "review required" without trying a merge it knows will be refused[/+] on Oct 16, 2026
  2. JacobStephens2 commented on Oct 16, 2026

    @JacobStephens2
    OwnerAuthor

    This was generated by AI during triage.

    Agent Brief

    Category: enhancement
    Summary: Before the Self-merge, a Merge run checks the pull request's reviewDecision. When a review blocks the merge, the run skips the merge attempt and the Repair round and ends as a named "review required" policy refusal.

    Current behavior:
    Once the pull request is open, ready, mergeable and green, a Merge run runs gh pr merge --merge --match-head-commit <sha>. If the Base branch requires an approving review that the PR lacks, GitHub refuses the merge. The run then goes back round the Repair loop: it merges the Base branch, pushes and waits for CI. That round finds nothing to fix, so the run ends as a policy refusal: exit 1, PR URL on stdout, GitHub's error on stderr, PR left ready for review, Claim kept. The summary says only failed with GitHub's raw error, so a user can't see at a glance that nothing is wrong except a missing review.

    Desired behavior:

    • Just before each Self-merge attempt (the first one and any after a Repair round), read the PR's reviewDecision (gh pr view --json reviewDecision). If it is REVIEW_REQUIRED or CHANGES_REQUESTED, do not call gh pr merge and do not take a Repair round for it. End the run at once as a policy refusal.
    • This refusal has its own wording on stderr and in the Run notification/summary. It names the reason, for example PR <url> needs an approving review before it can merge; it is ready for review, not just failed with GitHub's raw error.
    • Everything else about a policy refusal stays the same: exit 1, PR URL on stdout, PR left open and ready (not converted to draft, no failure commit pushed), Claim kept, cleanup as usual.
    • An empty or APPROVED reviewDecision (repositories with no review rule, or an approved PR) changes nothing: the Self-merge goes ahead as it does today, including the existing refusal handling for other policies.
    • If reading reviewDecision fails, it counts as "unknown" and the existing behavior applies. The read must never turn a run that could merge into a failure.
    • The Spec PR's Self-merge in a Spec run behaves the same way.

    Key interfaces:

    • The Self-merge step of the Delivery / Repair loop, where it decides between "merge", "repair" and "policy refusal": it gains a review-required branch, decided from the structured reviewDecision field, never by parsing GitHub's error text (ADR-0004).
    • The fake gh used in tests: it must be able to return a given reviewDecision from gh pr view --json.
    • The Run outcome / summary rendering and the Run notification: they gain a "review required" wording for this case.

    Acceptance criteria:

    • With the fake gh returning reviewDecision: REVIEW_REQUIRED on a green, mergeable PR, a Merge run never calls gh pr merge, takes no Repair round, exits 1, prints the PR URL on stdout and leaves the PR ready for review.
    • The same holds for CHANGES_REQUESTED.
    • stderr and the Run notification name the review requirement, not just a generic failure.
    • With reviewDecision empty or APPROVED, the Self-merge runs exactly as before (existing tests stay green).
    • If the reviewDecision read fails, the run falls back to today's behavior.
    • A Spec run's Spec PR Self-merge follows the same rules.
    • README's Merge run outcomes list and Failed runs section describe the review-required refusal. ADR-0004's Consequences gets a line saying the review requirement is now detected up front from reviewDecision.

    Out of scope:

    • GitHub auto-merge (gh pr merge --auto). ADR-0004 rejected it; this issue doesn't reopen that.
    • Merging with --admin to bypass the review.
    • Detecting the review requirement at launch, before any work, by reading branch protection or rulesets. This needs extra permissions and no PR exists yet; it could be a follow-up.
    • Requesting reviewers, or waiting/polling for a review to arrive.
    • Changing the exit code for policy refusals.
  3. added
    in-progressA Claim: thirdshift has taken this issue
    and removed
    ready-for-agentFully specified, ready for an AFK agent
    on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions