Repository navigation
shape-doctor.py: a conflicted shape pin's NEXT takes whole every copy both sides hold as the standard wrote it at their own pin, and a leg pin put back from before its bump says to commit it and run the pins row's bump-leg.py line (#547) - #586
Merged
Merged
Conversation
…e pin, every copy both sides hold byte for byte as the standard wrote it at that side's own pin, and gives only the rest to a person; and a leg pin put back from before its bump's own commit says, in its `why`, to commit it and run the `pins` row's `bump-leg.py` line (#547) Both are #460's lines in `pin_restore`, L2-8 and L2-9. L2-8. Since #496 (#485) every copy conflicted beside the shape pin went to a person to merge by hand, the copies two `update-shape.py apply` runs to different targets wrote included, though neither side had edited them; and a hand merge that kept both sides of a hunk, then `--accept-local`, pinned a stale line as the project's own edit, so every later upgrade of that copy was a `both`. Brett Heap ruled "Prove and take" (2026-10-14T23:54:30Z). The mechanism. `taken_with_the_pin` reads each side's stage of `contracts/shape-pin.yaml` through `check_pin` (`pin_at(..., whole=True)`) for the commit it names and its `files:` rows. A side of a conflicted copy is proved unedited where that side's pin has a row for it and its stage is, byte for byte, the standard's own file at THAT side's commit: the path mapped by `update-shape.py`'s own `source_for`, so it is the file `check` compares, and read by `git show` from the checkout the doctor runs from, which is how AGENTS.md says to run it. Nothing is fetched or cloned. A copy proved on both sides is pure tool output: the NEXT names it beside the pin in the one `git -C <root> checkout --ours -- <pin> <copies>`, so the copy taken matches the pin kept; `detail["taken_with_the_pin"]` lists it; and the `why` names it as taken whole, and why, beside the copies, manifest and README.md it still gives a person. The NEXT stays one command (#548's rule: every addition goes in `why`). `unreadable_next` is changed too, by four lines, because the `manifest kinds` row prints the same NEXT for the same conflicted pin. While the shape pin does not read nothing calls a copy a copy, so a copy under `contracts/` that the NEXT now takes whole -- the naming copy, the one a root keeps there -- came out `project` in that row's `restore`, git not asked, while its NEXT overwrote the file: the defect #485 fixed for a copy left to a person. It is now `unmerged`, as that one is, and the row's `detail` carries the same `taken_with_the_pin`. What stays a hand merge, exactly as before: a side whose stage differs or is missing; a side's pin that does not read, or has no row for the copy; a pinned commit the standard's checkout does not hold; a path the standard does not have at that commit; any read that fails. None of them proves that the copy holds no edit of the project, and taking such a copy whole is the loss #485 fixed: a copy kept by `--accept-local` on one side, dropped by the other side's copy with the hunks git merged cleanly beside it. The manifest and README.md stay a person's, as before (#267). L2-9. A slip amended into `bump-leg.py`'s own commit leaves the commit before it holding the leg pin for the OLD leg commit, so the `committed` restore's NEXT, run and committed, left the doctor saying DRIFTED and said nothing of the step that closes it. The NEXT is unchanged. `gitlink_left_behind` adds to its `why`, where the pin put back names another commit than the root's gitlink for that leg, both commits and "commit it, then run the bump-leg.py line the pins row names", with which line keeps the move and which undoes it. The gitlink is `recorded_gitlink`'s (the index, then HEAD), the read the `pins` row makes, so the sentence and the row it sends the reader to agree. Tests: new tests/test_doctor_pin_restore_merges.py. Every state is real git: the standard moved on by real commits, the project re-pinned by the real `apply`, the merge git's own, the root under a directory whose name holds a blank and an apostrophe, and every NEXT run as the reader's shell reads it. (a) both sides pure: both copies taken whole with the pin, and COMPLIANT once `project.yaml` is merged; (b) one side edited, on either side: a hand merge; (c) a checkout short of one side's commit, or of both: a hand merge; (d) a path the standard lacks at the commit one side's pin names: a hand merge; (e) one copy taken and one left, the `why` naming both; (f) L2-9's slip amended into the bump: the sentence, then the NEXT, a commit and the `pins` row's line end COMPLIANT, with a control where the slip is a commit of its own and the `why` says nothing more; (g) the NEXT that takes copies, run by `sh -c` (POSIX only); (h) the naming copy taken whole, `unmerged` and listed as taken in both rows. Mutants, each killed: taking whole without the proof, proving only the ours side or only the theirs side, comparing each side against the other side's pin or both against the kept pin, dropping L2-9's sentence, and dropping the `unreadable_next` change. No existing assertion changed. Lane: openreposhape-4 (openRepoShape-4) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideThis PR makes shape-pin conflict restoration safely take only proven tool-generated copies alongside the pin, keeps all uncertain copies for manual merging, and adds actionable guidance for leg pins restored from before their bump; extensive real-git tests validate behavior, diagnostics, and generated commands. Sequence diagram for safely restoring conflicted shape copiessequenceDiagram
participant Doctor as shape-doctor.py
participant Git as Git index
participant Pin as contracts/shape-pin.yaml
participant Standard as Standard checkout
Doctor->>Pin: pin_at(:2, whole=True)
Pin-->>Doctor: commit and files rows
Doctor->>Pin: pin_at(:3, whole=True)
Pin-->>Doctor: commit and files rows
Doctor->>Git: Read stage 2 and stage 3 copy blobs
Git-->>Doctor: Conflicted copy contents
Doctor->>Standard: source_for(copy, commit)
Standard-->>Doctor: Standard blob at each side's commit
alt Both stages match their pinned standard blobs
Doctor->>Git: checkout --ours -- pin copy
Doctor-->>Doctor: Record taken_with_the_pin
else Any proof fails
Doctor-->>Doctor: Leave copy for manual merge
end
Sequence diagram for restoring a leg pin left behind by a bumpsequenceDiagram
participant Doctor as shape-doctor.py
participant History as Pin history
participant Root as Root index or HEAD
participant User
Doctor->>History: Find newest readable pre-break leg pin
History-->>Doctor: Restored pin commit
Doctor->>Root: recorded_gitlink(leg path)
Root-->>Doctor: Current root gitlink
alt Pin commit differs from root gitlink
Doctor-->>User: why: commit restored pin, then run the pins row's bump-leg.py line
User->>User: Commit restored pin
User->>User: Run bump-leg.py --to gitlink to keep move or --to pin commit to undo
else Commits match
Doctor-->>User: No additional gitlink guidance
end
Flow diagram for proven-copy conflict restorationflowchart TD
A[Conflicted shape pin and copies] --> B[Read both side pins with pin_at]
B --> C{Each side names the copy and its commit is readable?}
C -- No --> F[Leave copy for a person]
C -- Yes --> D[Compare each stage with standard blob via source_for]
D --> E{Both sides match byte for byte?}
E -- Yes --> G[Add copy to taken_with_the_pin]
G --> H[One NEXT checks out pin and proven copies together]
E -- No --> F
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
…es, and every conflicted copy where the standard's checkout is a partial clone, stay a person's to merge, so `pin_restore` neither drops a project's executable bit nor fetches to prove a copy; with tests pinning a delete/modify conflict and a side whose pin has no row for the copy (#547) Fix round 1 for PR #586, from R586's review at 5248e70. F1, should-fix: the mode. A side was proved unedited by its bytes alone, so a copy whose executable bit the project changed on one side was taken whole as `--ours`: the other side's mode was dropped, and the `why` said neither side held an edit of the project. `pin_restore` now keeps each stage's mode from the `ls-files -u -z` listing it already reads (`{path: {stage: mode}}`), and `taken_with_the_pin` proves a copy only where `one_regular_mode` holds: the stages the two sides hold agree on ONE regular-file mode, `100644` or `100755`. Where they agree, the restore keeps the mode both hold. A side with no stage is left to the blob read, which finds nothing to read and proves nothing, so each reason a copy stays a person's has its own check and its own test. F5, the coordinator's decision on R586's O1: no fetch from the new proof path. In a `--filter` clone of the standard a `git show` of a blob the clone left out fetches it from the promisor remote, and Brett Heap's ruling is "never fetch, clone or touch the network". `partial_clone` reads the checkout's config (`extensions.partialclone`, `remote.*.promisor`), which fetches and writes nothing; where it names one, `pin_restore` proves no copy, every copy stays the hand merge, and the `why` says the checkout is a partial clone, so nothing was read from it. `update-shape.py`'s shared `Upstream.blob` is untouched: the `shape currency` row's older reach on a clean root goes on #460's checklist. N1: `taken_with_the_pin` returns at once with no copy to prove, before it builds a reader and reads both pins; `pin_restore` runs twice a run. The docstrings' lists of what stays a hand merge gain the mode the two sides disagree on and the partial clone. Tests, in tests/test_doctor_pin_restore_merges.py: - the Makefile made executable in the index on one side, either side: left to a person, bootstrap.py still taken. Set with `update-index --chmod=+x`, which is the same state on every system, where clearing bootstrap.py's bit is not: Windows commits it `100644`; - a delete/modify conflict (F2): the Makefile, at stages 1 and 2, left to a person and still unmerged after the NEXT; - the other side's pin restaged without the Makefile's `files:` row (F3), through `hash-object -w --stdin` and `update-index -z --index-info`, bytes on stdin: the Makefile left, bootstrap.py still taken; - a `--filter=blob:none` clone of the standard (F5): every copy left, the `why`'s sentence, and C2's two blobs still missing afterwards by `rev-list --objects --missing=print`, which never fetches. F4: the three composite asserts SonarCloud reported (S9073) are split. Mutants, each killed: R586's twelve (M1-M5, R1-R5, R2 and R3 by the new tests) and two more, dropping the mode check and dropping the partial-clone check. Lane: openreposhape-4 (openRepoShape-4) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 15, 2026
… merge for ruling 27 A clean merge of main 2bf8fd4 (#555's squash, on 26c1600), with no hand resolution: git auto-merged shape-doctor.py and no path was conflicted. The merge's tree, f9f6e6f, equals the tree `git merge-tree --write-tree 2ca4044 origin/main` prints (T), and it is the tree the targeted set passed on in a scratch merge of the predicted #555 squash before #555 landed: 1106 passed, 4 skipped (three PowerShell tests that need a Windows host and one that needs a case-insensitive disk), over the PR's own file, the doctor, bump-leg, update-shape and hygiene files. Lane: openreposhape-4 (openRepoShape-4) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
brettheap
marked this pull request as ready for review
October 15, 2026 18:07
|
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 5 hours by commenting |
brettheap
pushed a commit
that referenced
this pull request
Oct 15, 2026
…arkers of docs/handbook.html set to the merged README.md's section blob, the only conflict Merges main 70331aa, which holds #597 (Linux-only CI) and lane 4's #586 (shape-doctor.py, #547), so that #588 (#532) lands on a head whose merge base is a main that has touched none of its files since (ruling 27). README.md, shape-doctor.py, update-shape.py and tests/test_family_printed_quoting.py auto-merged; docs/handbook.html is the one conflict. The conflict is seven one-line hunks, each the marker at the top of a section that reads README.md § Starting a project in a new organisation. Main's side carried blob acdf65726ad6433d1d70386eb17f21b015673da0 and #588's side blob 20dfa48fe4008a2ebf77a4cf1aee232714072f27. Neither names the merged README.md's section, which now holds both changes, so all seven are set to 95f06438cf8088e29bba6f56991898f304405f3b: `readme_fingerprint` of that segment, imported from tests/test_repo_hygiene.py and applied to the `readme_segments` cut of the merged README.md. The same call over main's README.md and over #588's reproduces acdf657... and 20dfa48..., so it is the function the page's check reads. Every other line of the page is as git merged it, and the page was written as bytes. Lane: openreposhape-4 (openRepoShape-4) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
brettheap
pushed a commit
that referenced
this pull request
Oct 15, 2026
Main moved while this merge was being made: a61cf47 (#589) at the coordinator's request, then 70331aa (#586, shape-doctor.py only) and 2989b4c (#573: family.py, scaffold-project.py, docs/cli.md's scaffold and family sections, their tests). This merges 2989b4c, the tip at merge time. 10 commits since 2e6c6fa: 8890f57, fb786c1 (#581), 26c1600, 2bf8fd4, 654c476 (#597), 3f768a6, 024ea55, a61cf47 (#589), 70331aa (#586), 2989b4c (#573). One conflict, adopt-project.py, the end of `_entry_findings`' return: HEAD (#520) added `names_remediation` to the remediation list, so a misnamed `adopt_branch:` or `tracking_branch:` prints its remedy; main (#589, #449) added `pin_notes` to the notes, so a pin whose digest `check` could not recompute is said once at the end. Resolved by keeping both, each where its side put it: + names_remediation + tracking_remediation + moved_remediation + field_remediation, pin_notes + notes) The two edits touch different elements of the returned tuple, so neither changes what the other means: #589's `digest_findings, pin_notes = _pin_digest_findings(plan)` and its docstring paragraph auto-merged beside #520's `_branch_name_findings` call and paragraph. docs/cli.md auto-merged (#573 changed the scaffold and family sections, this branch the adopt section); `scripts/render-cli-reference.py --check` passes on the merge. Against the new main, each of this branch's six files (adopt-project.py, docs/cli.md, tests/test_adopt_branch_names.py, tests/test_adopt_plan_yaml_quoting.py, tests/test_adopt_split_branch.py, tests/test_adopt_template_values.py) differs by exactly the +/- lines it did against 2e6c6fa at c598ec3 (adopt-project.py: 399). Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
pushed a commit
that referenced
this pull request
Oct 15, 2026
…n-source-unread Merges origin/main 66267f0 so the PR's CI merge ref and the fix that follows run on current main. The fourteen landings since 2bf8fd4: #597, #578, #593, #589 (#449), #586, #573 (#537), #575 (#539), #566 (#528), #571, #588, #569 (#538), #582 (#523), #616 and #576 (#441, #442). Those that touch this PR's files: - adopt-project.py: #589 (`check` recomputes each pin's digest in the clone `plan` read it from: LOCAL_CLONE_RE, _recorded_clone, _why_not_rechecked, _recomputed_pin_finding, _pin_digest_findings), #582 (what `plan`, `execute` and AGENTS.md say around a run) and #566 (a source's own `single-repository.yaml`). - scaffold-project.py and docs/cli.md: #573, #569 and #576 (the `_declaration` docstring: `--pin-source` verifies the first chain link alone, which this PR's N3 wording already says). - tests/test_adopt_pins.py: #589's thirteen cases. - tests/test_scaffold_leg_path_collisions.py: #573. This commit holds the textual resolution only. One hunk conflicted, the `from shape_materialize import (...)` list at adopt-project.py:261. It is resolved as the union of both sides' changes to the list: main's added `pin_digest_from_source` (#589), and this PR's added `DIGEST_FROM_CLONE`, `DIGEST_FROM_GH`, `pin_source_path` and `refuse_an_unread_pin_source` and its removal of `one_printable_line`, whose last caller this PR deleted and to which main added none (keeping it is pyflakes' "imported but unused"). pyflakes adopt-project.py is clean on the merge. Every other file merged without a marker, and `scripts/render-cli-reference.py --check` is ok. The merge alone does not keep #589 working: this PR's `plan` records a bare `local-clone`, which names no clone for #589's `check` to read, and `check` refuses `local-clone (<path>)` as `plan-pin-malformed`. The next commit reconciles the two. Lane: openreposhape-2 (openRepoShape-2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 16, 2026
brettheap
pushed a commit
that referenced
this pull request
Oct 17, 2026
…d A3 (three SHOULDs, four nits), and notes entries for the seven pull requests landed since bf1f099, current to main 2000488 (#563, #683) Round A4, from lane 2's review (#630 issuecomment-6233033833, READY): - SHOULD 1: the doctor's exit-3 list names "a validator of its own that crashed or could not be run", so the case of one that cannot be given its `PYTHONPATH` (shape-doctor.py's EXIT CODES, #278) is listed too: README.md:1208-1222, its handbook twin (`doctor`) and the notes' docs line. The paragraph re-wraps to one more line: tests/readme-cap.d/683.txt is +2, and its text now says which causes the EXIT CODES block names and that #742 added the partial clone and #701 the naming policy. README.md is 1475 lines, its cap (1422 + 2 + 5 + 12 + 22 + 10 + 2). Both `Keeping a project's shape current` markers move to c728c970: `doctor` text and marker, `current` marker only. - SHOULD 2: #727's entry names the leg description, whose em dash stopped every `execute` against GitHub at the first leg. - SHOULD 3: #749's entry names `source-ambiguous`, for an `org/repo` that is also a directory here. - Nits: the doctor section's three near-duplicate pairs are merged (#636 with #737, #632 with #700 and #705, #586 with #736); #718 has its own bullet; #634's entry names `git_out`'s spelling for every caller and #744's the gate's `--link-source-label` and `--link-remedy`; the header comment says 2026-10-17 at main 2000488. Wave B1, `git log --first-parent bf1f099..2000488`: #706 (#664), #703 (#696), #670 (#646), #682 (#648), #726 (#667), #730 (#666) and #724 (#665), each from its squash commit; #726's and #682's from lane 5's lines (#630 issuecomment-6227129879), #682's with the unmerged `.gitmodules` its last round added, and #724's with lane 5's note that v1.0.0's test-hygiene line on the generator's `.pyc` files closes. The counts (106 pull requests; 116 of 135 milestone issues closed at 11:53Z), "current to main" and the open list (19) are at main 2000488, still placeholders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Lane: openreposhape-4 (openRepoShape-4)
Claim: #547 (comment)
What changed and why
Both lines are #460's, in
shape-doctor.py'spin_restore.L2-8. Since #496 (#485), every copy conflicted beside the shape pin went to a person to merge by hand. That included the copies two
update-shape.py applyruns to different targets wrote, which neither side had edited. A hand merge that kept both sides of a hunk, then--accept-local, pinned a stale line as the project's own edit.taken_with_the_pinreads each side's stage ofcontracts/shape-pin.yamlthroughcheck_pin(pin_at(..., whole=True)), for the commit it names and itsfiles:rows.100644or100755(one_regular_mode, fix round 1).update-shape.py's ownsource_for, so it is the filecheckcompares. It is read bygit showfrom the checkout the doctor runs from.partial_clone, fix round 1). There a read would fetch the blob from the promisor remote.git -C <root> checkout --ours -- <pin> <copies>, so the copy taken matches the pin kept.detail["taken_with_the_pin"]lists the copies taken. Thewhynames them as taken whole, and why, beside what it still gives a person.unreadable_nextis touched too, by four lines. Themanifest kindsrow prints the same NEXT for the same conflicted pin, throughunreadable_next.contracts/that the NEXT now takes whole came out"project"in that row'srestore("git not asked") while its NEXT overwrote the file. That copy is the naming copy, the one a root keeps there, and the issue names it.contracts/shape-pin.yamland a pinned copy both conflicted, the NEXT takes the taken side's copies whole, so pasting it drops a person's--accept-localedit to the copy and the doctor then says COMPLIANT #485 fixed for a copy left to a person."unmerged", as a copy left to a person is, and the row'sdetailcarries the sametaken_with_the_pinas theshape currencyrow's.L2-9. A slip amended into
bump-leg.py's own commit leaves the commit before it holding the leg pin for the OLD leg commit. Thecommittedrestore puts that pin back, and once it is committed the doctor said DRIFTED, with nothing about the closing step.gitlink_left_behindadds to itswhy, where the pin put back names another commit than the root's gitlink for that leg: both commits, and "commit it, then run the bump-leg.py line the pins row names", with which line keeps the move and which undoes it.recorded_gitlink(the index, then HEAD), as thepinsrow reads it.Every addition is in
why, never in a NEXT (#548's rule).Fix round 1 (R586's review at 5248e70), in 2ca4044:
--ours. That dropped the other side's mode, while thewhysaid neither side held an edit.pin_restorenow keeps each stage's mode from thels-files -u -zlisting it already reads.taken_with_the_pinproves a copy only where the stages the two sides hold agree on one regular-file mode.pin_restoreproves nothing, every copy stays a person's, and thewhysays the checkout is a partial clone, so nothing was read from it.extensions.partialcloneorremote.*.promisor.update-shape.py's sharedUpstream.blobis untouched. Theshape currencyrow's older reach on a clean root goes on Tracking: shape-doctor.py, reporting a repository's compliance #460's checklist.taken_with_the_pinreturns at once when there is no copy to prove.Brett's ruling
"Prove and take" (Brett Heap, 2026-10-14T23:54:30Z), on #547 L2-8:
whynames the copies taken and the copies left. The NEXT stays ONE command.Tests
New
tests/test_doctor_pin_restore_merges.py, 16 tests. Every state is real git: the standard moved on by real commits, the project re-pinned by the realapply, a real merge, and the root under a directory whose name holds a blank and an apostrophe. Every NEXT is run as the reader's shell reads it.project.yamlis merged and the merge committed;whynames both;pinsrow's keep-the-gitlink line end COMPLIANT. In the control, the slip is a commit of its own, and nothing is added;sh -c(WINDOWS_SKIP);unmergedin themanifest kindsrow'srestore, and listed intaken_with_the_pinby both rows;bootstrap.pystill taken.update-index --chmod=+x), which is the same state on every system.bootstrap.py's bit would not be: Windows commits it100644.files:row (plumbing, bytes on stdin): the Makefile left, andbootstrap.pystill taken;--filter=blob:noneclone of the standard: every copy left, thewhy's sentence, and C2's two blobs still missing afterwards.rev-list --objects --missing=printchecks that, and it never fetches.Targeted set, Linux, run with test identities and the frvenv on PATH, over 2ca4044's bytes (sha256 of every file checked against the head's blobs):
test_shape_doctor.py,test_doctor_next_is_a_command.py,test_doctor_unfinished_merge.py,test_bump_leg.py,test_doctor_gitlink_repairs.pyandtest_repo_hygiene.py.-rs):test_shape_doctor.py:9227: "the PowerShell line is printed, and powershell.exe exists, only on a Windows host";test_bump_leg.py:693: "needs a disk that ignores case (macOS, Windows)".files:orshape:header with a trailing comment is rewritten and keeps it,--branchis judged the same from any directory, andapply's messages say what is true (#437, #431, #535) #558, bootstrap.py: a leg detached off the pin is left where it is and said, so a commit made there is no longer stranded when its branch is already at the pin, thenot moving an existing branchline names where the checkout is, and bump-leg.py and AGENTS-shape.md say "or says why not" (#533) #556 and openRepoShape --doctor says it writes nothing into the repository but a --placement-plan file you name, keeps its clone for the NEXT lines that name it, shows its synopsis description again, and refuses a second --placement-plan or a second path (#546) #580 in it), the new file: 16 passed.Mutants, run against the new file at 2ca4044's bytes (R586's runner, copied):
unreadable_nextchangefiles:row requirementNo existing assertion changed outside the new file.
What stays a hand merge
Exactly what did before, for any copy not proved on BOTH sides:
files:row for the copy;And every conflicted copy where the standard's checkout is a partial clone. There, a read can fetch, so nothing is read, and the
whysays so.None of these proves that the copy holds no edit of the project. Taking such a copy whole is the loss #485 fixed: a copy kept by
--accept-localon one side, dropped with the hunks git merged cleanly beside it. The manifest and README.md stay a person's, as before (#267).Shared files
What this changes in
shape-doctor.py:pin_restore(itsls-files -ulisting now keeps each stage's mode);pin_at, which gains awholeread used only bypin_restore's new helper;taken_with_the_pin,as_the_standard_wrote_it,one_regular_mode,partial_cloneandgitlink_left_behind, and the constantsREGULAR_FILE_MODESandPARTIAL_CLONE_WHY. Onlypin_restoreuses them;unreadable_next(above).git merge-tree --write-treeof 2ca4044 against each head, every head re-read bygit ls-remoteat 12:41Z and again before the push:origin/main(#580 landed as dd3f23a)origin/fix/doctor-validator-verdicts(#557)origin/fix/doctor-next-detached-commits(#559)origin/l3-548-manifest-kinds(#555)l3-546-doctor-writes-wording(#580)fix/posix-paste-lines(P9)source_for,check_pin,root_kindandUpstreamare byte-identical inupdate-shape.pybetween b4c1f50 and dd3f23a. The proof reads the standard through them, so main'supdate-shape.pychanges do not move it.Out of scope
docs/release-notes/v1.0.0.md:512-513) list L2-8 and L2-9 as known limits. This PR lifts both, so the v1.1.0 notes should drop them. This PR does not edit the v1.0.0 notes.why, as on main.--literal-pathspecs; today's copy names hold no glob characters.shape currencyrow's lazy fetch from a partial-clone standard on a clean root is older than this PR. It goes on Tracking: shape-doctor.py, reporting a repository's compliance #460's checklist.Closes #547
🤖 Generated with Claude Code
Summary by Sourcery
Safely resolve provably tool-generated shape-copy conflicts and provide complete recovery guidance for restored leg pins.
New Features:
Bug Fixes:
Enhancements:
Tests: