Repository navigation
Description
repo_shape.git_out should hand a branch name that is not UTF-8 back to its callers, so that a leg on such a branch does not end every later make bootstrap in a traceback. The riders about names step (a) carries or cannot write ride with it.
From lane 4's checklist triage of 2026-10-16 (T2), approved by Brett Heap at 2026-10-16T13:36:07Z ("approve all triage recommendations"). One pull request covers the lines below, and it is the SAME pull request as #709, so that templates/assembly-root/scripts/bootstrap.py is re-pinned once and not twice.
Parent: #459. Milestone: v1.1.1 (a follow-up filed after Brett Heap's v1.1.1 word of 2026-10-16T13:35:28Z).
Authored after the v1.1.0 work; lands after the v1.1.0 tag unless the release owner (lane 3) says otherwise.
Lands after:
- lane 5's bootstrap.py (the family root's and the assembly root's):
make bootstrapwith no git on PATH ends in aFileNotFoundErrortraceback, exit 1, where the validators refusegit-not-runnable, exit 2 #694 (filed, no pull request yet). It edits the same_try_gitandgit_outsites intemplates/assembly-root/scripts/bootstrap.pythat L4-125 goes through (recorded_gitlink,_try_git, thegitrun), to catch anOSErrorwhere git is not on PATH. Whichever lands second re-gates against the other. - lane 2's Pinned shape copies: one bump, so AGENTS-shape.md is true of every root, the scaffold's chain WARNING offers only its own sources and spells
--pin-source, the root's not-used note spells it too, and THE LOCKSTEP RULE'sbumpruns (#610) #634 (ready; it editsscripts/repo_shape.py, a pinned copy). - bootstrap.py (the assembly root's): a leg moved off a branch has an ignored file the pin tracks overwritten and a merge in progress ended, with no word, and a tracking branch ahead of the pin with no commit of its own is left where it is #709, in the same pull request.
- lane 1's adopt-project.py
_default_branchreads the source's branch name throughgit_out, which decodes strictly, so a source whose HEAD (ororigin/HEAD) names a branch that is not UTF-8 endsplan,checkandexecutein a UnicodeDecodeError traceback, exit 1, fromSource.open, with no plan written and no refusal naming the branch #425 (v1.1.0, claimed):adopt-project.py's_default_branchreads the source's branch name through the same strictgit_out, so a source whose HEAD names a branch that is not UTF-8 endsplanin the sameUnicodeDecodeError. adopt-project.py_default_branchreads the source's branch name throughgit_out, which decodes strictly, so a source whose HEAD (ororigin/HEAD) names a branch that is not UTF-8 endsplan,checkandexecutein a UnicodeDecodeError traceback, exit 1, fromSource.open, with no plan written and no refusal naming the branch #425 asks thatgit_outNOT change, because it is pinned. This issue does change it, so one of the two pull requests decides the decode rule and the other follows; if this one lands first, adopt-project.py_default_branchreads the source's branch name throughgit_out, which decodes strictly, so a source whose HEAD (ororigin/HEAD) names a branch that is not UTF-8 endsplan,checkandexecutein a UnicodeDecodeError traceback, exit 1, fromSource.open, with no plan written and no refusal naming the branch #425's traceback goes with it.
Effort: S: one decode rule in git_out. L4-124 waits for its ruling. Platform: all (L4-124 was measured under LC_ALL=C PYTHONUTF8=0, because the review host has no Latin-1 locale).
Files: scripts/repo_shape.py (git_out, :1048 on c6122e8) and templates/assembly-root/scripts/bootstrap.py; both are pinned shape copies, re-pinned once, in the same pull request as #709.
Lane openRepoShape-4 claims it at filing; see its CLAIMED comment.
Why this is filed. Not an ordinary repository: the branch name has to be one that is not UTF-8, which bootstrap.py --branch $'a\xffb' (which #644 deliberately keeps), a manifest's "\udcXX" escape or a hand edit makes. But once it exists, EVERY later make bootstrap in that root ends in a traceback until the branch is renamed by hand, with nothing naming it. Line numbers are at c6122e8 (#639); main has moved since.
Lines
- L4-125 (P3): a leg on a branch whose name is not UTF-8 makes EVERY later
bootstrap.pyend in a traceback. The decode isrepo_shape.git_out's strictproc.stdout.decode("utf-8")(scripts/repo_shape.py:1048onc6122e8;:923when measured), reached viaplace_at_pin,_head_of(bootstrap.py:211) and_try_git(:120). Such a branch can be created bybootstrap.py --branch $'a\xffb', which bootstrap.py and validate-manifest.py: a branch holding a NUL or a lone surrogate is a finding and step (a) does not hand it to git, sotracking_branch: "a\ud83db"or a leg'sbranch: "a\x00b"no longer endsmake bootstrapin a subprocess traceback under amanifest ok(#455) #644 deliberately keeps, by a manifest's"\udcXX"escape (L4-126), or by hand. Measured on main: run 1 exit 0branch a\udcffb created; run 2 exit 1,UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 12. The head is the same (R455 O3). (source)
Rides along (backlog; tick it here if the same change covers it)
- L4-124 (NEEDS A RULING): a character the filesystem encoding lacks still ends bootstrap's step (a) in a traceback. The same on main and on the head. Measured with
LC_ALL=C PYTHONUTF8=0, because this host has no Latin-1 locale (locale -a: C, C.utf8, POSIX) andsys.getfilesystemencoding()is thenascii, the same mechanism:tracking_branch: "feature/日本"gives the validator 0manifest ok, then bootstrap 1,UnicodeEncodeError: 'ascii' codec can't encode characters in position 19-20: ordinal not in range(128). Under the default UTF-8 locale the same value createsfeature/日本. assembly-root bootstrap.py: a lone surrogate or NUL intracking_branch(or a leg'sbranch:) endsmake bootstrapin a subprocess traceback in step (a), andvalidate-manifest.pysaysmanifest ok, so no tool names it #455's own "Survive it" asks that "a branch the platform cannot hand to git" be treated as one git refuses, and bootstrap.py and validate-manifest.py: a branch holding a NUL or a lone surrogate is a finding and step (a) does not hand it to git, sotracking_branch: "a\ud83db"or a leg'sbranch: "a\x00b"no longer endsmake bootstrapin a subprocess traceback under amanifest ok(#455) #644 scoped it out on purpose (the_argument_faultdocstring). Where:bootstrap.py:125(_argument_faultasks NUL and lone surrogates only). Shape of a fix: fault wherever_fsencoded_length(char) == 0. It needs its own remediation (the name is good; run under a UTF-8 locale orPYTHONUTF8=1), which changes what a person is told, so it needs a ruling of its own (R455 O1). (source) - L4-126 (a question; R455 recommends no change here, and the fix at L4-125): step (a) CARRIES a manifest value holding U+DC80 to U+DCFF that step (b) then names as a finding.
tracking_branch: "a\udcffb", or a leg'sbranch: "\udc80": step (a) creates and checks outrefs/heads/a\xffb(resp.refs/heads/\x80) in each leg, because_argument_faultasks only whetheros.fsencodecan write the surrogate as one byte, and then the validator names the value (U+DCFF/U+DC80). Following the finding (editing back tomain) and running again ends inUnicodeDecodeError(measured: bootstrap 1, make 2). That is L4-125's decode, the same on main, where the validator said nothing. Two options: (a)_checkout_all_tracking_branches(bootstrap.py:840) asks the validator's any-surrogate rule of a value from the manifest and keeps theos.fsencoderule for--branchalone, about 6 lines and one test, so step (a) never acts on a value step (b) refuses; (b) leave it and fix the root cause in L4-125. R455 recommends (b): the input is hand-written and exotic, and (a) only hides one route into L4-125 (R455 F4). (source)
What is expected
git_outhas ONE decode rule for what git prints, and a latermake bootstrapon a leg whose branch isa\xffbendsbranch ... at ...and not a traceback. The rule is the pull request's to choose, but it must keep the name's bytes, since the name goes back to git. A test makes the branch withgit branch $'a\xffb'(POSIX only; skipped where the filesystem refuses the name, as the repository's other such tests are) and runs bootstrap twice.- L4-126 is answered by that fix, option (b), unless Brett Heap rules for option (a). The pull request says so and ticks it.
- L4-124 is NOT in the first change. It waits for a ruling from Brett Heap on what a person is told when the platform's encoding cannot write a good branch name, and stays open here until then.
Not a duplicate: lane 5's #694 is a missing git, not a name git cannot decode. No issue numbered #650 to #700 cites L4-124 to L4-126 (read at 13:17Z); #425 is the adopt-project.py reader of the same decode.
Each line above is a line of #459's checklist comment (issuecomment-6214587074). Tick it there too when this closes.
Lane: openreposhape-4 (openRepoShape-4)
Activity
brettheap commentedon Oct 16, 2026
CLAIMED — lane openRepoShape-4, session 11c6c0ef-495a-4a05-94cf-811b7b0a1012@Eagle, 2026-10-16T13:59:14Z, for #710
Logged in
lanes/log/openRepoShape-4.mdatab8737076b7a5f02b1ef962b466fff43396cc781.The three reads (lane-collision-protocol Rule 1):
brettheap commentedon Oct 17, 2026
(lane openRepoShape-5, 2026-10-16T23:59:42Z) One more site for #710, so no separate issue is filed for it.
_upstream_holdingin the assembly root'sbootstrap.py(templates/assembly-root/scripts/bootstrap.py:222at main66b230ed) readsfor-each-ref's upstream name as strict UTF-8, the same flaw that lane 5's #704 (PR #745) fixed in_head_ofby reading bytes and decoding withos.fsdecode. rv704 measured it ata1f2433fand at4e2b211b: with a tracking branch past the pin whose name and upstream are not UTF-8, and HEAD detached at the pin, bootstrap ends in aUnicodeDecodeErrorat_upstream_holding. The fix is the same as #745's.brettheap commentedon Oct 17, 2026
(lane openRepoShape-4, 2026-10-17T13:01:33Z) Brett Heap's ruling on L4-124, at 2026-10-17T13:01:07Z: "go with (a) for L4-124".
The case: under
LC_ALL=C PYTHONUTF8=0, the filesystem encoding isascii. There,tracking_branch: "feature/日本"passes the validator (manifest ok), and bootstrap then fails with aUnicodeEncodeErrortraceback.Option (a), as ruled:
_argument_faultalso faults any character thatos.fsencodecannot write.LC_ALL=C.UTF-8) or withPYTHONUTF8=1.Rejected:
tracking_branch(or a leg'sbranch:) endsmake bootstrapin a subprocess traceback in step (a), andvalidate-manifest.pysaysmanifest ok, so no tool names it #455's "Give that one a name git can create", because the name is fine;Lane 4's writer for #710 resumes with this ruling. Like every v1.1.1 PR, it waits for the v1.1.0 tag.
bootstrap.py: the L4-124 line calls a branch good only where git take…
bootstrap.py: git is asked whether a branch this system's encoding ca…
brettheap commentedon Oct 17, 2026
(lane openRepoShape-4, 2026-10-17T19:01:27Z) Where #710's decode rule lives: Option 2, as lane 4 ruled on 2026-10-17. This issue expected that "
git_outhas ONE decode rule". PR #824 puts that rule in the assembly root'sbootstrap.py, in_try_git, and leavesrepo_shape.git_out's strict UTF-8 decode as it is._try_gitreads git's output as bytes and decodes it the way the name goes back to git. On POSIX that isos.fsdecode, the inverse of theos.fsencodethatsubprocessapplies to each argument. On Windows it is UTF-8 (RV824's N3), becausesubprocesshands git its arguments throughCreateProcessW. This matches how bootstrap.py and AGENTS-shape.md: a leg with an operation in progress or an ignored file in the way is refused, P9 names the branch it left, and no git isgit-not-runnable, somake bootstraploses nothing (#704) (#694) #745 made_head_ofand_in_progressread.git_out's decode for every caller. The readers oforigin's URL inshape-doctor.py(thenamingrow'sorigin_name) andscripts/shape_advisory.py(repository_names) catchgit_out'sUnicodeDecodeErrorto mean that the URL names nothing (scripts/shape_advisory.pyrepository_namesand shape-doctor.pyorigin_urlandorigin_namereadgit remote get-url originthroughgit_outand catchRefusalandOSErroronly, so an origin URL that is not UTF-8 makesreadanswernot-answered(a single repository loses the Triad advisory, a leg clone its pointer to the assembly root) and endsshape-doctor.py --rootin a UnicodeDecodeError traceback, exit 1, where an ASCII origin gives NOT A SHAPE ROOT, exit 2 #385). Under anos.fsdecodegit_out, they would salvage a segment of such a URL instead, which changes what the doctor tells a person, outside bootstrap.py and repo_shape.py: a leg on a branch whose name is not UTF-8 makes every latermake bootstrapend in a UnicodeDecodeError, and a character the filesystem encoding lacks still ends step (a) in a traceback #710's files. adopt-project.py_default_branchreads the source's branch name throughgit_out, which decodes strictly, so a source whose HEAD (ororigin/HEAD) names a branch that is not UTF-8 endsplan,checkandexecutein a UnicodeDecodeError traceback, exit 1, fromSource.open, with no plan written and no refusal naming the branch #425 asked the same ofgit_outand closed through adopt-project.py:_default_branchkeeps a branch name's byte that is not UTF-8, so a source whose HEAD ororigin/HEADis oncaf<e9>is refused or adopted past it, and no longer endsplan,checkandexecutein a traceback (#425) #717, with a local decode inadopt-project.py's_default_branch.A comment at
_try_git's decode records this ruling (RV824's N6).Lane: openreposhape-4 (openRepoShape-4)
validate-manifest.py, bootstrap.py, bump-leg.py and update-shape.py: …
bump-leg.py and update-shape.py: a tracking branch is refused only fo…
setup-project.py and the assembly root's bootstrap.py: every Python c…
Merge main 0dee22b (#824, #710) into fix/715-yaml-reader-spaces: `_ar…
repo_shape.py strips only YAML's space and tab, so a value a Unicode …
bootstrap.py: a validator's exit 2 ends `bootstrap REFUSED`, exit 2, …