Skip to content

A Worktree is an isolated scope carved out of a shared repo β€” a disjoint directory, its own allocated ports, and a unique ADW ID β€” so N agents can work in parallel without stepping on each other.

Primitive

Worktree ​

Three isolation axes

Remove any one and parallelism collapses to serial. ​

πŸ“

Filesystem

git worktree add

Each run gets its own trees/{adw-id}/ checkout. Two agents in two worktrees never share a file path.

πŸ”Œ

Network

.ports.env

Unique backend + frontend ports per worktree. Two apps run concurrently without port collisions.

πŸͺͺ

Identity

{adw-id} everywhere

ADW ID in the dir name, branch name, log paths. Every artifact is traceable to its run.

All three, together. Drop filesystem β†’ merge conflicts. Drop network β†’ port collisions. Drop identity β†’ logs interleave and nothing is traceable.

How ports get allocated

A pure function of ADW ID. ​

md5(adw_id)%15=offset

Backend

9100 + offset

Frontend

9200 + offset

Why deterministic? Because cleanup must kill the processes on those ports β€” but cleanup runs when the state file is corrupted or gone. Hashing lets cleanup recompute the port from the ADW ID alone. Random or sequential allocation would require reading a file that no longer parses.

What's inside a worktree

One directory per run. ​

trees/cc73faf1/

trees/cc73faf1/# ADW ID as dirnameβ”œβ”€β”€ src/# sparse checkout (optional)β”œβ”€β”€ .ports.env# BACKEND_PORT=9107 FRONTEND_PORT=9207β”œβ”€β”€ adw_state.json# identity + phase history└── # linked to parent repo via `git worktree add`# branch: feat-47-cc73faf1-oauth2

The capacity ceiling is visible

15 concurrent worktrees. After that, port offsets collide. ​

intentional

The modulo 15 is a Schelling point, not a limitation.

Going past 15 requires switching to a different port range, not just hoping. The ceiling surfaces itself the moment it matters. Better a hard wall than silent port conflicts at scale.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16 βœ•

Cleanup is not optional

Three mechanisms. Layered. ​

primary

Per-run cleanup

Each Trigger/ADW calls purge_tree.sh on completion β€” success OR failure. The only mechanism you should rely on.

fallback

Weekly purge job

Cron sweeps worktrees older than N days. Catches runs that crashed before cleanup.

last resort

Manual audit

git worktree list + ls trees/ reveal stragglers when both automated mechanisms fail.

Without cleanup, the pool silently becomes the bottleneck. Symptom: "new ADW runs fail to start" with no obvious cause. Dozens of stale branches, orphaned processes holding ports.

The discipline ​

Parallelism without isolation is serial with extra steps.

Filesystem, network, identity β€” all three or none. Deterministic port hashing so cleanup works even when state is gone. Per-run cleanup as the primary mechanism. A Worktree is how the same repo can host five agents in flight without any of them noticing the others exist.