Appearance
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.