Architecture
A merge queue makes every change wait for the ones in front of it. Gitstalk checks each change on the exact code it would land on, lands it at once, and validates the stable line behind it. This page shows the pieces, how a change moves through them, and what we measured.
live This is how the hosted service runs today.
The picture
Everything is a Cloudflare Worker. Workers call each other through service bindings, not HTTP. Three kinds of container do the work that needs a real Linux filesystem.
browsers agents (MCP) git clients
| | HTTPS | | SSH (not public yet)
v v | v
web app ----------- mcp server | ssh server
\ | | /
+------------------+--------------------+----+
v service-binding RPC / git smart HTTP
GATEWAY repositories, engines, git proxy, Actions
| | |
v v v
runner containers job containers storage
(check, merge, (Actions jobs, Artifacts (git) · D1 · Durable Objects
revert) one per job) R2 · Queues · KV · Workers AI
Browsers, agents and git clients all end up at one place, the gateway. It owns every repository and the engine that decides what lands.
The path of a bean
-
Pushed
An agent pushes
bean/<name>. The gateway checks the credential, refuses anything that is not a bean, and passes the pack to storage with a token the agent never sees.WorkersArtifacts -
Pre-land check
A runner merges the bean onto the sprout and runs the whole suite on that exact tree, in a container leased for this bean. A red goes back to its author.
ContainersDurable Objects -
Landed on the sprout
A green bean lands at once, and later beans build on it.
Durable ObjectsArtifacts -
Validated
CI validates the sprout's newest commit, a few landings behind.
Containers -
On the stalk
A green validation moves the stalk to that commit. It never moves to anything unvalidated.
ArtifactsQueuesD1
Where each thing runs
| Product | What it does for you |
|---|---|
| Workers | The website, the MCP server for agents, the SSH front, and the gateway. They sit close to every client. |
| Durable Objects | One engine per repository, so landing decisions are made by one writer, in order. Also Actions runs and live streams. |
| Containers | The runner that merges and tests your bean, and one fresh container per Actions job. |
| Artifacts | Your git data, with no servers to run. It has no server-side merge, so merges happen in the runner. |
| D1 | Accounts, the repository list, access, and the activity index behind lists and Home. |
| Queues | Engine events to the activity index. The index runs a few seconds behind (mostly under 5). |
| KV | OAuth grants and tokens for agent sign-in. |
| R2 | Actions logs, the dependency cache and uploaded pictures. |
| Workers AI | Small decision models (Clef, Jev) that pick a view or a route, and the model calls of automations. |
Security model
- The gateway is the only holder of storage tokens. It mints short-lived Artifacts tokens itself. Your own credential never goes upstream, and agents never hold storage tokens.
- Agents never merge to the stalk. No token, key or role can push to the sprout or the stalk. Only the engine moves them.
- Untrusted code runs in per-job containers. Each pre-land check and each Actions job gets its own container, and Actions workflows run for a bean pushed by an agent session, a deploy token or a non-maintainer get only the secrets marked as available to pre-land checks.
- Secrets are write-only and masked. They are encrypted at rest and masked in logs. See Secrets and variables.
One access rule decides git over HTTPS, MCP and the web: a person's role, capped by the credential's scopes. A repository you may not see answers 404 everywhere.
What we measured
Against GitHub's merge queue, on real changes
The same 38 merged pull requests from fastify's history, each with its own tests, pushed in parallel to a GitHub repository with GitHub's merge queue and Actions, and to a Gitstalk repository. CI capacity was matched: 20 pre-land checks at once and 2 validations at once. The pushes were replayed on a schedule fitted to real agent runs, without models.
| Workers | Per change, median (GitHub / Gitstalk) | Faster | All 38 landed (GitHub / Gitstalk) |
|---|---|---|---|
| 4 (one seed) | 2.9 / 0.7 min | 4x | 46 / 24 min |
| 8 (one seed) | 3.7 / 0.8 min | 4.6x | 30 / 14 min |
| 16 (three seeds) | 7 / 1 min | 6 to 9x | 28 to 33 / 10 to 12 min |
With 16 workers Gitstalk landed 2 to 3 times as many changes per 10 minutes. Every run in this table landed all 38 changes correctly on both forges.
With real agents organising the work
One Claude Code lead with Sonnet worker subagents got the whole backlog on each forge. At 4 workers the forges tied: the agents were the bottleneck. At 8 workers Gitstalk's last task went green at 22 to 26 minutes (two runs) against GitHub's 41 (one run), and the median change integrated in 1.0 to 1.2 minutes against 5.4.
The synthetic 30-agent arena
30 Claude Code agents (Sonnet) worked 40 tasks that collide on purpose, on three seeds, against a batched merge queue we built to behave like GitHub's. Gitstalk shipped 39 to 40 of 40 against the queue's 34 to 35, and reached its 30th green task 1.7 to 2.2 times sooner, with no red validation (the queue had 9 to 13) and about the same agent spend. In the 12-agent version of this race, metered Cloudflare infrastructure cost $0.35 to $0.42 per Gitstalk race.
Runs and write-ups: research/race/runs, research/race/loadgen/README.md, research/race/ORCHESTRATED.md.
Engine rules
For the curious. Each rule was added because a measured run needed it. The engine is one SQLite-backed Durable Object per repository, so every decision about a repository is made by one writer, in order. Open a rule to read why.
Check the exact tree, before landing
Landing first and fixing forward collapsed with real agents: repairs cost about 7 times a task, and with 12 Sonnet agents only 2 of 40 tasks ever went green before it collapsed. Checking the merged tree before landing, and handing a red back to its author, removed the red trunk. Releasing the author while its check runs keeps agents busy.
The sprout window
When agents were released during checks, landings came in bursts (19 in one minute) and validation fell 27 commits behind. Now at most W landings may run ahead of validation. W starts at 8, grows by 2 with each green validation, halves on a red one, and stays between 2 and 16. Together with the other changes in that version, it held landings to about 6 a minute and took that race from 24 to 34 green tasks.
Check reuse
A bean that lands on the very commit its pre-land check passed needs no second run of the same suite on the same tree. On staging this replaced 7 to 8 of about 22 validations per race.
Revert first, then reset the red window
A red validation is confirmed by the same test failing twice, so a flake never reverts a good bean. When one bean is the only suspect it is reverted at once. Otherwise the engine resets the sprout: one new commit takes the stalk's tree, and every bean in the window re-runs its pre-land check and lands again, suspects one at a time. With the reset the sprout was green again about 1.3 minutes after a red at 30 agents, where an unrevertable break had once held it red for about 20 minutes.
Informed repair, then reconcile, then decide
A red resumes the author's own session with the failing tests and the intent and diff of the bean it collided with. A repeated red goes to a reconcile step, and only a genuine contradiction becomes a decision card, with the bean parked. See Decision cards.
Structural merge, re-checked
When git's line merge conflicts on code files, the runner retries with a structural merge (Mergiraf, run as a separate binary) on just those paths. A structurally merged tree was never checked as such, so it is always re-checked before it lands.
Dependency-aware starts
With a task list, a free agent takes a task that clashes with nothing in flight, longest dependency chain first. This applies where Gitstalk schedules the work (races, backlogs); pushed beans are taken in arrival order.
On-demand pre-land capacity
Each bean in check gets its own container from a shared pool, up to 32 per repository. Waiting for a container never counts against the suite's time limit, and a timeout is never reported as a red.
The full contract is in docs/claude-opus/31-gateway-engine-internals.md, with every rule's measurements in docs/claude-opus/11-experiments-summary.md.