Skip to content

T017: A lane whose recorded dir holds a space is no longer left out of worktrees --all and the inventory index: worktree_rows hands that dir on quoted where it holds a space (opensoft/openRepoTools#295) (part of opensoft/openRepoTools#186) - #3

Merged
brettheap merged 2 commits into
mainfrom
fix/dir-space-listing-295
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-code), of the opensoft/openRepoTools branch fix/dir-space-listing-295 at e0970a808af5, for opensoft/openRepoTools#295 (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, 95866d375199, carries it.

It carries that branch's own change against 50d05d4 (the head's merge of 50d05d4 is left out), for both of its paths: lanes-edit.sh (+15 −1) and the new tests/test_dir_with_space_295.py (+221). Both are code-leg paths, so opensoft/openRepoTools#295 has no spec-leg part and no paired spec PR.

What was wrong and what changed

What was wrong

A lane whose recorded directory holds a space, such as /Users/x/My Projects/foo, was left out of worktrees --all, answered 8 ("none") to worktrees <lane>, and never reached the inventory index, with no UNREAD, no PARTIAL and no warning.

lane-start writes a dir that holds a space quoted (quote_subfield), and every read of the lane's own log takes it whole. worktree_rows is the read behind lanes-edit.sh worktrees and lanes-index sync --source inventory, and it does not read the log again. It takes the listing's column 7, which is the dir with its quotes already taken off, and hands it on bare, as dir <column 7>, to the three reads that find where the lane's trees are: lane_control_root, lane_trees_list and lane_state_read. payload_subfield reads a bare value only up to its first space, so a lane recorded with dir "/Users/x/My Projects/foo" was given the dir /Users/x/My. That path's parent is a directory, so the control root became /Users/x/.lane-state/<lane>, where no trees directory is, and the lane was skipped in silence:

  • worktrees --all had no row for it, and worktrees <lane> exited 8, "none";
  • the inventory index never held its trees;
  • lane-trees <lane> listed them all the while, because it reads the lane's log itself.

Found by the independent delta review r3 of opensoft/openRepoTools#289 as its SHOULD-C. The bare hand-off to lane_control_root has been in worktree_rows since opensoft/openRepoTools#171 (f5444c5). opensoft/openRepoTools#289 gave the same payload to two more reads, lane_trees_list and lane_state_read, and did not change it.

What changed

One case in worktree_rows (lanes-edit.sh, +15 −1). The dir goes back by the rule lane-start's quote_subfield writes it with: quoted where it holds a space, bare where it does not.

case "${wr_dir:-none}" in
  *' '*) wr_pay="dir \"$wr_dir\"" ;;
  *)     wr_pay="dir ${wr_dir:-none}" ;;
esac

The issue's one-line fix quoted every value. This does not, and Brett Heap ruled it so on 2026-10-21, logged at 13:43Z: yes, quote only where a space is for #295 (his words, byte for byte; the issue is opensoft/openRepoTools#295). payload_subfield ends a quoted value at its first ", so quoting a bare dir that carries one would cut it short and drop the lane exactly as the space did. lane-start refuses to write such a dir, but a hand-written log line can hold one. Column 7 is read by payload_subfield's own rule, so it never holds both a space and a ", and the case hands back every value it can hold unchanged.

The writer and the independent review each swept lanes-edit.sh, lanes, lanes-index and lane-worktrees for the same shape. worktree_rows is the only place that wraps a stored sub-field value back into a payload after its quotes were taken off. Every other reader gets a raw log payload, the exact line being written, a validated writer's value, or no payload, and lanes-index builds its inventory from worktrees --all, so it gets the fix too.

Not in this PR

Old to new: the receipt

The original's own non-merge commits in opensoft/openRepoTools (50d05d4..e0970a8), 2 in all, are carried by one commit in this leg, 95866d375199. 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).

a90f0099b55d Test that a lane whose recorded dir holds a space keeps its trees in worktrees --all and in the inventory index, red on main until worktree_rows hands that dir on quoted (#295)
d3b125919a42 worktree_rows hands a lane's dir on quoted where it holds a space, so a lane recorded under a path with a space keeps its trees in worktrees --all and in the inventory index (#295)

The subjects are the original's, byte for byte; a bare (#N) in them names the root issue.

Resolutions

None. The patch applied clean, with no offset.

The pairing

No pair: opensoft/openRepoTools#295 has no spec-leg part (both of its paths are code-leg paths), so there is no spec PR for it, and nothing in this PR waits on one.

Tests

Run by the CODE writer, in a sandbox clone, with env -i (HOME, XDG_* and TMPDIR inside the sandbox), OPENREPOTOOLS_CODE_ROOT set and OPENREPOTOOLS_COMPOSED=0, as the leg's CI sets it. Each targeted run read this branch's own commit in its own worktree; that commit was b6df91fc2fa4 before the message amend, and the amend kept its tree, so the results stand for 95866d375199.

run exit result time
bash -n on lanes-edit.sh, lane and lanes, at every commit of the chain 0 all ok -
py_compile on every changed .py file and on lanes-index 0 all ok -
run.sh -k test_dir_with_space_295 0 4 passed 15.77 s

shellcheck, over the whole chain (main to the tip): errors 0 to 0 and warnings 108 to 108 (lane 14 to 14, lanes 8 to 8); notes up by 3, 2 and 2, all SC1003 on the literal '\' patterns of opensoft/openRepoTools#301's commit.

The pair runs below are of the two chains' tips, so they cover this commit with every later commit of its chain; apart from the targeted run above, no run was made at this commit alone. They are lane 4's independent paired review, 2026-10-31 (the letters are the review report's own), with OPENREPOTOOLS_SPEC_ROOT set to the spec clone shown, env -i, TMPDIR=/tmp and a 54-character XDG_STATE_HOME.

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)
(c) -k lane_helpers code tip + spec tip 0 42 passed, 6 skipped; 0 FAIL in the shell suite (the wrapper asserts " passed, 0 failed"), with a 54-character state root 2188.6 s (36:28)
(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. Run (d), the manual-reading tests at each branch, was skipped under the review's brief, because none of the five branches' test files reads the manual.

The CODE writer's first run of -k lane_helpers at the chain's tip, with a 212-character run root, gave 5 FAILs in the shell suite (4870 ok, 5 FAIL, 3 skipped), because rc_tree_id in tests/test_lane_helpers.sh lacks the 180-character cap that tree_id_for in lanes-edit.sh has, so at that length the two names differ and the planted records are never read; the chain changes neither, and run (c) above, with the 54-character state root, gave 0 FAIL.

Not run: the suite at the leg's main for comparison, bash 3.2, macOS and the assembly's composed check; the submodule was not initialized, so 6 tests skip.

Test files this commit adds or changes:

  • tests/test_dir_with_space_295.py, new (+221): four cases on one estate of three lanes, started from their log lines alone, with no LANES_LANE_STATE_ROOT, so that each lane's control root is worked out from its recorded dir. repoS-1 records dir "<root>/My Projects/repoS", quoted as lane-start writes it; repoP-1 records a plain dir, as the control; repoQ-1 records a bare dir that holds a " and no space. The cases: the writers file the quoted-dir lane where its dir places it (the precondition, which passes before the fix); the listing keeps its trees (worktrees --all and worktrees repoS-1); the inventory index keeps them; and the bare-quote lane keeps its trees (passes before the fix, and fails if the fix quotes every value).

The original's own record, from the root repository, at the root head and not repeated in this leg: on main's lanes-edit.sh, 2 failed, 2 passed (the listing case and the index case fail); with the fix, 4 passed; two mutants of the fix, each killed (the space arm bare again fails the same two cases, and quoting every value fails only the quote-mark case).

Release notes (v1.2.0)

Not established: whether lane 3 accepts this line, which it has not seen. No release-notes line was ever recorded for this PR; the line below was written from the PR's own text.

A lane whose recorded directory holds a space is no longer left out of worktrees --all, of worktrees <lane> and of the inventory index: worktree_rows hands the directory to the control-root read quoted where it holds a space, as lane-start writes it. (opensoft/openRepoTools#295)

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): an independent review of e0970a8, by an Opus reviewer that wrote none of the code, is LAND, with no MUST, SHOULD or NIT. Its probe takes payload_subfield, the listing's field() and the fix's case straight from the branch, runs 28 raw dir spellings through them, and compares the result with what the writers read from the raw line; the fix agrees on every value the listing can carry, under bash 3.2.57 and 5.2.21. It re-applied both mutants and confirmed the untouched lane-start and lane-handoff. The root's CI run 39612841509 at e0970a8 was green on all four jobs.

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#295 (comment 6313854616)

🤖 Generated with Claude Code

Summary by Sourcery

Fix worktree discovery so recorded directories are reconstructed with the correct quoting before lane state and tree data are read.

Bug Fixes:

  • Preserve worktrees and inventory entries for lanes whose recorded directories contain spaces.

Tests:

  • Add regression coverage for spaced directories, plain directories, and directories containing quote characters across worktree listings and inventory synchronization.

…trees --all and the inventory index: worktree_rows hands that dir to the control-root read quoted where it holds a space, as lane-start writes it

T017 continuation, in opensoft/openRepoTools-code, of the
opensoft/openRepoTools branch fix/dir-space-listing-295 at
e0970a808af5179123a8cf7ee5b5e52ce9718402 (issue
opensoft/openRepoTools#295). It carries that branch's own change
against 50d05d4, with the head's merge of main 50d05d4 left out. Both
of its paths, lanes-edit.sh and tests/test_dir_with_space_295.py, are
code-leg paths, so the spec leg has no part of it. worktree_rows hands
a lane's dir on to the control-root read quoted where it holds a space,
as lane-start's quote_subfield writes it, and bare where it does not.

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):
a90f0099b55d Test that a lane whose recorded dir holds a space keeps its trees in worktrees --all and in the inventory index, red on main until worktree_rows hands that dir on quoted (#295)
d3b125919a42 worktree_rows hands a lane's dir on quoted where it holds a space, so a lane recorded under a path with a space keeps its trees in worktrees --all and in the inventory index (#295)

Resolutions: none. The patch applied clean, with no offset.

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

sourcery-ai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Re-quote the recorded directory when building the payload so a path containing spaces is read whole without truncating bare paths containing quotes.

  • lanes-edit.sh L14955-14969

Tests

Add regression coverage for spaced directories in worktree listings and inventory indexing, while checking plain and quote-containing directories remain intact.

  • tests/test_dir_with_space_295.py L1-221

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

…lter, with the tree unchanged (opensoft/openRepoTools#295, opensoft/openRepoTools#228)

Brett Heap's ruling of 2026-11-08T12:08:48Z, option A, has SonarCloud ignore
shell:S7688, shell:S131 and shell:S7679 on opensoft_openRepoTools-code. Lane
openRepoTools-3 recorded it in opensoft/openRepoTools#228 comment 6721369920.
An open pull request keeps its last analysis until a push, so this commit
changes nothing: its tree is its parent's, 95866d3's.

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

sonarqubecloud Bot commented Nov 8, 2026

Copy link
Copy Markdown

@brettheap
brettheap marked this pull request as ready for review November 8, 2026 13:41
@brettheap
brettheap merged commit 609ad61 into main Nov 8, 2026
6 checks passed

@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

Needs a human reviewer. If the reconstructed payload is parsed incorrectly, worktree rows could be missing or misrepresented in the listing and inventory index. The index can be rebuilt with another inventory sync, and reverting restores the previous listing behavior; the change does not alter the lane’s recorded directory or checkout.


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

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