README + diagram: the agent swarm at scale, and where to publish

The swarm section now says what each branch is for: the landing branch ships and moves only when a
person approves a publish; the pilot branch is where reviewed PR branches come together; each plugin
or feature has its own PR branch. A new paragraph says how it scales (many people, each with several
agents, on many plugins: one PR branch each, seen on the pilot server once it joins). Step 5 names the
lock as a merge queue. Publishing to a public host happens only from the landing branch, when it is
ready, and a self-hosted git service is recommended because an agent can publish by accident.
The diagram gets the same: "a person approves" for the landing, "landing server", and a bottom band
for the scale and publishing rules. The PNG is re-rendered at 2x from the SVG source.
This commit is contained in:
Doxa Maps 2026-10-02 18:31:10 +00:00
parent e855e6f371
commit 7438c25230
3 changed files with 31 additions and 20 deletions

View file

@ -697,25 +697,29 @@ your own page, set `"locale"` in its `profile-config`. Arabic reads right to lef
**Many AI agents can build many plugins at once without breaking each other's work.** Every plugin
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.
- **The pilot branch (`development`)** is where reviewed PR branches come together. A pilot server
with hot reload follows it, so each change that joins can be seen there within about 15 seconds.
- **The landing branch (`main`)** is what ships. It moves only when a person approves a publish, and
the landing server rebuilds from it.
- **PR branches** hold one plugin or feature each. They start from the landing branch and join the
pilot branch, one at a time, after the checks pass and a second reader has read the change.
**It scales by adding PR branches, not by sharing one.** Many people, each with several agents, can
work on many plugins at the same time: every plugin or feature gets its own PR branch, and each one
can be seen on the pilot server as soon as it joins the pilot.
**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 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.
![The delegation model: the pilot branch (development) at the centre behind the pilot lock; publishing to the landing branch (main) and its outputs below it; inside the Plugin Studio; eight plugins around it, each owned by one agent; a coordinator and a gate-keeper over the agents; below, how a change lands in four steps, and the three outputs](documentation/readme-images/delegation-model.png)
![The delegation model: the pilot branch (development) at the centre behind the pilot lock; publishing to the landing branch (main) and its outputs below it; inside the Plugin Studio; eight plugins around it, each owned by one agent; a coordinator and a gate-keeper over the agents; below, how a change lands in four steps, the three outputs, and how it scales: one PR branch per plugin, a self-hosted git service, and publishing to a public host only from the landing branch](documentation/readme-images/delegation-model.png)
<sub>[Open the diagram full size](documentation/readme-images/delegation-model.png): on a phone its small text needs it.</sub>
### Set up the branch strategy
1. **The landing branch (`main`) is production.** It moves only when you publish (step 7).
1. **The landing branch (`main`) is what ships.** It moves only when a person approves a 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
@ -732,7 +736,7 @@ gate-keeper that reads each change before it lands, are jobs your harness gives
```bash
bun x vite --port 5301 --strictPort # the next agent uses 5302, and so on
```
5. **Land on the pilot one at a time, through a lock.** Inside the lock, merge your PR branch into a
5. **Join the pilot one at a time, through one lock (a merge queue).** 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:
@ -751,8 +755,8 @@ gate-keeper that reads each change before it lands, are jobs your harness gives
BUILD_ALLOW=1 bun run build # the build owner: every plugin
BUNDLE=<name> bun x vite build && bun run tree && bun run fix:sri # everyone else: one plugin
```
7. **Publish:** fast-forward the landing branch to a pilot commit that passed the checks, tag it, and
deploy from the tag:
7. **Publish, when a person approves it:** 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
git merge --ff-only <development-commit> # a commit that passed the checks
@ -760,12 +764,14 @@ gate-keeper that reads each change before it lands, are jobs your harness gives
git tag -a v1.0.0 -m "Release v1.0.0" && git push origin main v1.0.0
```
The tag's `public/dx-maps/` folder is the built site: deploy that
([how to deploy](./documentation/DEPLOY.md)).
([how to deploy](./documentation/DEPLOY.md)). Publish to a public host, such as GitHub, only from
the landing branch and only when it is ready.
### 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
Keep the repository on a git service you host yourself: a swarm pushes often, and an agent can
publish by accident. On a public host, one wrong push publishes work you did not mean to share, so
publish there only from the landing branch, when it is ready. 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
@ -798,7 +804,7 @@ So the project works like a busy kitchen:
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. **The landing branch moves only when you publish**, after the checks pass on that exact version.
4. **The landing branch moves only when a person approves a 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 767 KiB

