Skip to content

scaffold-project.py: --dry-run's help says its answer about each folder is the mode bits' and that it leaves nothing that stays, a --reuse-empty-repo re-run that takes a seed found only on seed/scaffold names that branch as remaining, and the unused COMMIT_RE import is gone (#921, #923) - #1052

Merged
brettheap merged 2 commits into
mainfrom
l3-921-923-scaffold-words
Oct 20, 2026

Conversation

@brettheap

@brettheap brettheap commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

The scaffold file's share of #921 and #923, v1.2.0 (draft). Four changes in scaffold-project.py, docs/cli.md regenerated for the scaffold's section, and rows in tests/test_scaffold_reuse_seeded_legs.py. RV1052f's review (READY, no MUST) is answered by one more commit, dff9aacb7, under "Review round" below.

What changed, and why

#923 U063, the scaffold half: --dry-run's help says what os.access can and cannot see (scaffold-project.py:376-384). The dry run asks os.access(W_OK | X_OK) (scripts/shape_materialize.py folder_in_the_way, target_in_the_way) and the real run's mkdir and first write can still be refused, so the help now says: "Whether each folder can be written in is asked of os.access, which reads the mode bits and on Windows says yes for every folder, so a quota, a Windows ACL or a read-only drive on Windows can pass here and be refused by the real run."

#921 U088, the scaffold half: "make no folder" is "nothing that stays" (scaffold-project.py:382-384). The run makes and removes openreposhape-seed-* and openreposhape-branch-* in the temporary folder, so the help now says: "It leaves nothing that stays: it makes and removes temporary folders, creates no remote and pushes nothing". "nothing that stays" is the phrase W921a uses in the README and the handbook. docs/cli.md:351-358 is regenerated with scripts/render-cli-reference.py; --check says it is what the generator produces.

#921 U006: a --reuse-empty-repo re-run that takes a seed found only on seed/scaffold says which branch remains.

  • only_commit (:533, :550) kept only the tips and threw the ref names away. It now keeps the names git ls-remote gave and returns them as a third element; its one other reader, a test, reads held[0].
  • _held_seed (:573) returns (commit, why, found_on), found_on being the branches the seed was found on when the tracking branch is not one of them (_seed_branches, :616).
  • _reusable_remotes (:751) prints, after the reuse ... (one commit, ...) line, on GitHub:
    NOTE the seed in <leg> was found only on its branch seed/scaffold: this run creates mainat it and does not touchseed/scaffold, so that branch remains, and on GitHub it may be the leg's default branch.
    and under --local-remote-dir, with no word of GitHub:
    NOTE the seed in <leg> was found only on its branch seed/scaffold: this run creates mainat it and does not touchseed/scaffold, so that branch remains.
  • The NOTE is _seed_branch_note (:631), which takes local. The dry run prints it too, since the question is asked before anything is made.

#923 U064, the scaffold half: the unused COMMIT_RE import (scaffold-project.py:95) is dropped. git grep COMMIT_RE -- tests finds no read of it off the scaffold module (every hit is repo_shape, adopt-project.py, family.py, bump-leg.py or a template, each importing it from repo_shape itself). pyflakes scaffold-project.py printed scaffold-project.py:94:1: 'repo_shape.COMMIT_RE' imported but unused at origin/main and prints nothing now: 0 left, 0 new.

Where the Direction left a choice

  • Any branch, not only seed/scaffold. The code never named seed/scaffold: it takes any leg whose one commit has the seed's tree. So the NOTE is for any branch the seed was found only on, named as found, and says "branches" and names both when there are two. The issue's words are the NOTE's words for the case it names.
  • "may be", not "is", and on GitHub only. The issue says it was not verified on github.com; the NOTE keeps "may be the leg's default branch" for a GitHub leg, and a --local-remote-dir leg, a bare repository on disk, is not told it. HEAD in the listing is not read as proof.
  • No NOTE where the tracking branch holds the seed too (main beside seed/scaffold): the re-run creates nothing then. A tag, a pull request's ref and HEAD are no branch.
  • The remote names the branch, so it is shown as shown_path shows a path (as it is, or as repr where a character in it is not printable). A branch with U+202E in its name prints in repr's spelling, never raw (a row builds one with chr(0x202E)).
  • The help names a read-only drive on Windows, not a read-only disk in general. The issue's evidence lists a quota, a read-only disk and a Windows ACL. On POSIX os.access(W_OK) does answer a read-only mount; on Windows it says yes for every folder (scripts/shape_materialize.py:1620-1621, setup-project.py:2611-2612), so a read-only drive there passes the dry run and the help says so (RV1052f SHOULD-1; the first draft left it out).

Left out, and why

Review round

RV1052f at head 396668b2: READY, no MUST. Fixed in dff9aacb7, one line per item:

  • SHOULD-1 and NIT 1: the --dry-run help names os.access, says it reads the mode bits and on Windows says yes for every folder, so a quota, a Windows ACL or a read-only drive on Windows can pass and be refused by the real run (scaffold-project.py:376-384). That drops "its mode bits'", which claimed the answer about a file in the way and a tree's contents too. docs/cli.md:351-358 is regenerated (its scaffold section is the only hunk), and the assert is tests/test_scaffold_reuse_seeded_legs.py:381 (test_dry_run_help_says_the_mode_bits_and_nothing_that_stays), which now also refuses "its mode bits'".
  • NIT 2: under --local-remote-dir the NOTE no longer says "and on GitHub it may be the leg's default branch". _seed_branch_note takes local (scaffold-project.py:631), passed from _reusable_remotes (:751); the GitHub wording is unchanged. test_the_seed_note_says_github_only_on_github (tests/test_scaffold_reuse_seeded_legs.py:372) has four rows: local with one branch and with two, and GitHub with one and with two, each the whole line. The --local-remote-dir tests' seed_branch_note helper (:224) holds the local line, and test_a_seed_pushed_to_a_seed_branch_alone_is_taken_too asserts no "GitHub" in the run's output.
  • NIT 3: test_a_seed_on_the_tracking_branch_as_well_says_no_branch_remains is now test_a_seed_on_the_tracking_branch_as_well_prints_no_seed_note (:279).
  • NIT 4: not changed. The Sourcery section below follows the robot line as Sourcery appended it; whether to cut it is lane 3's call.
  • NIT 5: two rows in test_the_branches_a_seed_was_found_on (:334, :336): ("refs/heads/seed/main",) -> ("seed/main",) and ("refs/tags/main", "refs/heads/seed/scaffold") -> ("seed/scaffold",). RV1052f's M3 now fails (below).

Tests

Each ran alone, under the stub gh (first on PATH, exit 97), GH_TOKEN=bogus, an empty GH_CONFIG_DIR and EMAIL=tests@openreposhape.invalid, at head dff9aacb7:

tests/test_scaffold_reuse_seeded_legs.py          82 passed in 50.64s   (76 before the review round: four rows of the NOTE test and two of the branches test are new)
tests/test_cli_reference.py                       23 passed in 38.73s
tests/test_dry_run_asks_remotes.py                32 passed in 10.67s
tests/test_scaffold_pin_and_reuse.py              75 passed in 23.37s
tests/test_scaffold_leg_path_collisions.py       104 passed in 3.82s
tests/test_agents_md_codes.py                     47 passed in 1.92s
tests/test_no_auto_maintenance.py                 60 passed in 9.32s
tests/test_update_add_codes_documented.py          6 passed in 0.45s
tests/test_repo_hygiene.py                       100 passed in 2.75s
tests/test_github_name_limits.py                  64 passed in 25.03s   (reads scaffold's --help)
tests/test_reuse_visibility.py                     2 passed in 2.90s
tests/test_ruleset_hint_tracking_branch.py        23 passed in 29.75s
tests/test_next_refspec_branch_length.py          51 passed in 26.21s

scripts/render-cli-reference.py --check: docs/cli.md is what the generator produces. pyflakes scaffold-project.py: no output. tests/test_shape_doctor.py was not run: this change touches neither shape-doctor.py nor a helper it imports. No pinned copy is touched.

Rows in tests/test_scaffold_reuse_seeded_legs.py: test_a_seed_pushed_to_a_seed_branch_alone_is_taken_too (the NOTE once, after the reuse line, the branch untouched, no word of GitHub), test_a_dry_run_says_the_seed_branch_too_and_makes_nothing, test_a_seed_on_the_tracking_branch_as_well_prints_no_seed_note, test_a_seed_on_two_branches_names_both, test_a_branch_name_is_shown_safe_in_the_seed_note, test_the_seed_note_says_github_only_on_github (4 rows), test_the_branches_a_seed_was_found_on (9 cases), test_dry_run_help_says_the_mode_bits_and_nothing_that_stays, and an added assertion in test_legs_holding_the_seed_are_reused_at_their_commits that a seed on main says no NOTE. No existing test pinned the old help words or make no folder.

Mutants

Each applied to scaffold-project.py alone, the file restored by cp after and checked with cmp.

First draft (at 396668b2):

Mutant Killed by
M1: the NOTE is never printed (U006: the ref is not told) test_a_seed_pushed_to_a_seed_branch_alone_is_taken_too, test_a_dry_run_says_the_seed_branch_too_and_makes_nothing, test_a_seed_on_two_branches_names_both, test_a_branch_name_is_shown_safe_in_the_seed_note (4 failed, 72 passed)
M2: _seed_branches does not exclude the tracking branch test_legs_holding_the_seed_are_reused_at_their_commits, the tracking-branch test, two cases of test_the_branches_a_seed_was_found_on (4 failed)
M3: the branch name is printed without shown_path test_a_branch_name_is_shown_safe_in_the_seed_note (1 failed)
M4: --dry-run help back to "make no folder" test_dry_run_help_says_the_mode_bits_and_nothing_that_stays (1 failed)
M5: a help word changed, docs/cli.md not regenerated tests/test_cli_reference.py, 5 failed (test_the_committed_reference_is_what_the_generator_produces among them)

Review round (at dff9aacb7):

Mutant Killed by
R1, RV1052f's M3: return () if any(ref.endswith("/" + tracking) for ref in refs) else tuple(branches) in _seed_branches. It survived all 76 tests before the two new rows test_the_branches_a_seed_was_found_on[a-branch-ending-in-the-tracking-name] and [a-tag-named-as-the-tracking-branch] (2 failed, 7 passed, run with -k test_the_branches_a_seed_was_found_on)
R2: _seed_branch_note ignores local ("." if False else ...), so a local NOTE says "on GitHub" test_a_seed_pushed_to_a_seed_branch_alone_is_taken_too, test_a_dry_run_says_the_seed_branch_too_and_makes_nothing, test_a_seed_on_two_branches_names_both, and the two local rows of test_the_seed_note_says_github_only_on_github (5 failed, 4 passed, run with -k)
R3: the help drops "on Windows" after "a read-only drive" test_dry_run_help_says_the_mode_bits_and_nothing_that_stays (1 failed)

Merges

git merge-tree --write-tree of this head dff9aacb7, after a fresh fetch: with origin/main (8a0572157): clean. With #1041 (c0ccf755f, scaffold-project.py, a docstring near :1070): clean. With #1051 (93dacf859): clean. The first commit sits on 82fc86752 (#1044); main has since changed only scripts/family.py, templates/family-root/scripts/bootstrap.py and three tests.

Part of #921

Part of #923

Lane: openreposhape-3 (openRepoShape-3)

🤖 Generated with Claude Code

Summary by Sourcery

Improve scaffold dry-run guidance and preserve branch context when reusing seeds found outside the tracking branch.

New Features:

  • Report when a reusable seed exists only on non-tracking branches, including which branches remain untouched and the possibility that one is the GitHub default branch.
  • Include the branch information in both normal and dry-run reuse output, with safe rendering of non-printable branch names.

Bug Fixes:

  • Clarify dry-run limitations and temporary-folder behavior in the scaffold CLI help.

Enhancements:

  • Remove the unused COMMIT_RE import from scaffold-project.py.

Documentation:

  • Regenerate the scaffold CLI reference to document mode-bit folder checks and that dry runs leave no persistent folders, remotes, or pushes.

Tests:

  • Add coverage for seeded-leg reuse across alternate branches, dry-run notes, multiple and non-printable branch names, tracking-branch handling, and updated help text.

…lder is the mode bits' and that it leaves nothing that stays, a `--reuse-empty-repo` re-run that takes a seed found only on `seed/scaffold` names that branch as remaining, and the unused `COMMIT_RE` import is gone (#921, #923)

`--dry-run` help (#923 U063, #921 U088): the folder question is `os.access`'s
answer, so a quota or a Windows ACL the bits do not show can pass the dry run
and be refused by the real run; and where it said "make no folder" it now says
it "leaves nothing that stays", since it makes and removes temporary folders.
`docs/cli.md` regenerated for the scaffold's section.

`only_commit` keeps the ref names `git ls-remote` gave, `_held_seed` returns
the branches the seed was found on when the tracking branch is not one of them,
and `_reusable_remotes` prints a NOTE after the `reuse` line: the branch
remains, and on GitHub it may be the leg's default branch (#921 U006). A dry
run says it too. Branch names come from the remote and are spelt as
`shown_path` spells a path.

The unused `COMMIT_RE` import is dropped (#923 U064): no test reads it off the
scaffold module, and pyflakes reports nothing for the file now.

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

sourcery-ai Bot commented Oct 20, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR updates scaffold dry-run documentation, removes an unused import, and enhances seeded repository reuse by retaining remote ref names so reruns can explain which non-tracking branches remain untouched; accompanying tests cover the new reporting, edge cases, safe rendering, dry-run semantics, and generated CLI documentation.

Sequence diagram for seeded repository reuse with branch preservation

sequenceDiagram
    participant Scaffold
    participant Remote
    participant Git
    participant User
    Scaffold->>Remote: _held_seed(role, url, values, tracking, scratch)
    Remote->>Git: only_commit(url, scratch)
    Git-->>Remote: commit, tree, refs
    Remote->>Remote: _seed_branches(refs, tracking)
    Remote-->>Scaffold: seed, unread, found_on
    Scaffold->>User: reuse target (one commit, seed)
    alt seed found only on another branch
        Scaffold->>User: _seed_branch_note(target, found_on, tracking)
        User-->>Scaffold: branch remains untouched
    else tracking branch also holds seed
        User-->>Scaffold: no branch-preservation note
    end
Loading

Flow diagram for scaffold dry-run behavior

flowchart TD
    A[scaffold --dry-run] --> B[Check folders with os.access W_OK and X_OK]
    B --> C{Folder appears usable}
    C -->|yes| D[May still be refused by quota or Windows ACL]
    C -->|no| E[Report refusal]
    A --> F[Create and remove temporary folders]
    F --> G[No lasting folders, remote, or push]
Loading

File-Level Changes

Change Details Files
Clarifies --dry-run limitations and cleanup guarantees in the scaffold CLI help and regenerated reference documentation.
  • Explains that folder checks reflect os.access mode-bit results and may miss quota or Windows ACL failures.
  • Replaces the misleading “make no folder” wording with a statement that temporary folders are created and removed, with no persistent folders, remotes, or pushes.
  • Regenerates the scaffold section of the CLI reference and validates it against the generator.
scaffold-project.py
docs/cli.md
tests/test_scaffold_reuse_seeded_legs.py
Preserves and reports non-tracking branches holding a reusable seed during --reuse-empty-repo reruns.
  • Extends remote inspection to retain ref names while preserving the one-commit seed detection behavior.
  • Identifies branch refs holding the seed, excluding the tracking branch and non-branch refs such as tags, pull-request refs, and HEAD.
  • Prints a safe, deterministic NOTE after the reuse line explaining which branches remain untouched and may be the GitHub default branch.
  • Emits the same branch note during dry runs and documents the behavior in helper docstrings.
scaffold-project.py
tests/test_scaffold_reuse_seeded_legs.py
Removes the unused COMMIT_RE import from the scaffold module.
  • Updates the import list and verifies the module is clean under pyflakes.
scaffold-project.py
Adds focused regression coverage for branch reporting, dry-run behavior, help text, output ordering, unsafe branch-name rendering, and tracking-branch edge cases.
  • Covers seeds found only on one or multiple non-tracking branches.
  • Verifies no note is emitted when the tracking branch also contains the seed.
  • Checks dry runs do not create refs while still displaying the note.
  • Exercises filtering of tags, pull-request refs, and HEAD, plus sorted branch output and non-printable names.
tests/test_scaffold_reuse_seeded_legs.py

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

@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-20T10:54:20Z) Independent review (RV1052f, opus) of head 396668b: READY. No MUST.
One SHOULD to fix in this PR before landing; CI tests was still running
at 10:52Z (tests-git-bash, package and SonarCloud passed).

SHOULD-1 scaffold-project.py:376-379 (docs/cli.md:352-354, test at
tests/test_scaffold_reuse_seeded_legs.py:347-351): the --dry-run help
names "a quota or a Windows ACL" but not U063's third cause, a read-only
disk. On Windows os.access says yes for every folder
(shape_materialize.py:1620-1621, setup-project.py:2611-2612), so a
read-only drive there passes the dry run and is refused by the real run.
Suggested words, which also fix NIT 1: "Whether each folder can be
written in is asked of os.access, which reads the mode bits and on
Windows says yes for every folder, so a quota, a Windows ACL or a
read-only drive on Windows can pass here and be refused by the real
run." Regenerate docs/cli.md and update the assert.

NIT 1 :376-377: "The answer about each folder is its mode bits'" claims
too much: only the write question is os.access; a file in the way and a
tree's contents are lexists/_not_a_folder and iterdir.
NIT 2 :629-647: under --local-remote-dir the NOTE says "on GitHub it may
be the leg's default branch" about a bare path; pass local and say
"its HEAD" there. A follow-up is fine.
NIT 3 :626: no NOTE when the seed is on main and seed/scaffold both,
though seed/scaffold remains. Within U006's "only on"; the body says so.
The test name at :277 ("says_no_branch_remains") reads as if the run
says that; consider "prints_no_seed_note".
NIT 4: the Sourcery section follows the robot line in the body.
NIT 5 (mutant): return () if any(ref.endswith("/" + tracking) for ref in refs) else tuple(branches) at :626 passes all 76 tests. Add two
params at :317-331: ("refs/heads/seed/main",) -> ("seed/main",) and
("refs/tags/main", "refs/heads/seed/scaffold") -> ("seed/scaffold",).

Probe, head and main 82fc867, local and stub-gh GitHub modes, cases
A B C E F G K J (13 setups, 26 runs): exit codes, gh call counts
(7/13, 2/2, 3/3) and refs match in every case; the only difference in
the normalised stdout and stderr is the added NOTE. It prints once per
run, in the dry and the real run; never for a refused leg (E, F) or
when main holds the seed too (B); names trunk under
--tracking-branch trunk (K); ignores a tag (G).
Tests at the head, one file at a time: seeded_legs 76, pin_and_reuse 75,
dry_run_asks_remotes 32, cli_reference 23, leg_path_collisions 104,
agents_md_codes 47, update_add_codes_documented 6, no_auto_maintenance
60, all passed. M1 and M2 re-made: 4 failed each, as reported.
merge-tree with origin/main 8a05721, #1041 c0ccf75 and #1051
93dacf8: all clean. #1051's README:484 "Nothing that stays" matches.

Lane: openreposhape-3 (openRepoShape-3)

…ked of `os.access`, which on Windows says yes for every folder, so a read-only drive there passes it as a quota or an ACL does, and the seed NOTE of a `--local-remote-dir` re-run no longer says a bare repository on disk may be the default branch on GitHub (#921, #923)

Review round of #1052 (RV1052f, READY, no MUST):
- SHOULD-1 and NIT 1: the help's wording, docs/cli.md regenerated, and the
  assert at tests/test_scaffold_reuse_seeded_legs.py.
- NIT 2: `_seed_branch_note` takes `local`; the GitHub wording is unchanged,
  and rows pin both.
- NIT 3: the test that prints no seed note is named for that.
- NIT 5: two rows kill the surviving mutant of `_seed_branches`.

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

Copy link
Copy Markdown

@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-20T11:20:16Z) Independent delta review (RV1052d) of fix round 1, 396668b..dff9aac: READY. No MUST, no SHOULD.

All of RV1052f's items are fixed:

  • SHOULD-1 and NIT 1: the --dry-run help now says the write question is asked of os.access, which on Windows says yes for every folder, so a quota, a Windows ACL or a read-only drive on Windows can pass. That matches shape_materialize.py:1620-1621 and setup-project.py:2611-2612. Only the write question goes to os.access (:1634, :1743). docs/cli.md has one hunk, in the scaffold section, and render-cli-reference.py --check passes. The assert at tests/test_scaffold_reuse_seeded_legs.py:390-399 pins the new sentence.
  • NIT 2: _seed_branch_note takes local, and _reusable_remotes passes it at scaffold-project.py:751. Under --local-remote-dir the NOTE has no GitHub clause; on GitHub it is unchanged.
  • NIT 3: the test is renamed, and the old name is gone.
  • NIT 5: the two params kill M3.

Tests at dff9aac, one file at a time under a stub gh:

  • test_scaffold_reuse_seeded_legs.py: 82 passed
  • test_cli_reference.py: 23 passed
  • test_no_auto_maintenance.py: 60 passed

Mutants:

  • M3 at :626: killed (2 failed).
  • R2, the NOTE ignores local: killed (5 failed).
  • R2b, the call at :751 drops local: killed (3 failed).
  • R2d, "." if True: killed (2 failed).
  • H1, the help drops the read-only drive: killed (1 failed).
  • R2c, the call at :751 always passes True: SURVIVES (82 passed).

merge-tree --write-tree of dff9aac is clean with:

The body has no closing keyword (closingIssuesReferences is empty). It ends Part of #921, Part of #923, the Lane line, then the robot line, before the Sourcery block.

NITs, neither blocking:

Note: dff9aac carries a Co-Authored-By: Claude Sonnet 5.5 trailer, and 396668b carries the Opus 5.5 one. Lane 3's squash message decides which trailer lands.

Lane: openreposhape-3 (openRepoShape-3)

@brettheap
brettheap marked this pull request as ready for review October 20, 2026 12:07
@sourcery-ai

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

@brettheap
brettheap merged commit 322302d into main Oct 20, 2026
5 checks passed
@brettheap
brettheap deleted the l3-921-923-scaffold-words branch October 20, 2026 12:07
brettheap added a commit that referenced this pull request Oct 20, 2026
…cks `<into>/[<Family>/]<Project>`, nothing that stays is created before the typed `yes`, and `passed_values` says which dash words argparse takes as values (#921, #923) (#1051)

AGENTS.md and the handbook said step (3) refuses a taken
`<into>/<Project>`, but it checks the clone path, and under `--family`
that is `<into>/<Family>/<Project>` unless the run already stands in the
family's folder. AGENTS.md now writes `<into>/[<Family>/]<Project>`, in
the refusal and in the `--family` row, and the handbook says the clone
path, `<into>/<Project>` or, where `--family` adds the family's folder,
`<into>/<Family>/<Project>`.

README.md, the handbook and setup-project.py's docstring said nothing is
created before the typed `yes`, but a run makes temporary folders along
the way and takes each away again: the write probe above the clone, and
the seed and branch folders in the temporary folder. They now say
nothing that stays is created before the `yes`, and name such folders.
setup-project.py's docstring names the checkout `--keep-shape-checkout`
keeps as the one that stays. AGENTS.md and the handbook's list of
refusals say "before anything that stays is created", the words the
scaffold's `--dry-run` help takes in #1052.

The docstring of `passed_values` said a value never starts with `-`.
argparse takes `-`, a negative number such as `-5` and a word with a
space such as `-x y` (but not one argparse reads as a scaffold flag,
such as `-h y`) as a flag's value, where `passed_values` reads none, so
step (4) reports from fewer values. The docstring says so now, and so
does the docstring of the test that pins it in
tests/test_setup_project_py.py.

The README grows three lines (tests/readme-cap.d/921.txt), and the seven
handbook markers carry the README section's new hash.

Part of #921
Part of #923

Lane: openreposhape-3 (openRepoShape-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 20, 2026
…er answer is `os.access`'s and that it leaves nothing that stays, as the scaffold's help does since #1052, and a test holds the seed NOTE's GitHub clause (#923) (#1063)

`family.py init --dry-run`'s help and the module docstring said the run
makes no folder, and not where its answer about a folder comes from.
They now say what #1052 made the scaffold's help say: whether each
folder can be written in is asked of `os.access`, which reads the mode
bits and on Windows says yes for every folder, so a quota, a Windows ACL
or a read-only drive on Windows can pass the dry run and be refused by
the real run; and the dry run leaves nothing that stays: it makes and
removes temporary folders, creates no remote or repository and pushes
nothing. The docstring names the folders: an `openreposhape-branch-*`
every time, and an `openreposhape-ident-*` for the author and for the
committer when that role's GIT_AUTHOR_ or GIT_COMMITTER_ variables are
set. A test pins the help's words, and docs/cli.md's family section is
regenerated.

`folder_in_the_way`'s docstring in shape_materialize.py now says that on
Windows the real `mkdir` can still be refused where `os.access` said
yes.

A unit test now holds the scaffold's seed NOTE at its call site: for a
GitHub leg it ends ", and on GitHub it may be the leg's default
branch.", and under `--local-remote-dir` it says nothing of GitHub.

Closes #923
Part of #921

Lane: openreposhape-3 (openRepoShape-3)
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

Development

Successfully merging this pull request may close these issues.

1 participant