Recovered from crashed session (Node OOM). Repo contains full P0-P6 scaffold: plugin.json/marketplace.json, AGENTS.md, ADRs 0001-0006, lh CLI (init/index/graph/lane/run/memory/host/report/doctor), 10 .github/agents, 12 CLI skills, instructions, context7 mcp.json, and unit/e2e test suite. Fixed: run.mjs read --in-tokens/--out-tokens but tests and CLI docs use --input-tokens/--output-tokens, so telemetry totals were always 0. Now accepts both forms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2.6 KiB
2.6 KiB
ADR 0003 — git worktree per write-lane; pluggable isolation backend
- Status: Accepted
- Date: 2026-09-09
Context
The harness drives parallel dynamic workflows on its own: the conductor re-plans and re-fans-out at every checkpoint. Multiple builder agents therefore write code concurrently.
Concurrent writes to a single checkout corrupt work — two agents editing the same file, or one agent's partial state being read by another, produces failures that are extremely hard to diagnose and that waste far more tokens than they save.
Decision
- Read-only lanes share the main checkout. Recon and review never write, so they are safe to fan out N-wide with no isolation.
- Every write lane gets its own
git worktree+ branch (lh/<runId>/<laneId>). - File-scope leases. Every lane declares
scopeglobs up front.lh lane createperforms a glob-intersection check against all live write lanes and rejects overlapping scopes. The check is deliberately conservative: when intersection is ambiguous, it rejects. - Sequential integration. A dedicated integrator agent merges lane branches one at a time and
runs one full verify. On conflict,
lh lane mergedoes not auto-resolve — it marks the lane blocked and returns the conflicted paths for escalation. - The isolation backend is pluggable —
worktree(default),inplace, and a stubbeddevcontainer, selected byconfig.isolation.backend.
Scope compliance is also a Ralph exit criterion: lh lane status reports files changed outside
the declared scope, and a lane with out-of-scope changes cannot pass.
Consequences
- Parallel writes are safe by construction rather than by convention.
- Lanes are cheap (a branch and a worktree), so the fully dynamic re-planning model can spawn and drop them freely.
- Merge conflicts surface as an explicit, escalatable state instead of silent corruption.
- Worktrees require git ≥ 2.5 and a real repository.
lh doctorandlh hostcheck for this and degrade toinplace+ sequential execution when unavailable. - Moving to per-lane devcontainers in v2 is a backend swap, not a rewrite.
Alternatives considered
- Shared checkout with file locks — rejected: locks are advisory, agents forget them, and a crashed agent leaves stale locks.
- Devcontainer per lane now — deferred to v2. Strongest isolation but a heavy dependency and a slow inner loop; the pluggable backend keeps the door open.
- Read-only parallelism only — rejected: it caps the speedup at exactly the phase that is already cheap.