Repository navigation
adopt-project.py: each clone execute makes names its remote origin, whatever clone.defaultRemoteName says, so execute no longer ends in REFUSED mounting the legs ("No such remote 'origin'") after both legs are pushed (#1261) - #1268
brettheap wants to merge 1 commit into
Conversation
…`, whatever `clone.defaultRemoteName` says, so `execute` no longer ends in `REFUSED mounting the legs` ("No such remote 'origin'") after both legs are pushed (#1261)
`git clone` names its remote after `clone.defaultRemoteName`, and
`execute` addressed its clones as `origin`: with `upstream` in the global
config, `_mount_the_legs`' `git remote set-url origin` exited 2 in the
clone `git submodule add` made, after both legs were pushed.
`REMOTE_NAMED_ORIGIN`, `-c clone.defaultRemoteName=origin`, now goes on
`_extract_leg`'s clone, the assembly's clone, `git submodule add` (a `-c`
reaches the clone it makes) and `check`'s rehearsal of `_extract_leg`'s
clone; `gh repo clone` is handed `--origin origin` after its `--`.
tests/test_adopt_clone_default_remote_name.py holds the rows, and
tests/test_adopt_source_clone_record.py's pin of the `gh repo clone` argv
names the new flag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideImplementationForce every Git clone used by
Pass
TestsAdd regression coverage for adoption under custom and invalid default remote names, compare resulting legs and remotes against the control run, and pin the GitHub CLI clone arguments.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
|
(lane openRepoShape-3, 2026-11-08T19:27:08Z) Lane 3's independent review of #1268 (for #1261), by RV1268 (opus), which wrote none of it, at I'm RV1268, the independent reviewer for PR #1268 (issue #1261), head Verdict: READYThere is no MUST finding. The fix works, every "Done when" item is pinned, and every gate I ran passes. One SHOULD is for the refresh after #1251 lands: it is about #1251's text, which is not on main yet, so it cannot be done on this head. Everything else is a NIT. All probes and pytest runs used uid 1000, 1. Before and after (
|
| global config | main be21751c3 |
head faa29987a |
|---|---|---|
defaultRemoteName = upstream |
plan 0, check 0, execute 2 REFUSED mounting the legs / error: No such remote 'origin' |
plan 0, check 0, execute 0, adoption verified: every source path is in exactly one place |
| empty (control) | 0 / 0 / 0, verified | 0 / 0 / 0, verified |
a..b |
plan 0, check 1 FINDING adopt-git-unasked (exited 128 there: fatal: 'a..b' ...), execute 2 REFUSED adopt-git-unasked |
0 / 0 / 0, verified |
- The legs. For each run I dumped
symbolic-ref HEAD,for-each-refand the sortedcat-file --batch-all-objects --batch-check: 52 lines each. These five arecmp-identical to main's control: main-upstream, head-empty, head-upstream, head-aab. I also hashed every object's full bytes (cat-file --batch-all-objects --batch | md5sum): specc6a4782e...and code3f12d592...in all five. - The clones' remotes. On main under
upstream, the assembly, the spec mount and both work clones holdremote.upstream.*, and the code mount is(absent). On the head underupstreamand undera..b, the remotes dump iscmp-equal to main's control. - The split commit. The trees differ only in
.gitmodulesandshape/README.md, and both are equal once each run's own path is taken out.
2. Does the -c reach the clone git submodule add makes?
Yes. RV1268-scratch/sm.sh under a global upstream:
FILE_PROTOCOL only add rc=0 remotes=[upstream ] set-url origin: error: No such remote 'origin' rc=2
FILE_PROTOCOL + REMOTE_NAMED_ORIGIN (before verb) add rc=0 remotes=[origin ] set-url origin: rc=0
GIT_CONFIG_PARAMETERS=fromparams, + -c remotes=[origin ]
GIT_CONFIG_COUNT=fromcount, + -c remotes=[origin ]
PARAMETERS + COUNT, + -c remotes=[origin ]
- With a global
a..b, the plainsubmodule addexits 128 ('a..b' is not a valid remote name), and with the-cit names the remoteorigin. - Nothing after the mount names
origin.grepof the head'sadopt-project.pyfinds oneoriginafter the mount:set-urlat :14976. Every push, fetch and ls-remote goes to an explicit url (:5029, :14118, :14735, :16076). - The head-upstream run went on through
split aa4da57ba8fe on adopt/three-repo-shape, the verification, andadoption verified.
3. The behaviour change beyond the issue
Passing under a..b is right. check's rehearsal exists to predict execute's clone, and that clone no longer reads the setting. execute under a..b really does succeed: I measured it, and the legs match the control. The person's own later clone (the NEXT line) still fails under a..b, as every clone of theirs does.
Interactions I measured:
GIT_CONFIG_PARAMETERS, with an empty global config:clone.defaultRemoteName=upstream: mainexecute exit=2 REFUSED mounting the legs; headexecute exit=0, legs and remotes equal to the control.a..b: maincheck exit=1(adopt-git-unasked); head 0 / 0 / 0.
- A global
remote.origin.fetch(+refs/pull/*/head:refs/remotes/origin/pr/*), plusupstream:- main execute 2; head execute 0.
- Head's remotes dump is identical to main's under that line alone (
head upstream+originfetch remotes == base originfetch-only remotes). The setting becomes a no-op, and the globalremote.origin.*does what it does without it.
- A global
remote.origin.url = /nonexistent/x.git, plusupstream. This is the one real change.- A plain
git -c clone.defaultRemoteName=origin clonefetches from the global url and exits 128. - main: check 0, then execute 2 at the mount, with both legs pushed (legs.dump 52 lines).
- head:
check exit=1 FINDING adopt-git-unasked, and execute refusesadopt-git-unaskedwithRemediation: no leg repository was created and nothing was pushed(legs(absent)). - That is an earlier refusal that names its cause, and it is exactly what that person gets without the setting. It is not a regression.
- A plain
4. The gh repo clone argv
- gh's manual gives
gh repo clone <repository> [<directory>] [-- <gitflags>...]: "Pass additionalgit cloneflags by listing them after--." - gh's source does the same.
clone.gosetsopts.GitArgs = args[1:](pflag drops the--).git/client.go'sparseCloneArgstakes the first argument that does not start with-as the target.Clonerunsgit clone <flags> <url> <target>. Nothing in gh readsclone.defaultRemoteName. - So
-- --quiet --origin originbecomesgit clone --quiet --origin origin <url> <dir>, which is correct. - It also keeps gh's fork step working under the setting: gh adds the fork's parent as a remote named
upstream. Without--origin, the clone's own remote would already beupstream. This part is read, not measured. - The pinned argv row is a real regression pin. D5 kills it, and the record pin fails 12. But it proves only our argv. See N4 for the behaviour it leaves untested.
5. The rows
- New module on the head:
6 passed in 9.17s. - With main's
adopt-project.pyswapped in:4 failed, 2 passed. The failures are the execute, remotes, check and gh rows, and the output showsREFUSED mounting the legs/error: No such remote 'origin'. The file was restored, checked withcmpagainst the head's, andgit diff --quiet HEADwas clean. - The setting reaches only each row's own child. I ran a probe module after the new one in the same pytest (
RV1268-scratch/test_zz_rv1268_leak.py; I put it in the mutant tree and moved it toquarantine/afterwards):8 passed. It checks that the session's global file holds nodefaultRemoteName, thatgit config --get clone.defaultRemoteNameexits 1, and that a plain clone after the rows namesorigin. - Done when:
- Item 1 is pinned by the execute row.
- Item 2 is pinned by the legs row, which passes on main too, by design.
- Item 3 is covered by the leak probe and the gates.
Mutants (RV1268-scratch/mutants.log). Each was restored with cmp and diff --quiet, and each restore was clean.
| mutant | result | killed by |
|---|---|---|
D1 drop _extract_leg's -c |
1 failed | remotes row |
D2 drop the mount's -c |
2 failed | execute and remotes rows |
D3 drop the assembly's -c |
1 failed | remotes row |
D4 drop the rehearsal's -c |
1 failed | check row |
D5 drop gh's --origin origin |
1 failed; record -k each_spelling_of_a_name: 12 failed |
gh row |
V1 value =orign |
2 failed | execute and remotes rows |
V2 key defaultRemoteNam |
3 failed | |
V3 constant [] |
3 failed | |
A2 -c after submodule add |
2 failed | |
G1 --origin origin before gh's -- |
1 failed; record: 12 failed | |
A1, A3, A4 -c after the clone verb |
6 passed | equivalent |
A1, A3 and A4 are equivalent mutants. git clone -c re-reads its config after writing it, and I measured that it names the remote origin, but it leaves clone.defaultRemoteName=origin in the clone's own .git/config. That is not a gap in the rows.
6. Gates
The gates ran one pytest at a time, with -rfs, GIT_CONFIG_GLOBAL=/dev/null, and basetemps /tmp/claude-1000/l3bt/RV1268-<group>:
- g1, the new module plus
test_adopt_source_clone_record.pyand the two modules it imports from (test_adopt_temp_work_roots.py,test_adopt_plan_leg_path_help.py), plustest_adopt_e2e.py:187 passed in 75.45s, 0 skipped. - g2,
test_adopt_split_branch.py,test_adopt_submodules.pyandtest_scaffold_leg_path_collisions.py:318 passed in 275.18s. Its import fromtest_adopt_pinsisasked_what, a plain function, not a fixture. - g3, the hygiene guards plus
test_cli_reference.py,test_no_auto_maintenance.pyandtest_clone_just_pushed.py:559 passed, 3 skipped in 84.57s. The skips are a Windows-only test and 2 for GIT_CONFIG_GLOBAL being set at session start. - Also, not run by me:
- CI on
pull/1268/mergee56915cf:20586 passed, 404 skipped, with filter-repo 2.47.0 installed. All four checks pass. - The SonarCloud gate is OK, with 0 open issues.
- The writer's chain log matches the body run for run, through
CHAIN-DONE. I read it and did not re-run it.
- CI on
7. Merges
| merge | result |
|---|---|
head x main 81eaf757c |
clean, tree 08fe007f977a; new rows on it: 6 passed |
head x main 9252ef208 (newest; it touches only family.py, README, the handbook and tests) |
clean, tree 41bb694bbb60; the PR's files and conftest are byte-equal to the 08fe007f tree |
head x #1251 abeac66d |
clean, tree 4474c9f5c0dd |
head x (main + predicted #1251 squash 64b5b255) |
clean, tree c6f9bc13cff4; new rows 6 passed; probe under upstream: execute 0, legs equal to main's control, remotes equal to the merge's control |
the same on 9252ef208 |
tree d8cc6004178f |
#1251 alone under upstream |
execute exit=2 REFUSED mounting the legs |
#1154 8a7828332 |
clean, tree 118ca7046350, as the body says |
What the refresh must keep: *REMOTE_NAMED_ORIGIN on _extract_leg's clone, ahead of #1251's git config --file <work>/.git/config --unset remote.origin.url. merge-tree keeps it with no conflict.
8. The body's claims
- Every number I re-measured matches:
4 failed, 2 passedand6 passed, the three-row table, the 52-line dumps, M1 to M5 (my D1 to D5), and the "which spelling reaches which clone" table. That last one I re-measured all except the template config with--origin origin. - There is one closing keyword (
Closes #1261), andclosingIssuesReferencesnames only adopt-project.py: withclone.defaultRemoteNamein the global git config,executeendsREFUSED mounting the legs("No such remote 'origin'") after both legs are pushed, as it names its clones' remoteorigin(RV1251's NIT-1 on #1251; follows #1247) #1261. The body is ASCII except the robot line. - Every line the "Out of scope" list cites was checked: each points at the code named and sits in the function the body names.
scaffold-project.py:2638-2644really has the same failure. I measured it (head,--local-remote-dir): empty configexit=0;upstreamexit=2,REFUSED a git or gh command failed ... git remote set-url origin <D>/remotes/Northwind-spec.git (in <D>/work/Northwind/spec) exit 2 ... error: No such remote 'origin'.
Findings
SHOULD
- S1, for the refresh after adopt-project.py:
executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251. The merged_extract_leg(treec6f9bc13, :14741-14753) carries adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251's comment: "A CLONE WITH NOoriginURL IS NOT A FAILURE (git exits 5): a globalclone.defaultRemoteNamegives the clone another remote, andexecutethen fails where main fails, atmounting the legs... That setting is its own defect."- With adopt-project.py: each clone
executemakes names its remoteorigin, whateverclone.defaultRemoteNamesays, soexecuteno longer ends inREFUSED mounting the legs("No such remote 'origin'") after both legs are pushed (#1261) #1268 in, that is false. The merged tree underupstreamexecutes toadoption verified. - The refresh should rewrite that comment, and say whether the exit-5 tolerance still has a cause.
- With adopt-project.py: each clone
NIT
- N1. The body's merge section is stale. It names main
be21751c3and adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251825923c76(tree9d358bd59ae4). Main is now9252ef208and adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251 is atabeac66d. Both merges are clean (trees in section 7). - N2. The scaffold failure is now measured, not "likely". No issue exists for it:
gh issue list --search defaultRemoteNamereturns only adopt-project.py: withclone.defaultRemoteNamein the global git config,executeendsREFUSED mounting the legs("No such remote 'origin'") after both legs are pushed, as it names its clones' remoteorigin(RV1251's NIT-1 on #1251; follows #1247) #1261. Lane 3 may want to file one. - N3. The premise row fails for a developer whose own global config holds the setting. Under GIT_CONFIG_GLOBAL holding
upstream:1 failed, 5 passed,assert ['upstream'] == ['origin'], intest_the_premise_a_plain_clone_under_the_setting_names_upstream. In that case the "without" run is no control either. CI is unaffected. - N4. The gh row pins the argv, not the behaviour. I emulated gh's forwarding (
RV1268-scratch/ghemu/gh) on acloned: truesource with--tracking-branch develop, wheredevelopexists only on the remote.- head under
upstream: plan 0, check 0, remoteorigin. - D5 under
upstream:check exit=1 FINDING plan-tracking-branch-missing: ... which is no branch of the source (its branches: main ...). - The rows do not see that.
gh_clonesintest_adopt_temp_work_roots.pycould forward the flags after--to make the row test the behaviour.
- head under
- N5. "Out of scope" leaves out
adopt-project.py's own reads of the person's sourceorigin. These are_origin_url:2941,ORIGIN_HEAD:2948,_branches_of:4906, :10090 and :17724.- I measured it: a source the person cloned under
upstream, whose url is set tohttps://github.com/testorg/Thing.git, gets fromplanwith no--org:REFUSED adopt-no-org: the source's origin names no organisation ... it has none. - The same source with its remote named
originreads the org.
- I measured it: a source the person cloned under
- N6. The first line under "What changed" reads "follow-up from lane 4's review of adopt-project.py:
executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251" rather than the lane template's "lane 3's independent reviews". It is accurate; whether to keep it is lane 3's call.
Not covered
- A real gh (stub and emulator only), the GitHub path of
execute, Windows, another git version, and setting values other thanupstream,a..b,fromparamsandfromcount. setup-project.py,family.pyandbump-leg.pyunder the setting.- The writer's 61-run chain (read, not re-run).
- Merges with the other 25 open PRs.
Housekeeping: while comparing the split trees, one command wrote a stray file by mistake, /tmp/claude-1000/rv1268-a.txt (2285 bytes of ls-tree output). It was not deleted, under the no-rm rule. Nothing was posted, pushed or committed. The only objects I made are prediction objects inside my own clone: commit-trees 64b5b255, 9773a634, b6699c88 and 4eb1ee16, with no refs.
Paths:
- Clone:
/workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV1268, atfaa29987a, clean. - Scratch:
/workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV1268-scratch/. It holdsmut/(mutant worktree, at the head, clean),base/(mainbe21751c3),probes/,gates.log,gate-g1.logtogate-g3.logandmutants.log. - Basetemps:
/tmp/claude-1000/l3bt/RV1268-{new,mut,g1,g2,g3}.
Lane: openreposhape-3 (openRepoShape-3)



What changed
A v1.2.1 follow-up from lane 4's review of #1251 (#1261). It lands under Brett Heap's v1.2.1 merge word (2026-10-23T13:10:26Z) once reviewed and green.
git clonenames the remote it makes afterclone.defaultRemoteName, andexecuteaddressed its clones asorigin. Withupstreamin the person's global git config,execute --local-remote-dirended inREFUSED mounting the legs, exit 2, after both legs were made and pushed. Each cloneexecutemakes now names its remoteorigin, whatever the person's config holds. No flag or command is added.adopt-project.pygainsREMOTE_NAMED_ORIGIN = ["-c", "clone.defaultRemoteName=origin"]besideFILE_PROTOCOL, and four git calls carry it:_extract_leg'sgit cloneof the source.git filter-repoaddresses that clone'soriginby name: it removesoriginand makes eachorigin/*a branch. Underupstreamit did neither (measured: both work clones keptremote.upstream.*). adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251'sgit config --unset remote.origin.urladdresses it too._mount_the_legs'git submodule add. A-con it reaches the clone it makes (measured below), whichgit remote set-url origin <leg url>andgit submodule syncthen address. This is the command that failed.git clone --template=in_commit_the_split. Nothing later in the run addresses this clone's remote by name: mutant M3 below still endsadoption verified. It is covered so that every cloneexecutemakes names its remote as it does without the setting. The row that compares each clone's remotes with a run without the setting kills M3.check's rehearsal of_extract_leg's clone (_split_clone_asked). Its docstring says it is asked "withFILE_PROTOCOL, asexecutegives each of its clones". Without the same-c, aclone.defaultRemoteNamegit refuses (a..b) would fail the rehearsal, andcheck, whereexecute's clones no longer read the setting.Source.clone, thecloned: truepath, runsgh repo clone <org/repo> <dir> -- --quiet --origin origin. gh runs git itself, so no-cof ours reaches its clone.--originis agit cloneflag, which gh passes on after its--as it passes--quiet. With it, the clone that_default_branch(refs/remotes/origin/HEAD) and_branches_of(refs/remotes/origin/) read names its remoteorigin. This was not measured against a real gh: the argv is pinned with a stub gh that logs and refuses.-con the git calls and not--origin:git submodule addtakes no--origin, so the mount needs the-cin any case. The-cthen gives the three git calls one spelling. On git 2.43.0, under a globalupstream, it outranks every other scope measured (below).Measured:
plan,check,execute --local-remote-dirThe standard source is
tests/conftest.py'smake_source_repo(directoryThing, projectNorthwind), withtest_adopt_e2e.py's three answers. It was made once, and each run adopts a copy of it. git 2.43.0, Python 3.12.3, git-filter-repo 2.47.0 (CI's pin, in a venv), with a stubgh(exit 97) first on PATH.GIT_CONFIG_GLOBALnames a scratch file holding the setting, or an empty file for the control.be21751c3faa29987adefaultRemoteName = upstreamplan ok), execute 2:REFUSED mounting the legsadoption verified: every source path is in exactly one placeadoption verified: ...adoption verified: ...defaultRemoteName = a..badopt-git-unasked, execute 2REFUSED adopt-git-unaskedbefore any legadoption verified: ...The end of main's
executeunderupstream(paths shortened):And main's
checkundera..b:FINDING adopt-git-unasked: ... the split's git clone of the source exited 128 there: fatal: 'a..b' is not a valid remote name.git symbolic-ref HEAD,git for-each-refand the sortedgit cat-file --batch-all-objects --batch-check(52 lines). The dumps arecmp-identical across main's control, main underupstream(pushed before the refusal), and this PR underupstream, the control anda..b.git config --get-regexp '^(remote|branch)\.'for each repository in--work-dir). On main underupstream, the assembly, the spec mount and both work clones heldremote.upstream.*andbranch.*.remote upstream. With this PR they match the control byte for byte once each run's base path is taken out: the assembly and both mountsorigin, and the work clones none, since filter-repo removesorigin.origin. The onlyoriginthe post-mount code names is_mount_the_legs'set-url.git submodule syncreads each mount's remote from its branch._push_the_legand the split's push go to explicit urls, andgh pr createandgh repo editname their repository. The run with this PR went through the split's commit, its push and the verification underupstream, toadoption verified.Measured: which spelling reaches which clone (git 2.43.0, global
upstream)git cloneupstreamgit clone --origin originorigingit -c clone.defaultRemoteName=origin cloneorigingit submodule add --force -q <repo> <path>(withFILE_PROTOCOLonly)upstream; thengit remote set-url originexits 2git -c clone.defaultRemoteName=origin submodule add ...origin; thenset-url originexits 0configholdingdefaultRemoteName = fromtemplatefromtemplate;originwith the-c, and with--origin originGIT_CONFIG_COUNTnamingfromcount, plus the-coriginGIT_CONFIG_PARAMETERSnamingfromparams, plus the-corigina..b: plain, with the-c, with--origin originfatal: 'a..b' is not a valid remote name;origin;originRows
tests/test_adopt_clone_default_remote_name.pyis new.test_adopt_e2e.py's module adoption makes a source of its own, and a source made twice is two histories, so the byte comparison needs both runs on copies of one source. Each row gives the setting to its own child only, in aGIT_CONFIG_GLOBALof its own: the session's file, then the setting.test_the_premise_a_plain_clone_under_the_setting_names_upstreamtest_execute_under_the_setting_exits_0_and_says_adoption_verified: fails on main withREFUSED mounting the legs.test_the_legs_are_the_bytes_a_run_without_the_setting_pushes: passes on main as well, since both legs were pushed before the mount refused.test_each_clone_execute_makes_has_the_remotes_it_has_without_ittest_check_passes_under_a_default_remote_name_git_refusestest_gh_repo_clone_is_handed_origin_for_the_remotes_name: a stub gh, first on PATH, logs one argument per line and exits 97.On main (adopt-project.py at main's bytes):
4 failed, 2 passed(the premise and the legs rows pass). With this PR:6 passed.tests/test_adopt_source_clone_record.py: its exact pin of thegh repo cloneargv gains"--origin", "origin".Mutants
Each part was dropped in turn from this PR's
adopt-project.py, the new module was run, and the file was restored, each restore checked withcmpandgit diff --quiet HEAD._extract_leg's clonetest_each_clone_execute_makes_has_the_remotes_it_has_without_itgit submodule addtest_execute_under_the_setting_exits_0_and_says_adoption_verified(error: No such remote 'origin'), and the remotes rowcheck's rehearsaltest_check_passes_under_a_default_remote_name_git_refusesgh repo clone's--origin origintest_adopt_source_clone_record.py -k each_spelling_of_a_name: 12 failedtest_gh_repo_clone_is_handed_origin_for_the_remotes_nameTests run
Each pytest was run one at a time as
/usr/bin/python3 -m pytest -q -p no:cacheprovider -rs(-rfsfor the chain), with a stubgh(exit 97) first on PATH, then a folder holding only a link to the venv'sgit-filter-repo2.47.0, and withGH_TOKEN=bogus, an emptyGH_CONFIG_DIR,GIT_SSH_COMMAND=false,GIT_CONFIG_GLOBALan empty scratch file andEMAIL=tests@openreposhape.invalid. Headfaa29987a. The new rows and the mutants first ran at391886b01, whoseadopt-project.pydiffers from this head's in comments only, and the new rows ran again atf741b30f8, which has this head's tree.tests/test_adopt_clone_default_remote_name.py:6 passed in 14.75s(and4 failed, 2 passedwithadopt-project.pyat main's bytes).tests/test_repo_hygiene.py tests/test_agents_md_codes.py tests/test_git_output_decoding.py tests/test_stdout_encoding.py tests/test_readme_sections.py tests/test_path_guard_hygiene.py, plustests/test_cli_reference.py(no help text moved),tests/test_no_auto_maintenance.py(it scans every test file forGIT_CONFIG_COUNT) andtests/test_clone_just_pushed.py(the one test that already namedclone.defaultRemoteName):559 passed, 3 skipped in 128.74s.execute(git grep -lof"execute",'execute'orEXECUTE, kept where the module also namesADOPToradopt-project: 61 modules),tests/test_shape_doctor.pyandtests/test_scaffold_leg_path_collisions.py. Each was run as one pytest, the modules that exercise the changed calls first: runs 1 to 3 together with every test module the module imports from, and runs 4 on with each it imports a fixture from (the pairing in which a module-scoped fixture can run twice):tests/test_adopt_source_clone_record.pytests/test_adopt_plan_leg_path_help.pytests/test_adopt_temp_work_roots.py:154 passed in 61.75s (0:01:01) EXIT=0tests/test_adopt_check_throwaway_repos.pytests/test_adopt_nested_attributes.pytests/test_adopt_relative_submodule_url.pytests/test_adopt_root_symlinks.py:466 passed, 4 skipped in 838.78s (0:13:58) EXIT=0tests/test_adopt_e2e.py:27 passed in 29.84s EXIT=0tests/test_adopt_clone_template.py:31 passed in 39.94s EXIT=0tests/test_adopt_mount_ignored.py:26 passed in 28.43s EXIT=0tests/test_adopt_clone_claimed.pytests/test_adopt_source_clone_record.pytests/test_adopt_temp_work_roots.py:151 passed in 90.43s (0:01:30) EXIT=0tests/test_adopt_late_failure.py:88 passed in 47.19s EXIT=0tests/test_adopt_history_gitlinks.py:45 passed in 66.50s (0:01:06) EXIT=0tests/test_adopt_verify.py:31 passed in 32.85s EXIT=0tests/test_adopt_split_branch.py:47 passed in 123.27s (0:02:03) EXIT=0tests/test_adopt_partial_clone_source.py:38 passed in 30.68s EXIT=0tests/test_adopt_filter_repo_failure.py:11 passed in 10.13s EXIT=0tests/test_adopt_relative_submodule_url.py:34 passed in 140.84s (0:02:20) EXIT=0tests/test_adopt_execute_refusals.py:181 passed in 279.10s (0:04:39) EXIT=0tests/test_adopt_submodules.py:167 passed in 227.35s (0:03:47) EXIT=0tests/test_scaffold_leg_path_collisions.py:104 passed in 6.32s EXIT=0tests/test_shape_doctor.py:446 passed, 3 skipped in 780.19s (0:13:00) EXIT=0CHAIN-DONEat 18:50Z on 2026-11-08). Each run is one pytest, and every one exits 0; four were not run again because each of their files had already run inside an earlier run:tests/test_adopt_branch_names.py:29 passed in 41.13stests/test_adopt_c_locale_bytes.py:17 passed in 42.81stests/test_adopt_contracts_dir.py:34 passed in 23.07stests/test_adopt_empty_symlinks.py:53 passed in 85.43s (0:01:25)tests/test_adopt_entry_paths.py:79 passed in 74.69s (0:01:14)tests/test_adopt_eol_block_through_links.py:13 passed, 2 skipped in 24.79stests/test_adopt_git_reads.py:37 passed in 46.77stests/test_adopt_git_rm_bytes.py:4 passed in 8.78stests/test_adopt_github_exits.py:23 passed in 56.35stests/test_adopt_gitmodules_values.py:187 passed in 145.84s (0:02:25)tests/test_adopt_ignored_shape_files.py:37 passed in 39.49stests/test_adopt_leg_keys.py:44 passed in 41.24stests/test_adopt_leg_path_collisions.py:95 passed in 61.55s (0:01:01)tests/test_adopt_leg_paths.py:351 passed in 86.79s (0:01:26)tests/test_adopt_manifest_values.py:82 passed in 104.78s (0:01:44)tests/test_adopt_nested_attributes.py:75 passed in 84.13s (0:01:24)tests/test_adopt_next_make_reads_first.py:40 passed in 42.07stests/test_adopt_pins.py:152 passed in 179.49s (0:02:59)tests/test_adopt_plan_value_order.py:20 passed in 22.91stests/test_adopt_plan_yaml_quoting.py:540 passed in 194.48s (0:03:14)tests/test_adopt_printed_sentences.py:54 passed in 38.78stests/test_adopt_root_manifest.py:27 passed in 15.86stests/test_adopt_root_shape_paths.py:121 passed in 87.24s (0:01:27)tests/test_adopt_root_symlinks.py: not run again (every file already ran in an earlier run)tests/test_adopt_shape_pin_and_work_dir.py(with 1 module it imports):226 passed, 3 skipped in 344.55s (0:05:44)tests/test_adopt_single_repository_record.py:39 passed in 19.17stests/test_adopt_spec_only.py:14 passed in 17.11stests/test_adopt_spelled_names.py:27 passed in 8.25stests/test_adopt_temp_work_roots.py: not run again (every file already ran in an earlier run)tests/test_adopt_template_values.py:78 passed in 64.28s (0:01:04)tests/test_adopt_tracking_branch.py:17 passed in 19.74stests/test_adopt_unenterable_source_and_locale.py(with 1 module it imports):40 passed in 16.90stests/test_adopt_unsearchable_source.py: not run again (every file already ran in an earlier run)tests/test_adopt_values_as_typed.py:40 passed in 30.52stests/test_adopt_work_dir_refusal.py(with 1 module it imports):259 passed, 3 skipped in 347.04s (0:05:47)tests/test_answered_paths_per_leg.py(with 1 module it imports):465 passed, 3 skipped in 720.53s (0:12:00)tests/test_doctor_recorded_answers.py(with 1 module it imports):475 passed, 3 skipped in 752.61s (0:12:32)tests/test_github_limits_init_check_org.py(with 2 modules it imports):264 passed in 65.52s (0:01:05)tests/test_github_name_limits.py: not run again (every file already ran in an earlier run)tests/test_leg_path_yaml_scalars.py:199 passed, 8 skipped in 30.66stests/test_ruleset_hint_tracking_branch.py:23 passed in 34.77stests/test_template_text_placeholders.py:142 passed in 71.49s (0:01:11)tests/test_template_values_single_pass.py:192 passed in 14.34stests/test_update_shape_merged_away.py(with 2 modules it imports):494 passed, 3 skipped in 706.68s (0:11:46)Merges
git merge-tree --write-tree(git 2.43.0) of this PR's headfaa29987awith main, and with each of the 27 open PRs that touch any of its files. That set came from onegh pr list --state open --limit 200 --json number,headRefOid,filescall, which listed 50 open PRs, and each PR touchesadopt-project.py.be21751c3: clean. This PR is one commit on it, tree470fe25d3fe8.executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251825923c76(lane 4's draft for adopt-project.py: under a one-byte locale such as Latin-1,executestops extracting the spec leg of a source whose path holds U+00E9, becausegit filter-repoprints the clone's origin url as U+FFFD to a stdout that cannot hold it #1247, in a fix round): clean, tree9d358bd59ae4, and no conflicted path. In the merged tree,_extract_legruns this PR's clone withREMOTE_NAMED_ORIGINand then adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251'sgit config --unset remote.origin.url, so under the setting that unset meets anorigintoo. Lane 3's queue lands adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251 first, and this PR takes the refresh: it is brought up to main after adopt-project.py:executeunsets the leg clone'sremote.origin.urlbeforegit filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) #1251 lands, and its rows run again there.plan written toandcloning <repository> (read only) intoname the caller's--outand--work-dirwith_shown, as the other lines of the report name a path, so a bidi control, a line feed or a tab in either no longer reaches the terminal as it was typed (#1115) #11548a7828332: clean, tree118ca7046350. An earlier head of this branch had a comment beside theprintline that adopt-project.py:plan written toandcloning <repository> (read only) intoname the caller's--outand--work-dirwith_shown, as the other lines of the report name a path, so a bidi control, a line feed or a tab in either no longer reaches the terminal as it was typed (#1115) #1154 rewrites inSource.clone, and conflicted there. That comment moved intoREMOTE_NAMED_ORIGIN's.git rm -fand writes the twins the root keeps back from the index, so on a disk that ignores caseexecutekeeps a set the plan splits across repositories or drops (#1183) #1237b557859fd: conflicts intests/test_adopt_check_throwaway_repos.py, which this PR does not touch.git merge-tree origin/mainwith adopt-project.py: the mount removes a path a case twin is at or under withgit rm -fand writes the twins the root keeps back from the index, so on a disk that ignores caseexecutekeeps a set the plan splits across repositories or drops (#1183) #1237 conflicts on the same path, so the conflict is between adopt-project.py: the mount removes a path a case twin is at or under withgit rm -fand writes the twins the root keeps back from the index, so on a disk that ignores caseexecutekeeps a set the plan splits across repositories or drops (#1183) #1237 and main.ad70474d2f501e19c0fb0, 125240b030cbfcc3440e34c57, 12493146c3ca5f2b8a69add6b, 122573c9f57e81bc2db9b1756, 1210791106c2be921a684eac1, 12076fa1edd56225062290ee7, 1198d38e4e36d4e504b380946, 1194900f77af9f2ad66f823f4, 11897d2f651e74f07177d74f7, 118607486a4985538a35fbb33, 1178c4beba1930cda14cffc49, 11775208e874e9ccb989ef0ef, 11718162b874ead8cb54ab27a, 117024ee133aaf6b8cf6b3969, 1153ff33ba12a9c689b3aa45e, 11437af5fabc318fdb587c528, 11410b8fb3205b7cab1fbcbd0, 11259549006fe8dfc89c1c82a, 11235c3908f8dc7ed59e06065, 1122c01c4d73da691d81bef4c, 1120c55e55e330a37f6f00895, 11182307036ab689cbddc0d5f, 1106bd97901ff70599644591b, 1105b28f40de0df254512c3fa.Out of scope
Read, not probed: these are clones other tools make and then address as
origin. Each is a possible follow-up, and none is changed here.scaffold-project.py:2638-2644(_build_assembly_root) runsgit -c protocol.file.allow=always submodule add --force -q <work clone> <path>, thengit remote set-url origin <url>inassembly/<path>. This is the shape of the failing mount here, soscaffold-project.py(andsetup-project.py/setup.sh, which drive it) can likely meet the same refusal.setup-project.py:3345-3350(clone_and_bootstrap) runsgit clone -q [--no-local] --recurse-submodules <assembly url> <clone>.origin_recorded_in(setup-project.py:2417, used at :2491) then readsremote.origin.urlfrom<clone>/.git/config, and reads none under the setting.bootstrap.pythen runs in that clone; its own reads were not surveyed.scripts/family.py:7288mounts a member withgit submodule add -q --force -- <url> <path>. The member'soriginis then addressed by_has_origin(:8879,git remote get-url origin, whose exit 2 is read as "no origin"),_on_a_remote_branch(:8780,refs/remotes/origin/),_origin_tag_reaches(:8930,ls-remote --tags origin) andcmd_bump(:9458, a fetch fromorigin).scripts/bump-leg.pymakes no clone. It reads a leg'srefs/remotes/origin/(:1094-1101) and fetchesorigin(:1503, used at :1520) in a leg that the person's or bootstrap's clone made, which under the setting has noorigin.setup-project.py:962clones the shape into a temporary checkout, and nooriginuse follows.scripts/family.py:6635and:7389andupdate-shape.py:711make--bareclones, and nooriginuse of those follows.update-shape.py'srefs/remotes/origin/reads (:5497, :5604, :5910) are of the person's own project clone.scaffold-project.py:2147,:2518,:2653andscripts/family.py:3324nameoriginthemselves withgit remote add originin repositories made bygit init.Closes #1261
Lane: openreposhape-3 (openRepoShape-3)
🤖 Generated with Claude Code