> ## Documentation Index
> Fetch the complete documentation index at: https://panopticon-cli.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Auto-Merge

> Opt-in scheduled auto-merge for solo Overdeck workflows

# Auto-Merge

When the Flywheel orchestrator is trusted to ship work without a human clicking
MERGE, you can flip a single toggle and Overdeck will schedule eligible PRs
for merge with a short cooldown window. During the cooldown an audible
announcement fires, a cancellable banner appears in the dashboard, and the
merge runs through the exact same code path as the MERGE button when the
cooldown expires.

<Warning>
  **Solo Overdeck workflows only.** Auto-merge moves the merge-consent decision
  from per-PR click to a configuration toggle. That trade is appropriate when the
  operator is the only human in the loop. In a shared Overdeck instance it
  shifts consent away from the person who would normally click MERGE — not
  appropriate for team workflows.
</Warning>

## Enabling

Auto-merge is gated by one persisted toggle in the dashboard's
`app_settings` store:

```bash theme={null}
# turn auto-merge on
pan flywheel config --set flywheel.require_uat_before_merge=false

# turn it back off
pan flywheel config --set flywheel.require_uat_before_merge=true

# inspect current state
pan flywheel config --get
```

The same toggle is exposed in the dashboard's Flywheel header as a checkbox.
The default is `true` (auto-merge OFF — operator UAT required before merge).

When the toggle is `false`, the Flywheel orchestrator may schedule auto-merge
for any issue that satisfies the eligibility predicate.

## Per-project default

Every registered project's HOME tab includes a **Project settings** panel, even
when the project has no in-flight pipeline issues. Its auto-merge control offers
**⚡ Auto**, **🔒 Hold for UAT**, and **Global default**, and the collapsed row
shows the current auto-merge and swarming values at a glance. The project default
applies only to issues without an explicit per-issue auto-merge setting.

Changes are saved through `POST /api/projects/:key/auto-merge-default` and stored
in `~/.overdeck/projects.yaml`.

<Note>
  **Auto-merge vs. UAT batch trains.** This toggle controls *per-issue* scheduled
  auto-merge — Overdeck merging one eligible PR at a time without a human click.
  The separate `flywheel.merge_train_enabled` flag enables [UAT batch
  trains](/features/merge-batches), where ready features are assembled into one
  tested batch you promote together. They are independent flags: auto-merge ships
  individual PRs on a cooldown; batch trains assemble-and-promote a tested bundle.
  Leave `require_uat_before_merge` at its default (`true`, auto-merge OFF) when you
  want a human to UAT each batch before promoting it.
</Note>

## Eligibility

A PR is eligible for auto-merge only when **all** of these are true:

* `readyForMerge` is `true` (review, test, and ship roles all passed)
* The PR is open (not closed, not draft, not already merged)
* GitHub reports all CI checks as completed and passing
  (no `checksFailed` and no `checksPending`)
* GitHub reports the PR as `mergeable` (no merge conflicts, branch protection
  satisfied)
* None of the **blocker labels** are present on the issue:
  * `needs-design`
  * `needs-discussion`
  * `do-not-merge`

Eligibility is re-checked when the cooldown expires. A PR that became
ineligible during the cooldown (e.g. someone added a `do-not-merge` label
while the timer was running) gets surfaced as a blocked entry instead of
merged.

## Cooldown

Cooldown is fixed at **5 minutes** of wall-clock time from when the
orchestrator schedules the merge to when the executor fires. The countdown is
persisted in SQLite, so it survives dashboard restarts — if the dashboard
sleeps through the deadline, the executor still picks the entry up on the
next tick and re-validates eligibility before firing.

The cooldown is not configurable today; it's a deliberate single-knob value
that gives the operator a predictable cancel window.

## Cancelling

Three ways to cancel an in-flight auto-merge during its cooldown:

1. The dashboard's pending-auto-merges banner has a Cancel button.
2. `DELETE /api/flywheel/auto-merge/:id` against the dashboard.
3. The CLI:

   ```bash theme={null}
   pan merge cancel PAN-123
   ```

   This calls the DELETE endpoint, removes the entry from the pending list,
   and emits an `auto-merge cancelled for PAN-123` TTS announcement so the
   operator knows the abort took effect.

Cancellation only succeeds during the cooldown window, before the executor
has transitioned the row to `merging`. Once the executor has started running
the merge there is nothing to cancel — at that point it's the same code path
as clicking MERGE.

## Queue interaction

The dashboard runs at most one merge at a time per project. If two
auto-merges become due at the same instant, the second is requeued with a
short backoff (`scheduledMergeAt` bumped by 60 seconds, status reverted to
`pending`) so the next executor tick re-evaluates eligibility and tries
again. Stale `merging` rows are prevented by this requeue path; the executor
never leaves a row stuck mid-flight when `triggerMerge()` returns a
non-terminal status.

## Inspecting state

```bash theme={null}
# Pending entries currently in cooldown
curl http://localhost:3011/api/flywheel/auto-merge/pending

# Rows that failed or were blocked during the executor tick
curl http://localhost:3011/api/flywheel/auto-merge/problems
```

The dashboard's Flywheel page surfaces both lists with countdown and cancel
controls.

## Failure handling

When the executor fires and the merge fails (e.g. surface-level rebase
conflict raised at merge time), the row is moved to `failed` with the failure
reason captured, a TTS announcement plays, and the orchestrator surfaces the
entry as an `investigate` suggestion in its next tick snapshot. The operator
can then either fix the underlying problem and reschedule, or cancel the
failed entry to clear it.

## Related

* `pan flywheel config` — read/write the two flywheel autonomy toggles
* `pan merge cancel <id>` — cancel a pending auto-merge
* `roles/flywheel.md` — the orchestrator's contract; references the toggle
  when deciding whether to call the scheduler vs. emitting a `merge`
  suggestion for human action.
