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>
50 lines
2.6 KiB
Markdown
50 lines
2.6 KiB
Markdown
# 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
|
|
|
|
1. **Read-only lanes share the main checkout.** Recon and review never write, so they are safe
|
|
to fan out N-wide with no isolation.
|
|
2. **Every write lane gets its own `git worktree` + branch** (`lh/<runId>/<laneId>`).
|
|
3. **File-scope leases.** Every lane declares `scope` globs up front. `lh lane create` performs a
|
|
glob-intersection check against all live write lanes and **rejects overlapping scopes**. The
|
|
check is deliberately conservative: when intersection is ambiguous, it rejects.
|
|
4. **Sequential integration.** A dedicated integrator agent merges lane branches one at a time and
|
|
runs one full verify. On conflict, `lh lane merge` does **not** auto-resolve — it marks the lane
|
|
blocked and returns the conflicted paths for escalation.
|
|
5. **The isolation backend is pluggable** — `worktree` (default), `inplace`, and a stubbed
|
|
`devcontainer`, selected by `config.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 doctor` and `lh host` check for this and
|
|
degrade to `inplace` + 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.
|