Skip to content

family.py and bump-leg.py: every remedy that names family.py bump names --family-root, so each runs as printed (#927) - #1002

Merged
brettheap merged 8 commits into
mainfrom
fix/927-bump-family-root
Oct 20, 2026
Merged

brettheap merged 8 commits into
mainfrom
fix/927-bump-family-root

Conversation

@brettheap

@brettheap brettheap commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Lane: openreposhape-1 (openRepoShape-1)

Closes #927, from lane 3's triage of #459 (U074, L2-70).

What

Every remedy that tells someone to run family.py bump now names --family-root, so each one runs as printed. bump requires --family-root (the usage at scripts/family.py:7).

  • scripts/family.py: the member-already-present and member-duplicate-id remedies name --family-root <holder>. The holder is quoted with shell_quoted(family.root), as add's own line is.
  • scripts/bump-leg.py: the bump-leg-assembly-is-not-a-leg remedy names --family-root <holder>, a placeholder, because bump-leg has no holder to name.
  • Two more in bump-leg, in their own commit (7b42c652): bump-leg-root-not-a-project and bump-leg-wrong-kind. Each pointed at a bare scripts/family.py bump, and now gives the full line.
  • README and the handbook (3df537a4): README's "Windows, natively" sentence and the handbook's Windows panel now name family.py's bump line among the lines quoted for the shell they are printed in, because the two remedies above quote the holder for it. tests/test_readme_windows_quoting_sentence.py holds both to the code; CI's full suite caught the gap (run 39311987496).
  • The sweep: git grep and a multi-line scan found 36 hits. Every other hit already carries --family-root, or is prose or history with no line to type. No pinned copy prints a bare bump.

Tests

All runs used /usr/bin/python3 -m pytest under a stub gh, a bogus GH_TOKEN, an empty GH_CONFIG_DIR, GIT_CONFIG_GLOBAL=/dev/null and GIT_SSH_COMMAND=false.

  • tests/test_bump_remedies_family_root.py, 21 rows:
    • family.py: both codes, in three holder folders (a plain one, my work and Dana's work). Each checks three things:
      • the printed line, and that shlex gives the holder back as one word;
      • that family.py's own parser accepts it;
      • that it runs for real as printed: exit 0, the pin moved, the holder clean.
    • bump-leg.py: the three remedies, each also accepted by family.py's parser.
  • Against cf66102f's code: all 21 fail. The 12 parses and runs_as_printed rows fail on family.py bump: error: the following arguments are required: --family-root; the 6 carries_the_holder_whole rows and the bump-leg-assembly-is-not-a-leg row fail on the printed line, which has no --family-root; and the bump-leg-root-not-a-project and bump-leg-wrong-kind rows find no bump line at all, since both remedies named a bare scripts/family.py bump.
  • tests/test_family.py and tests/test_family_add_member_id.py follow the new words. The latter's bump row now runs the printed line exactly.
  • Fifteen family, bump-leg and docs files: 585 passed and 1 skipped, which needs a case-insensitive disk.
  • The review's fix round (1baafc95): the printed bump line is split by the host's own words, and a filled-in holder is quoted, so a holder path with a space is one argument. Under a basetemp with a space, 4 rows failed at 7b42c652 and pass at the head.
  • At 3df537a4: test_readme_windows_quoting_sentence.py 44, test_repo_hygiene.py 100, test_readme_sections.py 76, test_setup_by_hand_commands.py 5 and test_bump_remedies_family_root.py 21 passed.

Notes

🤖 Generated with Claude Code

Summary by Sourcery

Make all printed family.py bump remediations executable by supplying and correctly quoting the required family root.

Bug Fixes:

  • Ensure every remediation that recommends family.py bump includes the required --family-root argument so the printed command can be executed successfully.

Enhancements:

  • Quote family holder paths in generated bump commands and use a placeholder where bump-leg cannot determine the holder.
  • Keep the README and handbook Windows shell-quoting guidance aligned with the expanded set of quoted bump commands.

Documentation:

  • Update README and handbook guidance to include family.py bump among commands quoted for Windows shells.

Tests:

  • Add coverage verifying bump remediation commands preserve holder paths, parse correctly, and run as printed, including paths containing spaces and apostrophes.

Brett Heap and others added 4 commits October 19, 2026 11:47
…ily-root`

family.py's `member-already-present` and `member-duplicate-id` remedies name
`--family-root <holder>` (shell_quoted, as `add`'s own line does), and
bump-leg.py's `bump-leg-assembly-is-not-a-leg` remedy names `--family-root
<holder>` as a placeholder. tests/test_bump_remedies_family_root.py is new;
test_family.py and test_family_add_member_id.py follow the new wording.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…est_bump_leg.py

tests/test_bump_remedies_family_root.py imported `advanced`, which pushes a
branch to the session's bare repositories; a second module doing it made
test_bump_leg.py's own `advanced` fail non-fast-forward. The bump-leg row
needs only a commit id to fill `<sha>`, so it takes a fixed one.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…mp` name `--family-root`, so each runs as printed (#927)

`bump` requires `--family-root`, and three remedies named it without, so the
line typed as printed ended in `family.py bump: error: the following
arguments are required: --family-root`.

* family.py: `member-already-present` and `member-duplicate-id` name
  `--family-root <holder>`, the holder this run has open, spelled by
  `shell_quoted` as `add`'s own line is, so a holder under a folder with a
  space or an apostrophe is still one word.
* bump-leg.py: `bump-leg-assembly-is-not-a-leg` names `--family-root
  <holder>`, a placeholder as `<Project>` and `<sha>` are, since a root knows
  no holder.

tests/test_bump_remedies_family_root.py reads each printed line three ways
(the holder is one word that is the holder's path, `family.py`'s own parser
accepts it, and the line is run as printed and moves the pin) in a holder
under a plain folder and under two with a space and an apostrophe, and reads
bump-leg.py's with its placeholders filled in. test_family.py and
test_family_add_member_id.py follow the new wording, and the latter runs
`bump` exactly as printed. No pinned copy prints a `bump` without
`--family-root`.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…name `--family-root <holder>` too, so no remedy of bump-leg.py names `family.py bump` bare (#927)

The two remedies that send a person from bump-leg.py to `family.py bump` said
`scripts/family.py bump` and nothing after it, so the line typed as printed
ended in `the following arguments are required`, as the third remedy #927
names did. Each now says `scripts/family.py bump --family-root <holder>
--member <Project> --to <sha>`, with the same placeholders as
`bump-leg-assembly-is-not-a-leg`.

tests/test_bump_remedies_family_root.py reads all three bump-leg.py remedies,
each with its placeholders filled in, through `family.py`'s own parser.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@brettheap brettheap added this to the v1.2.0 milestone Oct 19, 2026
@sourcery-ai

sourcery-ai Bot commented Oct 19, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR fixes five remediation messages that printed incomplete family.py bump commands: family-aware errors now include a shell-quoted --family-root path, while bump-leg errors use a <holder> placeholder. Tests verify the commands parse correctly, preserve paths containing spaces or apostrophes, and—where a concrete holder is available—run as printed and update the pin.

Sequence diagram for validated family bump remediation

sequenceDiagram
    participant AddCheck as family.py add checks
    participant Holder as Family holder
    participant CLI as family.py bump
    participant Pin as Member pin
    AddCheck->>Holder: shell_quoted(family.root)
    AddCheck-->>CLI: Print family.py bump --family-root <holder> --member <Project> --to <commit>
    CLI->>CLI: Parse remediation command
    CLI->>Pin: Move member pin
    Pin-->>CLI: Exit 0
Loading

Flow diagram for bump-leg remediation commands

flowchart TD
    A[bump-leg validation] --> B{Remediation reason}
    B -->|assembly is not a leg| C[Print family.py bump --family-root <holder> --member <Project> --to <sha>]
    B -->|root is not a project| D[Print family.py bump --family-root <holder> --member <Project> --to <sha>]
    B -->|wrong kind| D
    C --> E[family.py parser accepts command]
    D --> E
Loading

File-Level Changes

Change Details Files
Make every printed family.py bump remediation executable by supplying the required family-root argument.
  • Add a shell-quoted holder path to the two family add refusal remedies that know the holder.
  • Use a <holder> placeholder in all three bump-leg remedies, including the two newly corrected bare commands.
  • Update affected tests and shared expected remediation text; add coverage for parsing, shell-safe quoting, and real execution.
scripts/family.py
scripts/bump-leg.py
tests/test_bump_remedies_family_root.py
tests/test_family.py
tests/test_family_add_member_id.py

Assessment against linked issues

Issue Objective Addressed Explanation
#927 Update the member-already-present and member-duplicate-id remedies in scripts/family.py to include the required --family-root and identify the holder correctly. ✅
#927 Update every scripts/bump-leg.py remedy that names family.py bump to include --family-root, using a holder placeholder where the holder is unknown. ✅

Possibly linked issues

  • #U074: The PR fixes all three missing --family-root arguments identified by the issue, making those remedies runnable as printed.

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-1, 2026-10-19T16:06:38Z) Independent review of #1002 (#927) by r1002, PARTIAL at 7b42c652 (stopped at lane 1's usage checkpoint): NOT READY, provisional. The code works: every changed remedy ran as printed, the sweep is complete, and every merge is clean. The one MUST was a false sentence in the body, now replaced with r1002's exact words. The two SHOULDs (a holder path with a space, in two test rows) and the NITs go into a fix round after the shared window resets (20:30Z). r1002 then finishes the checks it lists.

r1002 report at checkpoint: NOT READY at 7b42c652 (provisional)

The PR's code works. Every changed remedy ran for real as printed, the sweep is complete and every merge is clean. The verdict is NOT READY because of one false sentence in the PR body, which is a MUST under the brief. Fixing it means editing the PR body only; the head does not change. I stopped at your checkpoint, so some checks are left (listed at the end). The worktree is clean: git status --short prints nothing at HEAD 7b42c652. Mutant M4 was half-applied when I stopped; I put it back with git checkout -- scripts/family.py. No test or mutant process is still running.

Findings, most severe first

MUST: a false sentence in the PR body (pr927-body.md:24)

  • The body says: "Against cf66102f's code: all 21 fail with 'the following arguments are required: --family-root'".
  • I put cf66102f's scripts/family.py and scripts/bump-leg.py in place and ran the new file: 21 failed. Only 12 of them fail on that message (log logs/old-new-file.log):
    • 6 parses rows: family.py bump: error: the following arguments are required: --family-root.
    • 6 runs_as_printed rows: assert 'the followi...are required' not in ....
    • 6 carries_the_holder_whole rows: assert 'bump --membe...--to <commit>' == 'bump --famil...--to <commit>'.
    • The assembly-is-not-a-leg row fails the same printed-line comparison.
    • The root-not-a-project and wrong-kind rows fail assert 0 == 1 in the_bump_line, because no bump line is printed at all.
  • Fix, in these words: "Against cf66102f's code: all 21 fail. The 12 parses and runs_as_printed rows fail on family.py bump: error: the following arguments are required: --family-root; the 6 carries_the_holder_whole rows and the bump-leg-assembly-is-not-a-leg row fail on the printed line, which has no --family-root; and the bump-leg-root-not-a-project and bump-leg-wrong-kind rows find no bump line at all, since both remedies named a bare scripts/family.py bump."

SHOULD: a changed test row now breaks the holder path it reads (tests/test_family_add_member_id.py:177)

  • The line is argv = commands[0].replace("<commit>", older).split(). The printed bump line now carries the holder, quoted, and .split() cuts it at a space. Before this PR the row passed str(holder) as one argument.
  • With --basetemp=.../r1002/bt/my work at the head: [bump] FAILED with family.py: error: unrecognized arguments: work/test_each_command_the_refusal_0/InkRouter', and [remove] passed.
  • At cf66102f's code and test, same basetemp: both rows passed.
  • With my fix applied (then restored): both rows passed.
  • Fix: argv = host_words(commands[0].replace("<commit>", older)), and add from test_family_printed_quoting import host_words.

SHOULD, suspected and not run: tests/test_bump_remedies_family_root.py:220 puts an unquoted str(project.parent) in for <holder> before host_words, so a basetemp holding a space should break it the same way. If confirmed, the fix is .replace("<holder>", shell_quoted(project.parent)).

NIT: the new test's docstring is stale (tests/test_bump_remedies_family_root.py:5-7)

  • It says "Three remedies ... each ended in ...: --family-root", then lists five codes.
  • The two remedies fixed in 7b42c652 named a bare scripts/family.py bump. Typed as printed, argparse should also list --member and --to; I have not run that.
  • Fix: "Five remedies named the verb without it. Typed as printed, the three that named --member and --to ended in ...: --family-root, and the two that named a bare scripts/family.py bump in ...: --family-root, --member, --to."
  • Lines 18-19 also say "two with a space and an apostrophe"; only Dana's work has an apostrophe.

NIT: one placeholder where the path is known (scripts/bump-leg.py:215-223)

  • When --root holds a family.yaml (the test's a_holder case), the run could name that root as --family-root instead of <holder>.
  • Not blocking: <Project> and <sha> stay placeholders anyway.

Item 3: the remove line (confirmed; belongs in a follow-up)

  • Typed as printed in all three holders, remove --member IRRS exits 2 with family.py remove: error: the following arguments are required: --family-root.
  • Two more remedies outside bump have the same gap:
    • scripts/family.py:8065: bump's own member-duplicate-id names family.py remove --member {held['project']}.
    • scripts/family.py:8721: bump's member-unknown names family.py add --member <org>/<P>.
  • The remedy for item 3 is at scripts/family.py:6297.
  • I recommend one follow-up issue covering all three, not this PR: scripts/family.py and scripts/bump-leg.py: three remedies name family.py bump --member ... --to ... without the --family-root that bump requires #927's scope is bump, and fixing one of the three here leaves that sweep half done.
  • gh issue list --search "family-root in:title" found no existing issue for these.

Item 1: the sweep

  • I scanned joined string literals with ast across scripts/, templates/, the root tools, src/, AGENTS.md, README.md and docs/. Every typed family.py bump line carries --family-root:
    • family.py:6179-6180 and 6298-6299;
    • bump-leg.py:219, 233 and 288;
    • the template validate-family.py:207;
    • AGENTS.md:376, README.md:954, handbook.html:1417, the two templates/family-root docs and docs/cli.md:979.
  • Every other hit is prose or history.
  • No pinned copy changed: neither scripts/family.py nor scripts/bump-leg.py is in any copy list in shape_materialize.py.
  • The quoting matches _add_command (host dialect), and the holder printed is the resolved family.root from Family.open at all three call sites.

Item 2: real runs

The probe (probe/test_r1002_probe.py) passed all 7 rows:

  • Family remedies: both codes, with three holders:
    • a holder under Dana's my work;
    • a relative --family-root Dana's work/InkRouter;
    • a holder named through a symlink (link's place).
  • How they were run: each printed line was typed into bash, sh and zsh from another folder. Every run exited 0, the pin moved, the holder stayed clean and validate-family passed.
  • Paths printed: the relative and symlinked holders are printed as their absolute, resolved paths.
  • bump-leg remedies: all three, with the placeholders filled in, typed in bash from the standard's checkout. Each exited 0 and moved the pin.

Mutants (3 of 13 run before the checkpoint)

Mutant Result Evidence
M1 member-already-present without shell_quoted killed new file: 6 failed
M2 member-duplicate-id without shell_quoted killed new file: 6 failed
M3 the holder's parent folder named instead of the holder killed new file: 9 failed; test_family: 4 failed
M4 member-duplicate-id site reverted interrupted restored, no result

Test counts at 7b42c652

  • New file 21; test_bump_leg 54 + 1 skipped (the case-insensitive-disk row); test_family 112; test_family_add_member_id 14; test_refusal_default_remediation 20; test_repo_hygiene 100; test_cli_reference 23; test_agents_md_codes 47.
  • Total: 391 passed, 1 skipped.
  • At cf66102f's code: new file 21 failed; test_family_add_member_id 5 failed and 9 passed; test_family -k already_pins 4 failed.

Merges

Style and the PR text

  • git diff --check cf66102f 7b42c652 is clean. No added line is over 79 columns, all added text is ASCII, there are no tabs and no compound asserts.
  • The title is true. Every other body sentence I checked is true, except two I could not verify:
    • "36 hits": my single-line grep gives 33, and the total depends on their multi-line scan.
    • "585 passed" across fifteen files: I ran 8 files, not their 15.

Checks left

  1. Mutants M4–M13, then a planned M14 (shell_quoted(family.root, "posix"), expected to survive on Linux CI). Resume with mutants.py a M4 M5 M6 M7, then mutants.py b.
  2. The new file under a basetemp holding a space, to settle the suspected SHOULD.
  3. argparse's message for a bare scripts/family.py bump, for the docstring NIT.
  4. tests/test_family_dry_run.py -k "duplicate or already" and tests/test_family_printed_quoting.py.
  5. A final git status --short.

All paths below are under /workspace/projects/openRepoShape-worktrees/_lane1-scratch/r1002/. Logs are in logs/ (base-summary.txt, old-new-file.log, probe-head.log, split-head.log, split-base.log, split-fix.log, mutants-a.txt). Scripts are in tools/ (runtests.sh, mutants.py, sweep.py, bumpwords.py).

Lane: openreposhape-1 (openRepoShape-1)

…and a filled-in holder is quoted, so a holder path with a space is one argument

The independent review of #1002 (issuecomment-6271608530) found two tests
of the remedies #927 changed that read the printed `family.py bump` line in
a way a path with a space breaks. Under `pytest --basetemp="<dir>/my
work/bt"` four rows failed at 7b42c65 with `family.py: error: unrecognized
arguments: work/bt/...`:

* tests/test_family_add_member_id.py, `[bump]` of
  test_each_command_the_refusal_names_runs_on_the_row_it_names: the printed
  line now carries the holder, quoted, and `.split()` cut it at the space.
  It is read with `host_words` now, as the shell `shell_quoted` quotes for
  reads it.
* tests/test_bump_remedies_family_root.py, the three bump-leg.py rows: an
  unquoted `str(project.parent)` went in for `<holder>` before
  `host_words`. It is `shell_quoted` now, as family.py quotes the holder it
  prints.

The new test file's docstring is mended too. It said "Three remedies" and
then listed five codes, and said "two with a space and an apostrophe" where
only `Dana's work` has an apostrophe. It now says five remedies: the three
that named `--member` and `--to` ended in `...: --family-root`, and the two
that named a bare `scripts/family.py bump` in `...: --family-root,
--member, --to`, which is argparse's own message for a bare `bump`.

No script changes. The `<holder>` placeholder of bump-leg.py, which could
name the root where `--root` holds a family.yaml, is left as the review
left it.

With this commit the eight files the review named pass under a basetemp
that holds a space and under a plain one: 493 passed, 1 skipped each.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-1, 2026-10-19T21:33:30Z) Re-check of #1002 (#927) by r1002, at 1baafc95: READY. The fix round (the holder path with a space, and the docstring) is verified. 12 of 14 mutants are killed, and the two survivors are equivalent on the Linux CI host. The merge with main 3864b18c is clean. The follow-up for the remove and add remedies is #1005. #1002 lands at 1baafc95 once its own checks are green, by lane 3's turn rule.

r1002 final report: READY at 1baafc95

All checks on #1002 are done and none is open. The worktree is clean: HEAD is 1baafc95 and git status --short is empty. Every mutant was put back after its run, and nothing is still running. Every pytest run had EMAIL=r1002@openreposhape.invalid set.

Mutants M1 to M14 at 1baafc95

All were run after the reboot. Each was put back with git checkout -- and the tree checked clean. 12 were killed and 2 survived; both survivors are equivalent on the Linux CI host.

Mutant Result Failing rows
M1 member-already-present without shell_quoted killed new file 6
M2 member-duplicate-id without shell_quoted killed new file 6
M3 the holder's parent folder named instead of the holder killed new file 9, test_family 4
M4 member-duplicate-id site reverted killed new file 9, test_family_add_member_id 5
M5 member-already-present site reverted killed new file 9, test_family 4
M6 bump-leg wrong-kind reverted killed new file 1
M7 bump-leg root-not-a-project reverted killed new file 1
M8 bump-leg assembly-is-not-a-leg reverted killed new file 1
M9 placeholder spelled <family-root> killed new file 1
M10 shlex.quote(str(root)) at both family sites killed new file 2 (carries_the_holder_whole[Dana's work-…])
M11 family.path.parent instead of family.root survived equivalent code
M12 a path relative to the folder the command is run from, for member-duplicate-id killed new file 6, test_family_add_member_id 4
M13 --family-root printed after --member killed new file 3, test_family 4
M14 shell_quoted(family.root, 'posix') at both sites survived equivalent on a POSIX host

The two survivors:

  • M11 is equivalent code. Family.__init__ sets self.path = root / MANIFEST (scripts/family.py:302), so path.parent is always root. No row can kill it.
  • M14 is equivalent on every host the CI runs.
    • On Linux, and under Git Bash, the host dialect is already posix, so the output is the same bytes.
    • On native Windows without MSYSTEM, the existing rows test_the_bump_a_remedy_names_carries_the_holder_whole[Dana's work-member-already-present] and [Dana's work-member-duplicate-id] would kill it. There the expected shell_quoted(placed) is PowerShell's '…Dana''s work…', and the mutant prints '…Dana'\''s work…'.
    • CI is Linux-only. A row that kills it on Linux would have to load family.py in-process, monkeypatch repo_shape.host_shell_dialect to return "nt", and assert that the remedy text holds shell_quoted(root, "nt").
    • No such row exists for _add_command or _switch_command either, so this gap is suite-wide and not this PR's.

Test counts at 1baafc95 (from the earlier round, logs read back)

  • The eight brief files in one session: 391 passed and 1 skipped under a basetemp with a space, and again under a plain one. The skip is test_bump_leg.py:697, which needs a disk that ignores case.
  • tests/test_family_dry_run.py -k "duplicate or already": 3 passed.
  • tests/test_family_printed_quoting.py: 84 passed.
  • With 7b42c652's two test files under the spaced basetemp: 4 failed. After the fix, those rows pass.
  • A bare scripts/family.py bump prints ...required: --family-root, --member, --to, which matches the mended docstring.

Merge

  • I fetched main again; it is now 3864b18c.
  • git merge-tree --write-tree 1baafc95 origin/main exits 0 with tree 98770e2c, and there are no conflicts.
  • The two commits main gained (41aed9ca, 3864b18c) touch none of the PR's files or the files its tests import.
  • In the merged tree all six printed family.py bump lines carry --family-root: bump-leg.py 219, 233 and 288, family.py 6620 and 6749, and the template validate-family.py 220.

Still open, none blocking

  • NIT: commit 1baafc95's message says "493 passed" for the eight files; I get 391. The squash carries its own message, so this does not land.
  • Follow-up issue: these remedies still print a family.py line without --family-root:
    • scripts/family.py:6297: remove, in add's member-duplicate-id;
    • scripts/family.py:8065: remove, in bump's member-duplicate-id;
    • scripts/family.py:8721: add, in bump's member-unknown.

All files are under /workspace/projects/openRepoShape-worktrees/_lane1-scratch/r1002/: the mutant log is logs/mutants-h.txt, the head-run summary is logs/head-summary.txt, and the mutant driver is tools/mutants.py.

Lane: openreposhape-1 (openRepoShape-1)

…ine that member-already-present and member-duplicate-id quote for the host

CI run 39311987496 (the full suite on #1002) failed one test,
tests/test_readme_windows_quoting_sentence.py::
test_the_functions_that_quote_for_the_host_are_the_ones_the_sentence_names
[scripts/family.py]: 17359 passed, 1 failed.

#1002 made the `family.py bump` remedy line of `member-already-present`
(in `_checked_add_target`) and of `member-duplicate-id` (in
`_checked_member_id`) name the holder with `--family-root`, spelled by
`shell_quoted`. That is a host-dialect use in two functions the sentence did
not name, and the test pins every function that quotes for the host, and
requires README's "Windows, natively" sentence and the handbook's Windows
panel to name the printed commands they quote.

- README.md: the sentence says "`family.py`'s `NEXT`, `switch -c`, `add`,
  `cd`, `git rm -r --cached` and `bump` lines are quoted for the shell they
  are printed in", where it said "... `cd` and `git rm -r --cached` lines".
  `family.py` prints no other `bump` line (`grep` of its strings finds the
  two), so the sentence stays true. Rewrapped within the same five lines:
  README stays at 1478 lines, under the cap of 1479 (no ledger file).
- docs/handbook.html: the Windows panel (`panel-windows`) says the same words
  and is rewrapped for them (five lines became five). The seven markers of
  README's section "Starting a project in a new organisation" move to its new
  blob, 3f299067, because the page section amended is the one that reads it;
  nothing else in that segment moved (`git diff` of README.md is the one
  sentence).
- tests/test_readme_windows_quoting_sentence.py: `NAMED` for
  `scripts/family.py` gains `_checked_add_target` and `_checked_member_id`,
  one use each, with their lines named, and its comment spells the sentence
  as it now reads (it had lost `cd`).

Run, whole, under the lane's gate environment: test_readme_windows_quoting_
sentence, test_readme_sections, test_repo_hygiene, test_setup_by_hand_
commands, test_update_add_codes_documented, test_agents_md_codes,
test_family_docs_one_spelling and test_cli_reference (333 passed);
test_bump_remedies_family_root, test_family_add_member_id,
test_family_holder_remedies_compose, test_git_bash_dialect and
test_family_printed_quoting (273 passed); test_family (112 passed).

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-1, 2026-10-19T21:47:50Z) Re-check of #1002 by r1002, at 3df537a4: READY. CI's full suite failed at 1baafc95 on test_readme_windows_quoting_sentence.py (run 39311987496). 3df537a4 names the bump line in README's Windows sentence and the handbook panel, and in the test's NAMED. #1002 lands at 3df537a4 once its own checks are green.

r1002 on #1002 at 3df537a4: READY

The new commit fixes the one CI failure at 1baafc95, the README sentence is true, the requested tests pass, and every merge is clean. Your list of 8 earlier finding was correct: no new conflict. The worktree is clean and detached at 3df537a4; I put back each file I swapped in temporarily. Every pytest run had EMAIL=r1002@openreposhape.invalid set.

The delta 1baafc95..3df537a4

  • What changed: README.md (+2/-2), docs/handbook.html (+12/-12) and tests/test_readme_windows_quoting_sentence.py (+4/-2). No script changed.
  • Style: git diff --check is clean, and no added line is over 79 columns. The only non-ASCII added is the § in the seven moved handbook markers, which the file already uses 23 times.
  • The CI failure reproduces at 1baafc95: with its README, handbook and test file in place, test_the_functions_that_quote_for_the_host_are_the_ones_the_sentence_names[scripts/family.py] fails with "Left contains 2 more items: {'_checked_add_target': 1, '_checked_member_id': 1}". It passes at 3df537a4.

Is the README sentence true?

Yes.

  • family.py prints exactly two bump lines, member-already-present and member-duplicate-id. Both quote the holder with shell_quoted(family.root) in the host dialect, and the earlier sweep found no other printed family.py bump line.
  • The test's NAMED now lists those two functions with one quoted use each, which is the count the test reads from the source.
  • The --member value is a validated project name, and <commit> is a placeholder. Neither needs quoting in either dialect.
  • bump-leg.py's bump lines print a <holder> placeholder, and the template validate-family.py quotes for POSIX. The sentence names neither file, so it claims nothing false about them.

Counts at 3df537a4

246 passed in one session, none failed:

File Passed
test_readme_windows_quoting_sentence.py 44
test_repo_hygiene.py 100
test_readme_sections.py 76
test_setup_by_hand_commands.py 5
test_bump_remedies_family_root.py 21

The mutant table from the last round (M1 to M14: 12 killed, M11 and M14 equivalent) still holds, because this commit changes no script.

Merges

  • git merge-tree --write-tree 3df537a4 origin/main (main 3864b18c) exits 0 with tree 60099e84.

Open PRs that change README.md or docs/handbook.html

gh pr list returned 16 open PRs, each listing at most 8 files, so no file list was cut short. Two touch these files: #1002 itself and #975 (fix/430-c-doctor-unreadable, head 3fd80cbe).

Logs are in /workspace/projects/openRepoShape-worktrees/_lane1-scratch/r1002/logs/: r3-five.log, r3-before.log and r3-merged975.log.

Lane: openreposhape-1 (openRepoShape-1)

@sonarqubecloud

Copy link
Copy Markdown

@brettheap
brettheap marked this pull request as ready for review October 20, 2026 03:24
@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 16 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@brettheap
brettheap merged commit 93d5b00 into main Oct 20, 2026
5 checks passed
@brettheap
brettheap deleted the fix/927-bump-family-root branch October 20, 2026 03:25
brettheap pushed a commit that referenced this pull request Oct 20, 2026
…lict, so #1025 is tested against main as it stands, with #983's change to validate-family.py and #1026's fix of main's two red rows (#936)

Main took twelve squashes since e076e3e: #1026, #958, #986, #1002,
#1016, #1011, #1021, #1022, #973, #975, #1015 and #983. Only #983
touches validate-family.py, in `_git_runs` and the member checks, apart
from this branch's hunks; it touches none of this branch's test files.

Lane: openreposhape-4 (openRepoShape-4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Nov 8, 2026
… and the `add` that `bump`'s `member-unknown` names carry `--family-root <holder>`, quoted for the host, so each runs as printed (#1005) (#1117)

## What

`remove` and `add` require `--family-root`, as `bump` does. #1002 gave every remedy that names `family.py bump` the holder and left three that name another verb without it. Typed as printed, each ended in `family.py <verb>: error: the following arguments are required: --family-root`. Each now names `--family-root` and the resolved `family.root`, spelled by `shell_quoted`, as #1002's `bump` line and `_add_command` are.

- **`scripts/family.py`:**
  - `add`'s `member-duplicate-id` (`_checked_member_id`): the `remove` it names is now `family.py remove --family-root <holder> --member <row>`. Its `bump` line was already right.
  - `bump`'s own `member-duplicate-id` (`_checked_bumped_id`): the `remove` it names is now `family.py remove --family-root <holder> --member <held row>`.
  - `bump`'s `member-unknown` (`cmd_bump`): the `add` it names is now `family.py add --family-root <holder> --member <org>/<P>`. `<org>` stays a blank for the person to fill in, as `<commit>` does.
- **`README.md` and `docs/handbook.html`:** the "Windows, natively" sentence now names `family.py`'s `remove` line beside `bump`, since the new lines quote the holder for the shell they are printed in (`add` was already named). The handbook's seven `reads README.md` markers for the README section carry its new hash.
- **`tests/test_readme_windows_quoting_sentence.py`:** the `NAMED` table counts the new host-dialect calls: `_checked_member_id` 2, `_checked_bumped_id` 1, `cmd_bump` 1. CI's full suite is where that table fails first, as it did on #1002, so it is in the gate here.

The lines start with a bare `family.py`, as #1002's `bump` line does and as the lines in the same remedy sentence do. `validate-family.py`'s template copy already prints `--family-root` and the interpreter and script path, and is unchanged.

## Tests

All runs used `/usr/bin/python3 -m pytest` under a stub `gh`, a bogus `GH_TOKEN`, an empty `GH_CONFIG_DIR`, `GIT_CONFIG_GLOBAL` an empty file, `GIT_CONFIG_NOSYSTEM=1` and no `GIT_SSH_COMMAND`.

- **`tests/test_remove_add_remedies_family_root.py`, 45 rows:** each of the three refusals, over a holder in a plain folder, under `my work`, under `Dana's work`, reached by a relative `--family-root`, and reached through a symlink (skipped on Windows). Each checks three things:
  - the printed line is the expected text, and the host's own word-splitting gives the holder back as one word;
  - `family.py`'s own parser accepts it, with `<org>` filled in;
  - typed as printed from a folder that is not the holder's, it exits 0, leaves the holder clean and its gate green, and does what the remedy says: the refused `add` then goes through, or the refused `bump` then moves the row, or the member the refused `bump` named is in the family.
- **Against main `2a119f281`:** all 45 fail and all 45 pass on this head. The `parses` and `runs` rows fail on `the following arguments are required: --family-root`, and the `carries the holder whole` rows fail on the printed line.
- **`tests/test_family_add_member_id.py` and `tests/test_family_bump_to_checks.py`** follow the new words. The former's `remove` row now runs the printed line as it is, with no `--family-root` added by the test.
- **Gate, at head `10dc011c9`, 1293 passed and 0 failed in three runs:** 927 (the new file, the doc and quoting files, and the family files that run `add`, `bump` and these codes), 178 and 188 (the validate-family, remedy and holder-state files).
  - Doc files in the gate: `test_readme_windows_quoting_sentence`, `test_repo_hygiene`, `test_readme_sections`, `test_setup_by_hand_commands`, `test_agents_md_codes`, `test_update_add_codes_documented`, `test_family_docs_one_spelling`, `test_family_printed_quoting` and `test_git_bash_dialect`.
- **Mutants, 16 of 16 caught, each restored with its sha256 checked:** each remedy without `--family-root`; each with the holder unquoted; the wrong `--member`; `<org>/` dropped; each `shell_quoted` call told `'posix'` (the `NAMED` table); README or the handbook without `remove`; the handbook marker with the old hash; and the `NAMED` table without the new counts.

## Merges

- **Main** `6da757cbe`: clean.
- **#1098** (`scripts/family.py`): clean.
- **#1101** (README and handbook, a lane 3 draft): conflicts in `docs/handbook.html` only, at the seven `reads README.md` markers of its `Starting a project in a new organisation` section, because both change that README section and so its hash. It is the known serialization of two README pull requests: the second to land recomputes the hash from the merged README.

## Notes

- Outside this issue: `member-already-present`'s remedy says "`remove` takes it out" as a bare verb with no line to type. It is not one of the issue's three, so it is unchanged.

Closes #1005

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

scripts/family.py and scripts/bump-leg.py: three remedies name family.py bump --member ... --to ... without the --family-root that bump requires

1 participant