Three Agents, Zero Collisions
Project11 min · Scope → Isolate → Supervise → Land · Updated 2026-09-15
You end this lesson with: fleet/collision-report.md — evidence three concurrent agents did not collide, plus the failure you caused on purpose.
Chapters
- Brief01
- The Rule This Lab Tests02
- Steps03
- Acceptance04
- Rubric05
- Key Takeaways06
Project 02. Three Agents, Zero Collisions
Illustrative composite. A three-person team once ran three agents against one shared dev database, because writing a separate
.envfile for a twenty-minute task felt like busywork. Two of the agents defaulted to the same$DB_PATH. By the time the third agent's pull request came up for review, four seeded rows had quietly become three — one agent's write had overwritten another's mid-run, and neither process had thrown an error. The bug took longer to find in review than either task had taken to build, because nothing about the failure looked like a collision; it looked like a bug in the code.
Lesson four gave you a launcher that assigns a port range and a private database per agent. Lessons five through seven added a containment tier, a permission policy tied to it, and a credential and egress policy the agents run under. This project asks you to actually run three agents at once, against one repository, and produce evidence — not a claim — that those controls held. Then it asks you to break one control on purpose, on the same repository, and write down exactly what happened, because the fastest way to learn what an isolation control actually stops is to watch it fail. You hand over both halves in one file.
Your deliverable is fleet/collision-report.md — evidence that three concurrent agents did not collide, plus the failure you caused on purpose. It serves the Isolate stage: the boundary work from module two only counts once you have watched it hold, and watched it fail, under real concurrency.
Brief
Run the three tasks below concurrently, in three worktrees, under fleet/isolate.sh from lesson four. Use your own repository if it fits the shape — a dev server bound to one port, a local database file — or use the sample layout.
Sample repository: orbit-tasks
orbit-tasks/
src/
server.ts # dev server, binds to $PORT (default 4000)
db.ts # opens the sqlite file at $DB_PATH (default ./data/orbit.db)
routes/ # auto-loaded by filename, one route per file
tasks.ts
jobs/ # auto-loaded by filename, one job per file
components/
data/
orbit.db # sqlite dev database, gitignored
.env.example
server.ts reads $PORT and $DB_PATH at startup and nothing else. Every route and job file registers itself by living in its own directory, so adding one never requires editing a file another task also touches.
The three task specs
Task 1, "the search route." Goal: add GET /tasks/search?q= returning every task whose title contains q, case-insensitive. Files it may touch: src/routes/search.ts only, a new file. Interfaces it must not invent: no new query language, call the existing db.query() helper. Done test: a request against the agent's own assigned port returns the matching rows as JSON. Ceiling: 20 minutes.
Task 2, "the archive job." Goal: add a job that sets archived = 1 on every task older than 30 days with status = "done". Files it may touch: src/jobs/archive.ts only, a new file. Interfaces it must not invent: no new scheduler, the job runs once when invoked directly. Done test: running the job against the seed data flips the expected rows and no others. Ceiling: 20 minutes.
Task 3, "the tag filter." Goal: add a dropdown component that filters the rendered task list by tag, client-side only. Files it may touch: src/components/TagFilter.tsx only, a new file. Interfaces it must not invent: no new state library, read from the list already in scope. Done test: selecting a tag in the running dev server narrows the visible rows. Ceiling: 20 minutes.
The three tasks are disjoint by construction: no shared file, no undefined interface between them, so lesson two's test marks all three parallel before isolation even enters the picture. That is what makes this project about the boundary the worktree does not give you for free, not about task scheduling.
The left half is what you prove first. The right half is what you build on purpose in step three, so the report holds evidence of both shapes, not just the one that worked.
The acceptance checks (given in full)
- Distinct ports: each agent's dev server is bound to its own assigned port, confirmed by a request to that exact port, not to a port you remembered starting.
- No shared database writes: each agent's
$DB_PATHpoints at its own copy ofdata/orbit.db; no write from one agent's run appears in another agent's database file. - Three branches: three worktrees, three branches, one commit per agent, no agent committing to another's branch.
- No cross-tree file edits:
git diff --statfor each agent's branch touches only the one file its task spec names.
The Rule This Lab Tests
Use a bare git worktree add when the only thing separating your agents is which branch is checked out — between agents you already trust with your host's ports, its dependencies, its credentials. Isolate every other shared resource yourself: port, database, credentials — or accept that two agents will eventually collide on one of them. This project is where that rule gets tested against a stopwatch instead of a claim: the three task specs above are already disjoint by file, so the worktree's own guarantee, a private branch, comes for free. Everything else in fleet/collision-report.md is what you had to allocate yourself, and the failure you cause on purpose in step three is what happens the moment you stop.
| Resource | Does a worktree isolate it for free? | What this project asks you to prove |
|---|---|---|
| Branch and working directory | Yes | Nothing — the three branches in step 1 cost nothing extra |
| Network port | No | A distinct port per agent, confirmed by a real request |
| Database file | No | A distinct $DB_PATH per agent, confirmed by a real query |
Steps
Step 1 is worked — a filled launcher example is given below. Step 3 is faded: you pick which control to break and check your reasoning before you run the drill. Steps 4 and 5 are open — what you find and how you restore it depend entirely on the control you chose.
-
Launch three agents under
fleet/isolate.sh, one per task spec — worked. A filled example for one agent:fleet/isolate.sh agent-1 mainprints its assigned port and database path, something likeport: 4001 db: data/orbit-agent-1.db; run the same command foragent-2andagent-3before any agent starts working. Confirm the launcher assigned each a distinct port and a distinct copy ofdata/orbit.db. Output: three launcher-assigned rows referenced fromfleet/collision-report.md. -
Run all three tasks to completion. Collect the evidence the acceptance checks ask for: a request against each port, a query against each database copy,
git diff --statfor each branch. Output: the evidence section offleet/collision-report.md, one subsection per check. -
Remove one isolation control on purpose — faded. Pick one: point all three agents'
$DB_PATHat the same file, point all three at the same$PORT, or drop the per-agent worktree and run all three from one checkout. Decide which one is likeliest to fail quietly instead of loudly before you check your reasoning below, then re-run one task, or a fresh fourth task shaped like the other three, under the weakened setup. Output: the exact control you changed, named precisely, infleet/collision-report.md. -
Document exactly what broke — open. The symptom you saw — an overwritten row, a refused port bind, a file neither task's spec named — which of lesson four through seven's controls would have stopped it, and how you would notice it in a real fleet before it reached review. Output: the failure section of
fleet/collision-report.md. -
Restore the control and confirm the fleet is clean again — open. Re-run the same task under the restored isolation and show the check passing. Output: the closing line of
fleet/collision-report.md.
Acceptance
- Three worktrees launched from
fleet/isolate.sh, each with a distinct port and a distinct database copy, confirmed before any agent starts working. - Evidence exists for all four checks from the Brief: distinct ports, no shared database writes, three branches, no cross-tree file edits.
- Exactly one isolation control is removed on purpose and named precisely — which file, which environment variable, which flag.
- The failure is reproduced and described with its actual symptom, not a predicted one.
- The failure section names which lesson-four-through-seven control would have stopped it.
- The control is restored and the same task re-run clean, with that result shown in the report.
Rubric
| Criterion | Weak | Strong |
|---|---|---|
| Collision evidence | "No collisions happened," with no artifact attached | A port response, a database query and a git diff --stat per agent, all attached |
| Task fidelity | Tasks edited until they no longer touch a real shared resource | The three task specs run unmodified, genuinely disjoint by file |
| Deliberate failure | A hypothetical: "removing the port assignment would probably collide" | A real removed control, a real re-run, a real captured symptom |
| Root-cause naming | "Isolation broke" | The specific control removed is named and tied to the specific lesson that introduced it |
| Recovery | The report ends at the failure | The control is restored and a clean re-run is shown |
Key Takeaways
- Prove isolation with evidence per agent, not a clean-looking terminal.
- Keep the three tasks genuinely disjoint so any collision found is real.
- Remove exactly one control at a time so the failure has one traceable cause.
- Name the broken control and the lesson that introduced it, precisely.
- Restore the control and show the re-run clean before closing the report.
What You Have Now
fleet/collision-report.md — evidence that three concurrent agents did not collide, plus the failure you caused on purpose. It sits beside fleet/isolate.sh, fleet/port-map.md, fleet/containment.md, fleet/permissions/ and fleet/access.md as proof that module two's controls hold under real concurrency, not only in the lesson that introduced each one. Module three's venue cutover reuses this same evidence-over-claim standard for a fleet that has left your laptop.
NO-QUIZ
Quiz coming to this lesson
This lesson doesn't have a graded quiz yet — completion is still tracked, just not verified against questions.
Reading is free — your progress isn't being saved
Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.
30-day money-back guarantee. One-time payment — lifetime access and updates.