Repository navigation
The name guard and the SessionStart hook name an unreadable register or binding log instead of guessing a branch (#60) - #208
Merged
Conversation
…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>
Reviewer's GuideThe 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 validationsequenceDiagram
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
Sequence diagram for unreadable binding log handlingsequenceDiagram
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
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
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>
|
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
marked this pull request as ready for review
October 18, 2026 15:57
|
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 |
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>
This was referenced Oct 21, 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>
This was referenced Oct 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



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_textanswers empty text and exit 0 when neitherorigin/<branch>:<path>nor the working file renders, because it ends in aprintf. 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 (windowrepoGD-1, this uuid the row's last id, register text empty):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 foldedlane_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 torepoLate-1a day ago, before theSTARTEDthe row's own log carries, and the lanerepoTwo-1has two logs differing by case. The hook printed:That statement is about a binding nobody read, and here it is false.
What changed
register_text | awk 'NF { t = 1 } END { exit !t }'runs right before theTHE ROWsection, and on no text the guard refuses with exit 2 (only 2 blocks a prompt), naming the read and printing the safe-mode bypass:[ ! -f ]refusal. I tried that first. There, neither the window nor the session had been read yet, so this refusal's triple printedwindow 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.$SE_CACHE_FILEfor the life of the process, so the test moves the first render rather than adding one. WithGIT_TRACEon a register padded to 1.3 MB, the agreeing case makes 1git showof the register and 12 git commands in all, both before and after. The addedcat | awkcosts 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_newernow has a third state. It returns0newer ·1not newer, or nonameSince·5the lane's log could not be read. Anylane_binding_utcstatus 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.gr_sinceinguard_runwas the guard's input toguard_rename_is_neweruntil 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 onejnumper prompt.No doc quotes either changed message.
docs/README-lanes.mdalready 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>…; thegr_sinceline removed.lanes-edit.sh: guard_rename_is_newer: header comment and body.lanes-edit.sh: ssb_name_line: thenameSource: userrename branch, now acaseon 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, beforea15_unpublish.Tests
Amendment 12 section: a register that is there and whose text could not be read.
LANES_DIRkeeps the logs and alias table in place, andLANES_FILEnames a file on no published tree, soregister_textfalls through to it.row not read, not the last arm's sentence, and the safe-mode bypass.[ -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: userrename torepoLate-1from a day ago, in a window bound torepoTwo-1. Asserts thatsession-startexits 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
testsjob is the record. I built a scratch runner from this branch'stests/test_lane_helpers.sh: the prologue (lines 1–971,SRC_DIRpointed at the tree under test), the definitions ofE,LOGD,LANE,LANES_CMDandprofiles_root, the whole Amendment 12 section, the Amendment 15 section through the two-logs fixture, and the footer. It ran in its ownmktemp -dsandbox withenv -u LANES_EDIT -u LANES_WORKSPACE_ROOT -u LANES_REPO -u LANES_LANE -u LANES_FILE -u LANES_DIR -u LANES_PATH -u TMUX:lanes-edit.sh:343 passed, 7 failed. The 7 are exactly the new assertions (the window-in-triple one passes on both sides).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 -non both changed files, andgit 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:
Enhancements:
Tests: