Repository navigation
Pin openRepoShape at v1.1.0, 190133d on its main: six of the eight mounted files moved (bootstrap places legs only where no commit is lost; the family Makefile refuses a holder without siblings.py); no test expectation moved - #233
Conversation
…gitlink and contracts/openreposhape-pin.yaml move together, the digest recomputed Brett Heap's hold of 2026-10-13 (#186, comment 6152410188) held every bump of upstream/openRepoShape until openRepoShape's v1.0.0 tag. His word of 2026-10-17T21:51Z, recorded on #186 (comment 6241785035): "Yes, wait for v1.1.0", meaning pin straight to v1.1.0, so there is one pin update and one rehearsal instead of a v1.0.0 rehearsal redone days later. v1.0.1 cannot be pinned: 8cda139 sits on release/v1.0, not on main. v1.1.0 is an annotated tag, dereferenced locally and through the API: git rev-parse v1.1.0 v1.1.0^{commit} -> b9c509997727927acc20b15d9b9e04aa08b56c01 (tag, tagger 2026-10-17T21:29:43Z) -> 190133d5e704e380c430f87ca9c4e31746de0012 gh api repos/opensoft/openRepoShape/git/tags/b9c50999... --jq .object.sha -> 190133d5e704e380c430f87ca9c4e31746de0012 On openRepoShape's main, as AGENTS.md's pinned-standard rule 2 requires: gh api repos/opensoft/openRepoShape/compare/main...190133d5e704e380c430f87ca9c4e31746de0012 -> behind (ahead_by 0, behind_by 2) Bump run as contracts/openreposhape-pin.yaml states: git -C upstream/openRepoShape fetch origin main --tags git -C upstream/openRepoShape checkout 190133d5e704e380c430f87ca9c4e31746de0012 python3 -c "...from repo_shape import tree_digest; print(tree_digest('upstream/openRepoShape', 'HEAD'))" Old commit: 7f84ca42ca86a8902928345109d2bf6bad87bd91 Old tree_sha256: 3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8 New commit: 190133d5e704e380c430f87ca9c4e31746de0012 New tree_sha256: 7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912 The digest is recomputed, not adjusted. 190133d's helper on 7f84ca4's tree prints the old row 3be52767... again, and 7f84ca4's helper on 190133d's tree prints the new row 7a66972c..., so sorted-ls-tree-r-v1 means the same on both sides. Only `commit:` and `digests.tree_sha256` change in the pin file. Nothing under upstream/openRepoShape was edited. Part of #186. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7 of 190133d
The docstring of
test_r01_composed_the_documented_one_liners_resolve_through_the_root_entry_point
cited the pointer as openRepoShape:280 at 7f84ca4. At the pinned
190133d the same line is 547, and its bytes are unchanged:
cmp <(git show 7f84ca4:openRepoShape | sed -n 280p) \
<(git show 190133d:openRepoShape | sed -n 547p) # equal
So the test's BYTE FOR BYTE claim still holds, and only the citation
moves with the pin. A docstring-only change: the test's pipeline string
is untouched.
Part of #186.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-pin-v1.0.1 Part of #186. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 53 minutes by commenting |
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR performs a focused openRepoShape dependency bump from 7f84ca4 to the main-branch commit 190133d (v1.1.0), updates the corresponding verified tree digest, and refreshes one documentation-only pin citation. The upstream behavioral changes are consumed through the submodule; no product code or test expectations are modified, and the described test runs remain passing aside from a pre-existing environment-isolation issue. Sequence diagram for verifying the openRepoShape pin bumpsequenceDiagram
participant Maintainer
participant Contract as contracts/openreposhape-pin.yaml
participant Submodule as upstream/openRepoShape
participant Verify as tests/test_upstream_pin.py
Maintainer->>Submodule: checkout 190133d5e704e380c430f87ca9c4e31746de0012
Maintainer->>Contract: update commit
Maintainer->>Contract: update digests.tree_sha256
Verify->>Contract: read commit and digest
Verify->>Submodule: compute sorted-ls-tree-r-v1
Submodule-->>Verify: 7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912
Verify-->>Maintainer: pin and materialized tree verified
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
brettheap
left a comment
There was a problem hiding this comment.
Independent review of #233 at b52394d: LAND after fixes
The pin itself is right, and nothing in the diff should change. Rule 2 holds, the digest is recomputed (I got the same number three independent ways), the pin file and the gitlink move in one commit, and the docstring citation is correct.
The fixes are to the PR body, plus two follow-up issues. No code change is needed. Two of the body's claims about what v1.1.0 does to the estate commands are wrong, and I reproduced each one at both pins (findings 1 and 2). Neither is caused by this bump: park, resume and status run each estate's own copies of these files, not this mount. But both arrive with v1.1.0 holders, and this suite cannot see either. Land once the body is corrected, the two issues are filed and linked, and Linux tests and tests-no-submodule are green.
Findings
1. should-fix: resume's leg guard ignores a leg's own branch:, and v1.1.0's bootstrap now moves such a leg
The PR body says: "Bootstrap's new moves (fast-forward, move back, the other-branch checkout) never get a leg that resume lets through into a state the guard missed." That is false for a leg that declares its own branch:.
The two sides.
- This repository.
resume:692-694,root_legs_ok, compares every leg's HEAD withtracking_branch_of "$root", which is the root'stracking_branch. - openRepoShape at
190133d.templates/assembly-root/scripts/bootstrap.py:1064places each leg onleg.get("branch") or branch.templates/assembly-root/scripts/validate-manifest.py:627,_leg_branch_findings(opensoft/openRepoShape#455), makes a leg'sbrancha validated field that "wins overtracking_branch".bootstrap.py:578/:599,fast_forward_to_pin(opensoft/openRepoShape#603 → opensoft/openRepoShape#615), now fast-forwards a tracking branch that is behind the pin and checks it out, even from ANOTHER branch. At7f84ca4, a branch tip that was not the pin was never moved.
Reproduction. I built the fixture with the suite's own helpers (seed_workspace, standalone_manifest, run, offline), and each pin's own bootstrap.py and repo_shape.py:
- the root's
tracking_branch: main; - the spec leg's row has
branch: develop; - the leg is checked out on
mainat the pin, with localdevelopone commit behind the pin; - the superproject is clean.
[7f84ca4] resume exit 0; refused the root: False; leg HEAD after: main
[7f84ca4] bootstrap said: [spec] spec: PIN 62ba004bce1f != branch develop tip c1be5eb7666b
[190133d] resume exit 0; refused the root: False; leg HEAD after: develop
[190133d] bootstrap said: [spec] spec: branch develop fast-forwarded b8223eefe609 -> 11176b1c0d97, the pin; ...
At v1.1.0, resume reports success and the leg has moved. That is the move F3 of the review on #83 exists to refuse. The converse also holds: a leg sitting on its own declared branch is refused as "not its tracking branch 'main'".
Fix.
- (a) In the PR body, qualify the sentence: it holds for legs with no
branch:of their own (finding 4), and not for a leg that declares one. Link the issue. - (b) File an issue in this repository:
root_legs_okshould compare each leg with that row's ownbranch:, falling back to the root'stracking_branch, exactly asbootstrap.py:1064does.legs_ofalready walks those rows.- Add a test built like the fixture above.
2. should-fix: is_family_folder keys on name:; at v1.1.0 the family folder is the holder's repository name, and make siblings stops before cloning otherwise
The two sides.
- This repository. The shared resolver requires the folder to equal
family.yaml'sname::park:259-268,resume:242-251andstatus:380-389, at[ "$YAML_VALUE" = "$name" ]. - openRepoShape at
190133d.templates/family-root/scripts/siblings.py:18, "WHICH NAME<Family>IS (#629)": "It is the holder's REPOSITORY name ... It is NEVERname:, the display name". The README template says the same (templates/family-root/README.md:61-67).siblings.py:38, "THE PARENT-FOLDER CHECK, BEFORE ANYTHING IS CLONED (#543)", and:1330: the run now stops, exit 1, and clones nothing. At7f84ca4it cloned first and warned after.
Reproduction. I built a holder from each pin's own family-root files, with family.yaml holding name: "QuillWorks" and repository: testorg/Quill. That is what family.py init --family Quill --name QuillWorks writes. It has one member, reached through a local bare remote.
| layout | at 7f84ca4 |
at 190133d |
|---|---|---|
QuillWorks/QuillWorks, the only layout park/status resolve |
make siblings exit 0, member placed |
make siblings exit 2 (make over siblings' 1): "siblings: stopped before cloning: the holder is not in a folder named Quill. Nothing was cloned, fetched or moved." No member placed. |
Quill/Quill, v1.1.0's layout |
park Quill --dry-run and status Quill exit 2 |
the same |
The park refusal even contradicts itself: "REFUSED: no estate named 'Quill' ... An estate is a FAMILY folder (Quill/Quill/family.yaml)", while that file exists.
So for a family whose display name differs from its repository name, no layout works for both this repository's commands and a v1.1.0 holder. The suite cannot see it: FAMILY_YAML (tests/test_park_resume_commands.py:111-117) always writes name: equal to the repository basename.
The PR body also files #629 only under spelling ("opensoft/openRepoShape#454, opensoft/openRepoShape#629 → opensoft/openRepoShape#642"). And it says make siblings "asks about the family folder before it clones". It does not ask: it refuses and clones nothing.
Fix.
- (a) In the PR body:
- restate opensoft/openRepoShape#543 as stop-before-clone;
- restate opensoft/openRepoShape#629 as the folder rule;
- add both to "Why the behaviour changes ... turn nothing red", with the issue link.
- (b) File an issue:
is_family_foldershould also accept a folder equal to the basename ofrepository:, keepingname:for holders laid out before #629. Change all three copies together, sincetest_the_three_commands_carry_the_same_resolver_byte_for_byteholds them equal.- Check that
resume'sROOT_REPOSITORY="$MANIFEST_ORG/$MANIFEST_DIRNAME"(resume:1185) agrees with the new rule. - Add a fixture whose
name:differs from its repository.
3. note: four assertions that cannot see what they guard
These are not caused by this PR. At 190133d each passes for the right reason, which I checked with the suite's own builders. But none would go red if upstream moved the thing it couples to.
tests/test_park_resume_commands.py:1247-1248."(b) the layout"and"holder TestFam"also appear inmake siblings' own tee'd output. A heading change that sentresume's step (5) (resume:1420,grep -q '^(b) the layout$') to(no layout table ...)(resume:1435) would stay green. At190133deach string appears twice, with no fallback line. Fix: assert.count(...) == 2, or assert that"(no layout table" not in stdout.:1981.BOOTSTRAP-{name} ranappears twice at both pins, because the holder's own bootstrap also runs each pinned member'smake bootstrap. So it does not prove that the sibling's own bootstrap ran. Fix: assertcount == 2.:1826-1840. It never checks the bootstrap's exit code. At190133dthe code is 0 (bootstrap ok; step (a) printedon main at ... (branch tip == pin)). Fix: assertproc.returncode == 0.:1843-1851. It asserts neitherresume's exit code nor the absence of "make bootstrapdid not exit 0". Fix: assert both.
4. note: the comment above root_legs_ok (resume:679-691) still names only two bootstrap moves
At 190133d, step (a) also:
- fast-forwards a behind tracking branch;
- moves a held branch back to the pin, which
_held_upstream_past_the_pinallows only from a HEAD detached AT the pin.
For legs with no branch: of their own, I walked every state the guard lets through (on the tracking branch; detached at the pin) against fast_forward_to_pin and move_back_to_pin. None loses a commit, so the PR's analysis holds there. Refresh the comment along with finding 1's fix.
5. note: opensoft/openRepoShape#503's $(error) path is unobserved here, as the PR says
A holder without scripts/siblings.py now stops on make's $(error), exit 2. Under park --all it is counted as refused (exit 2), exactly as the old can't open file was, so park's classification does not change. It is fine to leave.
6. note: the docstring citation is right, but nothing checks it
- The citation. Line 547 of
190133d:openRepoShapeissay " curl -fsSL https://raw.githubusercontent.com/opensoft/openRepoTools/main/openRepoTools | bash -s -- --install".cmpfinds it equal to line 280 of7f84ca4. - Nothing checks it automatically.
- The test (
tests/test_install_payload_source.py:917-922) runs only in composed acceptance, so it skips in a standalone checkout and on CI. - Its pipeline is a string literal, so "BYTE FOR BYTE" is a docstring claim only.
- A standalone hygiene assertion that reads that line out of
upstream/openRepoShapewould check it.
- The test (
- No other citation moved. Grepping
tests/for<file>:<n>andline <n>citations finds no other openRepoShape line reference.
Verified, no finding
- Rule 2.
gh api repos/opensoft/openRepoShape/compare/main...190133d5e704e380c430f87ca9c4e31746de0012returnsstatus: behind,ahead_by: 0,behind_by: 7, with merge base190133d.v1.1.0is tag objectb9c50999..., which peels to190133d5e704e380c430f87ca9c4e31746de0012, both locally and through the API. The release was published 2026-10-17T21:56:03Z. - Rule 3, the digest. I recomputed it in a fresh clone at
190133dthree ways, and all three give7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912:- (1) the pin file's own bump command, with the pinned
repo_shape.py; - (2) independently:
git ls-tree -r -z 190133d | LC_ALL=C sort -z | tr '\0' '\n' | sha256sum; - (3) the forge's recursive tree, with 320 records and not truncated.
- (1) the pin file's own bump command, with the pinned
- Rule 3, the cross-check.
- The old row
3be52767...reproduces. 7f84ca4's own helper, run on190133d, gives7a66972c....- The
tree_digestbody is byte-identical at both pins.
- The old row
- Rule 3, one commit.
6a8b320touches exactlycontracts/openreposhape-pin.yamlandupstream/openRepoShape, and onlycommit:andtree_sha256change in the pin file. The pin file has no tag or date field to move, and.gitmodulesis unchanged. - "Six of eight".
git diff --numstat 7f84ca4 190133dmatches every +/− in the body's table. Both.gitignores are unchanged.templates/workspace-rootis the same tree object (48e0be8) at both pins, so the byteswip initfetches at the pin do not change. - PR body.
- Base. Main moved to
2732d59(#212:lanes-edit.sh,skills/handoff/SKILL.mdand one new test) after this branch merged983d8c7.git merge-treeis clean. This PR's CI run tests merge refbdb8982, which is2732d59+b52394d.
What I ran
All of it ran in a fresh clone of this repository at b52394d, with the submodule initialized from GitHub (190133d (v1.1.0)), and a separate fresh clone of openRepoShape.
Scoped tests ran at the head under flock on the shared lock, with every listed LANES_* and TMUX variable unset, and a private HOME, TMPDIR, --basetemp and PYTHONPYCACHEPREFIX. Locally that is pytest 9.1.1, while CI pins 8.3.4.
tests/test_upstream_pin.py+tests/test_park_resume_commands.py: 151 passed.tests/test_status_command.py -k family: 3 passed.tests/test_install_payload_source.py -k one_liners: 2 skipped (composed acceptance).
Probe scripts (scratch, outside the repository) built the scenarios in findings 1–3 from the suite's own builders and each pin's own files.
Not run: the full suite. CI's Linux tests and tests-no-submodule are the suite of record. At the time of this review, guard-launch-mode had passed, and tests and tests-no-submodule were still running.
🤖 Generated with Claude Code
Takes in #232 (tests/run.sh records its lock owner), #233 (the openRepoShape pin at v1.1.0, 190133d) and #229 item 22 (the bench-root host-path hygiene rule). The two sides touch disjoint files, and no file this branch adds names a bench-root path. Lane: openRepoTools-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Lane openRepoTools-2, 2026-10-18: the full suite measured at #233's bump commit (tree
The tree measured
What ran
Each failure, classified
#180 on main since then: #215 ( The cause of the two SIGINT failures is supported, not proven: the harness started the run in the background from a non-interactive shell, so the run inherited SIGINT as ignored. The baseline rerun logs A diagnostic is queued: Install check:
Digest and compare
Lane: openRepoTools-2 |
Brings in d424b64 (#201), 61a7378 (#215, the lane-start clause (c) TAIL fix), 19c2e25 (#232, tests/run.sh's lock owner), f685866 (#233, the openRepoShape pin at v1.1.0, 190133d) and f595e44 (#229 item 22, the hygiene rule on bench-root host paths) on top of 83d2690. Both sides change lanes-edit.sh and docs/README-lanes.md, in disjoint hunks: main's are `swapped`'s row spelling (Amendment 15) and its manual paragraph, the branch's are project-legs, lane-reconcile's leg and paired-root reads and the T018 section. git merged both with no conflict. bash -n passes on lanes-edit.sh, lane-handoff, lane-start, lane-end, tests/run.sh and tests/test_lane_helpers.sh. Lane: openRepoTools-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Lane openRepoTools-2, 2026-10-18: addendum to 6244714538, the SIGINT diagnostic. Result: with SIGINT not ignored, both
Lane: openRepoTools-2 |
…rea, and add the lines for #263, #289, #294 and #296, the changes after a42946e (#228) `docs/release-notes/v1.1.0.md` takes the fixes of lane 3's review of d8a349d (#293 comments 6314185715 and 6314529807, the second of which replaces three of the corrected texts of the first) and the lines for the changes after a42946e. The review's fixes: - Line 45 (#255, #271) no longer says that `lane-reconcile` and `lane-handoff` read a dependency nested in a leg: only the sweep and `lane-end` do. It says that a leg directory this account cannot search is unreadable and never `absent`, that a nested dependency is unreadable to the sweep and `lane-end` too, and that the sweep still reads a declared leg beneath such a directory as `absent` (#272, open). It also says NOT POLLED where the tool does. - Line 46 (#280, #283): an `awk` exits, it does not return, and the sentence on a status of 0 or 8 is gone. - Line 61 (#214): the fence never checks whose a local commit is, only that it adds or changes a register or handoff file. - The `<other-changes>` item counts 44 of the 53, because the openRepoShape pin's line (#233) is in the list, and the other 9, not 43 and 10. The milestone item names #247 and lists the six entries of 2026-10-20. - #209 is not tests-only: its `-e` fixes `lanes`' stderr filter under macOS's BSD grep, so it moves from the test suite to the lane area, and its one line there carries its test changes too. It is cited once. The lines for the changes after a42946e, each in its area and worded from its squash commit and description: #263 (d9065df) and #289 (fb2cf36) under the register and `lanes-edit.sh`, #294 (acc89ea, which closes #292) under `lane`, `lane-start`, `lane-end` and the name guard, and #296, which pins every Ubuntu runner to ubuntu-24.04, under the test suite and its checks. #296 has not landed yet: lane 3 lands it right before #293. The `<other-changes>` item says the lines were added on 2026-10-21 and are not in its counts, and the placeholder stays for #293 itself. Not touched: lane 3's optional sentence on #271 and its NIT on the tag. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… 1.1.0 and list, by area and from the squash titles of aaa7bc8..a42946e, what else changed on main since v1.0.0 (#228) (#293) Part of #228. It brings `docs/release-notes/v1.1.0.md` up to date on main: first on `a42946e`, as lane 3 asked on Brett Heap's word (#228 comment 6303608345, the section for lane openRepoTools-2, task 1), then with lane 3's review of `d8a349d` (comments 6314185715 and 6314529807 on this pull request), with the lines for the three changes that landed after `a42946e`, and with the line for #296, which landed right before this pull request. It is one file, changed in two commits (`d8a349d` and `bebb77d`), 59 insertions and 4 deletions against main. Lands last before rehearsal D's freeze; lane 3 reviews and merges it (#228 6303608345) **What changed** - **Lane 3's review is applied,** in the second commit: - **The line on #255 and #271** no longer says that `lane-reconcile` and `lane-handoff` read a dependency nested in a leg, since only the sweep and `lane-end` do. It says that a leg directory this account cannot search is unreadable and never `absent`; that a dependency nested in a leg whose directory, or one above it, it cannot search is unreadable to the sweep and `lane-end` too; and that one known gap remains, #272, where the sweep reads a declared leg beneath such a directory as `absent`, so `lane-end` does not hold on it. It also says NOT POLLED where the tool prints it, and it says that the item closes two gaps in #246, where it said "both gaps" with nothing before it to refer to. - **The line on #280 and #283:** an `awk` exits and does not "return", and the sentence on a status of 0 or 8 is gone, because a reader of the notes cannot act on it. - **The line on #214:** the fence passes a local commit only when it adds or changes a register or handoff file, and never checks whose it is, so the line no longer says "the lane tooling's own". - **The counts in the `<other-changes>` item:** the pin's line (#233) is in the list, so the list carries 44 of the 53, and the other 9 have their lines under "What 1.1.0 adds", not 43 and 10. The item says "the openRepoShape pin" where the runner pin of #296 could be taken for it. - **The milestone item** names #247, so it lists the six entries the milestone held on 2026-10-20. - **#209 is not tests-only.** Its `-e` fixes `lanes`' stderr filter under macOS's BSD `grep`, so it moves from the test suite to the lane area, after #208's, and its one line there also carries its test changes: the `repoG#8` assertion and the count of bash files in prose. It is cited once. - **Lines for the changes after `a42946e`:** #263 (`d9065df`), #289 (`fb2cf36`) and #294 (`acc89ea`, which closes #292) landed on 2026-10-21, from 11:28Z to 11:30Z. Each has a line in its area, worded from its squash commit and its description: #263 and #289 under "The register and `lanes-edit.sh`", and #294 under "`lane`, `lane-start`, `lane-end`, the name guard and their helpers". - **#296 has its line too,** last under "The test suite and its checks": CI and the release workflow run on `ubuntu-24.04`, because `ubuntu-latest` is now Ubuntu 26.04, and `macos-latest` is unchanged. It landed right before this pull request, as `5afba4a`. - **"What 1.1.0 adds" gains two lines,** after the annotated-tags item. They are for the three entries that closed in the v1.1.0 milestone after the draft was written: - **#255,** fixed by #271: the lane tools name what they could not read in a triad's legs. `lane-handoff` names every tree-inventory record that is not a whole schema-1 one, and a leg directory this account cannot search is unreadable and never `absent`. Only the sweep and `lane-end` also see a dependency nested in such a leg, since `lane-reconcile` and `lane-handoff` read declared legs only, and #272 stays open as the known gap. - **#280,** fixed by #283: `lane-handoff` reads the lane's lifecycle whole and parses it afterwards, so an `awk` that exits early can no longer turn `lane-state`'s SIGPIPE into a lifecycle that could not be read. - #283 is #280's pull request, so the three numbers make two lines. Each line cites the issue and its pull request, as the hook-pair line does for #237 and #247. - **"What else changed since v1.0.0" is drafted** from `git log aaa7bc8..a42946e`, which is 53 squash commits, one pull request each and no merge commit. It is grouped by area, one line each, and each line ends with its pull request. It lists 44 of the 53: the pin's line (#233) at its head and 43 by area, as 4 on the estate commands, 10 on the register and `lanes-edit.sh`, 11 on `lane`, `lane-start`, `lane-end` and the name guard, 6 on the handoff and its skill, 1 on the lane tools in a triad's legs (#246), 9 on the test suite and its checks, and 2 on the triad migration's records. - **The other 9 are accounted for elsewhere:** the package series of #228 (#262, #267, #268, #269, #270 and #284) is covered by #228's lines, and #247, #271 and #283 have the lines above. - **The lines added on 2026-10-21** are for the four changes after `a42946e`: #263 and #289 on the register and `lanes-edit.sh`, #294 on `lane`, `lane-start`, `lane-end` and the name guard, and #296 on the test suite and its checks. The areas now hold 47 lines, one for each of 47 pull requests, and #233's line at the head of the list makes 48. - **The list is redone at the tag.** It is drafted from the squash titles only. - **"Before the tag" is updated in three items:** - `<pr-count>` gives the count at `a42946e`, which is 53; - `<other-changes>` says what was drafted, which 9 pull requests have their lines under "What 1.1.0 adds", that the lines for #263, #289, #294 and #296 were added on 2026-10-21, and what is left to do at the tag; the placeholder's own line now stands for the changes after `a42946e` that have no line above; - the milestone item names the six entries the milestone held on 2026-10-20: #228 still open, #237 closed by its pull request #247, #255 closed, and #280 closed by its pull request #283. **Not added:** nothing that has landed. #296 landed right before this pull request and has its line. This pull request itself, and whatever lands after it, is what the `<other-changes>` placeholder stands for. None of #263, #289, #294, #296 and #292 is in the v1.1.0 milestone, which still holds the six entries of 2026-10-20. **How this keeps the draft's rules** - **One-line paragraphs:** every added line is its own list item, and none is wrapped. - **References:** every reference above "Before the tag" is spelled `opensoft/openRepoTools#N`, with no bare `#N`, since the notes are published from another repository after the migration. - **Placeholders:** `<other-changes>` stays as a named placeholder in code font, as the closing line of the list and as its checklist item. `<pr-count>` is unchanged apart from the drafting-time count. - **The file's closing lines are untouched:** the self-naming last line stays last. **Tests** - **T023's verify command** passes: the last line names `openRepoTools-spec` and `docs/release-notes/v1.1.0.md`, `## Before the tag` is there, and so is `pipx install --force openrepotools`. - **Coverage:** a script over `git log aaa7bc8..acc89ea`, 56 commits and no merge, finds each pull request cited above "Before the tag" except the six of #228's package series, which #228's lines cover. That is 46 by area, #233 at the head of the list, and #247, #271 and #283 under "What 1.1.0 adds". #296 is not in that range, and its line cites it. - **Hygiene:** by grep over `tests/`, no test names this file. The two that read its content scan every tracked file, and both are in `tests/test_repo_hygiene.py`. The only other test that names `release-notes` is in `tests/test_release_workflow.py`, and it reads `release.yml`, not the notes. All of `tests/test_repo_hygiene.py` was run on the file, through `tests/run.sh` with every `LANES_*` and `TMUX*` variable unset: ```text -k 'repo_hygiene' -v collected 2933 items / 2696 deselected / 237 selected 237 passed, 2696 deselected in 2.59s ``` - **Not run:** the whole suite. CI's `tests` job is the suite of record. This pull request's own runs on `bebb77d` went red on `ubuntu-latest`, which is Ubuntu 26.04, for the reasons #296 gives, because #296 was not yet on main. The record is lane 3's queue run over main, #296 and `bebb77d`, on `ubuntu-24.04` (below). **Where the draft's rules left room, and lane 3's answers (comment 6314185715)** - **Which section holds #255 and #280:** "What 1.1.0 adds", because the milestone is Brett Heap's scope for the release and #237 with #247 already sit there. - **`<other-changes>` stays** as a closing placeholder after the drafted list, since this pull request itself lands after `a42946e`. - **How much to list:** the tests-only and migration-record lines stay through the tag, because the check that every pull request has a line depends on them. If Brett Heap wants a shorter body, they fold into one line that still lists every pull request number. - **Issues and pull requests:** the milestone lines cite both, and the area lines cite the pull request only. **Lane 3's re-check of `bebb77d`** (#293 6315668503) is MERGE AFTER FIXES. - **What holds:** every line lane 2 listed, the recount behind line 140 (44 of the 53 pull requests in `aaa7bc8..a42946e`, and 56 in `aaa7bc8..acc89ea`), the file's rules, and T023's verify commands. - **One SHOULD and two NITs, all wording:** - line 45's sentence on a dependency nested in a leg, where "one above it" reads as a directory above the leg, which is #272's case. The text was lane 3's own; - "One known gap" in the same line; - line 74's last clause. - **Why they wait:** lane 3 merges the notes as tested and carries the three fixes into the notes' final pass at the tag. A push here would cost another CI round while lane 2 is out of usage until 15:30Z, and the notes are edited again at the tag in any case. Lane: openRepoTools-2 Landed by lane openRepoTools-3, as queue prefix `lane3-queue-u/p2-293` (tree `9b879ca`; tests.yml run 39595166877, green on `ubuntu-24.04`), right after #296. Before the landing, lane 3 merged main into the branch, so that its own checks ran over main with #296; the content is unchanged. Brett Heap's word, of 2026-10-20T22:5xZ: "merge all when green for all merges thru v1.1.0. use this for all lanes" (#228 6303614082). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>



Part of #186
Independent review: 5560570028 (LAND after fixes); findings 1-2 are filed as #235 and #236, and notes 3, 5 and 6 as #193 item 26.
Why v1.1.0
Brett Heap's hold of 2026-10-13 (#186, comment 6152410188) held every bump of
upstream/openRepoShapeuntil openRepoShape v1.0.0 was tagged. It said the bump would come as ONE pull request after the tag, as #188 was, scheduled by lane 1, and to expect test updates in it. Then, on 2026-10-17T21:51Z, Brett gave his word, recorded by lane 3 on #186 (comment 6241785035): "Yes, wait for v1.1.0", and pin straight to it. That makes one pin update and one rehearsal, instead of a v1.0.0 rehearsal redone days later.v1.0.1 was never a candidate. Its commit
8cda139(opensoft/openRepoShape#577) sits on openRepoShape'srelease/v1.0, not onmain, socompare main...8cda139isdiverged, and AGENTS.md's pinned-standard rule 2 pins only a commit onmain.The fresh adoption rehearsal and plan at this pin come after this lands, as a separate task.
The target: v1.1.0, dereferenced, on
mainThe v1.1.0 release is published (2026-10-17T21:56:03Z).
contracts/openreposhape-pin.yamlrecords the commit, not the tag.What moved upstream:
7f84ca4...190133dstatus: ahead,ahead_by: 261,behind_by: 0, 281 files. Six of the eight files this suite mounts changed, one more than the hold notice counted at v1.0.0, because v1.1.0 also touched the assembly-root Makefile's help text. Unchanged:.gitignores;templates/workspace-root/files thattests/test_wip_init_command.pyandopenRepoTools --installread (git diff --stat 7f84ca4 190133d -- templates/workspace-rootis empty).Each upstream reference below is an opensoft/openRepoShape issue → pull request.
templates/assembly-root/Makefilemake bootstrapputs legs onto tracking branches at their pins "where that loses no commit, or says why not" (opensoft/openRepoShape#603 → opensoft/openRepoShape#615). Every recipe is unchanged.templates/family-root/Makefilesiblings,parkandresumefirst ask make's$(wildcard)whetherscripts/siblings.pyis there. A holder without it gets a refusal by name from$(error)(make's exit 2), namingupdate-shape.py checkandapply --add. Before, it died oncan't open file(opensoft/openRepoShape#489 → opensoft/openRepoShape#503).templates/family-root/scripts/siblings.pymake siblingschecks the family folder BEFORE it clones, and REFUSES (exit 1, nothing cloned, fetched or moved) when the holder is not in a folder named after the holder's repository; it clones each member on its tracking branch (opensoft/openRepoShape#543 → opensoft/openRepoShape#578). The folder rule itself: the family folder and the holder are named after the holder's REPOSITORY, never aftername:, the display name (opensoft/openRepoShape#629 → opensoft/openRepoShape#642,siblings.py:18). The same PR spells the family name and every member row, so no run ends in a traceback underPYTHONIOENCODING=ascii(opensoft/openRepoShape#454). The printed folder move is quoted (opensoft/openRepoShape#486, opensoft/openRepoShape#487, opensoft/openRepoShape#488 → opensoft/openRepoShape#507). That move runs as typed past a taken staging name and names a dangling link. A NUL or lone surrogate inproject:or a url is a finding,.gitmodulesis read as git reads it, and a tag-only branch is named (opensoft/openRepoShape#690 → opensoft/openRepoShape#805). git output is decoded as UTF-8 (opensoft/openRepoShape#217 → opensoft/openRepoShape#230).templates/family-root/scripts/bootstrap.py--no-membersprints the case-variant move (opensoft/openRepoShape#648 → opensoft/openRepoShape#682). A member with an operation in progress, or an ignored file in the way, is refused, and a machine with no git isgit-not-runnable(opensoft/openRepoShape#704, opensoft/openRepoShape#694 → opensoft/openRepoShape#745). Output is spelled and stdout escaped (opensoft/openRepoShape#391 → opensoft/openRepoShape#456). git output is decoded as UTF-8 (opensoft/openRepoShape#230).templates/assembly-root/scripts/bootstrap.py• a tracking branch BEHIND the pin is fast-forwarded to it, and a fresh clone's branch AHEAD of the pin with no commit of its own is moved back to it (opensoft/openRepoShape#475 → opensoft/openRepoShape#490);
• a leg DETACHED OFF the pin is left where it is and said (opensoft/openRepoShape#533 → opensoft/openRepoShape#556);
• a leg on ANOTHER branch whose tracking branch is behind the pin is fast-forwarded and checked out, as one at the pin already was (opensoft/openRepoShape#603 → opensoft/openRepoShape#615);
• a leg with an operation in progress, or an ignored file in the way, is refused before any move, and no git is
git-not-runnable(opensoft/openRepoShape#704, opensoft/openRepoShape#694 → opensoft/openRepoShape#745);• a branch holding a NUL or lone surrogate is a finding and is never handed to git (opensoft/openRepoShape#455 → opensoft/openRepoShape#644);
• output is spelled (opensoft/openRepoShape#456).
scripts/repo_shape.pyNew helpers:
spelled,escape_unencodable_stdout,shell_quotedandshell_line(opensoft/openRepoShape#456, opensoft/openRepoShape#507).Pins and links: product keys, link sources and pin sources (opensoft/openRepoShape#409, opensoft/openRepoShape#453, opensoft/openRepoShape#576, opensoft/openRepoShape#638, opensoft/openRepoShape#634).
Adoption and family:
originreading (opensoft/openRepoShape#591), the submodule-leg record (opensoft/openRepoShape#394), relative.gitmodulesurls (opensoft/openRepoShape#245), family gitlink findings (opensoft/openRepoShape#406) and plan-writer escaping (opensoft/openRepoShape#247).Subprocess and refusals: UTF-8 subprocess reads (opensoft/openRepoShape#230) and remedy-less refusals (opensoft/openRepoShape#494).
tree_digestandTREE_DIGEST_DEFINITION(sorted-ls-tree-r-v1) did not change. Nothing in this repository imports anything else from it.The bump: pin and gitlink in ONE commit, digest RECOMPUTED
The bump ran exactly as
contracts/openreposhape-pin.yamlstates. The first commit holds exactly two paths:contracts/openreposhape-pin.yamlandupstream/openRepoShape. In the pin file onlycommit:anddigests.tree_sha256change, and every comment is kept.tree_sha2567f84ca42ca86a8902928345109d2bf6bad87bd913be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8190133d5e704e380c430f87ca9c4e31746de00127a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912Cross-checks in both directions:
190133d's helper, run on7f84ca4, prints the old row3be52767…again.7f84ca4's own helper (itsscripts/repo_shape.pybytes, run from a scratch copy), run on190133d, prints the new row7a66972c….So
sorted-ls-tree-r-v1means the same thing on both sides of the bump. Nothing underupstream/openRepoShapewas edited; the bump is a checkout of a different commit.Remaining references to the old pin
command grep -rn -- 7f84ca4 --exclude-dir=upstream --exclude-dir=.git .finds these:commit:line, which the first commit moves.tests/test_install_payload_source.py, which cited openRepoShape's--installpointer asopenRepoShape:280 at 7f84ca4. At190133dthe same bytes are on line 547, so the second commit moves the citation.cmpof the two lines is equal, so the test's BYTE FOR BYTE claim still holds. The change is docstring-only, and the test's pipeline string is untouched.specs/004-migrate-to-triad/andopenspec/changes/migrate-to-triad/: rehearsal records, checklists, the inventory, and the adoption plan made at7f84ca4. These are records of runs at that pin, so they stay as they are..gitmodulesnames nobranch=, so it does not move.Tests: no expectation moved
No test expectation moved, so this PR changes no test and no product code. Every run below is at
190133d, withHOME,TMPDIR,--basetempandPYTHONPYCACHEPREFIXisolated under a scratch directory.Before the merge of
main(0af03bc, onaa14de3):tests/test_upstream_pin.pytests/test_park_resume_commands.pytests/test_status_command.pytest_wip_init_command,test_test_roots,test_install_payload_source,test_repo_hygieneThe 9 skipped tests are composed-acceptance tests, which a standalone checkout always skips.
In the last row all five failures were
test_wip_init_and_the_lane_helpers_read_one_pointer_file_the_same_way, and the cause was the run's environment, not the pin. The lane session exportedLANES_REPOandLANES_WORKSPACE_ROOT, andwip_envdoes not strip them, solanes-edit.shfound a real register and exited 8 where the test expects 1. With those variables unset, as on CI, all 6 parametrizations pass. That isolation gap predates this PR and is #193 item 25.After the merge of
main(this head;983d8c7, #196, touchesspecs/only). Each run had everyLANES_*andTMUX*variable removed, which the run verified (0 left):tests/test_upstream_pin.pytests/test_wip_init_command.py, the module holding the test abovetests/test_install_payload_source.pyFull suite: a local
tests/run.shunderflock ${TMPDIR:-/tmp}/openrepotools-pytest.lock, with the lane variables unset, was stopped for an account swap at about 19%. By then it had run 300 passed, 9 skipped, 0 failed. It was not re-run: CI is the suite of record (AGENTS.md ruling 3), so this PR's Linuxtestsandtests-no-submodulejobs are the full result.Why the behaviour changes the hold notice pointed at turn nothing red, and the two gaps they open that this suite cannot see:
siblings,parkandresumerefuse by name whenscripts/siblings.pyis absent, and update-shape.py says the Makefile it copies calls it, so a holder updated without--addno longer fails oncan't open file(#489) openRepoShape#503, the family Makefile. The new refusal fires only for a holder WITHOUTscripts/siblings.py.seed_holderintests/test_park_resume_commands.pyis the suite's only real family holder, and it copiessiblings.pyfrom the pin, withrepo_shape.py, which the familybootstrap.pynow importsspelledandescape_unencodable_stdoutfrom. Soparkandresumepass through the new guard and run as before. No test here observes the refusal itself.bump-leg.pythenmake bootstrap, andgit clone --recurse-submodulesthenmake bootstrap, leave the leg on its branch AT the pin, no longer detached undernot moving an existing branch(#475) openRepoShape#490, bootstrap.py: a leg detached off the pin is left where it is and said, so a commit made there is no longer stranded when its branch is already at the pin, thenot moving an existing branchline names where the checkout is, and bump-leg.py and AGENTS-shape.md say "or says why not" (#533) openRepoShape#556, 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) openRepoShape#615 and bootstrap.py and AGENTS-shape.md: a leg with an operation in progress or an ignored file in the way is refused, P9 names the branch it left, and no git isgit-not-runnable, somake bootstraploses nothing (#704) (#694) openRepoShape#745, assembly bootstrap's step (a).branch:of its own:resume'sroot_legs_okrefuses a root whose leg is on any branch but the root's tracking branch, or is detached anywhere but the pin, before any bootstrap runs. Bootstrap's new moves (fast-forward, move back, the other-branch checkout) never take a leg the guard lets through into a state it missed; the review walked every such state.branch:, that does NOT hold. The guard compares the leg with the ROOT'stracking_branch(resume:694), while bootstrap places the leg on its own branch (bootstrap.py:1064at190133d). Soresumeexits 0 over a leg bootstrap moved, and refuses a leg sitting on its own branch. The blind spot predates v1.1.0: with the declared branch AT the pin, the leg moves at7f84ca4too. 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) openRepoShape#615 widens it to a declared branch BEHIND the pin. It is filed as resume's leg guard checks each leg against the root's tracking_branch, not the leg's own branch:, so it lets bootstrap move a leg (exit 0) and refuses a leg on its own branch #235, reproduced at both pins. This PR does not cause it, because estates run their own copies ofbootstrap.py, not this mount.resumerelies on is lost: a leg mid-merge on its tracking branch, which the guard lets through, is now reported and left alone.mainwhenmainis at the pin, now also whenmainis behind it.test_the_real_bootstrap_would_have_moved_that_legpasses against the new bytes, so that guard still guards something real.make siblingsandfamily.py siblings: clone each member on its tracking branch, warn before cloning outside a<Family>folder, and run the holder's pinned siblings.py openRepoShape#543 and family.py init--name: the holder's README and AGENTS.md name its folder after the display name, wheremake siblingsneeds the repository's name, so a holder laid out as its README says clones nothing openRepoShape#629, the family folder. Nothing here is red, because the suite's only family (FAMILY_YAML,tests/test_park_resume_commands.py:111-120) has aname:equal to its repository's basename.park,resumeandstatusfind a family folder byfamily.yaml'sname:(is_family_folder,park:259-268). A v1.1.0 holder'smake siblingsrequires the folder to carry the repository's name, and stops before cloning otherwise. So a family whosename:differs from its repository has no layout both accept.Not done, deliberately
upstream/openRepoShape.scripts/siblings.py. Such a test would observe family Makefile:siblings,parkandresumerefuse by name whenscripts/siblings.pyis absent, and update-shape.py says the Makefile it copies calls it, so a holder updated without--addno longer fails oncan't open file(#489) openRepoShape#503's refusal, but it is new scope (Triad migration: follow-ups deferred at the landing of #190 and #192 #193 item 26).--installdocstring citation. Line 547 at190133dequals line 280 at7f84ca4bycmp, but only composed acceptance runs that test. A hygiene assertion that reads the line out of the mount is Triad migration: follow-ups deferred at the landing of #190 and #192 #193 item 26.resume'sroot_legs_ok, and its comment, are left as they are. The comment still names only the two moves bootstrap made at7f84ca4. The guard is correct for legs with nobranch:of their own, and wrong for legs that declare one. Both the comment refresh (review note 4) and the per-leg branch check belong to resume's leg guard checks each leg against the root's tracking_branch, not the leg's own branch:, so it lets bootstrap move a leg (exit 0) and refuses a leg on its own branch #235.wip_envisolation gap is left for its own change.tests/test_wip_init_command.pylets a caller'sLANES_REPOandLANES_WORKSPACE_ROOTthrough tolanes-edit.sh. It is unrelated to the pin, so it is Triad migration: follow-ups deferred at the landing of #190 and #192 #193 item 25 and this PR leaves it alone.🤖 Generated with Claude Code