Repository navigation
Description
Goal: make bootstrap moves a leg only where nothing the person has is lost, says what it left, and tells the same story for every state it meets.
Filed by lane openRepoShape-5 on Brett Heap's word of 2026-10-16T12:17:02Z ("#458's update-shape/bump-leg (~22)"), from the seven lines of 6201724792 (lane 4's R603 review of #615): the draft numbers them as the comment does, takes six, and leaves line 6 deferred (see below). The code's own docstrings hand three of them to this checklist (templates/assembly-root/scripts/bootstrap.py:284-287 and :454-456: "#458's to rule on"; :351-352: "P9 says nothing of the branch it leaves; that is #458's"). Lane 4 judged all but the deferred one OPEN on main 95780dd (#473 comment 6215386495); lane 5 re-measured each on main 879d804 with a scaffolded project and local bare remotes (git 2.43.0).
Rulings, decided by Brett Heap in lane 5's session:
- R1, lines 1 and 2: a leg that is in the way of a move REFUSES. Use
--no-overwrite-ignoreon the moves, and refuse while a merge, cherry-pick, revert or rebase is in progress. Word of 2026-10-16T13:07:34Z, "take all recommendations". - R2, line 4: NARROW the sentence at
templates/assembly-root/AGENTS-shape.md:95-96. Same word. - R0, the pin: this lands before the v1.1.0 tag, in its one shape bump. Word of 2026-10-16T13:36:23Z, "take all recommendations for R0 and the five lines".
- It is filed after his "yes create v1.1.1" of 13:35:28Z, but R0 puts it in v1.1.0.
Lands after: #648 for line 7 only (fix/648-bootstrap-and-gate-order, lane 5's own, edits templates/family-root/scripts/bootstrap.py; it leaves the docstring's paragraph (b) alone, so line 7 can instead be folded into that branch as one sentence). #634 (lane 2's) edits templates/assembly-root/AGENTS-shape.md at :77-84, about ten lines from line 4's sentence. One pull request also closes #694, make bootstrap with no git on PATH, which edits the same two bootstrap.py files. It is stacked on #682 (#648), which changes the family root's bootstrap.py.
Lines (path:line at main 879d804; bootstrap.py is templates/assembly-root/scripts/bootstrap.py unless a line says otherwise. The comment's names: P9 is place_at_pin from a leg on another branch, T7 is fast_forward_to_pin from one)
- Line 1: Every placement that changes files overwrites an ignored file at a path the pin tracks, silently. The checkouts and the merge carry no
--no-overwrite-ignore:_check_out(:254-271,git checkout -q <branch>), the missing-branchcheckout -b(:607) and the on-branchmerge --ff-only(:471); the docstrings at :284-287 and :451-456 name it. Measured for P9 (place_at_pinfrom another branch): with the leg on an orphan branchotherwith an empty tree,README.mdlisted in the leg'sinfo/excludeand holdingMY LOCAL NOTES,scripts/bootstrap.pyprintson main at 63f67d2d1933 (branch tip == pin)and the file now holds the pin's# Atlas-spec. The other three paths by reading, with git's default. Git 2.43.0 has the flag for both (checkout -handmerge -hlist--[no-]overwrite-ignore); measured:git checkout --no-overwrite-ignore mainover the same file exits 1The following untracked working tree files would be overwritten by checkout: README.mdand leaves the file. (R603; lane 4's L4-74.) - Line 2: Moving a leg off a branch with a merge in progress ENDS the merge.
_move_and_check_out(:274-303),place_at_pin(:384-415) and the missing-branch path (:607) check out another branch with nothing asked of the git dir. Measured for P9: on a branchawithgit merge --no-commit --no-ff bstaged andMERGE_HEADpresent,scripts/bootstrap.pyprintson main at 63f67d2d1933 (branch tip == pin),MERGE_HEADis gone and the leg showsA b.txtonmain: the staged result went with it. T7 and the missing-branch path by reading. A cherry-pick or a revert in progress is reasoned only (R603), not run. (R603; L4-75.) - Line 3: P9's line does not name the branch HEAD left.
place_at_pin(:414) printson <branch> at <pin> (branch tip == pin)and never calls_say_left(:347-360), which T7 (fast_forward_to_pin, :497-498) does for the same move;_say_left's docstring says P9 is "Tracking: update-shape.py and bump-leg.py, keeping a project's shape copies and leg pins current #458's". Measured in the run of line 1: the line is the whole of what was said of the leg that was onother. (R603; L4-76.) - Line 4: A tracking branch AHEAD of the pin with no commit of its own is left whenever HEAD is not detached at the pin.
_held_upstream_past_the_pin(:241-251) requires_head_of(sub) == (pin, None), somove_back_to_pin(:502-549) starts only from there. Measured: withmainat its upstream's tip79775b0, ahead of the pin63f67d2, the leg detached at the pin getsbranch main moved back 79775b0826f5 -> 63f67d2d1933, the pin; nothing is lost, origin/main still holds those commits, and ... merge --ff-only origin/main brings the branch forward, while the same branch with HEAD on it getsPIN 63f67d2d1933 != branch main tip 79775b0826f5/not moving an existing branch. The checkout stays on main at its tip. Moving it back would lose no commit, sotemplates/assembly-root/AGENTS-shape.md:95-96("places each leg on its tracking branch AT the pin where that loses no commit, and leaves one detached at any other commit, saying why") does not describe that state. (R603; L4-77.) - Line 5: A HEAD that is a symbolic ref outside
refs/heads/is read two ways.place_at_pinaskscurrent is None(:404) and so places the leg;fast_forward_to_pinaskscurrent.startswith("refs/heads/")(:468-469) and ends in_say_neither. Measured withgit -C spec symbolic-ref HEAD refs/remotes/origin/main: the branch at the pin is placed (on main at 63f67d2d1933 (branch tip == pin)), and the branch behind the pin getsthe checkout is at 63f67d2d1933 (on refs/remotes/origin/main), which is neither. Exotic, and the same on main before bootstrap.py: a leg on another branch whose tracking branch is behind the pin is fast-forwarded and checked out as one at the pin already is, and the family holder's AGENTS-shape.md and bump-leg.py say bootstrap places a leg where that loses no commit (#603) #615. (R603; L4-78.) - Line 7:
templates/family-root/scripts/bootstrap.py:31-33still promises placement unconditionally. The docstring's paragraph (b) says each member bootstraps "its legs onto their tracking branches at their pinned commits"; the holder's AGENTS-shape.md (:63-65) andbump-leg.pyalready say "where that loses no commit". It was left out of bootstrap.py: a leg on another branch whose tracking branch is behind the pin is fast-forwarded and checked out as one at the pin already is, and the family holder's AGENTS-shape.md and bump-leg.py say bootstrap places a leg where that loses no commit (#603) #615 because the file is a pinned copy and changing it adds a re-pin; bootstrap.py and validate-family.py:family bootstrap okwith no member checked out, an earlier row'smember-uninitializedhiding a case-variant refusal, andmember-gitlink-unnamedwith no command under--no-members#648 re-pins it anyway. (R603's last line; L4-80.)
Deferred, not drafted into the change (stays on #458, line 6 of the comment): the current != refs/heads/<branch> compare (:469, and place_at_pin's already, :408) is case-sensitive, so a branch that differs from the tracking branch only in case could take T7's path and branch -f would write the loose ref file both names share on a case-insensitive disk. Reasoned only, and nothing here can run it: CI is Linux only since #597, so it needs a macOS or a Windows run by hand (L4-79: DOUBTFUL).
Direction
- 1:
--no-overwrite-ignoreon the three commands; the refusal then reaches the person as git's own lines through_say_refused, as a refused checkout does today, and the leg stays where it is. For T7 the branch has already moved bybranch -f(_move_and_check_out's docstring says the next run finds it at the pin); keep that and say it. A test per path with an ignored file in the way (the P9 case above is the model; the oldest git these scripts support is for the writer to check against the flag). - 2: before any move that leaves a branch (P9, T7, the missing-branch path), refuse when the leg's git dir holds
MERGE_HEAD,CHERRY_PICK_HEAD,REVERT_HEAD,rebase-merge/orrebase-apply/, in the file's own refusal form: say which operation, that nothing moved, and what to do (finish or abort it, then run bootstrap again). Measure the cherry-pick and revert cases in the test; the merge is measured above. - 3: call
_say_left(head, current, named)fromplace_at_pinwhen HEAD was on anotherrefs/heads/branch, as T7 does; extend the P9 test to read the line. - 4: (R2) narrow the sentence to what the code does: a leg that is not detached at the pin, with a branch ahead of it, is told
not moving an existing branch, which is a why. The code alternative, moving a branch back that is its upstream's tip from HEAD-on-the-branch or from another branch, needsgit reset --keep <pin>(branch -frefuses the checked-out branch) and moves someone's checked-out branch under them; recommended against. - 5: one answer for both:
place_at_pinalso ends in_say_neitherfor a HEAD that is on a ref outsiderefs/heads/(recommended; the commits made there land on a remote-tracking ref), orfast_forward_to_pinplaces it. Say which in the docstrings. - 7: one docstring sentence, "puts each member's legs on their tracking branches at their pins where that loses no commit, and says why where it does not", as the holder's AGENTS-shape.md has it.
Overlaps: #648 (line 7, above) and #634 (the same file as line 4, apart); no open PR edits templates/assembly-root/scripts/bootstrap.py. tests/test_bootstrap_after_bump.py and the files that grew with #556, #615 and #644 hold today's lines.
Mark each line → this issue on #458 (the deferred one stays), and tick it there when this closes.
🤖 Generated with Claude Code
Activity
brettheap commentedon Oct 16, 2026
CLAIMED — lane openRepoShape-5, session 50cede29-ab82-4ca3-9f67-d98e1a58c8d2@Eagle, 2026-10-16T14:02:04Z, for #704
Logged in
lanes/log/openRepoShape-5.mdat539b3278aaa7d91123f86473c131593a029ead15.The three reads (lane-collision-protocol Rule 1):
bootstrap.py: a cherry-pick or revert sequence whose stop was committ…
Merge #682's fix round 45c512e (fix/648-bootstrap-and-gate-order, wit…
Merge #682's second fix round 23e1105 (fix/648-bootstrap-and-gate-ord…
Merge #682's third fix round f74f640 (fix/648-bootstrap-and-gate-orde…
bootstrap.py and validate-family.py: a member no credential would che…
Merge origin/main (40e678e) into l3-563-docs
README.md, the handbook and the v1.1.0 notes: RV630's four nits, and …
bootstrap.py: step (a) decodes git's output as the system decodes a n…
bootstrap.py: a validator's exit 2 ends `bootstrap REFUSED`, exit 2, …
bootstrap.py: a leg whose HEAD is on a branch that differs from the t…
bootstrap.py: a missing tracking branch is not made while any `refs/h…
the assembly root's validate-manifest.py and bootstrap.py: a path thi…