You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
lane-end close-out gate: refuse to end a lane whose inventory still has worktrees, branches, scratch or caches — the dry-run sweep first, lane-end --sweep --yes to retire them in the same run; landing retires its own tree #163
On Brett Heap's word of 2026-10-05 ("fold the three into 162 and file the close-out gate"), from the finding that workspace creation outpaces workspace closeout (the xFactory cleanup analysis: completed worktrees left after landing; branches outliving their purpose; scratch and caches beside repositories).
The gate
lane-end <lane> (and --retire) runs #162's sweep as a DRY RUN first and refuses to end the lane while its inventory still has anything to retire — worktrees (#97's sidecar inventory), their branches, local branches with no worktree that the lane created, lane scratch, caches — exactly as it refuses today while the lane holds open objects in its log. The refusal prints the disposition table and the one command that clears it:
lane-end: openRepoTools-3 still owns 3 worktrees (2 clean+merged; 1 dirty) and 5 branches — not ended.
retire them: lane-end openRepoTools-3 --sweep --yes (rescue branches first; see the table)
or review: lane-worktrees sweep openRepoTools-3 --dry-run
lane-end --sweep --yes performs #162's dispositions (rescue before any removal; never a live writer; FOREIGN trees left alone), writes one register NOTED line per tree, and then ends the lane in the same run. --force-end ends the lane WITHOUT retiring (a word, logged with its reason) for the cases a person decides to keep a tree alive past the lane — the trees then show as orphaned in lanes --index --worktrees (#161) with the ended lane as owner.
Landing retires too
The shipped landing path — whatever command squashes a lane's PR with proof (today each lane's private squash-land.sh; a lane-land is the natural home, filed when that script is adopted) — removes the PR's worktree and both branches when the tree is clean at the landed head, as the private script does now, and records it. A landing that leaves a dirty tree says so and leaves it to the sweep.
Why a gate and not a reminder
The cleanup records show landing and retirement happening as separate acts for months, and the separate act not happening. lane-end already has the shape — refuse while open objects remain — so the gate adds one more thing it counts, from the inventory #97 already keeps.
Tests
Shell-suite cases: a lane with a clean merged tree refuses to end, ends with --sweep --yes, the tree and branches are gone, the register line names them; a dirty tree gets its rescue branch on the fake origin before removal; a live writer's tree is never touched and the lane refuses to end; --force-end ends and the orphan shows in the inventory; the refusal's printed command is the one that clears it.
Folded in on Brett Heap's word of 2026-10-05 ("file the not prevented fixes") — the inventory-only door and the guard checks
From the re-analysis of the ten cleanup causes: standalone clones (cause 2) and temporary work inside the estate (cause 4) were DETECTED by the sweep, not prevented. Two additions make the inventory the only door:
the session's cwd is a git repository under the estate that NO lane's inventory knows (a clone, or a worktree nobody recorded) → "this tree is not a lane's: lane-worktree adopt <path> or work in lane-worktree add …";
untracked, non-ignored paths exist directly under .lane-worktrees/<lane>/ or the estate root that are not inventory worktrees → "scratch belongs in ${XDG_STATE_HOME:-$HOME/.local/state}/openRepoTools/lanes/<lane>/scratch/ or the harness scratchpad; move it or lane-worktrees sweep --include-scratch".
Both checks read only the inventory and git status --porcelain --ignored=no of the cwd's parent; neither reads the index (Amendment 14 clause (b)).
Tests: a hand-made clone under the estate refuses the prompt and the remedy adopts it; a stray scratch dir refuses until moved; an inventory worktree passes; the checks add under 50 ms to the guard.
Lane: openRepoTools-3
Folded in on Brett Heap's word of 2026-10-05 ("fold them") — cause 18, ignored scratch escaping git status
The guard's scratch check (and the sweep's) reads git status --porcelain --ignored — ignored material included — not the default porcelain that hides it. Ignored directories directly under .lane-worktrees/<lane>/, the estate root or a worktree root above a size threshold (default 50 MB; sweep.conf) refuse the prompt the same way untracked scratch does, naming the directory and its size and the remedy (lane-worktrees sweep --include-caches for caches/venvs; the scratch directory for the rest). The nightly report lists ignored directories over the threshold estate-wide.
On Brett Heap's word of 2026-10-05 ("fold the three into 162 and file the close-out gate"), from the finding that workspace creation outpaces workspace closeout (the xFactory cleanup analysis: completed worktrees left after landing; branches outliving their purpose; scratch and caches beside repositories).
The gate
lane-end <lane>(and--retire) runs #162's sweep as a DRY RUN first and refuses to end the lane while its inventory still has anything to retire — worktrees (#97's sidecar inventory), their branches, local branches with no worktree that the lane created, lane scratch, caches — exactly as it refuses today while the lane holds open objects in its log. The refusal prints the disposition table and the one command that clears it:lane-end --sweep --yesperforms #162's dispositions (rescue before any removal; never a live writer; FOREIGN trees left alone), writes one registerNOTEDline per tree, and then ends the lane in the same run.--force-endends the lane WITHOUT retiring (a word, logged with its reason) for the cases a person decides to keep a tree alive past the lane — the trees then show as orphaned inlanes --index --worktrees(#161) with the ended lane as owner.Landing retires too
The shipped landing path — whatever command squashes a lane's PR with proof (today each lane's private
squash-land.sh; alane-landis the natural home, filed when that script is adopted) — removes the PR's worktree and both branches when the tree is clean at the landed head, as the private script does now, and records it. A landing that leaves a dirty tree says so and leaves it to the sweep.Why a gate and not a reminder
The cleanup records show landing and retirement happening as separate acts for months, and the separate act not happening.
lane-endalready has the shape — refuse while open objects remain — so the gate adds one more thing it counts, from the inventory #97 already keeps.Tests
Shell-suite cases: a lane with a clean merged tree refuses to end, ends with
--sweep --yes, the tree and branches are gone, the register line names them; a dirty tree gets its rescue branch on the fake origin before removal; a live writer's tree is never touched and the lane refuses to end;--force-endends and the orphan shows in the inventory; the refusal's printed command is the one that clears it.Refs #162, #161, #97.
Lane: openRepoTools-3
🤖 Generated with Claude Code
Folded in on Brett Heap's word of 2026-10-05 ("file the not prevented fixes") — the inventory-only door and the guard checks
From the re-analysis of the ten cleanup causes: standalone clones (cause 2) and temporary work inside the estate (cause 4) were DETECTED by the sweep, not prevented. Two additions make the inventory the only door:
lane-worktree add <slice> [--branch <name>] [--from <ref>]— the one verb a lane uses to make a worktree: it runsgit worktree addAND records the tree in the lane's Crash-consistent lane worktree recovery: a lane now says WHERE its session stopped — RUNNING → SWAPPING → SWAPPED with a generation/operation fence, a machine-readable worktree inventory taken at every handoff, and a resume reconciliation that reports and resets nothing #97 inventory in one act (path, branch, base, lane, UTC). A worktree made by hand is still legal git, but it is FOREIGN to every sweep untillane-worktree adopt <path>records it.UserPromptSubmitguard, through the register service of Amendment 22 act 2: the SQL register under lanes-edit.sh — mode=primary writers in one transaction each, the estate switch and lanes/STORE, the write journal and the renderer (one mirror commit per write), exit 69, fail-closed readers, lanes-index import/rollback, SERIALIZABLE claim order, and the agreement tests #165 once it exists, directly until then; both refuse with exit 2 and print the one remedy):lane-worktree adopt <path>or work inlane-worktree add …";.lane-worktrees/<lane>/or the estate root that are not inventory worktrees → "scratch belongs in${XDG_STATE_HOME:-$HOME/.local/state}/openRepoTools/lanes/<lane>/scratch/or the harness scratchpad; move it orlane-worktrees sweep --include-scratch".Both checks read only the inventory and
git status --porcelain --ignored=noof the cwd's parent; neither reads the index (Amendment 14 clause (b)).Tests: a hand-made clone under the estate refuses the prompt and the remedy adopts it; a stray scratch dir refuses until moved; an inventory worktree passes; the checks add under 50 ms to the guard.
Lane: openRepoTools-3
Folded in on Brett Heap's word of 2026-10-05 ("fold them") — cause 18, ignored scratch escaping
git statusThe guard's scratch check (and the sweep's) reads
git status --porcelain --ignored— ignored material included — not the default porcelain that hides it. Ignored directories directly under.lane-worktrees/<lane>/, the estate root or a worktree root above a size threshold (default 50 MB;sweep.conf) refuse the prompt the same way untracked scratch does, naming the directory and its size and the remedy (lane-worktrees sweep --include-cachesfor caches/venvs; the scratch directory for the rest). The nightly report lists ignored directories over the threshold estate-wide.Lane: openRepoTools-3