Skip to content

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

Merged
brettheap merged 3 commits into
mainfrom
chore/openreposhape-pin-v1.0.1
Oct 18, 2026

Conversation

@brettheap

@brettheap brettheap commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

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/openRepoShape until 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's release/v1.0, not on main, so compare main...8cda139 is diverged, and AGENTS.md's pinned-standard rule 2 pins only a commit on main.

The fresh adoption rehearsal and plan at this pin come after this lands, as a separate task.

The target: v1.1.0, dereferenced, on main

$ git -C upstream/openRepoShape rev-parse v1.1.0 'v1.1.0^{commit}'
b9c509997727927acc20b15d9b9e04aa08b56c01
190133d5e704e380c430f87ca9c4e31746de0012
$ gh api repos/opensoft/openRepoShape/git/tags/b9c509997727927acc20b15d9b9e04aa08b56c01 --jq '.tag, .object.sha, .tagger.date'
v1.1.0
190133d5e704e380c430f87ca9c4e31746de0012
2026-10-17T21:29:43Z
$ gh api repos/opensoft/openRepoShape/compare/main...190133d5e704e380c430f87ca9c4e31746de0012 --jq '{status, ahead_by, behind_by}'
{"ahead_by":0,"behind_by":2,"status":"behind"}

The v1.1.0 release is published (2026-10-17T21:56:03Z). contracts/openreposhape-pin.yaml records the commit, not the tag.

What moved upstream: 7f84ca4...190133d

status: 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:

  • the two .gitignores;
  • the nine templates/workspace-root/ files that tests/test_wip_init_command.py and openRepoTools --install read (git diff --stat 7f84ca4 190133d -- templates/workspace-root is empty).

Each upstream reference below is an opensoft/openRepoShape issue → pull request.

file +/− what moved
templates/assembly-root/Makefile +3 −2 Help text only. make bootstrap puts 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/Makefile +32 −0 siblings, park and resume first ask make's $(wildcard) whether scripts/siblings.py is there. A holder without it gets a refusal by name from $(error) (make's exit 2), naming update-shape.py check and apply --add. Before, it died on can't open file (opensoft/openRepoShape#489 → opensoft/openRepoShape#503).
templates/family-root/scripts/siblings.py +516 −94 make siblings checks 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 after name:, 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 under PYTHONIOENCODING=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 in project: or a url is a finding, .gitmodules is 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 +405 −35 A member no credential would check out fails the family bootstrap. Every row's gitlink is asked before any checkout, and --no-members prints 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 is git-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 +776 −52 Step (a) places a leg only where that loses no commit, or says why not:
• 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.py +1352 −187 The YAML reader is hardened: quoted scalars and escapes, flow items and their separators, an explicit-key refusal, block-scalar records, a non-UTF-8 refusal, refused indicator-led plain scalars and empty flow entries, and line-numbered remedies (opensoft/openRepoShape#193, opensoft/openRepoShape#244, opensoft/openRepoShape#257, opensoft/openRepoShape#265, opensoft/openRepoShape#284, opensoft/openRepoShape#390, opensoft/openRepoShape#635, opensoft/openRepoShape#817).
New helpers: spelled, escape_unencodable_stdout, shell_quoted and shell_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: origin reading (opensoft/openRepoShape#591), the submodule-leg record (opensoft/openRepoShape#394), relative .gitmodules urls (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_digest and TREE_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.yaml states. The first commit holds exactly two paths: contracts/openreposhape-pin.yaml and upstream/openRepoShape. In the pin file only commit: and digests.tree_sha256 change, and every comment is kept.

commit tree_sha256
old 7f84ca42ca86a8902928345109d2bf6bad87bd91 3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8
new 190133d5e704e380c430f87ca9c4e31746de0012 7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912

Cross-checks in both directions:

  • 190133d's helper, run on 7f84ca4, prints the old row 3be52767… again.
  • 7f84ca4's own helper (its scripts/repo_shape.py bytes, run from a scratch copy), run on 190133d, prints the new row 7a66972c….

So sorted-ls-tree-r-v1 means the same thing on both sides of the bump. Nothing under upstream/openRepoShape was 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:

  • The pin's commit: line, which the first commit moves.
  • One test docstring in tests/test_install_payload_source.py, which cited openRepoShape's --install pointer as openRepoShape:280 at 7f84ca4. At 190133d the same bytes are on line 547, so the second commit moves the citation. cmp of 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.
  • Dated evidence under specs/004-migrate-to-triad/ and openspec/changes/migrate-to-triad/: rehearsal records, checklists, the inventory, and the adoption plan made at 7f84ca4. These are records of runs at that pin, so they stay as they are.

.gitmodules names no branch=, 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, with HOME, TMPDIR, --basetemp and PYTHONPYCACHEPREFIX isolated under a scratch directory.

Before the merge of main (0af03bc, on aa14de3):

selection result
tests/test_upstream_pin.py 15 passed
tests/test_park_resume_commands.py 136 passed
tests/test_status_command.py 200 passed
test_wip_init_command, test_test_roots, test_install_payload_source, test_repo_hygiene 358 passed, 9 skipped, 5 failed from the environment (below); that test re-run with the lane variables unset: 6 of 6 passed

The 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 exported LANES_REPO and LANES_WORKSPACE_ROOT, and wip_env does not strip them, so lanes-edit.sh found 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, touches specs/ only). Each run had every LANES_* and TMUX* variable removed, which the run verified (0 left):

selection result
tests/test_upstream_pin.py 15 passed
tests/test_wip_init_command.py, the module holding the test above 63 passed, all 6 parametrizations of that test among them
tests/test_install_payload_source.py 100 passed, 9 skipped (composed acceptance)

Full suite: a local tests/run.sh under flock ${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 Linux tests and tests-no-submodule jobs 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:

Not done, deliberately

🤖 Generated with Claude Code

Brett Heap and others added 3 commits October 17, 2026 21:57
…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>
@sourcery-ai

sourcery-ai Bot commented Oct 17, 2026

Copy link
Copy Markdown

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 @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 17, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This 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 bump

sequenceDiagram
    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
Loading

File-Level Changes

Change Details Files
Pins the mounted openRepoShape submodule to the dereferenced v1.1.0 commit and records its recomputed tree digest.
  • Updates the contract commit from 7f84ca4 to 190133d.
  • Recomputes the sorted-ls-tree-r-v1 SHA-256 digest and preserves the pin metadata/comments.
  • Moves the submodule gitlink without editing files under the mounted upstream tree.
contracts/openreposhape-pin.yaml
upstream/openRepoShape
Refreshes the sole non-contract reference to the old upstream pin without changing test behavior.
  • Updates a test docstring to cite the new upstream source line and commit.
  • Leaves all assertions, expectations, and pipeline strings unchanged.
tests/test_install_payload_source.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sonarqubecloud

Copy link
Copy Markdown

@brettheap brettheap left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 with tracking_branch_of "$root", which is the root's tracking_branch.
  • openRepoShape at 190133d.
    • templates/assembly-root/scripts/bootstrap.py:1064 places each leg on leg.get("branch") or branch.
    • templates/assembly-root/scripts/validate-manifest.py:627, _leg_branch_findings (opensoft/openRepoShape#455), makes a leg's branch a validated field that "wins over tracking_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. At 7f84ca4, 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 main at the pin, with local develop one 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_ok should compare each leg with that row's own branch:, falling back to the root's tracking_branch, exactly as bootstrap.py:1064 does. legs_of already 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's name:: park:259-268, resume:242-251 and status: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 NEVER name:, 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. At 7f84ca4 it 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:
  • (b) File an issue:
    • is_family_folder should also accept a folder equal to the basename of repository:, keeping name: for holders laid out before #629. Change all three copies together, since test_the_three_commands_carry_the_same_resolver_byte_for_byte holds them equal.
    • Check that resume's ROOT_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 in make siblings' own tee'd output. A heading change that sent resume's step (5) (resume:1420, grep -q '^(b) the layout$') to (no layout table ...) (resume:1435) would stay green. At 190133d each string appears twice, with no fallback line. Fix: assert .count(...) == 2, or assert that "(no layout table" not in stdout.
  • :1981. BOOTSTRAP-{name} ran appears twice at both pins, because the holder's own bootstrap also runs each pinned member's make bootstrap. So it does not prove that the sibling's own bootstrap ran. Fix: assert count == 2.
  • :1826-1840. It never checks the bootstrap's exit code. At 190133d the code is 0 (bootstrap ok; step (a) printed on main at ... (branch tip == pin)). Fix: assert proc.returncode == 0.
  • :1843-1851. It asserts neither resume's exit code nor the absence of "make bootstrap did 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_pin allows 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:openRepoShape is say " curl -fsSL https://raw.githubusercontent.com/opensoft/openRepoTools/main/openRepoTools | bash -s -- --install". cmp finds it equal to line 280 of 7f84ca4.
  • 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/openRepoShape would check it.
  • No other citation moved. Grepping tests/ for <file>:<n> and line <n> citations finds no other openRepoShape line reference.

Verified, no finding

  • Rule 2. gh api repos/opensoft/openRepoShape/compare/main...190133d5e704e380c430f87ca9c4e31746de0012 returns status: behind, ahead_by: 0, behind_by: 7, with merge base 190133d. v1.1.0 is tag object b9c50999..., which peels to 190133d5e704e380c430f87ca9c4e31746de0012, 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 190133d three ways, and all three give 7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912:
    • (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.
  • Rule 3, the cross-check.
    • The old row 3be52767... reproduces.
    • 7f84ca4's own helper, run on 190133d, gives 7a66972c....
    • The tree_digest body is byte-identical at both pins.
  • Rule 3, one commit. 6a8b320 touches exactly contracts/openreposhape-pin.yaml and upstream/openRepoShape, and only commit: and tree_sha256 change in the pin file. The pin file has no tag or date field to move, and .gitmodules is unchanged.
  • "Six of eight". git diff --numstat 7f84ca4 190133d matches every +/− in the body's table. Both .gitignores are unchanged. templates/workspace-root is the same tree object (48e0be8) at both pins, so the bytes wip init fetches at the pin do not change.
  • PR body.
    • It has no closing keyword.
    • Every openRepoShape reference is spelled opensoft/openRepoShape#n. The bare #186, #188 and #196 are this repository's own items.
    • Comments 6152410188 and 6241785035 on #186 exist and say what the body says.
    • compare main...8cda139 is diverged.
  • Base. Main moved to 2732d59 (#212: lanes-edit.sh, skills/handoff/SKILL.md and one new test) after this branch merged 983d8c7. git merge-tree is clean. This PR's CI run tests merge ref bdb8982, which is 2732d59 + 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

@brettheap

Copy link
Copy Markdown
Contributor Author

Body corrected per the independent review 5560570028: findings 1-2 → #235, #236; notes → #193 item 26. No code change; the head stays b52394d.

@brettheap brettheap added the ready landing gate: runs tests-macos once before the squash label Oct 18, 2026
@brettheap
brettheap merged commit f685866 into main Oct 18, 2026
8 checks passed
@brettheap
brettheap deleted the chore/openreposhape-pin-v1.0.1 branch October 18, 2026 02:09
brettheap pushed a commit that referenced this pull request Oct 18, 2026
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>
@brettheap

Copy link
Copy Markdown
Contributor Author

Lane openRepoTools-2, 2026-10-18: the full suite measured at #233's bump commit (tree 01fc493f = 6a8b320) before it landed as f685866: no failure caused by the bump; 1441 passed, 3 failed, all 3 pre-existing or environmental (9 skipped, all by design).

f685866 landed at 2026-10-18T02:08:43Z. I read its contracts/openreposhape-pin.yaml blob, eea57fb, and its upstream/openRepoShape gitlink, 190133d, with gh api; both equal the measured tree's. Main is now f595e44, and this measurement does not cover it.

<R> below is the bench's projects directory. The evidence is in <R>/.openrepotools-private-prep/work-20261017/lane2-pinbump-v101-run/, which has its own STATE.md.

The tree measured

What ran

  • Command: the command of CI's Linux tests job, python3 -m pytest tests -q, with pytest 8.3.4 in a venv on the system Python 3.12.3, and CI's four GIT_* identity variables.
  • Added flags: -p no:cacheprovider, plus --basetemp and --junitxml pointed into the run directory.
  • Environment: env -i, so no LANES_*, TMUX or CLAUDE_* variable reaches the run.
    • HOME, PYTHONPYCACHEPREFIX and --basetemp are scratch directories in the run directory.
    • OPENSPEC_TELEMETRY=0 is set, and ~/.local/bin is not on PATH.
  • TMPDIR: 86 characters long, the length W17 used when it measured the tests/run.sh: a long run root truncates the row stamp so test_lane_helpers.sh's clause (c) TAIL case fails locally while CI's plain pytest passes #180 cut on main.
  • Lock: flock -w 7200 on the workstation's shared pytest lock (${TMPDIR:-/tmp}/openrepotools-pytest.lock).
    • Queued 2026-10-17T22:13:25Z, took the lock at 22:24:06Z, so the wait was 10 min 41 s.
    • Ran until 2026-10-18T00:39:01Z: wall time 8093.94 s (2:14:53).
  • Collection: 1453 tests, the same number main aa14de3 collects.
  • Result: 3 failed, 1441 passed, 9 skipped, exit 1.
    • The log's sha256 is a89aa85d01d76cc5d4749e9b8a03577923cb89f55d88626910a9719b4f618d39; the junit file's is fcebd748…12f1.
    • All 9 skips are the composed-acceptance cases in test_install_payload_source.py, which skip by design in a standalone checkout. No test skipped because the dependency was missing.
  • Files that read the moved upstream files all passed:
    • test_park_resume_commands 136, test_status_command 200, test_upstream_pin 15;
    • test_wip_init_command 63, test_test_roots 40, test_repo_hygiene 160;
    • test_install_payload_source 100 passed and 9 skipped.

Each failure, classified

Test Class Evidence
tests/test_lane_helpers_suite.py::test_the_lane_helper_suite_passes PRE-EXISTING (#180 row-stamp cut) It did not time out. The shell suite ended 4596 passed, 4 failed, 0 skipped, 0 pending, and the four FAIL rows are repoA, repoA11b, repoCase and repoMix. W17's cut model (keep 230 characters, then cut back to the last space) applied at TMPDIR length 86 says repoA needs 247 characters, repoCase 246 and repoMix 243, so all three are dropped. repoA11b's printed row is cut before dir , so the model cannot compute it, exactly as on main. W17's run of the shell suite on main at pin 7f84ca4, also at TMPDIR length 86, has the same four FAIL titles at the same relative lines, the same 4596 / 4 footer and the same repoA11b row.
tests/test_run_wrapper.py::test_a_killed_run_removes_its_run_root_and_stops_the_suite[flock-2-130] PRE-EXISTING / ENV (not the bump) subprocess.TimeoutExpired … tests/run.sh … timed out after 30 seconds. Only this SIGINT case fails; the SIGTERM cases pass. It fails the same way at the baseline (same openRepoTools head aa14de3, pin 7f84ca4): a scoped rerun with the same harness gave 2 failed in 60.38s.
…[mkdir-lock-2-130] PRE-EXISTING / ENV (not the bump) Same evidence as the row above, in the same baseline rerun.

#180 on main since then: #215 (61a7378, landed after the measured base aa14de3) closes #180. It moves the repoA11b TAIL case to a checkout at a short fixed path. Lane 2 has not re-run the shell suite at current main, so whether repoA, repoCase and repoMix still fail there at TMPDIR length 86 is not measured.

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 SigIgn 0000000000000007, in which bit 1 is SIGINT. bash cannot trap a signal that was ignored when it started, so the trap … INT in run.sh never fires and the wrapper never exits. #233's Linux CI passes these same cases. W17's earlier run (its r3) cleared the same failure class by resetting SIGINT before flock.

A diagnostic is queued: C-sigdfl runs the two SIGINT cases at the bump with SIGINT reset to the default before the suite starts. It is waiting for the lock, and its result will follow as an addendum.

Install check: ./openRepoTools --install was run offline into a fresh HOME, at the bump and at the baseline.

  • Offline means shims for gh, curl and the rest that refuse and log each call, proxies pointed at a dead port, and GIT_ALLOW_PROTOCOL=file.
  • Both runs exit 0 and make 0 network calls.
  • Each places 31 files. The 30 that are not the install receipt are byte-identical between the two runs, and the receipt's 29 (name, sha256) rows are identical.
  • The install places nothing from the submodule. Only wip init reads it, through the 9 files of templates/workspace-root/, and those did not change in 7f84ca4..190133d.

Digest and compare

  • tree_sha256 at 190133d is 7a66972c7de193c050f77f97bffa13d8543c28d74f61ea210644e65aa3f37912 (sorted-ls-tree-r-v1).
    • It was recomputed with 190133d's own scripts/repo_shape.py, following the pin file's recipe.
    • 7f84ca4's copy of repo_shape.py gives the same number, and the old pin's 3be52767… is reproduced at 7f84ca4.
  • gh api repos/opensoft/openRepoShape/compare/main...190133d5e704e380c430f87ca9c4e31746de0012 read status: behind at 2026-10-18T01:41Z: ahead_by 0, behind_by 19, merge base 190133d. So 190133d is on openRepoShape's main.
  • 7f84ca4..190133d is 261 commits. Six of the 8 files the suite mounts changed; the two .gitignores did not.

Lane: openRepoTools-2

brettheap pushed a commit that referenced this pull request Oct 18, 2026
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>
@brettheap

Copy link
Copy Markdown
Contributor Author

Lane openRepoTools-2, 2026-10-18: addendum to 6244714538, the SIGINT diagnostic. Result: with SIGINT not ignored, both test_run_wrapper.py SIGINT cases pass at the bump (190133d) and at the old pin (7f84ca4). The harness cause is confirmed at both pins.

<R> is the bench's projects directory. The logs are in <R>/.openrepotools-private-prep/work-20261017/lane2-pinbump-v101-run/logs/.

  • Command and environment: the same setup as the full run in 6244714538.
    • Only the two node IDs test_a_killed_run_removes_its_run_root_and_stops_the_suite[flock-2-130] and [mkdir-lock-2-130] were run, with python3 -m pytest <ids> -q and pytest 8.3.4.
    • The run used env -i, so no LANES_* or TMUX variable reached it. HOME, --basetemp and PYTHONPYCACHEPREFIX were scratch directories, and TMPDIR was 86 characters long, as before.
    • The one change was that SIGINT was reset to its default before pytest started, using a Python exec shim. The run was wrapped in timeout 120.
  • Trees: the bump is the measured tree 01fc493f (= 6a8b320), with the gitlink at 190133d. The baseline is main aa14de3 with the gitlink at 7f84ca4. I ran them one at a time.
  • SIGINT state, as SigIgn in each log:
    • In both diagnostic runs it is 0000000001001004. Bit 1, which is SIGINT, is clear; the remaining bits are SIGQUIT, SIGPIPE and SIGXFSZ.
    • In the failing runs of 6244714538 it was 0000000000000007, in which bit 1 is set: SIGHUP, SIGINT and SIGQUIT were ignored.
  • Results:
    • At the bump: 2 passed in 0.60s, wall 1 s, exit 0.
    • At the baseline: 2 passed in 0.92s, wall 2 s, exit 0.
    • Neither run came near the 120 s cap. Before, with SIGINT ignored, both cases timed out at 30 s at both pins.
  • The lock was skipped under lane 2's rule: a scoped run of 2 minutes or less may skip it when HOME, TMPDIR, --basetemp and PYTHONPYCACHEPREFIX are all scratch directories.
    • The diagnostic that was queued for the lock had waited from 02:24:13Z without getting it, and was cancelled at 03:37:52Z, before it started.
  • What this means for the two run_wrapper failures in 6244714538:

Lane: openRepoTools-2

brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap added a commit that referenced this pull request Oct 21, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready landing gate: runs tests-macos once before the squash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant