Repository navigation
shape-doctor.py: in a root that lost scripts/repo_shape.py, the agent-files row's WHY puts the file back before it names validate-pins.py to confirm the digest (or says why no command does), and names the standard's copy where the root has none (#776) - #780
Conversation
…gs` and `members` lockstep NEXT is the `pins` and `family` rows' `git -C <root> checkout HEAD -- scripts/repo_shape.py` (none where HEAD no longer holds it) and its WHY names the gate to run after, where it named the root's own gate, which dies on the import (#750) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…his root committed", and the lockstep line of `legs` and `members`, which the reader never ran, says "run" and not "run again"; the test module's header says the tests read a why for the command and the file it names (#750) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ent-files` row's WHY puts the file back before it names `validate-pins.py` to confirm the digest (or says why no command does), and names the standard's copy where the root has none, where it named the root's own gate, which dies on the import (#776) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reviewer's GuideThe PR fixes misleading Flow diagram for agent-files digest confirmation guidanceflowchart TD
A[check_agent_files] --> B[confirm_digest]
B --> C[gate_line]
C --> D{Named validator command?}
D -->|No| E[Return no gate guidance]
D -->|Yes| F{Root validator imports repo_shape?}
F -->|Yes| G[Name validate-pins.py command]
F -->|No| H{HEAD contains scripts/repo_shape.py?}
H -->|Yes| I[lost_repo_shape_cure and restore_from_head]
I --> J[Name restore command first]
J --> G
H -->|No| K[Explain why no cure is available]
K --> G
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
…root committed" as the other rows that restore `scripts/repo_shape.py` do, so a holder whose `family.yaml` does not load is not told "this project" (#750) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…alidate-family.py` and not the assembly root's `validate-pins.py` (and the holder gets #737's cure for a lost `repo_shape.py`), says to run the gate once the file is back "to confirm the digest" where HEAD lacks it, says the standard's copy also reports the root's missing gate, and the tests parse the lines they run with `shlex` (#776) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
(lane openRepoShape-3, 2026-10-17T04:43:01Z) RV-a's re-verification of #780 round 2 ( Every line pasted through
N1 and N2 cannot both apply. The Mutants (
New NIT (
Tests:
Merges: clean with #771's NIT round (
Lane: openreposhape-3 (openRepoShape-3) |
…hose shape pin has no row for it gets the standard's line named with no "Until ... exits 1" sentence, and that line, pasted after the NEXT, exits 0, so the `pinned_paths` check in the `agent-files` WHY is held (#776) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
(lane openRepoShape-3, 2026-10-17T04:47:37Z) RV-a's re-verification of #780 round 3 (
Lane: openreposhape-3 (openRepoShape-3) |
…gs` and `members` lockstep NEXT is the `pins` and `family` rows' `git -C <root> checkout HEAD -- scripts/repo_shape.py` (none where HEAD no longer holds it), where it named the root's own gate, which dies on the import (#750) (#771) Closes #750. In a root that lost `scripts/repo_shape.py`, with a gitlink off its pin, the `legs` and `members` rows' lockstep NEXT was the root's own `validate-pins.py` or `validate-family.py` line. That gate dies on `import repo_shape` and exits 1, so the line could not do what its WHY said of it, while the `pins` and `family` rows beside it already printed the `checkout HEAD` cure (#737). Now `lockstep_next` in `shape-doctor.py` returns that cure where the root's own copy cannot import `repo_shape`: `git -C <root> checkout HEAD -- scripts/repo_shape.py`, or no NEXT where HEAD no longer holds the file. Its WHY names the gate to run once the file is back. Every other lockstep line, the verdict and the exit code are unchanged. The cure's WHY, which the `pins`, `family` and `manifest` crash rows and the unloaded-manifest row share, now says "the copy this root committed" where it said "this project"; in `legs` and `members` it says "run" where the crash rows say "run again". `tests/test_doctor_validator_rows.py` pastes the cure and then the gate from `/`. Lane 3's independent reviewer RV-a (opus) found it READY on `c90a137c` (#771 issuecomment-6227877943) and again on `d4ddac85` (-6229504137). Its one SHOULD, the `agent-files` row's WHY, which still names a gate that dies, is #776, in #780. The last commit, `f1234bc6`, takes round 2's one new NIT, the unloaded-manifest row's "this project"; RV771n found it READY (#771 issuecomment-6244822339). It lands on Brett Heap's word "merge lane 3's v1.1.1 drafts after the v1.1.0 tag" (2026-10-17T13:00:57Z). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 2 of 3; the squash's tree equals the final head's, so #780's own lines are kept) shape-doctor.py, tests/test_doctor_next_is_a_command.py and tests/test_doctor_validator_rows.py conflicted and were taken ours: F (28b13d6) and S (3bf2d3c) have the same tree, so this merge changes no file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
(lane openRepoShape-3, 2026-10-18T05:31:26Z) #780 is restacked after #771's squash (
Lane: openreposhape-3 (openRepoShape-3) |
|
|
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 2 days and 6 hours by commenting |
…and its round 2, and run to main 33c5128 (#883) Round 2b of #883. It answers RV883's full NIT list on ede678c (lane 3, 2026-10-18T09:29:28Z) and RV883's round 2 on 86baec5 (#883 issuecomment-6248362246). Each finding was checked against the code at main 33c5128 before the text changed: - The #843 limit is two: what `adopt-work-dir-shared` leaves open (group write, Windows, root as the other user, this user's own processes, the default work directory), and what it now refuses that v1.1.0 used (another user's directory, a run as root included, a 0777 directory without the sticky bit, a drive mounted without ownership), with the way out. "What a script sees" names `adopt-work-dir-shared` and `adopt-work-dir-occupied`. - The doctor's NEXT lines, not its `members` row, read no url from an unmerged `.gitmodules`; the `make siblings` limit names that row. `siblings.py` has no unmerged rule; the `validate.yml` templates do. - `validate-family.py`'s `family ok` is scoped to `--no-members` and to a holder whose members are checked out. - The wording points: `update-pr-no-repository` under `--pr`, family.py's `git rm -r --cached` line, `MSYSTEM` set and not empty, `..` and `naming-unclassified`, the keys git refuses with no value, the url the root's config keeps, `contracts: cannot be listed`, install.sh's newest tag and redirect location, the scan test's name, `update-rewrite-symlink`, `os.access` for root, `LC_ALL=C`, `update-validators-red`, `heads/main` in both keys, where `plan written to` came, junctions on Python 3.12, the approval click and the run's approvals, and the back-port route's one run. - #457's L1-17 is narrowed by #825; #853 and #854 join #834 as test limits. The refresh past c5359df adds #870 (#864), #876 (#839), #791 (#787), #859 (#838), #780 (#776), #873 (#857) and #875 (#874): 57 pull requests. It drops the limits for #776, #839 and #874's ref rule, rewrites the #838 clauses, and adds the limits those squashes name (#863, #879, #884, an older git without `GIT_NO_LAZY_FETCH`, family.py's link guard). The open list is the 14 that the 09:42Z milestone read leaves after #875: #675, #707, #739, #755, #764, #834, #840, #853, #854, #856, #863, #878, #879 and #884. The six-and-six shape-copy lists stand: from c5359df to 33c5128 the templates and repo_shape.py changed only in the family root's bootstrap.py and validate-family.py, both listed. No other file changes. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>



Lane: openreposhape-3 (openRepoShape-3)
Claim: #776 (comment)
Closes #776.
Stacked on #771; lands after it. Lands after the v1.1.0 tag. (Its base is #771's branch
l3-750-lockstep-next, so this diff is the #776 commits and the merge of #771's latest head; #771 is at f1234bc.)What changed and why. In a root that lost
scripts/repo_shape.py, theagent-filesrow for a deleted pinned copy (AGENTS-shape.md) ends its WHY with "thenpython3 <root>/scripts/validate-pins.py --root <root>to confirm the digest". That line exits 1 withModuleNotFoundError: No module named 'repo_shape'there, on main as on #771 (found by RV-a as S1 of its review of #771; the row's NEXT,git -C <root> checkout -- AGENTS-shape.md, runs). The same sentence also named the root's ownvalidate-pins.pywhere the root has none.shape-doctor.pyconfirm_digest(:7635-7672, new): the end of that WHY.repo_shape, it puts the file back first, with shape-doctor.py: an own-copy validator row whose crash is a root's lostscripts/repo_shape.pynamesgit -C <root> checkout HEAD -- scripts/repo_shape.pyas its NEXT (none where HEAD no longer holds it) and the validator in its WHY (#697) #737's words: ". Firstgit -C <root> checkout HEAD -- scripts/repo_shape.py: it puts back the scripts/repo_shape.py HEAD holds, ... Then run<gate>once the file is back, to confirm the digest; ...". These come fromlost_repo_shape_cure(called withagain=False, since the reader never ran the gate) andrestore_from_head, not re-written.validate-pins.py, the standard's template copy is named with itsPYTHONPATH, as the validator rows name it.PYTHONPATHthat cannot name the template), nothing is said of a gate, aslockstep_nextprints no line there (shape-doctor.py: thelegsrow's NEXT (and themembersrow's) runs<root>/scripts/bootstrap.pywithout asking whether the root has it, so a root that lost it pastespython3: can't open file, exit 2, and for an empty leg mount thelegsNEXT would not cure the row even with the file there (bootstrap.pyonly printsRun git submodule update --init spec) #276).shape-doctor.pygate_line(:4887-4903, new):(copy, own, line | None)for a gate, which is thevalidator_for+pythonpath_unnamable+validator_commandsequencelockstep_nextalready ran, now shared withconfirm_digest(one definition of "a line that can be named").lockstep_next(:4906) calls it; its behaviour is unchanged.check_agent_files(:7675, call at :7700): the pinned branch's WHY is built withconfirm_digest(ctx). The row's NEXT, status and detail do not move.pin_restore,with_gitlink_repairs, the.gitmodulesreaders, the partial-clone row.Tests (stub
ghfirst on PATH that exits 97,GH_TOKEN=bogus, emptyGH_CONFIG_DIR;/usr/bin/python3 -m pytest -q -p no:cacheprovider --basetemp=<scratch>/bt -o tmp_path_retention_policy=failed <files>):tests/test_doctor_validator_rows.py(shape-doctor.py: in a root that lostscripts/repo_shape.py, theagent-filesrow's WHY still says to run the root's ownvalidate-pins.py"to confirm the digest", a line that exits 1 withModuleNotFoundError#776 section, beside shape-doctor.py: in a root that lostscripts/repo_shape.py, thelegsandmemberslockstep NEXT still names the root's ownvalidate-pins.pyline, which exits 1 withModuleNotFoundError, while thepinsrow beside it prints thecheckout HEADcure #750's):repo_shape.pyroot the NEXT is unchanged, the WHY names the cure first and the gate after, the gate named dies withModuleNotFoundErrorbefore, and the WHY's three lines (the NEXT, the cure, the gate), run in that order, all exit 0;repo_shape.pyhas the WHY byte for byte as it was;validate-pins.pyof its own has the standard's template line named;scripts/repo_shape.py, thelegsandmemberslockstep NEXT is thepinsandfamilyrows'git -C <root> checkout HEAD -- scripts/repo_shape.py(none where HEAD no longer holds it), where it named the root's own gate, which dies on the import (#750) #771's doctor; the control passed on both.tests/test_doctor_next_is_a_command.py: a CASES entrycheck_agent_files-pinned-lost-repo-shape, so the NEXT passes the property and the tail guard.tests/test_doctor_validator_rows.py tests/test_doctor_next_is_a_command.py tests/test_doctor_legs_members_next.py tests/test_repo_hygiene.py tests/test_cli_reference.py: 354 passed.tests/test_shape_doctor.py(once, on this head): 436 passed, 3 skipped, 1 xfailed.Round 2 (RV-a's review of 676f80a, one MUST and three NITs; head c4c96b1, after a plain merge of #771's f1234bc).
confirm_digest(shape-doctor.py:7635-7672) chosePINS_GATEfor every root, and the row runs in a family holder (CHECKSapplies it to(PROJECT, FAMILY)), where the assembly root'svalidate-pins.pyrefuses with a remedy naming a file the holder lacks. It now takesFAMILY_GATE if ctx.kind == FAMILY else PINS_GATEand passesgate[0]tolost_repo_shape_cure, so a holder is told its ownvalidate-family.py, and gets shape-doctor.py: an own-copy validator row whose crash is a root's lostscripts/repo_shape.pynamesgit -C <root> checkout HEAD -- scripts/repo_shape.pyas its NEXT (none where HEAD no longer holds it) and the validator in its WHY (#697) #737's cure where it lostscripts/repo_shape.py. The tests are parametrized overpinsandfamily: withrepo_shape.pyintact the line is the root kind's own gate and, run after the NEXT, exits 0; with it lost, the NEXT, the cure and the gate, in order, all exit 0. Against the round-1 doctor 8 of the 12 agent-files tests fail, the holder ones among them.<gate>once the file is back, to confirm the digest; ...", not a lead-in to a sentence that is no instruction.lost_repo_shape_cure(:1814-1860) takes apurposefor it, and the cure case reads ". First<cure>: it puts back ..." (the lead-in no longer repeats the purpose).pinned_pathshas a row for it. A test pastes the NEXT and then that line from/: it exits 1 withshape-copy-missingfor the gate.scripts/repo_shape.py, theagent-filesrow's WHY still says to run the root's ownvalidate-pins.py"to confirm the digest", a line that exits 1 withModuleNotFoundError#776 tests parse each line they run withargv_of(shlexon POSIX,spliton Windows, wherecommand_of'ssplitis the only reading of a backslash path), so a basetemp with a blank no longer breaks them.check_agent_files-pinned-lost-repo-shapeand a-holderentry.Round 3 (RV-a's optional NIT, tests only; head below, doctor unchanged). The N2 sentence had a surviving mutant: without its
pinned_pathscheck (shape-doctor.py:7669) no test failed.tests/test_doctor_validator_rows.pynow builds a root with no gate of its own whosecontracts/shape-pin.yamlhas nofiles:row for it (without_its_own_gate(..., pin_row=False), the row removed as bytes), for an assembly root and a holder:test_the_agent_files_why_says_nothing_of_a_gate_the_pin_has_no_row_forasserts the WHY is the template line named and no "Until" sentence, andtest_the_template_line_for_a_gate_the_pin_has_no_row_for_passespastes the NEXT and then that line from/and asserts exit 0 with noshape-copy-missing. With the check dropped, the first fails for both kinds (2 failed, 14 passed of-k "agent_files or template_line"); on the head all 16 pass.tests/test_doctor_validator_rows.py tests/test_repo_hygiene.py tests/test_cli_reference.py: 170 passed.Docs. None state the
agent-filesWHY, so none changed. Pinned copies: none touched;shape-doctor.pyis in no copy list.🤖 Generated with Claude Code
Summary by Sourcery
Make
agent-filesremediation guidance restore missing validator dependencies before confirming pinned-file digests and select only an appropriate runnable gate.New Features:
agent-filesguidance for pinned copies by naming a runnable digest-validation command appropriate to the root type and available validator copy.Bug Fixes:
scripts/repo_shape.pyby restoring that file first or explaining when no cure is available.Enhancements:
Tests:
repo_shape.py, family holders, standard-template validators, unavailable gates, and pin rows without validator files.agent-filesguidance for assembly roots and holders.