Repository navigation
update-shape.py apply --branch judges the pin, the manifest and the copies from the working tree but commits HEAD plus only the paths it wrote, so over an uncommitted in-place apply it exits 0 with a commit whose own validate-pins.py is red, dies on git's "nothing to commit", or says "nothing to do" and makes no branch #436
Description
Lane: openreposhape-3 (openRepoShape-3)
What happens. prepare reads the pin and classifies every copy from the WORKING TREE. _nothing_to_do decides from that reading, and so do the rows _write_copies writes. The validators also run over the working tree. The commit is git commit -- <paths> over only the copies this run wrote, plus the pin and the manifest. Over a tree that is HEAD's, those agree. #379 made the --pr re-run refuse when they do not (update-rerun-uncommitted). Every other path still mixes the two sources.
Measured on main 45e01f4. The project was scaffolded at A into local bare remotes. Upstream commits then changed scripts/validate-manifest.py (B), scripts/validate-pins.py (C) and Makefile (D) under templates/assembly-root/. "In place" means apply --at C --yes with no --branch, left uncommitted. It leaves M on the pin, project.yaml, validate-manifest.py and validate-pins.py.
(a) On main, in place at C, then a first --branch run at D:
apply --root <root> --upstream <upstream> --at <D> --yes --branch shape/d exit 0
copied Makefile
re-pinned contracts/shape-pin.yaml and project.yaml <C> -> <D>
ok contracts/shape-pin.yaml: 11 copied shape file(s) match their digests
committed on shape/d: Makefile, contracts/shape-pin.yaml, project.yaml
git status --porcelain M scripts/validate-manifest.py M scripts/validate-pins.py
scripts/validate-pins.py in a clean worktree of shape/d: exit 1
FINDING shape-copy-drift: scripts/validate-pins.py: sha256 cc3484bf… contracts/shape-pin.yaml records b05c27da…
FINDING shape-copy-drift: scripts/validate-manifest.py: sha256 e15c4745… contracts/shape-pin.yaml records cc513d09…
(a′) The same without --branch (in place at C, then in place at D). It prints NEXT git -C <root> checkout -b shape/update-<D> && git -C <root> commit -m 'Re-sync the shape @ <D>' -- Makefile contracts/shape-pin.yaml project.yaml. Run as printed, that line makes the same red commit.
(b) On shape/update, whose HEAD re-pins B (made by apply --at B --branch shape/update --push), in place at C, then back to B. The result is the same with and without --push --pr:
apply --root <root> --upstream <upstream> --at <B> --yes --branch shape/update [--push --pr] exit 2
copied scripts/validate-pins.py
re-pinned contracts/shape-pin.yaml and project.yaml <C> -> <B>
... pins ok / manifest ok
REFUSED committing the re-synced shape on shape/update. THE EXACT COMMAND WAS:
git commit -q -F - -- contracts/shape-pin.yaml project.yaml scripts/validate-pins.py
nothing to commit, working tree clean
ROLLED BACK: ... restored scripts/validate-pins.py, contracts/shape-pin.yaml, project.yaml
(c) On main, in place at C, then a --branch run at C. The result is the same with and without --push --pr:
apply --root <root> --upstream <upstream> --at <C> --yes --branch shape/c [--push --pr] exit 0
nothing to do: every copied file matches opensoft/openRepoShape @ <C>, which the pin already names
No shape/c branch is made, and nothing is committed or pushed. _awaits_its_pull_request answers False because --branch is not the current branch, so #379's check is never reached.
Where. On 45e01f4, in update-shape.py:
cmd_apply(:2587):_nothing_to_doat :2599 reads the working tree, and the commit's pathspec is built at :2622._awaits_its_pull_request(:2770)._refuse_what_head_does_not_commit(:2802) and_not_what_head_commits(:2852): update-shape.py: a--prre-run finishes the landing only when the working tree holds what HEAD commits at the pin, the manifest and every pinned copy, and is refused asupdate-rerun-uncommittedotherwise, so an in-placeapply --at Cleft uncommitted on a branch that re-pins B no longer gets B pushed under a pull request titled C (#333) #379's comparison, which is asked only on the re-run path.commit_on_branch(:1779), withgit commit -- <paths>at :1892._refuse_red_validators(:2535), which validates the working tree and not the commit.next_line's branchless form (:3054).
Why it matters.
- (a) exits 0 and prints "match their digests" over a commit its own validator rejects, and it leaves two pinned copies modified. Pushed, that commit is a red pull request. AGENTS.md step 6 promises that
applyrolls back when the validators go red. - (b) names git's "nothing to commit" as the failure where the tool could have named the state.
- (c) silently skips a branch and pull request that were asked for, with exit 0.
Direction: decide from one source. When a commit will be made (--branch), compare the pin, the manifest and every pinned copy with HEAD before the first write, using #379's _not_what_head_commits. Refuse by name, as the re-run does, saying "commit them or put them back". That covers (a), (b) and (c). The alternative is to build the commit's pathspec from every pinned path that differs from HEAD, not only from what this run wrote. The branchless NEXT line needs the same answer.
Keep:
- the explicit pathspecs (no
-a, nothing swept from the index); - update-shape.py: a
--prre-run finishes the landing only when the working tree holds what HEAD commits at the pin, the manifest and every pinned copy, and is refused asupdate-rerun-uncommittedotherwise, so an in-placeapply --at Cleft uncommitted on a branch that re-pins B no longer gets B pushed under a pull request titled C (#333) #379's rule that README and untracked dirt are not consulted; - a clean tree's behaviour;
- update-shape.py
apply --addstages the new file with a plaingit add, so a path the operator's excludes ignore fails after the copies, the re-pin and the branch are written, nothing is rolled back, andcheckthen exits 0 over a re-pin nobody committed #202's rollback.
Source.
- PR update-shape.py: a
--prre-run finishes the landing only when the working tree holds what HEAD commits at the pin, the manifest and every pinned copy, and is refused asupdate-rerun-uncommittedotherwise, so an in-placeapply --at Cleft uncommitted on a branch that re-pins B no longer gets B pushed under a pull request titled C (#333) #379 (update-shape.pyapply --branch --prre-run:_awaits_its_pull_requestreads the pin from HEAD while the "nothing to do" test reads the working tree, so a re-run over a tree that an in-placeapply --at Calready wrote pushes HEAD and titles the pull request with C #333),Left out, all three clauses. - The update-shape.py
apply --branch --prre-run:_awaits_its_pull_requestreads the pin from HEAD while the "nothing to do" test reads the working tree, so a re-run over a tree that an in-placeapply --at Calready wrote pushes HEAD and titles the pull request with C #333 writer's measurements (cases S6, S7 and S8 on c7c02fa and ab623dd), re-measured here on 45e01f4. - This lane's review of update-shape.py: a
--prre-run finishes the landing only when the working tree holds what HEAD commits at the pin, the manifest and every pinned copy, and is refused asupdate-rerun-uncommittedotherwise, so an in-placeapply --at Cleft uncommitted on a branch that re-pins B no longer gets B pushed under a pull request titled C (#333) #379: "the neighbouring paths ... are disclosed under## Left out".
Related: #333 (closed by #379), #204, and #202 (closed; it noted that later runs "read those edits as the truth").
Activity
brettheap commentedon Oct 12, 2026
CLAIMED — lane openRepoShape-3, session 43f4ac63-0116-41de-977d-afc23cdf7fdf@Eagle, 2026-10-12T17:56:54Z, for #436
Logged in
lanes/log/openRepoShape-3.mdatc4fd0f39a7818350bf629b9c3a8344fc3a1207a6.The three reads (lane-collision-protocol Rule 1):
brettheap commentedon Oct 12, 2026
(lane openRepoShape-3, 2026-10-12T18:56:22Z) Ruling, Brett Heap 2026-10-12, on this issue's direction: refuse by name. Before the first write,
apply --branchcompares the pin, the manifest and every pinned copy with HEAD (#379's comparison) and refuses, saying to commit those changes or put them back. It does not widen the commit to every path that differs.update-shape.py: a pinned copy replaced by a directory that HEAD comm…
update-shape.py: `apply --branch` lstats what stands at a path before…
update-shape.py: `apply --branch` compares the pin, the manifest and …
Merge main cc8f2da into fix/adopt-plan-quote-yaml-keywords (#181)