diff --git a/README.md b/README.md
index 53e1c92d4..af2c5bafb 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ capabilities, three outputs, one shared library, one build.
| **One app nests every map** — and each stays embeddable on its own | [capability 5](#capability-5--app-shell-the-research-gallery) · `bun run check:composite-reg` |
| **5 capabilities, every one shippable in every output** | `bun run verify:5-caps` |
| **Shared library, private plugins** — reuse without breaking each other | `bun run check:library-index` |
-| **One owner per plugin, a second reader for every change, one landing at a time** | [agent swarm](#build-it-with-an-agent-swarm) |
+| **One owner per plugin, a second reader for every change, one merge at a time** | [agent swarm](#build-it-with-an-agent-swarm) |
## For vibe coders: build, open the Studio, embed a map
@@ -695,50 +695,63 @@ your own page, set `"locale"` in its `profile-config`. Arabic reads right to lef
## Build it with an agent swarm
**Many AI agents can build many plugins at once without breaking each other's work.** Every plugin
-has one agent that owns it, and changes are added to `development`, the shared working version, one
-at a time. `main` is the production version: it moves only when you publish a release.
+has one agent that owns it, and the work moves through three kinds of branch:
+
+- **The pilot branch (`development`)** is the shared working version. A development server with hot
+ reload follows it, so each change that lands can be seen there within about 15 seconds.
+- **The landing branch (`main`)** is production. It moves only when you publish, and the production
+ server rebuilds from it.
+- **PR branches** hold one feature each. They start from the landing branch and land on the pilot
+ branch, one at a time, after the checks pass.
**Bring your own harness.** dx-maps works with whatever AI coding agent or agent harness you already
use. The repo gives you the branch strategy below, the checks (`bun run gates:pre`) and the Plugin
-Studio; it does not ship a harness. Roles such as a coordinator that puts the landings in order, or a
+Studio; it does not ship a harness. Roles such as a coordinator that puts the merges onto the pilot in order, or a
gate-keeper that reads each change before it lands, are jobs your harness gives to its agents.
-
+
[Open the diagram full size](documentation/readme-images/delegation-model.png): on a phone its small text needs it.
### Set up the branch strategy
-1. **`main` is production.** It moves only when you publish a release (step 7).
-2. **`development` is the shared working branch.** Create it once, from `main`:
+1. **The landing branch (`main`) is production.** It moves only when you publish (step 7).
+2. **The pilot branch (`development`) is the shared working branch.** Create it once, from `main`:
```bash
git fetch origin && git switch -c development origin/main && git push -u origin development
```
-3. **One branch and worktree per plugin agent**, from `origin/development`, then install once in each:
+3. **One PR branch and worktree per feature**, each started from the landing branch, then install
+ once in each:
```bash
- git worktree add -b regions/work ../dx-maps-regions origin/development
- git worktree add -b upg100/work ../dx-maps-upg100 origin/development
+ git worktree add -b regions/work ../dx-maps-regions origin/main
+ git worktree add -b upg100/work ../dx-maps-upg100 origin/main
cd ../dx-maps-regions && bun install --frozen-lockfile
```
-4. **One preview server per agent, each on its own port:**
+4. **One preview server per agent on your own machine, each on its own port** (in the cloud, the one
+ pilot server below takes this role):
```bash
bun x vite --port 5301 --strictPort # the next agent uses 5302, and so on
```
-5. **Land one at a time, through a lock.** Catch up with `development`, run the checks, and push only
- if nothing fails (`gates:pre` exits non-zero when a check fails, so the push never runs then):
+5. **Land on the pilot one at a time, through a lock.** Inside the lock, merge your PR branch into a
+ throwaway copy of the pilot branch, run the checks, and push that merge only if nothing fails
+ (`gates:pre` exits non-zero when a check fails, so the push never runs then). Your PR branch itself
+ stays one feature on the landing branch; only the pilot gets the merge:
```bash
flock /tmp/dx-maps-development.lock sh -c '
- git fetch origin && git rebase origin/development &&
- bun run gates:pre && git push origin HEAD:development'
+ git fetch origin && git switch --detach origin/development &&
+ git merge --no-edit regions/work &&
+ bun run gates:pre && git push origin HEAD:development
+ git switch regions/work'
```
- `flock` guards one machine. Agents on several machines need a shared lock, such as one your
+ If the merge stops on a conflict, run `git merge --abort`, fix the clash on your PR branch and land
+ again. `flock` guards one machine. Agents on several machines need a shared lock, such as one your
harness provides.
6. **One agent owns the full build**; the others build only their own plugin:
```bash
BUILD_ALLOW=1 bun run build # the build owner: every plugin
BUNDLE= bun x vite build && bun run tree && bun run fix:sri # everyone else: one plugin
```
-7. **Release:** fast-forward `main` to a `development` commit that passed the checks, tag it, and
+7. **Publish:** fast-forward the landing branch to a pilot commit that passed the checks, tag it, and
deploy from the tag:
```bash
git fetch origin && git switch main && git merge --ff-only origin/main
@@ -749,6 +762,20 @@ gate-keeper that reads each change before it lands, are jobs your harness gives
The tag's `public/dx-maps/` folder is the built site: deploy that
([how to deploy](./documentation/DEPLOY.md)).
+### Developing in the cloud with a swarm
+
+Keep the repository on a forge you host yourself: a swarm pushes often, and on a public host one wrong
+push publishes work you did not mean to share. Give each app two servers: a **pilot server** that
+follows the pilot branch with hot reload, and a **landing server** that rebuilds from the landing
+branch. The cloud container in `deployment/cloud/` runs both today (`BRANCH=development` for the pilot server,
+`PRODUCTION_BRANCH=main` for the landing server; `BRANCH` defaults to `main`). One pilot server per app, rather
+than one per pull request, keeps the memory the same however many pull requests are open. Each
+developer can still build on their own machine with the Plugin Studio and push their branch.
+
+Planned, not built yet: switching the pilot server to show one pull request at a time (with a table of
+the open pull requests under it), and rebuilding the landing branch from the accepted pull requests in
+order, so a rejected one is simply left out of the next rebuild.
+
How to contribute, and the bar for shared code: [documentation/CONTRIBUTING.md](./documentation/CONTRIBUTING.md).
Taking contributions from a contributor's own forge into your GitHub repository: [documentation/contribute/TUTORIAL.md](./documentation/contribute/TUTORIAL.md).
Diagram source: [`delegation-model.svg`](./documentation/readme-images/src/delegation-model.svg).
@@ -766,13 +793,13 @@ So the project works like a busy kitchen:
1. **Each agent works in its own branch and copy of the project** — its own counter, so nobody bumps
anybody. One owner per plugin, and one per shared file.
-2. **Only one change lands at a time.** Whoever holds the *landing lock* first catches up with
- everyone else's latest work, fixes any clash itself and runs every check; the change goes into
- `development` only if nothing fails. `development` always works.
-3. **Someone keeps order.** A coordinator can put the landings in order, and a gate-keeper can read
+2. **Only one change lands at a time.** Whoever holds the *pilot lock* first catches up with
+ everyone else's latest work, fixes any clash itself and runs every check; the change goes into the
+ pilot branch only if nothing fails. The pilot branch always works.
+3. **Someone keeps order.** A coordinator can put the merges onto the pilot in order, and a gate-keeper can read
each change by its content before it lands. Your harness gives these jobs to its agents.
-4. **`main` moves only when you publish a release**, after the checks pass on that exact version.
- A preview can follow `development`; the published site follows `main`.
+4. **The landing branch moves only when you publish**, after the checks pass on that exact version.
+ The pilot server follows the pilot branch; the production server rebuilds from the landing branch.
That's how many plugins get built at the same time, in one project, without the maps breaking.
@@ -784,12 +811,12 @@ That's how many plugins get built at the same time, in one project, without the
| Word | In plain terms |
|---|---|
| **repo** | the project folder, with its full history |
-| **development** | the shared working version: every agent's change is added here, one at a time |
-| **main** | the production version: it moves only when `development` is published |
+| **development** (the pilot) | the shared working version: every agent's change is added here, one at a time |
+| **main** (the landing) | the production version: it moves only when `development` is published |
| **worktree** | a private copy of the project for one agent to work in |
| **merge conflict** | two changes touched the same lines; someone has to decide how to combine them |
-| **rebase** | catching your work up with everyone else's latest before adding it |
-| **landing lock** | only one change lands on `development` at a time; its holder catches up and runs every check first |
+| **merge** | combining your branch with everyone else's latest work; here it happens inside the pilot lock, in a throwaway copy of the pilot |
+| **pilot lock** | only one change merges onto `development` at a time; its holder catches up and runs every check first |
| **tag** | a fixed name for one release commit, such as `v1.0.0`, so you can always deploy exactly it |
diff --git a/documentation/readme-images/delegation-model.png b/documentation/readme-images/delegation-model.png
index 3711c69b1..ad16d0da6 100644
Binary files a/documentation/readme-images/delegation-model.png and b/documentation/readme-images/delegation-model.png differ
diff --git a/documentation/readme-images/src/delegation-model.svg b/documentation/readme-images/src/delegation-model.svg
index 8e8e63e5e..a773495cc 100644
--- a/documentation/readme-images/src/delegation-model.svg
+++ b/documentation/readme-images/src/delegation-model.svg
@@ -10,7 +10,7 @@
-How dx-maps is built: one owner per plugin, one landing at a time
+How dx-maps is built: one owner per plugin, one merge at a time
@@ -29,8 +29,8 @@
-LANDING LOCK
-ONE LANDING AT A TIME
+PILOT LOCK
+ONE MERGE AT A TIME
@@ -38,9 +38,10 @@
-development
-every change
-lands here
+pilot
+development
+every change
+lands here
PLUGINS
AGENTS
@@ -121,14 +122,14 @@
coordinator
gate-keeper
-a coordinator puts the landings in order;
+a coordinator puts the merges in order;
a gate-keeper checks each one by its content
one owner per plugin, in its own branch · a second reader for every change
-development — shared branch
+pilot branch (development)
-landing lock — one at a time
+pilot lock — one at a time
Plugin Studio — the one repo
@@ -138,9 +139,9 @@
agent — owns one plugin
-coordinator — orders landings
+coordinator — orders merges
-gate-keeper — checks landings
+gate-keeper — checks each merge
How a change lands — one at a time, so many plugins can be built at once
@@ -163,21 +164,21 @@
3
One at a time
-in the lock: merge development,
+in the lock: merge the pilot,
rebuild, run every check;
push only if nothing fails
→
4
-Promote to main
-main is production: it moves
-only when the owner approves,
+Publish to landing
+landing (main), production:
+moves only when the owner approves,
after full checks on that version
-main → ONE build → one web folder → three outputs
-the dev preview follows development · the published site follows main
+landing (main) → ONE build → one web folder → three outputs
+the pilot server follows development · the production server rebuilds from main
OUTPUT 1
The web folder