When most commits in a repository are written by agents, the merge step stops being a conversation and becomes a policy engine. There is no reviewer to impress and no queue of human approvals to wait behind. What you need instead is a pipeline that can answer, mechanically: what does this commit have to prove, did the exact tree that will land prove it, and who else is integrating right now.
The monorepo behind this site answers with three cooperating mechanisms: an affected-check planner that scopes the gate, a resource scheduler that keeps parallel agent sessions from oversubscribing the machine, and a durable local merge queue that serializes integration. All three run on the developer’s own machines; hosted CI is post-push evidence, not the gate.
the affected plan
bun run check:affected computes the smallest honest gate for the current work. It compares HEAD with the merge base against the local origin/main ref, then widens the comparison to include the index, the working tree, deletions, both sides of renames, and nonignored untracked files. From that change set it picks the deepest owning workspace, expands reverse dependents, and runs only the checks those selections require: generated checks, dependency analysis, types, lint, tests, production builds, and browser surfaces. A test-only edit does not select a production build.
The planner’s honesty is in its failure modes, each of which is deliberate:
--dry-runprints the exact plan without running anything, so an agent can inspect the gate it is about to trigger.- Missing history, graph changes, unknown ownership, or any other uncertain selection falls back to the complete gate. Uncertainty widens the check; it never narrows it.
- Unmerged paths fail immediately, because neither an affected nor a complete check can validate conflicted source.
- A clean local comparison succeeds without running a gate at all.
That last point is the quiet economics of the design: a tree with no changes proves itself in milliseconds, which keeps the tight edit loop ungated.
resource lanes
Several agent sessions share one machine, and a naive bun run build from three worktrees at once turns the host into a queue nobody designed. The scheduler in scripts/check-resource-scheduler.ts admits work through weighted, kernel-held permits coordinated through the repository’s Git common directory, so linked worktrees share one pool.
The scaling is small and explicit. Hosts with at least 12 logical CPUs expose four permits, at least six expose three, at least three expose two, and smaller hosts one. Work classes buy different weights: shared takes one permit, heavy takes two (build-capable Turbo graphs, production bundling, ordinary browser verification), and exclusive drains the pool for machine-global state like fixed-port browser checks, native tools, performance evidence, and provider mutation.
Two details keep the mechanism honest under agents. CPU is sampled before permit acquisition, so a pressured host does not leave a childless owner holding capacity. And a detached guardian retains each kernel lease until the entire workload process group exits; if an invoking agent dies while its workload is suspended, the guardian resumes it so it can finish and release. The documented rule is that runtime age alone never reaps a live workload.
the queue
bun run merge:queue -- submit --commit HEAD --label "task name" --wait hands a finished task to integration. The queue is durable local state, not a hosted service: every linked worktree shares .git/jungle-merge-queue-v1/queue.sqlite and the refs below refs/jungle/merge-queue/, and concurrent submitters coordinate through short SQLite transactions.
Submission is more flexible than the single-commit shape suggests. --commit repeats in replay order when one task owns several compatible commits, submitted together so the remote validates one final head. --full requests the complete gate for work that outgrows the affected plan. --front gives an item priority without preempting an integration already in progress, and the queue alternates priority and normal work so repeated priority submissions cannot starve older items. --verify-delivery with --verify-project <name> attaches an immutable post-merge production-verification scope; it rejects a missing or empty scope rather than inferring one from changed paths.
The processor pipeline:
- Records the task’s exact commit refs as an immutable queue item outside the worktree.
- Fetches
origin/mainand creates a queue-owned detached worktree. - Replays only the recorded commits onto that exact base.
- Installs the locked dependencies and runs the affected or requested complete gate on the replayed tree.
- Requires the worktree
HEADand index tree to match the candidate exactly, rejects index masking flags, and demands an emptyporcelain-v2status including submodules and nonignored untracked files. That exact commit/tree proof is recorded as a versioned, append-only receipt beside the durable candidate ref. - Fetches
origin/mainagain. A moved remote head invalidates the evidence and forces a fresh replay and gate. - Pushes the tested object with an ordinary non-force fast-forward, reads back remote ancestry, then records the item merged.
Exactly one processor runs at a time, serialized by a kernel-held lease that deliberately does not consume the check scheduler’s permits, so editing and focused checks continue while the head integrates. There is no permanent daemon: waiting submitters try the lease non-blockingly, one becomes the processor, and the rest poll their own durable items and retry election after the active processor releases. Processor health is classified from a durable heartbeat as active, unreleased, or released, which is how parallel agents tell progress from abandonment before attempting recovery. doctor, recover, retry, replace, promote, and cancel are the inspection and repair verbs; a queue item accepts exactly one replacement, and a validated candidate with an ambiguous push outcome stays blocked with its evidence rather than being pushed again.
The queue also protects its own lock ordering. A processor-owning command refuses to run inside an inherited check lease from the same repository, because a wrapped queue command would otherwise wait on capacity its own parent still holds. Small rules like that are what keep a roomful of agents from deadlocking each other on machinery nobody was watching.
the remote boundary
The provider side is configured to match the same posture. The repository’s main sits under a GitHub ruleset named Immutable main with no bypass actors: it blocks deletion, blocks non-fast-forward updates, and requires linear history. There is no pull-request requirement and no required status check; the queue supplies the exact-tree validation those mechanisms would approximate, and the ruleset supplies the destructiveness floor the queue does not need.
Post-push CI validates the delivered main SHA but cannot gate a fast-forward that already completed. A red main is repaired forward: preserve the failing run and SHA as evidence, fix in a task worktree, submit the fix through the same queue. Never reset, force-push, or merge-commit around it.
outcome names
The delivery vocabulary is closed, and each name means something measurable:
| Outcome | Meaning |
|---|---|
SOURCE ALL-CLEAR |
The tested source commit merged to main and post-push CI is green |
PROVIDER ALL-CLEAR |
The provider reports that exact SHA READY on Production and fresh alias lookups bind every registered alias to it |
PUBLIC ALL-CLEAR |
Direct TCP, hostname-valid TLS, and HTTP probes pass across the mandatory resolver matrix, plus a direct browser readback |
REPUTATION PENDING |
Provider ownership is clear but a system or threat-filtering vantage still rewrites or blocks the domain |
DNS INCONCLUSIVE |
A required resolver is unavailable or the matrix disagrees |
The names exist because agents report outcomes, and a report like “deployed, probably fine” is unactionable. submit --wait alone ends at source integration and must not be reported as public delivery.
The waiter itself is scoped the same way. submit --wait processes only through its exact target item and releases the processor lease the moment that item is terminal, leaving later items for another waiter or an explicit drain. A wait <item-id> on a merged item reruns only read-only delivery verification; it does not elect a processor for finished work, and a healthy processor heartbeat extends the wait through a legitimately long drain instead of timing out into a false failure.
The pattern generalizes cleanly: the merge queue is not where review happens. It is where evidence is produced. The commit that lands is the commit that was replayed, gated, and receipted, and any agent or human can verify that chain after the fact without trusting the submitter.
sources
- The monorepo behind this site (projects):
scripts/merge-queue.ts,scripts/check-affected.ts,scripts/check-resource-scheduler.ts, and the delivery runbooks indocs/monorepo.mdanddocs/main-delivery.md. - personal-monorepo-template: the public starting point for the same single-maintainer shape.