Skip to content

The name guard and the SessionStart hook name an unreadable register or binding log instead of guessing a branch (#60) - #208

Merged
brettheap merged 3 commits into
mainfrom
fix/guard-names-unreadable-reads-60
Oct 18, 2026
Merged

brettheap merged 3 commits into
mainfrom
fix/guard-names-unreadable-reads-60

Conversation

@brettheap

@brettheap brettheap commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Lane: openRepoTools-5. Fixes the two indeterminate reads #60 names. Each one picked a branch of the (b) table instead of naming the read.

What was wrong

1. The register's text. register_text answers empty text and exit 0 when neither origin/<branch>:<path> nor the working file renders, because it ends in a printf. The guard's only register check was [ ! -f "$LANES_FILE" ]. A register file that exists but cannot be read, with no published copy, therefore reached the table with no rows. The table's last arm then refused it. Measured at f87fd5a with the suite's own fixtures (window repoGD-1, this uuid the row's last id, register text empty):

lanes-edit:   row      the register has no row for `repoGD-1`
lanes-edit: this window is lane repoGD-1, whose row does not name aaaa0012-1111-4000-8000-aaaa00121111 at all — the harness minted a new transcript with nobody acting (a /clear, a usage reset, a profile switch). ...
lanes-edit: run: lane-start --no-launch repoGD 1

Both the sentence and the cure are wrong for a read that did not happen.

2. The lane's binding log (drifted since the issue was filed). Since #87 the guard no longer calls guard_rename_is_newer. Its one remaining caller is the SessionStart hook (ssb_name_line). That test folded lane_binding_utc's 1 ("the log could not be read", e.g. two published logs differing only by case) into "no binding, so the rename is newer". Measured at f87fd5a: the session was renamed by a person to repoLate-1 a day ago, before the STARTED the row's own log carries, and the lane repoTwo-1 has two logs differing by case. The hook printed:

session name 'repoLate-1' is a lane name YOU set, newer than this window's binding to 'repoTwo-1' — the name guard offers the move at your next prompt (Amendment 12(h) rule 2); nothing was renamed here

That statement is about a binding nobody read, and here it is false.

What changed

  • The guard now tests the register's text positively, once, before the first row read. register_text | awk 'NF { t = 1 } END { exit !t }' runs right before the THE ROW section, and on no text the guard refuses with exit 2 (only 2 blocks a prompt), naming the read and printing the safe-mode bypass:
    lanes-edit:   window   gdsess:@12 'repoGD-1'
    lanes-edit:   session  aaaa0012-1111-4000-8000-aaaa00121111 'repoGD-1' (nameSource user) pid … profile t1
    lanes-edit:   row      not read
    lanes-edit: the register's TEXT could not be read — neither `origin/main:lanes/register-60.md` nor …/register-60.md rendered a line — so the ROW cannot be read and the triple cannot be verified. A register that could not be read is not a register with no row for this lane, and an indeterminate read refuses (Amendment 12(d)). If this workstation cannot answer at all, `claude --safe-mode` runs with every hook off — …
    
    • Where it sits, and why that differs from the issue's suggestion. The issue proposed putting the test beside the [ ! -f ] refusal. I tried that first. There, neither the window nor the session had been read yet, so this refusal's triple printed window not in tmux 'none' about a session that is in tmux. At the head of the row reads, the test is still once and before the table, and the triple is accurate.
    • Cost, against the 5 s budget. The text is cached beside $SE_CACHE_FILE for the life of the process, so the test moves the first render rather than adding one. With GIT_TRACE on a register padded to 1.3 MB, the agreeing case makes 1 git show of the register and 12 git commands in all, both before and after. The added cat | awk costs about 6 ms. A $( ) capture of the same text cost about 30 ms, which is why the check streams. Agreeing-case wall time over 11 alternating runs: before median 0.507 s, after 0.523 s (load average about 18). All 22 runs exited 0 and printed nothing.
  • guard_rename_is_newer now has a third state. It returns 0 newer · 1 not newer, or no nameSince · 5 the lane's log could not be read. Any lane_binding_utc status other than 0 or 8 is 5. The direction the issue asked to keep holds: an unreadable log is never "not newer", so the hook never types over a person's own /rename.
  • The SessionStart hook names that read. It refuses nothing and exits 0 as before:
    session name 'repoLate-1' is a lane name YOU set, and lane repoTwo-1's object log could not be read, so whether you set it after this window's binding is NOT known — nothing was renamed here, and the name guard puts it to you at your next prompt (Amendment 12(h) rule 4)
    
  • Dead code removed. gr_since in guard_run was the guard's input to guard_rename_is_newer until The name guard offers a readable, recoverable lane/session mismatch three choices, and lane-start resumes an exact transcript uuid, never a title #87, and nothing reads it. Removing it also saves one jnum per prompt.

No doc quotes either changed message. docs/README-lanes.md already promises that an unreadable register is refused by naming the read (the "Fail closed" section), and the code now does that.

Functions and regions edited

  • lanes-edit.sh: guard_run: new block immediately before # ---- THE ROW, from origin/<branch>…; the gr_since line removed.
  • lanes-edit.sh: guard_rename_is_newer: header comment and body.
  • lanes-edit.sh: ssb_name_line: the nameSource: user rename branch, now a case on the test's status.
  • tests/test_lane_helpers.sh: the Amendment 12 section, a new block after the "payload naming no cwd" case. The Amendment 15 section, a new block inside the "two published logs for one lane" fixture, before a15_unpublish.

Tests

Amendment 12 section: a register that is there and whose text could not be read. LANES_DIR keeps the logs and alias table in place, and LANES_FILE names a file on no published tree, so register_text falls through to it.

  • Empty file (runs on every host and uid). Asserts exit 2, the read named, the window in the triple, row not read, not the last arm's sentence, and the safe-mode bypass.
  • Mode-000 copy of the register (the issue's literal case). Asserts the same refusal. It is skipped as root, the suite's existing pattern.
  • Why not a dangling symlink. The brief suggested one, but it is not a fixture for this check: [ -f ] is false for a dangling link, so the existing workspace refusal already answers it before and after this change.

Amendment 15 section: the two-logs-differing-by-case fixture. A nameSource: user rename to repoLate-1 from a day ago, in a window bound to repoTwo-1. Asserts that session-start exits 0, names "lane repoTwo-1's object log could not be read", never says "newer than this window's binding", and types nothing.

Fail-before and pass-after, proved locally in isolation. The full suite was not run locally, per AGENTS.md; CI's tests job is the record. I built a scratch runner from this branch's tests/test_lane_helpers.sh: the prologue (lines 1–971, SRC_DIR pointed at the tree under test), the definitions of E, LOGD, LANE, LANES_CMD and profiles_root, the whole Amendment 12 section, the Amendment 15 section through the two-logs fixture, and the footer. It ran in its own mktemp -d sandbox with env -u LANES_EDIT -u LANES_WORKSPACE_ROOT -u LANES_REPO -u LANES_LANE -u LANES_FILE -u LANES_DIR -u LANES_PATH -u TMUX:

  • Source tree with f87fd5a's lanes-edit.sh: 343 passed, 7 failed. The 7 are exactly the new assertions (the window-in-triple one passes on both sides).
  • This branch: 350 passed, 0 failed, 0 skipped.

Also passing: python3 -m pytest tests/test_guard_launch_mode.py tests/test_repo_hygiene.py (165 passed), bash -n on both changed files, and git diff --check.

Closes #60

🤖 Generated with Claude Code

Summary by Sourcery

Fail closed on unreadable register and binding-log reads so the name guard and SessionStart hook never infer state from data they could not read.

Bug Fixes:

  • Make the name guard refuse with an explicit unreadable-register message instead of misreporting that the lane has no row.
  • Prevent SessionStart from treating an unreadable lane binding log as evidence that a user rename is newer, and report the indeterminate read without renaming.

Enhancements:

  • Remove the obsolete guard rename timestamp input and add a distinct unreadable-log state to rename comparisons.

Tests:

  • Add coverage for unreadable register files and case-colliding binding logs in the guard and SessionStart hook tests.

…or binding log instead of guessing a branch (#60)

Two reads in the name guard's family still picked a branch of the (b) table
when they had failed, rather than naming the read (Amendment 12(d)).

The register's text. `register_text` answers empty text and 0 when neither
`origin/<branch>:<path>` nor the working file renders. The guard checked only
`[ -f "$LANES_FILE" ]`, so a register that is there and unreadable reached the
table with no rows and was refused by its last arm: "whose row does not name
this uuid at all", cured by `lane-start --no-launch`, which cannot mend a read.
The guard now tests the register's text positively, once, before the first row
read and after the window and session reads, so the triple it prints names what
was read and `row not read`. It still answers 2. The text is cached for the
process, so this moves the first render rather than adding one: GIT_TRACE
counts one `git show` of the register per prompt with and without the test.

The binding log. `guard_rename_is_newer` folded `lane_binding_utc`'s 1 (log
unreadable, e.g. two logs differing only by case) into "no binding", so the
SessionStart hook, its one caller since #87, told a person their rename was
"newer than this window's binding" about a log it never read. It now returns
5 for that read; the hook says the lane's object log could not be read and
leaves the name alone, as before. `gr_since`, the guard's input to that test
until #87, is read by nothing and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR makes both guard and SessionStart behavior fail closed on indeterminate reads: the guard positively verifies register text before reading rows, while rename recency gains an explicit unreadable-log state that SessionStart reports without acting. Focused regression tests cover diagnostics, exit behavior, and prevention of accidental renames.

Sequence diagram for fail-closed register validation

sequenceDiagram
    participant Guard as guard_run
    participant Register as register_text
    participant Rows as Row reader
    participant Refusal as guard_refuse

    Guard->>Register: register_text
    Register-->>Guard: Rendered register text
    alt Text contains a line
        Guard->>Rows: Read the row
    else Text is empty or unreadable
        Guard->>Refusal: guard_refuse
        Refusal-->>Guard: Exit 2 with named read and safe-mode bypass
    end
Loading

Sequence diagram for unreadable binding log handling

sequenceDiagram
    participant Hook as ssb_name_line
    participant Recency as guard_rename_is_newer
    participant Binding as lane_binding_utc

    Hook->>Recency: guard_rename_is_newer
    Recency->>Binding: lane_binding_utc
    alt Binding log readable and rename is newer
        Binding-->>Recency: Binding timestamp
        Recency-->>Hook: Status 0
        Hook-->>Hook: Report newer rename, do not rename
    else Binding log cannot be read
        Binding-->>Recency: Read error
        Recency-->>Hook: Status 5
        Hook-->>Hook: Name unreadable log, do not rename
    end
Loading

File-Level Changes

Change Details Files
Fail closed when the register text cannot be read, instead of treating an empty read as a missing lane row.
  • Streams the cached register text through awk once before row evaluation and refuses with exit 2 when no content is rendered.
  • Reports the unread register, preserves an accurate window/session/row diagnostic, and includes the safe-mode bypass.
  • Removes the obsolete nameSince extraction from the guard path.
lanes-edit.sh
tests/test_lane_helpers.sh
Distinguish an unreadable lane binding log from a binding that is absent or older/newer.
  • Extends guard_rename_is_newer with status 5 for unreadable logs while retaining statuses for newer and not-newer cases.
  • Treats unexpected lane_binding_utc failures as unreadable rather than as evidence of rename recency.
lanes-edit.sh
Make SessionStart explicitly report unreadable binding logs without renaming or suppressing the hook.
  • Branches on the new status and names the affected lane log and unknown ordering.
  • Keeps SessionStart exit status 0 and leaves the user's session name unchanged.
lanes-edit.sh
tests/test_lane_helpers.sh
Add regression coverage for both indeterminate-read scenarios and their required side effects.
  • Tests empty and mode-unreadable register files for exit 2, accurate diagnostics, and absence of the misleading row message.
  • Tests case-colliding published logs to verify SessionStart reports the unreadable log, does not claim recency, and performs no rename.
tests/test_lane_helpers.sh

Assessment against linked issues

Issue Objective Addressed Explanation
#60 Detect when the register’s text cannot be read before consulting the name table, and refuse with a message that names the unreadable register read rather than claiming the lane has no row. ✅
#60 Preserve an unreadable lane binding log as a distinct state, so the hook neither claims a rename is newer than an unread binding nor silently treats it as not newer; name the unreadable log and leave the session name unchanged. ✅

Possibly linked issues


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

…tests this PR on today's main

Main moved 15 commits past this branch's base f87fd5a, through the suite's machinery and pin (.github/workflows/tests.yml, contracts/openreposhape-pin.yaml, tests/conftest.py, tests/test_repo_hygiene.py, upstream/openRepoShape), after this PR's last green run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tests this PR on today's main

Main moved 4 commits past this branch's base 2cb14a9, through the suite's machinery and pin (), after this PR's last green run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

brettheap added a commit that referenced this pull request Oct 18, 2026
…ane holds the object (#74) (#204)

Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137725493) was green on head af5b7ce with main 586dea2 in its tree.

Independent review (lane 5, Opus, of 4996156; the merges of main add nothing to the PR's diff): LAND.

Closes #74

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 18, 2026
…so a migrated PAUSED row stops showing NO LOG (#89) (#206)

Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137733527) was green on head cd3ced0 with main 586dea2 in its tree. Main 0a49697 merged with head cd3ced0 is tree f88c2f1, which queue run 39137981522 (workflow_dispatch of tests on 3f5f4b9) tested whole and green.

Independent review (lane 5, Opus, of 00b75e6; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed the unpickable (row) lanes as built (2026-10-18).

Closes #89

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap
brettheap marked this pull request as ready for review October 18, 2026 15:57
@sourcery-ai

sourcery-ai Bot commented Oct 18, 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 1 day and 9 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@brettheap
brettheap merged commit fca60f5 into main Oct 18, 2026
5 checks passed
brettheap added a commit that referenced this pull request Oct 18, 2026
…s why refuse it before writing, and the deferred lane-start command keeps --agent (#85, #72 items 5, 6) (#218)

Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137747959) was green on head bfc5ddd with main 586dea2 in its tree. Main fca60f5 merged with head bfc5ddd is tree b188309, which queue run 39137992777 (workflow_dispatch of tests on 586df3b) tested whole and green.

Independent review (lane 5, Opus, of 99f3853; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed refusing CR/LF at the door (2026-10-18).

Part of #85. Part of #72 (items 5-6).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 18, 2026
…ane-handoff renames the window only once the handoff can no longer be refused (#80 slices B and C) (#220)

Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137756635) was green on head 0b531e5 with main 586dea2 in its tree. Main 01eff2c merged with head 0b531e5 is tree a388312, which queue run 39137998354 (workflow_dispatch of tests on f335793) tested whole and green.

Independent review (lane 5, Opus, of 9f6fd2d; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed the rename trade as built (2026-10-18).

Part of #80 (slices B and C).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 18, 2026
…ession ids, so the dead-lane --force check and duplicate-holder fail closed (#67) (#221)

Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137764839) was green on head 14696c7 with main 586dea2 in its tree. Main be0743b merged with head 14696c7 is tree 0052eff, which queue run 39138003629 (workflow_dispatch of tests on 147cbf6) tested whole and green.

Independent review (lane 5, Opus, of fbd2bb1; the merges of main add nothing to the PR's diff): LAND.

Closes #67

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap pushed a commit that referenced this pull request Oct 18, 2026
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

None yet

Projects

None yet

1 participant