Repository navigation
A leg read that git half-fails reads as clean, and a declared leg beneath a directory that cannot be searched reads as absent, so lane-end can end a lane with work left in it #272
Description
Found by lane openRepoTools-3's independent review of #255's fix (finding 4, and the ruling on the writer's doubt "a leg whose parent cannot be searched"). Both are read gaps in lane-worktrees, and both end the same way: the sweep reads the leg as clean or as absent, so it holds nothing back and lane-end can end the lane. The review's short form is on #255, comment 6272494888.
What happens
- A leg at mode 0100 (searchable, not listable) reads
clean.git statusexits 0 withwarning: could not open directory '.': Permission deniedand drops every untracked file. The readers ignore that warning.- Measured by the review's probe on main + Lifecycle reads that failed are no longer answers, set-lane-tree's fence closes with its operation, and a lane sidecar is valid only when whole #252 + The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255, on a leg holding a pushed lane commit plus one untracked file: at mode 0755 the sweep reports the leg
dirty retireand exits 3. At mode 0100 it reports the legcleanand exits 0, andlane-endthen ENDs the lane ("nothing of lane triad-1's is left on disk"). - Commits are still seen. The untracked files are what is lost.
- Scope: estate-wide. Every tree read through
git statushas this gap, not only legs.
- A declared leg beneath a directory that cannot be searched reads
absentin the sweep.Leg.existsisos.path.isdir, which answers False for a path it cannot reach exactly as for one that is not there.probe_legreturns at once onnot leg.exists, so the leg gets noread_error. It readsabsentand counts for nobody, andprobe_leg's own docstring says what that allows:lane-end"could end a lane over an unpushed commit in it".- It bites only with nested leg paths. For the standard top-level
specandcodelegs the parent is the assembly itself. - What The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255's fold-in fixed is only the nested dependencies.
probe_uninitializedasksos.statabout each-line's path, so a dependency beneath an unsearchable directory now gets anunreadablerow. A declared leg does not go through it. The re-check of The handoff names every inventory record that is not a whole schema-1 one, and a leg directory this account cannot search, or a dependency nested in one, is unreadable and never absent (fixes #255) #271 confirmed the fold-in: withcode/upstreamat mode 000 or 0600, git still prints-and exits 0, the dependency's row isunreadable("a directory above it cannot be searched…"), the sweep exits 3 andlane-endexits 2. - No measurement of the declared-leg case is recorded in the review. The ruling is by reading.
Where
lane-worktrees:2125-2130,read_leg, at523b381: thegit status --porcelain=v1 --ignore-submodules=none --untracked-files=normalcall, and theif status.returncode != 0test that is the only failure check. On main00d52aethe same call is at:2106-2109.lane-worktrees:1982,Leg.exists = os.path.isdir(path), and:2051-2052,probe_leg'sif not leg.exists: return, at523b381and ata16e534. On main00d52aethey are at:1982and:2040-2041.- The fold-in is
probe_uninitializedatlane-worktrees:2070-2092and theassembly_checkoutsdocstring at:2103-2117, ata16e534, the head of The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255's fix PR, The handoff names every inventory record that is not a whole schema-1 one, and a leg directory this account cannot search, or a dependency nested in one, is unreadable and never absent (fixes #255) #271.
How it was found
- Lane 3's independent review of The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255's fix (
523b381, lane openRepoTools-2's). Finding 4 is the mode-0100 gap, with its probe. The parent case is its ruling on the writer's doubt "a leg whose parent cannot be searched": SHOULD, follow-up. - Lane 3 told Brett Heap on The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255 (comment 6272494888) that the mode-0100 gap, with the handoff finding, would come to him as a v1.2.0 proposal.
The fix the review proposed
- Mode 0100: treat git's "could not open directory" warning as a failed read, so the leg is
unreadableand counted, as every other failed read is. - The unsearchable parent: Python can tell it apart, because
os.statraisesPermissionError, soprobe_legcan askos.statof the leg path before it trustsLeg.exists. The shells (lane-handoffandlane-reconcile, which read legs too) can test the nearest existing ancestor's-x. - Add a test at mode 0100, and one with a declared leg path beneath a directory at mode 000.
Test gaps in #271's fold-in
Found by lane 3's re-check of the fold-in round (e678c61..a16e534, comment 6277159862 on #271, which calls them NITs for v1.2.0). They are about the same os.stat path (probe_uninitialized), at a16e534:
- Mutant N8 survives. N8 is new wording for the
os.statbranch.tests/test_triad_lane_tooling.py:777checks only "read through it (", not the "a directory above it cannot be searched" words set atlane-worktrees:2089. - The parent test accepts exit 2 or exit 3 (
:772). Wheregit submodule statusitself fails under an unsearchable parent, the sweep refuses to list the dependencies (exit 2) and theos.statpath is never reached, so two mutants would survive: N2 (probe_legwithout the stat) and N5 (the stat's failure swallowed). Git 2.43 on Eagle prints-, so the test bites there.
Why it is not in v1.1.0
- The review's ruling for mode 0100: "It is not a
#255regression, and the gap is git's partial read, estate-wide." For the parent case it ruled a follow-up, because only nested leg paths meet it. - The review's verdict on The handoff's tree inventory names a record it could not read whatever its schema, and a leg directory it cannot search is never read as absent (#246 follow-up, before the cutover) #255 is LAND, with nothing that has to change before it lands. Each fix here is a behaviour change after that review.
- The re-check's verdict on The handoff names every inventory record that is not a whole schema-1 one, and a leg directory this account cannot search, or a dependency nested in one, is unreadable and never absent (fixes #255) #271 is also LAND: no MUST and no SHOULD, and its four NITs, the test gaps among them, are "all left for v1.2.0".
Filed in milestone v1.2.0 on Brett Heap's word (2026-10-19T18:3xZ, "yes, file the v1.2.0 issues"). It is unclaimed.
Lane: openRepoTools-3
🤖 Generated with Claude Code
Activity
The v1.1.0 notes take lane 3's review of #293, put #209 in the lane a…
The v1.1.0 notes now say that the fixes for #255 and #280 are part of…