After

Width:  |  Height:  |  Size: 926 KiB

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="2086" viewBox="0 0 1500 2086" font-family="Inter, 'Helvetica Neue', Arial, sans-serif">
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="2256" viewBox="0 0 1500 2256" font-family="Inter, 'Helvetica Neue', Arial, sans-serif">
<defs>
<marker id="aA" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#2563eb"/></marker>
<marker id="aS" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#7c3aed"/></marker>
@ -9,7 +9,7 @@
<path id="agL" d="M 194,850 A 556,556 0 0 1 1306,850"/>
<path id="mqL" d="M 679,884 A 71,71 0 0 0 821,884"/>
</defs>
<rect width="1500" height="2086" fill="#ffffff"/>
<rect width="1500" height="2256" fill="#ffffff"/>
<text x="750" y="54" text-anchor="middle" font-size="34" font-weight="800" fill="#0f172a">How dx-maps is built: one owner per plugin, one merge at a time</text>
<circle cx="750" cy="850" r="540" fill="none" stroke="#2563eb" stroke-width="1.6" stroke-dasharray="3 7" opacity=".75"/>
<circle cx="750" cy="850" r="355" fill="none" stroke="#15803d" stroke-width="2.2" opacity=".85"/>
@ -173,12 +173,12 @@
<text x="1149.0" y="1641" text-anchor="middle" font-size="19" font-weight="800" fill="#fff">4</text>
<text x="1177.0" y="1641" font-size="19" font-weight="800" fill="#0f172a">Publish to landing</text>
<text x="1135.0" y="1680" font-size="15" fill="#475569">landing (main), production:</text>
<text x="1135.0" y="1702" font-size="15" fill="#475569">moves only when the owner approves,</text>
<text x="1135.0" y="1702" font-size="15" fill="#475569">moves only when a person approves,</text>
<text x="1135.0" y="1724" font-size="15" fill="#475569">after full checks on that version</text>
<line x1="750" y1="956" x2="750" y2="1786" stroke="#334155" stroke-width="2.5" stroke-dasharray="2 5" opacity=".0"/>
<rect x="60" y="1812" width="1380" height="254" rx="20" fill="#f8fafc" stroke="#cbd5e1" stroke-width="2"/>
<text x="750" y="1856" text-anchor="middle" font-size="22" font-weight="800" fill="#0f172a">landing (main) → ONE build → one web folder → three outputs</text>
<text x="750" y="1882" text-anchor="middle" font-size="16" fill="#475569">the pilot server follows development · the production server rebuilds from main</text>
<text x="750" y="1882" text-anchor="middle" font-size="16" fill="#475569">the pilot server follows development · the landing server rebuilds from main</text>
<rect x="80.0" y="1908" width="420" height="130" rx="14" fill="#fff" stroke="#15803d" stroke-width="2.5"/>
<text x="290.0" y="1930" text-anchor="middle" font-size="13" font-weight="800" fill="#64748b">OUTPUT 1</text>
<text x="290.0" y="1962" text-anchor="middle" font-size="22" font-weight="800" fill="#0f172a">The web folder</text>
@ -197,4 +197,9 @@
<text x="1210.0" y="1988" text-anchor="middle" font-size="15" fill="#475569">the same folder, wrapped by Tauri</text>
<rect x="1110.0" y="2002" width="200" height="26" rx="13" fill="#15803d" opacity=".13"/>
<text x="1210.0" y="2020" text-anchor="middle" font-size="12" font-weight="800" fill="#15803d">WORKING</text>
</svg>
<rect x="60" y="2090" width="1380" height="146" rx="20" fill="#eff6ff" stroke="#93c5fd" stroke-width="2"/>
<text x="750" y="2132" text-anchor="middle" font-size="22" font-weight="800" fill="#0f172a">At scale: many people × many agents × many plugins</text>
<text x="750" y="2164" text-anchor="middle" font-size="16" fill="#475569">one PR branch per plugin or feature → joins the pilot through the lock → previewed on the pilot server</text>
<text x="750" y="2192" text-anchor="middle" font-size="16" fill="#475569">in the cloud: a self-hosted git service, because an agent can publish by accident</text>
<text x="750" y="2218" text-anchor="middle" font-size="16" fill="#475569">publish to a public host only from landing (main), when it is ready</text>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB