Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

PR Merge Queue

Omniscio's PR Merge Queue: an in-app view listing every open pull request across your configured repos, sorted into lanes by risk, with one-click sessions that prepare a merge in an isolated worktree. Covers the master flag, the toolbar and sidebar mounts, the lanes, background auto-refresh, Inbox nudges, archiving, batch merge and the current limits.

Scope: this page explains the queue's interface and merge-session behavior. Immutable revisions, local landing, leased publication, GitHub settlement, author conversations, rollout, and recovery are owned by the PR lifecycle front door.

What it is

Omniscio's PR Merge Queue is an in-app view that surfaces every open GitHub pull request across the repos you've configured, classifies each one into a lane that reflects how safe / risky / batchable it is, and lets you spawn an Omniscio Claude CLI session to prepare the merge on a single click. The session runs in a fresh, isolated worktree on the PR's branch with a composed merge prompt (bring the PR in → resolve conflicts intelligently → run tests), then hands the prepared result to the operator lifecycle. The session never pushes a remote base branch. Local landing, leased relay publication, and independent GitHub MERGED settlement happen under separate authority after preparation.

The view is manual by default — Omniscio does the triage and the orchestration locally (so you see why a PR is in each lane), and you click Merge on each card.

The queue keeps itself fresh in the background. Once the feature is enabled and you've configured at least one repo, a background poll re-fetches every repo's open PRs on a fixed interval (default 10 minutes) and saves the result. Opening the view is therefore instant — it shows the last saved data with an "Updated Nm ago" freshness label and live-updates while you watch as new background refreshes land. You never have to click Refresh to get current data, though the manual Refresh button is still there for an on-demand pull. See Background auto-refresh below.

The Inbox tells you when a PR needs you. When a repo has a PR that needs a human decision, or a merge that got stuck, the unified Inbox shows one self-clearing row per PR — an amber "PR #N needs review" or a red "PR #N merge stuck". Dismissing a row archives just that PR; clicking it renders that PR's repo queue right in the Inbox detail pane — you stay in the Inbox; the row disappears on its own once the next background refresh finds it no longer pending. See Inbox nudges below.

You can dismiss PRs you don't care about. Each PR card has an Archive action — and each Inbox PR row can be dismissed directly (middle-click on desktop / the dismiss action on mobile) — that hides the PR from the list like archiving an email, without closing the PR on GitHub. An archived PR drops out of the Inbox everywhere — both the "needs review" count and the "merge stuck" signal — so dismissing one quiets it completely, not just in the open view. A transient Show archived toggle brings them back (dimmed, below the active pills) so you can Unarchive any you change your mind about. See Archiving (dismissing) a PR below.

You can attach your own merge guidance. Two levels: per-repo standing instructions that ride along with every merge for that repo, and an opt-in per-merge (or per-batch) box for guidance specific to one merge. Both are advisory — they never override the hard merge-safety rules. See Custom merge instructions on the second page.

Related PRs can be prepared as a batch in one session. When triage groups several non-overlapping PRs into the Batch lane, a single Merge batch together button spawns ONE session that applies all of them in dependency order onto a local branch and runs the test suite once at the end — leaving that branch ready for you to merge. (It never touches your base branch or pushes.) See Batch merge below.

Opt-in: Auto-Merge Daemon. On top of the always-on background refresh, a separately flag-gated daemon can auto-spawn merge sessions for fast-lane PRs on repos with trustLevel: 'autonomous'. Other lanes (standard, batch, conflict-likely, risky, hold, escalate, reject) and lower trust levels (pause-and-ask, fast-lane-only) still wait for an explicit click. A dry-run mode lets you preview decisions without spending; a per-repo daily budget cap (default $5 USD) skips spawning once today's cost (UTC day) hits the cap. Two further opt-ins reshape what a tick spawns: a multi-machine split (sharding) so several installs partition the same repo's PRs without ever double-merging one, and auto-batch, which groups several non-overlapping fast PRs into ONE session instead of one per PR — both default OFF, see Settings shape. The master flag defaults OFF and switching it ON requires an explicit confirmation modal. (Auto-refresh and auto-merge are independent: the background poll runs whenever the feature is on, regardless of whether auto-merge is enabled.)

Where to find it

PR Merge Queue is switched on with one settings flag, and once it is on it appears in two places — a toolbar icon and a sidebar row — with a third, narrower mount inside the Inbox detail pane.

Master flag

PR Merge Queue is a registry-driven Omniscio integration gated on AppSettings.prMergeQueueEnabled (default false). Toggle it at Settings → Features → "PR Merge Queue" (search-discoverable via the search index id pr-merge-queue-enabled).

What the flag actually gates — four surfaces, each with its own check:

Surface Gate
Toolbar <GitPullRequest> icon visibleWhen: (s) => s.prMergeQueueEnabled === true (toolbar-catalog.ts)
Sidebar virtual project row hidden when the flag is off (project-visibility.ts)
CLI control-server routes getSettings().prMergeQueueEnabled === true (cli-server-pr-merge-queue-routes.ts)
Background poll / auto-merge daemon the tick returns early when the flag is off (auto-merge-daemon.ts)

With the flag ON: both UI surfaces appear, and the view renders an empty-state CTA when prMergeQueueRepos[] is empty so users always have a path forward.

What turning it off does. The toggle controls where the PR Merge Queue appears and whether it runs in the background. With it off, both UI surfaces are hidden and the background poll and auto-merge daemon return early without fetching or spawning anything — so nothing merges on its own. Starting a merge is desktop-only either way; see Starting a merge is desktop-only above.

Two surfaces

PR Merge Queue is a registry-driven virtual project — it appears in two places once the master flag is ON:

  • Toolbar icon — <GitPullRequest> button (pinned toolbar item id 'pr-merge-queue'). Click it to open the view as an overlay. The bundle lazy-loads on first open.
  • Sidebar virtual project — appears as a sidebar row alongside MemPalace, Bookmarks, etc. Clicking it activates the virtual project so the view occupies the main pane (no SessionsSidebar fallback — panelOwnsLayout: true in INTEGRATION_UI_REGISTRY).

Both surfaces mount the same PrMergeQueueView component — it accepts LayoutSlotProps (width, borderSide, isMobile) so the sidebar mount lays out edge-to-edge while the toolbar overlay keeps its compact framing.

A third mount renders PrMergeQueueView inside the Inbox detail pane — when a pr-merge-queue inbox row is selected it shows in-pane (not as a bounce-out to the virtual project). That mount passes lockedProjectId to pin the view to the one repo and hide the repo dropdown + close-X. See Inbox nudges below.

Mobile layout. The view renders one vertical list of PR pills on both desktop and mobile (full-width pills on a phone). There is no lane switcher — the single render path serves both form factors.

Starting a merge is desktop-only (security). On a phone you can browse the queue, refresh it, archive and unarchive PRs, and work the inbox rows exactly as on desktop — but the two buttons that SPAWN a merge session, Merge and Merge batch together, only work in the desktop app. Tapping them on a paired phone returns "Merging a pull request is only available in the desktop app."

Why: those two actions start a billed AI session whose job is to land code, and they pass your free-text Add instructions straight into that agent's prompt. Web Access authorises a device once, at pairing — it has no per-action confirmation — so a phone that was paired (or a leaked session on one) could otherwise start paid, code-landing agents with instructions of its own choosing. Everything read-only stays available on mobile; only the spend-and-land actions moved behind the desktop. Kick off the merge from the desktop app, then watch and steer the resulting session from your phone as usual.

How it behaves

The view is manual by default: Omniscio does the triage and the orchestration locally, and you click Merge on each card. This section walks the day-to-day path — opening the view, reading the lanes, starting a merge — and everything that happens around it.

How to use it

  1. Open the view. Either click the toolbar <GitPullRequest> icon, or click the PR Merge Queue row in the sidebar (both surfaces require the master flag ON in Settings → Features). The view lazy-loads its bundle on first open.
  2. Pick a repo. A dropdown at the top of the view lists every repo you've configured. The first time you open the view there will be none — you'll see an empty state telling you to add one in Settings → PR Merge Queue. Click Add a repo, pick an Omniscio project from the dropdown, and Omniscio will inspect the project folder's local git config (git remote get-url origin + git symbolic-ref refs/remotes/origin/HEAD) to pre-fill the GitHub slug, base branch, and display name. If the project isn't a GitHub remote (private GitLab, no remote set, etc.) the form stays blank and you can fill it in manually. The detection is local-git-only — no gh auth required at this stage (the gh requirement only kicks in for the actual queue refresh). The repo settings form also has a Standing merge instructions textarea — see Custom merge instructions on the second page.
  3. The lanes are already populated. Because the background poll keeps a saved snapshot per repo, switching to a repo shows its last fetched queue immediately, with an "Updated Nm ago" label next to the repo selector. You only click Refresh when you want an on-demand pull right now — it shells out to gh pr list --json ... and then gh pr view <n> per open PR, six at a time (progress streams as "Refreshing… (enriched/total)"; a 50-PR repo is usually a few seconds), re-runs triage + orchestration, and replaces the snapshot. If the most recent background refresh of a repo failed, the freshness label flags it so you know you're looking at last-good data.
  4. Read the lanes. Each PR card shows author, title, size, CI status, mergeability, and the reasons it was placed in its lane. In the redesigned view the eight engine lanes are shown as one vertical list of PR pills, each tagged with one of three plain statuses — Ready (fast / standard / batch), Needs your call (risky / conflict-likely / escalate / hold), or Blocked (reject). The detailed lane still drives triage internally; the status is the user-facing label. The lanes are:
    • fast — small, low-risk, CI green: easy auto-merge candidate
    • standard — typical PR: needs human review then merge
    • batch — multiple small PRs that can be merged together
    • conflict-likely — overlaps another open PR in the same files
    • risky — touches paths matching your riskyPaths globs (DB migrations, auth code, etc.)
    • hold — depends on another PR that isn't merged yet
    • escalate — needs a more senior reviewer (size, surface area, controversy signals)
    • reject — failing CI, draft, or otherwise not mergeable
  5. Click the Merge button on any card. A Blocked PR (draft, failing CI, or not mergeable) shows a quick confirm first ("Merge a blocked PR?"), then proceeds — the merge session still only prepares the worktree and never pushes or touches your base branch. Omniscio:
    • Creates the merge session WITHOUT building a worktree itself (createSessionWithPrompt({ isolationOverride: false, source: 'pr-merge-queue' })). Omniscio only names the worktree path + records it; the spawned agent builds it (the old in-process git worktree add was a ~17k-file checkout that timed out under load and failed merges to even start — 2026-06-02, contract the-agent-builds-its-own-worktree).
    • Sends the composed merge prompt — its RULE 1 tells the agent to create its own worktree at that path, set up node_modules, then bring the PR in per the rule carried in the prompt itself. Omniscio runs no git for the merge.
    • Spawns it in the background — it does NOT take over your current view. A success toast confirms the spawn and carries an Open action to jump to the merge session if you want; otherwise you stay exactly where you were. (Auto-focusing the freshly-spawned session was the 2026-06-01 "PR Merge Queue took over my whole session" bug — see contract a-spawned-merge-never-steals-the-active-session).
    • Optional per-merge guidance. Each card has an Add instructions link (a <MessageSquarePlus> toggle) that reveals a small textarea ("Optional: extra guidance for this merge"). Leave it collapsed and Merge stays one-click; type something and it rides along as advisory context in the merge prompt. See Custom merge instructions.
  6. Prepare a whole batch at once (Batch lane). When triage puts 2 or more PRs in the Batch lane, a Merge batch together (N) bar appears at the top of the PR list. Click it and Omniscio spawns ONE session that applies all the grouped PRs in dependency order onto a local branch in a single worktree and runs the tests once at the end — then stops with that branch ready for you to merge, instead of one session per PR. The same Add instructions toggle lets you attach per-batch guidance. See Batch merge.
  7. Watch the session prepare the merge. The prompt tells Claude to read the diff, bring the PR into the worktree (merging the PR's head when it is landing all of it, cherry-picking the author's commits when it is leaving anything out — never rebasing, which would rewrite the author's commits and cost them credit), build that merge with the bounded construction rather than a bare git merge --no-ff (npm run pr:merge-bounded, which runs the real merge and then puts every path outside the PR's own delta back to exactly what your base branch has, so a base that has moved on since the PR forked cannot drop or revert your newer work), run npm run audit:pr-merge-scope as a MANDATORY check after every landing it performs — the head merge, the resync, and the cherry-pick it uses when it is leaving something out (a refusal is reported to you as a blocked PR and never as a silent drop), resolve conflicts by understanding intent (never blind ours/theirs), run tests if a command is supplied, and then stop — leaving the worktree ready for you to merge. It explicitly does not touch the base branch (master), does not push anything, and does not perform the merge: you do that final step yourself, with the conflict/test work already done. If Claude can't get the worktree ready safely, it writes a one-line reason to ./AMC_MQ_GIVE_UP.txt in the worktree and exits. When it stops, its final message leads with a plain-language, bulleted "What this PR does" summary (plus a short "anything to watch out for" line) written for a non-technical reader, above the technical details — even on a give-up (it explains what it was trying to do and what blocked it). The default prompts bake this in; see Editing the merge prompt and contract the-default-prompts-demand-a-plain-language-report.

The merge procedure lives in the prompt itself. Earlier builds told every merge session to assemble the PR with a /merge-remote-prs skill. That skill was retired on 2026-09-06: it assembled by cherry-picking or squashing, which never publishes the pull request's own head commit, so GitHub could never mark the PR merged and its author never got credit. The shipped prompt (pr-merge-queue-prompt-templates.ts) now carries the rule inline, so nothing has to be installed for a session to prepare a PR correctly. The one doctrine is pr-merge-contract.md.

Background auto-refresh

The queue refreshes itself in the background so you don't have to click Refresh. A periodic queue-poll task re-fetches every configured repo's open PRs on a fixed interval and persists each repo's result as a snapshot. The view loads that saved snapshot the instant you open it (no GitHub round-trip on open), shows an "Updated Nm ago" freshness label next to the repo selector, and live-updates while open as later background polls land.

Behavior in prose:

  • When it runs. Whenever the feature is enabled (prMergeQueueEnabled) and at least one repo is configured. This is independent of auto-merge — turning auto-merge off does not stop the background refresh; the poll still keeps your snapshots fresh and your Inbox accurate.
  • How often. The interval is the prMergeQueueAutoMergePollMinutes setting (default 10 minutes, clamped 1–120). The same setting governs both the refresh cadence and the auto-merge daemon's tick — they share one timer. Changing it takes effect on the next Omniscio start (the running task keeps its boot-time interval).
  • What each tick does, per repo. Fetches the snapshot via the same refreshQueue path the manual Refresh uses, recomputes the two attention counts, writes the snapshot row, and — only when the attention summary actually changed vs. the last row — pushes an update to any open view / the Inbox. An idle repo whose counts didn't move doesn't wake the UI. If a repo's fetch fails, the prior snapshot is kept (so the view still shows last-good data) and the freshness label flags the failure.
  • A tick only re-reads the PRs that actually changed. Reading a PR's file list and CI status costs one GitHub call per PR, so a tick used to cost one call for the listing plus one for every open PR — measured at 182 calls on a repo with 181 open PRs, every 10 minutes. Each saved PR now records the commit it was built from, and a tick re-reads a PR only when that commit or its merge state has moved since last time. Those are the only two things that can make the saved detail wrong, and the cheap listing call already reports both, so everything else is reused as-is. A steady tick costs a handful of calls instead of hundreds — and because the snapshot is saved to disk, this holds across an Omniscio restart too. The result is unchanged: a PR whose commit moved, or whose checks finished, is always re-read.
  • Manual Refresh still works. The Refresh button does an immediate on-demand pull and replaces the snapshot; it does not disable or reset the background timer.
  • Kill switch. Power users can set the env var AMC_DISABLE_PR_QUEUE_POLL=1 to make the tick a no-op (no polling at all), reverting to the old behavior where only the auto-merge daemon fetched (and only when auto-merge was on). The view then shows whatever was last saved and you refresh manually.

Inbox nudges

When a repo needs your attention, the unified Inbox shows one row per PR that needs you — so you notice each one on the dashboard (and on mobile) without opening the queue, and can deal with them individually. Each row is one of two kinds:

  • A PR that needs a human decision — a PR triaged into the review-needed lanes (Escalate, Risky, Conflict-Likely, Hold) shows an amber "PR #N needs review" row. (A PR you've archived, or one that already has a running merge session, is excluded — see Archiving (dismissing) a PR and Starting a merge clears the nudge below.)
  • A merge that got stuck — a merge session that gave up (wrote its give-up file), or an auto-merge run that failed, shows a red "PR #N merge stuck" row.

A PR that is both stuck and review-needed collapses to a single row (the red stuck row wins). Stuck rows sort above review rows within the same repo.

Key behaviors:

  • One row per PR, with a stable id of pr-merge-queue-<projectId>-<prNumber>. (This replaced the old one-row-per-repo summary on 2026-06-02 so each PR can be dismissed on its own.)
  • Also shows in the repo's project view (not Inbox-only). Because the rows are tied to the repo's real Omniscio project, the same nudge surfaces in that project's "Needs You" sidebar section — on desktop and mobile — and bumps the project's amber attention badge, so you see it whether you're in the Inbox or sitting in the project. It behaves like the session rows beside it: Tab / J / K (and mobile tap) reach it in render order, and clicking or keyboard-activating it opens the repo's queue in place in the project's main panel (the same surface the Inbox rows open) — you stay in the project, and closing it returns you there rather than the global Inbox; it self-clears together with the Inbox rows. This is the general "project-scoped inbox attention also appears in its project" rule — see project-needs-you-attention-contract.md.
  • Dismiss a row to archive that PR. Dismissing a PR row (middle-click on desktop / the dismiss action on mobile) archives that one PR — the same per-repo Archive the queue view's card button performs, so it drops out of the lanes and quiets everywhere. There's no undo toast (matching Omniscio's other archive-style dismissals); recover it via the queue view's Show archived → Unarchive. See Archiving (dismissing) a PR.
  • Click to view in-pane. Clicking the row renders that PR's repo merge queue in the Inbox detail pane and keeps you in the Inbox — it does NOT bounce out to the full-screen PR Merge Queue view. (All of a repo's PR rows open the same repo-locked pane — the click focuses the repo, the dismiss targets the one PR.) The pane reuses PrMergeQueueView locked to the one repo (lockedProjectId), so the repo dropdown + close-X are hidden; the full view stays reachable from the toolbar icon / sidebar row. Selection lives in the activeInboxPrMergeQueueProjectId store slice (mutex-paired with the other inbox-detail slices, like drip / scheduled-message). See pr-merge-queue-contract.md (rules one-inbox-row-per-attention-needing-pr / a-row-opens-in-the-inbox-detail-pane).
  • Snooze is still per-repo. Snoozing any of a repo's PR rows routes through the universal inbox snooze gate and hides all of that repo's PR rows until the snooze expires.
  • Self-clears. The rows are derived purely from the saved snapshot (enriched on read into the actual review-needed / stuck PR numbers), not from an ephemeral "should fire" flag. The instant the next background refresh finds a PR no longer review-needed or stuck, its row disappears on its own. Removing a repo from settings drops all its rows immediately. Because the rows and the view read the same snapshot, what you see in the Inbox always matches the queue.
  • Starting a merge clears the nudge. The moment you click Merge (or Merge batch together) and a merge session is running for a PR, that PR is treated as handled and its "needs review" row drops out immediately — without waiting for the next refresh. It does not wait for the PR to actually merge on GitHub: the merge session only prepares the merge, so the PR still appears in the full queue view until it's merged/closed. If that merge session ends without finishing (you close it, it errors, or it gives up), the PR's row returns on the next background refresh — and a give-up shows up as the red "merge stuck" row in the meantime. (The exclusion uses the same session-aware "is a merge live for this PR?" check that stops a second merge being spawned for it — see A PR being handled is never re-spawned.)

Archiving (dismissing) a PR

Sometimes a PR is open but you don't want it cluttering the queue — a long-lived draft you're tracking elsewhere, someone else's WIP, a PR you've decided to leave for later. Archive dismisses it from the queue the way archiving an email clears it from your inbox, without closing the PR on GitHub. It's a personal, per-repo preference — purely local to Omniscio.

  • Archive a PR. Every active PR card has an Archive button — and every Inbox PR row can be dismissed (middle-click on desktop / the dismiss action on mobile), which archives that same PR. Either way the card disappears from the list immediately and your dismissal is saved per-repo in settings (AppSettings.prMergeQueueArchivedPrs), so the PR stays hidden across refreshes, repo switches, and app restarts — until you unarchive it.
  • Archive from the keyboard. You don't have to reach for the mouse. With the queue focused, the arrow keys move a highlight between PR cards (it lands on the first card automatically when the queue opens) and the archive key — the same shortcut that archives elsewhere in Omniscio, E or Ctrl+W by default, or whatever you've rebound it to — archives the highlighted card and jumps to the next one, so you can clear several PRs in a row without the mouse. Pressing it on an archived card (with Show archived on) unarchives it instead. The key is scoped to the queue while it's focused, so it never archives one of your sessions by mistake, and typing into a card's Add instructions box is left alone. Locked by the rule keyboard-archive-stays-in-the-panel in pr-merge-queue-contract.md.
  • It quiets the Inbox too — review and stuck. An archived PR is dropped from the Inbox the instant you archive it — both its "needs review" row and its "merge stuck" row — recomputed from the saved snapshot with no GitHub re-fetch, so dismissing a PR stops it nagging you everywhere, not just in the open view. (Before 2026-06-02 a stuck merge was deliberately left showing even after archiving; the archive-clears-both-inbox-counts reversal changed that so archiving means "I've handled this" and clears the PR completely — dismissing a stuck PR's row is exactly how you make that failure signal go away.)
  • Show archived / Unarchive. When a repo has any archived PRs, a Show archived (N) toggle appears in the header. Flip it on and the archived PRs reappear dimmed, appended below every active pill (not slotted back into position — the view is one flat list, so archived cards always render last), each with an Unarchive button that restores it to the queue (and brings it back into the review count). The toggle is a transient view preference — it resets to off when you close the view, like an email client's Archive folder, and is never persisted.
  • Everything else counts only active PRs. The Show archived (N) count, the Inbox attention counts, and the Merge batch together button all operate on the active (non-archived) cards only — archiving a batchable PR shrinks the set that button will merge. Archiving is orthogonal to triage: a hide-and-recount filter layered on top of the list, never a lane of its own, so a PR keeps whatever lane triage gave it.
  • If you archive every PR in a repo, the list is replaced by a one-line "All N PRs in this repo are archived" hint with a Show archived link — so you're never left staring at a blank queue.
  • Works on mobile. In the vertical-pill mobile view, the same Archive / Unarchive actions and the Show-archived toggle apply.

Stored as AppSettings.prMergeQueueArchivedPrs (a projectId → PR-number[] map). The per-repo count exclusions (both review and stuck) and the instant cache recompute live in src/main/services/pr-merge-queue/attention-summary.ts; both the queue view's Archive button and the Inbox row's dismiss write the whole next map through the same shared setPrArchived helper and the normal settings-save path, which fires the recompute. Because the list keys on PR number, a number that later closes is simply never matched again (harmless), and the per-repo 500-PR cap bounds the list. Locked by the rules archived-prs-are-a-filter-not-a-lane, archive-clears-both-inbox-counts, archiving-recomputes-from-cache-only, the-archive-write-sends-the-whole-map, the-inbox-lists-are-enriched-on-read and dismissing-a-row-archives-the-pr in pr-merge-queue-contract.md.

Batch merge

When triage groups several related, non-overlapping PRs into the Batch lane, you can merge the whole set with one click instead of spawning a session per PR.

  • Where. A Merge batch together (N) bar appears at the top of the PR list (the view is one flat list, not lane columns) — shown only when 2 or more PRs are batchable (a one-PR "batch" is just a normal merge).
  • What it does. Clicking it spawns ONE session in ONE worktree that applies all the grouped PRs in dependency order (cherry-picking each, verifying each landed cleanly with no dropped commits and no leftover conflict markers), runs the test suite once after the entire set lands, and lands the result on a clearly-named local branch in the worktree — then stops, ready for you to merge. It never touches your base branch and never pushes anything. The PRs were grouped precisely because their file sets don't overlap, which is what makes "test once" safe.
  • Why it's safer than N sessions. Independent diffs can't silently break each other, so a single green run after the whole set lands verifies all of them — and there's one integrate/test cost instead of N.
  • Per-batch guidance. The same Add instructions opt-in box lets you add guidance for the whole batch (combined with the repo's standing instructions, same as the single-PR path).
  • Stop conditions. On any unsafe state — an unexpected conflict, a failed verification check, two PRs introducing the same DB migration version, or a test failure it can't fix in 1–2 attempts — the session stops and writes a give-up reason rather than leaving a partial or unsafe set on the ready branch.

Limitations (current)

  • N+1 calls on Refresh. Each PR triggers a separate gh pr view. Repos with many open PRs are slow; progress is streamed via PR_MERGE_QUEUE_REFRESH_PROGRESS. (The background poll absorbs this cost off the critical path, so an open view rarely waits on it.)
  • Poll interval change requires restart. Changing prMergeQueueAutoMergePollMinutes (which governs both the background refresh cadence and the auto-merge tick) takes effect on the next Omniscio start — the running task keeps its boot-time interval.
  • Batch grouping is triage-driven, not hand-picked. The Merge batch together button merges exactly the PRs triage placed in the Batch lane; you can't currently hand-select an arbitrary subset to batch.

For agents

The rest of the PR Merge Queue — what it persists, the in-flight guard that stops a PR being merged twice, custom and per-repo merge instructions, editing the merge prompt, the triage and orchestration modules, the lane decision tree, the IPC channels, the auto-merge daemon and AI summaries — is in PR Merge Queue (part 2).

Related

  • silent-recipe-sessions.md — concept of source-tagged sessions; PR Merge Queue sessions tag source: 'pr-merge-queue' (manual), 'pr-merge-queue-batch' (batch), or 'pr-merge-queue-auto' (daemon).
  • integration-contracts.md — the virtual-project / sidebar-row / toolbar-icon registry contract this feature plugs into.
  • Postmortem: pr-merge-queue-postmortem.md — build history, design decisions, DO NOT RETRY rules.

Last verified 2026-10-02