Skip to content

T017: Where a lane's log or register cannot be read, a named worktree read is UNREAD, not none, the listing says what is missing, a writer is unknown, not 0, and lane-state exits 10, not 8 (opensoft/openRepoTools#290) (part of opensoft/openRepoTools#186) - #10

Merged
brettheap merged 1 commit into
mainfrom
fix/named-read-none-290
Nov 8, 2026

Conversation

@brettheap

@brettheap brettheap commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

What this is

This is the T017 continuation, in this leg (opensoft/openRepoTools-spec), of the opensoft/openRepoTools branch fix/named-read-none-290 at b99f904e15b8, for opensoft/openRepoTools#290 (part of opensoft/openRepoTools#186). The original tree and branch stay as the archived original (lane 4's decision, opensoft/openRepoTools#186 comment 6548343086). One commit here, 430ea20784ac, carries it.

It carries the spec-leg part of that branch's own change, which is its head against 50d05d4 with its merge of main 50d05d4 (db5d564) left out: docs/README-lanes.md, +31 −8 in the original; the commit's own diff against the chain's base is +31 −7, and the SPEC writer's proof found five of the seven hunks identical to the original's and the other two to be the conflict regions below, compared with git's own marker merge. The change's other four paths (lanes-edit.sh, lanes-index, tests/test_lanes_index.py and tests/test_named_read_unreadable_290.py) are the paired commit in opensoft/openRepoTools-code. It is stacked on the spec PR for opensoft/openRepoTools#302 (#9), as the chain has it; two hunks of the manual overlap opensoft/openRepoTools#291's, resolved as recorded below.

What was wrong and what changed

What was wrong

The manual's exit-code row for 10 and its list of reads that fail closed did not cover a lane's log or the register that could not be read; its text on the named read, its writer_live column and its account of a log file that will not open described reads that, where the log or the register could not be read, answered as if there were nothing to read (none, 8, 0, or no warning). opensoft/openRepoTools#290's code now says that it could not read: a named worktrees <lane> is one UNREAD line and not none, the lanes listing says what is missing and exits 1 where it names no lane for that reason, a tree's writer is unknown and not 0, and lane-state exits 10, not 8, over a log it could not read, so lanes-index holds the lane's rows.

What changed

docs/README-lanes.md, +31 −7 against the chain's base, seven hunks at git's default context, grouped here as six items in the order of the file:

  1. The exit-code row for 10: lane-state also spends it where no LANES_LANE_STATE_ROOT names the control root and the lane's object log could not be read, so where its snapshot is kept is not known. (Resolution 1 below: this row also keeps A lane control root that cannot be searched reads as "no trees", so an inventory sync removes its rows (from #289's review) openRepoTools#291's closing sentence.)
  2. The list of reads that fail closed: "Five more" becomes "Six more", the last two become the last three, and the events' own list of the published logs, where it could not be made, is a new bullet: the listing says that no lane's log is read in it and classes no row DORMANT. A new paragraph says that the listing's other list of the logs, the one that names a lane with a log and no row, is said where it could not be made, and that a listing that names no lane where the register, the archive or that list could not be read is exit 1, never the 8 of "no lane".
  3. A new paragraph on lane-state's read of its log: it finds the snapshot under the control root its log's dir places and reads that log once, with its status; a log git could not read is 10 as well, and lanes-index holds such a lane's rows for that reason, in lane-state's own words.
  4. The writer_live column: NULL also where the register's ids or the lane's log, which holds its binding, could not be read.
  5. The named-read paragraph (resolution 2 below): the named read reads the lane's log once, and where that read fails and no LANES_LANE_STATE_ROOT names the root, the lane is one UNREAD line and exit 0, never the 8 of none; so is a name whose register read failed where no tree was found under it. lanes --worktrees <lane> prints either as inventory NOT READ.
  6. The log file that will not open: it is named, as a published log git could not read is, and the logs after it are still read; it no longer leaves no warning.

The manual's added text keeps the original's bare issue numbers, such as (#N), byte for byte. In this leg's manual they name opensoft/openRepoTools issues, as its other pre-split text does.

Not in this PR

Old to new: the receipt

The original's own non-merge commits in opensoft/openRepoTools (50d05d4..b99f904), 11 in all, are carried by one commit in this leg, 430ea20784ac. The list is the commit's own body, and it equals the original's non-merge commits read from the chain's refs/root/ ref (checked).

b4b0355fd081 Add the tests that a read which could not be made never answers none: the named worktree read, the lanes listing, the no-origin log read and lanes-index's generation read (#290)
286e82197e9a Add the guards a fix for the named read needs: one read of the lane's log, no writer over a binding nobody read, no DORMANT class over a log list that failed, and lane-state's 10 naming the snapshot it found (#290)
f14efed183bd WIP: A named worktree read says NOT READ where its lane's log or the register its name is resolved by could not be read, the lanes listing says a log list it could not make, and lane-state is 10 over a log it could not read (#290) - written, not yet run green
4b1031d78337 The guard for a lane with no published log asks with no control-root override, as a workstation does, so a read that took "no such log" for "could not be read" now fails it (#290)
41ca9cb19683 A named read whose lane's log tree cannot be listed is pinned as an UNREAD line, so the ls-tree that tells an unreadable log from an absent one is tested (#290)
e5069fe5e236 The lanes contract, both exit-code tables and the manual's list of reads that fail closed now name what #290 changed: the listing's 1, lane-state's 10 over a log it could not read, and the events' list of the logs (#290)
a2b52ed1c8a5 The comment over the inventory read's own two log-list reads no longer says known_lanes answers 0 either way: its published list answers 1 where it could not be made (#290)
da187ba448d5 The hold lanes-index makes over lane-state's 10 gives lane-state's own sentence with LANES_DEBUG set, not the "(exit 10)" line die adds after it (#290)
9c0aae54978e Add the test that lane-state finds a lane's snapshot by the whole dir its log records, bare with a quote mark in it as on main, and quoted with a space in it (#290)
bc825a4bf326 lane-state hands the dir it read on quoted only where it holds a space, as lane-start writes it, so a bare dir with a quote mark in it finds its snapshot as on main (#290)
b99f904e15b8 The lane-state dir test now pins a bare dir holding a TAB and a quote mark, read whole as on main, so the rule stays a space and not any whitespace (#290)

The subjects are the original's, byte for byte; a bare (#N) in them names the root issue. f14efed183bd is a WIP checkpoint whose subject says "written, not yet run green"; it is the original's own commit, listed as it was written, and this commit carries the final state that the later commits turned green.

Of these, the commits that touch docs/README-lanes.md (the original's range on that path) are f14efed183bd, e5069fe5e236. The others change code-leg paths only, and their part is the paired code PR's.

Resolutions

Two conflicts, both in the manual and both against opensoft/openRepoTools#291's text; the other hunks applied at offsets +13, +31 and +30, because the chain carries opensoft/openRepoTools#291's and opensoft/openRepoTools#302's added lines.

  1. The exit-code row for 10: kept both sides, A named worktree read answers "none" for a lane whose log or register could not be read (from #289's review) openRepoTools#290's lane-state clause (the object log could not be read) and A lane control root that cannot be searched reads as "no trees", so an inventory sync removes its rows (from #289's review) openRepoTools#291's closing sentence ("Both spend it, too, ..."); a word-level three-way merge of the row is clean.
  2. The named-read paragraph: kept A lane control root that cannot be searched reads as "no trees", so an inventory sync removes its rows (from #289's review) openRepoTools#291's sentence (with A tree record with no path: line still swaps the tree's row in the inventory index for a row keyed by the record's id: the loss #291's part F fixes for an unreadable record is open for a malformed one openRepoTools#302's wording) first, so that "Nor does" still follows "never prints PARTIAL", then A named worktree read answers "none" for a lane whose log or register could not be read (from #289's review) openRepoTools#290's sentences; A named worktree read answers "none" for a lane whose log or register could not be read (from #289's review) openRepoTools#290's opening "It reads the lane's log once" became "The named read reads the lane's log once", so that "It" does not point at the UNREAD line of the sentence before.

Not established: whether lane 3 prefers the other wording. Resolution 2 is a judgment on wording, not a mechanical merge: the root drafts' ORDER.md names no text for it, and it was settled on the plain intent of both sides. Lane 4's independent paired review found that the words that come from neither side are the only ones in either chain, and judged them minimal and correct. The alternative is opensoft/openRepoTools#290's sentences first, then opensoft/openRepoTools#291's, with no edit at all.

The paragraph's join, as the SPEC writer's report shows it (its … marks text left out here):

 gives, and never prints `PARTIAL`. Nor does a lane the listing DID name and
 could not read — … that is the lane's own `UNREAD` line, and
 only that lane's rows are held (#291, #302).
-gives, and never prints `PARTIAL`. It reads the lane's log once, and where
+The named read reads the lane's log once, and where
 that read fails and no `LANES_LANE_STATE_ROOT` names the root, …

The pairing

The code part of this change is the commit 2c15aa6613c3 on fix/named-read-none-290 in opensoft/openRepoTools-code, its own PR, opensoft/openRepoTools-code#7 (base fix/pathless-tree-record-302). The code leg's checks read the manual through OPENREPOTOOLS_SPEC_ROOT: tests/test_repo_hygiene.py reads docs/README-lanes.md (call sites at lines 1373, 1404, 1423, 3139 and 3572 of the code leg's main; 1404 is the tuple of surfaces that a loop reads through doc()) and tests/test_test_roots.py pins which manual a run reads. The code leg's own CI (OPENREPOTOOLS_COMPOSED: '0', no spec leg beside the checkout) skips those checks, so they bind only in a composed run or with the variable set to a spec clone. A search of the manual lines this change touches for the strings those checks pin (the rung-count heading, the two settlement quotes, every lane on this workstation, the exit-code section's two markers and lane-end <lane> --retire) finds none: read, not run. So the two PRs are one change in two repositories, and they land together, as a pair. The code PR goes first, so that the manual never describes behaviour the code lacks: the paired code PR, opensoft/openRepoTools-code#7, first, then this one. The state that order passes through, the code chain's tip beside the spec leg's main, passed -k test_repo_hygiene in the independent review (run (e) under Tests: 223 passed, 14 skipped; that run read the chains' tips, not this commit alone). The other order's state, the spec tip beside the code leg's main, was not run. I found no check that turns either order red; that is a reading, not a run.

Tests

The manual is tested from the code leg, not here: this leg has no code and no CI workflow of its own. tests/test_repo_hygiene.py reads docs/README-lanes.md through OPENREPOTOOLS_SPEC_ROOT (tests/test_test_roots.py pins which manual a run reads). The pair is fix/named-read-none-290 in opensoft/openRepoTools-code, commit 2c15aa6613c3.

The pair's hygiene runs, from lane 4's independent paired review (2026-10-31), with OPENREPOTOOLS_SPEC_ROOT set to the spec clone shown (env -i, TMPDIR=/tmp). They read the spec chain's tip, which is this PR's commit, with the code chain's tip beside it. The letters are the review report's own: (c) is the shell-suite run, in the paired code PR, and (d) was skipped.

run code + spec exit counts time
(a) -k test_repo_hygiene code tip 5f2995d43893 + spec tip 8104f2cf965c 0 223 passed, 14 skipped, 2944 deselected 11.1 s (33 s wall)
(b) -k test_repo_hygiene, baseline code main 2a057a6 + spec main 9f8b21a 0 223 passed, 14 skipped, 2772 deselected 9.2 s (10 s wall)
(e) -k test_repo_hygiene code tip 5f2995d43893 + spec main 9f8b21a 0 223 passed, 14 skipped 5.5 s

The pair runs read the chains' tips as they were before the message amend (code 5f2995d43893, spec 8104f2cf965c). The amend kept every tree (git diff from each old commit to its new one is empty), so the runs stand for the amended tips, code 2c15aa6613c3 and spec 430ea20784ac. No failure is new at the tips.

Release notes (v1.2.0)

The release-notes lines for this change are in the paired code PR, opensoft/openRepoTools-code#7 (fix/named-read-none-290 in opensoft/openRepoTools-code), once, in the PR that carries the code change. This PR repeats none.

Review

READY, lane 4's independent paired review of both chains, 2026-10-31. It found no MUST and no SHOULD against the commits, and three NITs. Report sha256: 4ac9e5441affc6aeac48e6d73419580f6786440dc0e5dd32722cc40b8070a682. The review read the chains before the message amend (tips 5f2995d43893 and 8104f2cf965c, the same trees as the amended tips).

The original's recorded review, from the root repository (no lane 3 review comment exists for it): the independent review of db5d564 is LAND, with no MUST; its N1 (the contract comment, the exit-code table's row for 10 and the list of reads that fail closed) is fixed in e5069fe, whose manual part is in this PR's commit with the rest of the manual's part. The later quoting fix and its delta review touch no manual text.

Landing

It lands only on Brett Heap's word, PR by PR; nothing in this text is a landing.

Lane: openRepoTools-4
Claim: opensoft/openRepoTools#290 (comment 6313867435)

🤖 Generated with Claude Code

Summary by Sourcery

Update the lanes specification to distinguish unreadable state from absent state across lane listings, named reads, and lifecycle inspection.

Bug Fixes:

  • Document unreadable lane logs, registers, and log lists as unread or missing rather than absent, including the resulting listing and exit-code behavior.

Enhancements:

  • Clarify lane-state, named worktree reads, writer liveness, and unreadable log-file behavior in the lanes specification.

Documentation:

  • Update the lanes manual to specify UNREAD named reads, exit 10 for unknown snapshot locations, exit 1 for incomplete listings, and NULL writer liveness when binding data cannot be read.

…e read says UNREAD instead of none, the lanes listing says what is missing, a tree's writer is unknown instead of 0, and lane-state exits 10 instead of 8

This is the T017 continuation, in this leg
(opensoft/openRepoTools-spec), of the original opensoft/openRepoTools
branch fix/named-read-none-290 at
b99f904e15b88da1e3f575e258cbd134f7747f63, issue
opensoft/openRepoTools#290. The original branched from main 50d05d4 and
its head merges 50d05d4 at db5d564, so its own change is its head
against 50d05d4 with that merge left out (the merge's tree equals git's
automatic merge). Spec-leg part of its own change: docs/README-lanes.md
(+31 -8: the exit-code table's row for 10, the list of reads that fail
closed and its paragraph on the other list and exit 1, the named read,
the writer_live column, the log file that will not open, and
lane-state's read of its log). Its other paths (lanes-edit.sh,
lanes-index, tests/test_lanes_index.py and
tests/test_named_read_unreadable_290.py) belong to the code leg and are
the paired commit there; the leg table sends docs/ to this leg with no
rename. This continuation stacks on the one for
opensoft/openRepoTools#302, as ORDER.md's chain has it, and two hunks of
the manual overlap opensoft/openRepoTools#291's, resolved as recorded
below.

The subjects below are quoted from the originals; a bare #N in them is
opensoft/openRepoTools#N.

Old-to-new receipt, the original's own non-merge commits in
opensoft/openRepoTools (50d05d4..b99f904):
b4b0355fd081 Add the tests that a read which could not be made never answers none: the named worktree read, the lanes listing, the no-origin log read and lanes-index's generation read (#290)
286e82197e9a Add the guards a fix for the named read needs: one read of the lane's log, no writer over a binding nobody read, no DORMANT class over a log list that failed, and lane-state's 10 naming the snapshot it found (#290)
f14efed183bd WIP: A named worktree read says NOT READ where its lane's log or the register its name is resolved by could not be read, the lanes listing says a log list it could not make, and lane-state is 10 over a log it could not read (#290) - written, not yet run green
4b1031d78337 The guard for a lane with no published log asks with no control-root override, as a workstation does, so a read that took "no such log" for "could not be read" now fails it (#290)
41ca9cb19683 A named read whose lane's log tree cannot be listed is pinned as an UNREAD line, so the ls-tree that tells an unreadable log from an absent one is tested (#290)
e5069fe5e236 The lanes contract, both exit-code tables and the manual's list of reads that fail closed now name what #290 changed: the listing's 1, lane-state's 10 over a log it could not read, and the events' list of the logs (#290)
a2b52ed1c8a5 The comment over the inventory read's own two log-list reads no longer says known_lanes answers 0 either way: its published list answers 1 where it could not be made (#290)
da187ba448d5 The hold lanes-index makes over lane-state's 10 gives lane-state's own sentence with LANES_DEBUG set, not the "(exit 10)" line die adds after it (#290)
9c0aae54978e Add the test that lane-state finds a lane's snapshot by the whole dir its log records, bare with a quote mark in it as on main, and quoted with a space in it (#290)
bc825a4bf326 lane-state hands the dir it read on quoted only where it holds a space, as lane-start writes it, so a bare dir with a quote mark in it finds its snapshot as on main (#290)
b99f904e15b8 The lane-state dir test now pins a bare dir holding a TAB and a quote mark, read whole as on main, so the rule stays a space and not any whitespace (#290)

Recorded resolutions:
docs/README-lanes.md, the exit-code row for 10: kept both sides,
  opensoft/openRepoTools#290's lane-state clause (the object log could
  not be read) and opensoft/openRepoTools#291's closing sentence (Both
  spend it, too, ...); a word-level three-way merge of the row is clean.
docs/README-lanes.md, the named-read paragraph: kept
  opensoft/openRepoTools#291's sentence (with
  opensoft/openRepoTools#302's wording) first, so that Nor does still
  follows never prints PARTIAL, then opensoft/openRepoTools#290's
  sentences; opensoft/openRepoTools#290's opening It reads became The
  named read reads, so that It does not point at the UNREAD line of the
  sentence before.

Lane: openRepoTools-4
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Documentation

Update the exit-code contract to make lane-state return 10 when its object log cannot be read, retaining the accompanying lane-trees failure wording.

  • docs/README-lanes.md L1232

Document the additional fail-closed log-list read and explain when the listing reports missing log-list, register, or archive reads instead of treating them as no lane.

  • docs/README-lanes.md L3249-3251, L3260-3270

Explain that lane-state reads the lane log once and returns 10 on an unreadable log, with lanes-index holding that lane’s rows.

  • docs/README-lanes.md L3391-3396

Clarify that writer_live is NULL when the register’s IDs or the lane log binding cannot be read, because writer liveness is then unknown.

  • docs/README-lanes.md L3868

Specify that named worktree reads report an unreadable log or register as UNREAD, not none, and describe the listing’s inventory NOT READ output.

  • docs/README-lanes.md L3954-3960

Document that an unreadable log file is named as unreadable and does not prevent later logs from being read.

  • docs/README-lanes.md L3979-3981

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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

brettheap pushed a commit that referenced this pull request Nov 8, 2026
…tree equals the tree its head was tested with: the head was cut from 4233c9a, and #7 to #10 changed the manual since (opensoft/openRepoTools#198)

The merge is clean. Its tree equals what `git merge-tree --write-tree` gave
for df909ba and aed1852 before the merge was made (70b0337), and
`docs/README-lanes.md` is the only file either side touched. No conflict was
resolved by hand, and no line of the slice's text was changed.

This is an added commit on the draft branch, not a rewrite: df909ba stays
an ancestor, so the push is a fast-forward.

Lane: openreposhape-2 (openRepoShape-2)
Co-Authored-By: Claude Sonnet 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

Development

Successfully merging this pull request may close these issues.

1 participant