Skip to content

F: merge the task's published PR, not github.pullRequest #121

Closed

Description

@mchwang

Problem

Since #103 (PR #110), the runner publishes its own pull request for a task and records it in the Store (taskPullRequests, state opened, with number, base and marker). The guarded merge gate still targets only github.pullRequest from review.json:

  • web/server.ts builds new GhMergeGateway(config.github). pr view, the already-fixed check's ownPullRequests, queueWatermark, inspectQueue and pr merge all use config.pullRequest.
  • The configured PR's head is not the task head, so the head blocker always fires. The task's own PR (Fixes #issue) is "another open PR" to the already-fixed check, so already-fixed fires too. If the configured PR had the same head, the gate would merge the wrong PR.
  • A merge attempt does not record its PR, so a reconcile or queue poll after the target changes reads another PR.
  • The gate never reads isDraft, so it can show "ready" for a draft that GitHub will not merge.
  • GhMergeGateway requires pullRequest, so a review with a runner needs a placeholder number.

Decided (2026-10-03)

  1. Target. With a runner block, the gate targets the task's PR. That is the task's one opened record in the configured repository and github.baseBranch, and GitHub must show it as the only open PR from the task branch, into that base, with that record's marker on its first line, and not a draft. Anything else is a blocker. github.pullRequest is optional with a runner; if it is given and differs, the gate refuses. Without a runner, github.pullRequest is required and used as today.
  2. Pinning. Both validation passes (and the queue-mode third pass) must resolve the same PR. beginMergeAttempt re-reads the record in its transaction: still opened, same number, no opening or update in flight. The attempt stores its PR number. Reconcile, queueWatermark, inspectQueue and pr merge use the attempt's number. The status cache is keyed by PR number.
  3. Already-fixed check. ownPullRequests is the target plus every PR number the task records in the repository, as in the pre-PR check. A merged own PR still counts as a match.
  4. Docs. guarded-merge.md, merge-queue.md, pull-request-opening.md ("When the server publishes") and the README github block.

Acceptance

Regressions that fail before the change: a target change between validation passes; a publish or update starting during validation; a configured PR that disagrees; a draft target; a second open PR from the task branch; a queue poll after the target changes; an attempt saved without a PR number.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions