Merge
Register auto-merge once and Stamp merges the approved head when it is ready.
Auto-merge
Register auto-merge once (only the PR's author can), then get the head reviewed (see Review and approve). Stamp merges the current head once it is approved and ready; you do not poll.
stamp pr merge NUMBER --repo OWNER/REPO --auto --head HEAD_SHA --base BASE_SHAThe registration follows later pushes to the branch (nothing to re-run), but each new head needs its own approval before it merges; on a merge-queue base it is enqueued at the current head instead. --auto --status shows the head it waits on; it ends when the PR is merged or closed, on --auto --cancel, or after 14 days.
On a merge-queue base, registering does not enqueue by itself: the PR enters the queue when its auto-merge check finds it ready, and the queue is first in, first out by that entry time, not by registration time. PRs registered at about the same moment have no guaranteed order between them (a check that finds the auto-merge lease busy is retried a few seconds later). Read where a request stands with stamp pr queue status NUMBER --repo OWNER/REPO: autoRequeue: true on a stale request means the queue puts the same request back itself, position kept; do not re-enqueue. A landed request reports memberCommit (this PR's own commit on the base) and batchTip (where the base ended after the whole batch); landingSha is the batch tip, kept for older readers. GitHub shows a queue-landed PR as closed, not merged (Stamp publishes the batch commit itself), so is:merged and gh pr list --state merged miss it; it carries the stamp-merged label instead: gh pr list --state closed --label stamp-merged, or search is:closed label:stamp-merged (a plain --label lists only open PRs).
To find the queue candidate run that tested a PR (anyone's, not only yours: batches are repository state, while queue requests stay their requester's), run stamp pr checks NUMBER --repo OWNER/REPO: after the PR's own checks it prints merge queue runs:, one line per recent batch with the PR in it (outcome, batch id, stamp-mq/ branch, run id, reason), newest first, and under a failed one the command that prints its failed jobs: stamp run view RUN_ID --repo OWNER/REPO --log-failed. The same batches are queueRuns in pr view --json (omitted when there are none or the queue is not yours to read; pr checks --json stays the bare checks array). stamp run list --repo OWNER/REPO --branch stamp-mq/BATCH_ID lists a candidate branch's runs.
A base that is a registered merge-queue target is never merged directly, by auto-merge or by an agent, even while its queue is not enabled (saved but not yet enabled, or paused). The verdict then reads QUEUE_UNAVAILABLE, never READY. Auto-merge waits: --auto --status says waiting for the merge queue on BRANCH to be enabled (waitingOn: QUEUE_UNAVAILABLE), you are told once, and it is enqueued as soon as the queue is enabled or resumed. An agent's stamp pr merge there is refused with QUEUE_TARGET_NOT_ENABLED; a person can still merge by hand. The notice, the refusal and the status name why in queueNotEnabledReason, and the next step follows from it: verified_not_enabled (a repository admin runs stamp queue enable OWNER/REPO), not_verified (stamp queue verify OWNER/REPO --pr NUMBER, then enable), paused (a repository admin resumes it on the queue page; agents cannot, and stamp queue enable is refused with BATCH_QUEUE_PAUSED), pause_unconfirmed (stored before Stamp recorded pauses: a repository admin confirms on the queue page; an agent's enable is refused with BATCH_PAUSE_UNCONFIRMED), other_installation (set up under another installation; set it up again), and disabled, retired, not_configured, state_unreadable. stamp pr queue status says queueState PAUSED for an admin's pause (or an unconfirmed one), NOT_ENABLED for a queue saved and not enabled yet. Turning the queue on checks up to 25 of the repository's waiting registrations at once, oldest first. The rest wait for the fallback sweep: every 10 minutes it checks one page of 50 of up to autoMergeScan (20000) live registrations (all repositories, oldest first by registration write — a safety ceiling raised from 500, review of #1239 item 2: no cost per run beyond a bigger result set, since the store's filtering scan already covers every matching row regardless of this limit; GitHub reads and merges stay capped at 50 per run either way), so with N of them the worst-case wait until a registration is CHECKED (not merged: merging still needs its approvals and checks) is ceil(N / 50) x 10 minutes, strictly conditional on N <= autoMergeScan AND N holding steady between runs (ordinary churn): that bound is exact there, for any N. While N (within the ceiling) is itself climbing every run with nothing finishing, the bound is not exact — the rotation's page count is derived from the live count each run, so a registration can wait longer than ceil(N / 50) for as long as the climb continues, recovering once it stops. Above the ceiling there is no guarantee: registrations ranked past autoMergeScan are not swept until the pool shrinks below it. Event-driven checks (a registration's own deliveries) are unaffected by this limit. If Stamp cannot read whether the base is a queue target, auto-merge waits a pass (QUEUE_STATE_UNKNOWN) and a direct merge is refused with QUEUE_STATE_UNAVAILABLE (nothing was merged; retrying is safe). If the queue refuses the enqueue for a reason that will not change on its own (batch_workflow_changed, batch_workflow_invalid, batch_merge_conflict), the registration ends (QUEUE_REFUSED, with the reason in --auto --status) and you are told once with the next step: change the PR and register again, or merge it directly (stamp pr merge NUMBER --repo OWNER/REPO --head SHA --base SHA once that head is approved, by your self-approval with evidence (see Review and approve) or by another reviewer, or a person). Any other refusal is waited out.
The verdict on a PR
stamp pr view prints Stamp's verdict under the title, pinned to the head and base it was decided for, and names who approved that head. The first state that applies wins: MERGED, CLOSED, DRAFT, CONFLICT, CI_UNREADABLE, CI_FAILING, CI_NOT_EXECUTED (a required check never reported, or was skipped in a workflow run where a job failed or was cancelled), CI_PENDING, REVIEW_UNREADABLE, CHANGES_REQUESTED, STALE_REVIEW, NEEDS_REVIEW, QUEUE_READY (approved; it lands through Stamp's merge queue), BEHIND (also when the branch must be up to date and the base moved, while GitHub still says clean), BLOCKED (GitHub isn't allowing the merge yet; the verdict's blockedReasons name what it waits on when the evidence shows it: REVIEWS_REQUIRED "1 of 2", CODEOWNERS_REVIEW_REQUIRED, LAST_PUSH_APPROVAL_REQUIRED, CHANGES_REQUESTED, SIGNED_COMMITS_REQUIRED (under the current merge method), LINEAR_HISTORY_REQUIRED, CONVERSATION_RESOLUTION_REQUIRED, REQUIRED_CHECK_MISSING, DEPLOYMENT_REQUIRED, BRANCH_BEHIND; empty when GitHub does not say), OPTIONAL_CHECK_FAILING (approved and every required check passed, but GitHub says "unstable" because checks outside the required set did not pass; the verdict's optionalFailing names them. It does not clear on its own: auto-merge waits for a clean state and tells the author once, so fix or re-run those checks, or merge by hand with stamp pr merge), UNCONFIRMED (GitHub does not confirm a clean merge yet, including a "blocked" in the two minutes after the last check completed, while GitHub recomputes, and a merge state GitHub has not computed yet; Stamp asks GitHub again and re-checks shortly), QUEUE_UNAVAILABLE (it would be READY, but its base is a registered merge-queue target whose queue is not enabled: it waits for the queue; a person can still merge by hand), READY.
A required check the repository's workflow reported as skipped counts as satisfied, as it does on GitHub, unless a job in the same workflow run failed or was cancelled (then the skip may be a broken needs:, not a rule). READY also needs GitHub's own mergeable state to be clean.
A failure in any run on the head counts toward CI_FAILING, including manually dispatched (workflow_dispatch) runs, even when GitHub says clean; re-running the failed jobs clears it, because only the newest attempt of each run counts.
Merge queue (agents)
An agent can set up, verify and enable Stamp's merge queue for a branch, with the same discovery, confirmation and verification as the settings page:
stamp queue setup OWNER/REPO --branch BRANCH [--workflow ID]
stamp queue save OWNER/REPO --branch BRANCH --workflow ID --ci-policy head|all --max-batch N --wait SECONDS --timeout SECONDS [--protect GLOB... | --protect-none] --confirm
stamp queue verify OWNER/REPO --pr NUMBER
stamp queue enable OWNER/REPO
stamp queue status OWNER/REPOsetup lists the workflows, the jobs it detected, the branch-required checks and the digest it would confirm. --workflow names the primary (Test) workflow only: branch-required checks it lacks are found in other workflows run on the same head (listed as additional workflow:), sampled from a recent green run whose pull request is still open, and every candidate must pass them too. save reads that discovery again and shows what it confirms. --protect GLOB (repeatable) replaces the queue's protected path list and --protect-none clears it; a save with neither keeps the stored list. verify runs the saved CI on an approved pull request without merging it; enable only succeeds once that verification passed. verify accepts a GitHub approval or a Stamp approval from anyone but the author at the pull request's current head.
status (--json: the same object) names the active batch and two facts, each null when it does not apply. baseWait: the active batch failed on a red target branch and waits for the branch's own CI to recover (batchId, base commit, workflowId, runId, runUrl of the red run, since, waitingSeconds, nextCheck); nothing to re-enqueue, the target branch's CI must pass. stalled: the queue should move and does not (reasonbatch_overdue | base_wait_long | waiting_no_batch, since, batchId, ageSeconds); the requesters of the affected requests get one merge_queue_stalled notice per stall. Do not re-enqueue; ask the repository maintainer or the Stamp operator.
Changing the CI through the queue. A pull request that changes what judges the queue (a configured workflow such as .github/workflows/test.yml, anything under .github/actions, or a local action or reusable workflow a configured workflow uses) is not refused: it is tested alone, in a batch of its own, and judged by the workflow as its own merged tree defines it (it carries a non-author approval at its exact head, so the CI change was reviewed). Its receipt (stamp pr queue status), its notification, the draft candidate and the queue page say "tested alone because it changes the CI definition (PATH)". When it lands, the queue re-pins its workflow to the new definition by itself; the same happens when the workflow changes on the target branch outside the queue (the queue's audit records workflow_repinned:PATH:OLD->NEW). Only when a configured workflow file is gone, or no longer runs on pull requests or names the required checks, do requests fail with batch_workflow_invalid naming the file: a repository admin then runs stamp queue setup, save and verify again. A candidate that would leave the workflow in that state is refused the same way. Protected paths (--protect) are treated the same: a pull request changing one is tested alone, and the receipt names the file. Only a verification refuses either (batch_workflow_changed naming the file): verify with a pull request that changes neither.
Merging around the queue. A registered target lands only through its queue: while the queue is not enabled (after save until it is enabled, or while paused) an agent's direct merge is refused with QUEUE_TARGET_NOT_ENABLED and auto-merge waits (QUEUE_UNAVAILABLE) instead of merging; a person can still merge. An auto-merge registration whose enqueue the queue refuses for good (batch_workflow_changed, batch_workflow_invalid, batch_merge_conflict) ends (QUEUE_REFUSED) and its registrant is told once, so a later change of the queue's state never merges it silently.
The boundary: only a registered queue target (a repository and branch the Stamp operators registered in a reviewed deployment change) of a repository your server's GitHub App covers, and only Stamp's own queue mode. Anything else is refused with QUEUE_TARGET_NOT_REGISTERED, REPOSITORY_NOT_COVERED or QUEUE_MODE_AGENT_UNSUPPORTED; status lists the registered targets.