Repository navigation
Description
Lane: openreposhape-5 (openRepoShape-5)
(lane openRepoShape-5, 2026-10-12T19:25:29Z)
Found by lane 5's review of fix/bootstrap-print-name-escaped (the branch for #391), its F2, and reproduced on origin/main 53bee5b. The NUL row is lane 5's own addition while reproducing it. Not claimed. It is the sibling of #391, with a different mechanism: #391's value ends the run in a print, this one in an argument handed to git, and in both the run ends one step before the validator that could name the problem.
What is wrong. Step (a) of templates/assembly-root/scripts/bootstrap.py places each leg on its tracking branch. The branch is --branch, else project.yaml's tracking_branch, else main, and a leg's own branch: wins over all three (_checkout_all_tracking_branches, str(leg.get("branch") or branch)). It reaches git as argv (rev-parse --verify --quiet refs/heads/<branch>, checkout -q -b <branch> <pin>) through _try_git, which catches Refusal and nothing else:
def _try_git(args: list[str], cwd: Path) -> str | None:
try:
return git_out(args, cwd=cwd)
except Refusal:
return Nonesubprocess cannot encode a lone surrogate into an argument (UnicodeEncodeError) and refuses a NUL (ValueError: embedded null byte). Neither is a Refusal, so the run ends in a traceback from subprocess.py through repo_shape.git_out, exit 1 (make bootstrap: 2), with (a) legs on tracking branches printed and nothing after it. A branch git merely refuses (a\x1bb) is handled: _try_git returns None and the leg says could not create branch ...; leaving detached.
No tool names the value. validate-manifest.py never reads tracking_branch or a leg's branch (there is no branch in the file), so it prints manifest ok and exits 0 for both. Compare #280: a name holding a lone surrogate is now a finding (manifest-name, #390), which is the treatment these two keys lack.
SHAPE=<checkout of origin/main>
STUB=$(mktemp -d); printf '#!/bin/sh\nexit 97\n' > "$STUB/gh"; chmod +x "$STUB/gh"
export PATH="$STUB:$PATH" GH_TOKEN=bogus GH_CONFIG_DIR=$(mktemp -d)
export GIT_AUTHOR_NAME=T GIT_AUTHOR_EMAIL=t@example.invalid GIT_COMMITTER_NAME=T GIT_COMMITTER_EMAIL=t@example.invalid
D=$(mktemp -d)
python3 "$SHAPE/scaffold-project.py" --org testorg --project Atlas --elected-by 'T H' --elected-on 2026-09-02 \
--local-remote-dir "$D/remotes" --work-dir "$D/work" > /dev/null
git -c protocol.file.allow=always clone -q --recurse-submodules "$D/remotes/Atlas.git" "$D/Atlas"
cd "$D/Atlas" || exit 1
for value in main 'a\\ud83db' 'a\\x00b'; do
sed -i "s/^tracking_branch: .*/tracking_branch: \"$value\"/" project.yaml
grep '^tracking_branch' project.yaml
python3 scripts/validate-manifest.py | tail -n 1; echo "validator exit ${PIPESTATUS[0]}"
python3 scripts/bootstrap.py > /dev/null 2> "$D/err"; echo "bootstrap exit $?"; tail -n 1 "$D/err"
make bootstrap > /dev/null 2>&1; echo "make bootstrap exit $?"
done
sed -i 's/^tracking_branch: .*/tracking_branch: main/' project.yaml
sed -i '0,/^ path: spec$/s// path: spec\n branch: "a\\ud83db"/' project.yaml
python3 scripts/validate-manifest.py | tail -n 1; python3 scripts/bootstrap.py > /dev/null 2> "$D/err"; echo "exit $?"; tail -n 1 "$D/err"Observed on origin/main 53bee5b, Python 3.12.3:
project.yaml |
validate-manifest.py |
scripts/bootstrap.py |
|---|---|---|
tracking_branch: main (control) |
manifest ok: Atlas (atlas), 3 legs, exit 0 |
exit 0 |
tracking_branch: "a\ud83db" |
manifest ok: Atlas (atlas), 3 legs, exit 0 |
exit 1, UnicodeEncodeError: 'utf-8' codec can't encode character '\ud83d' in position 12: surrogates not allowed, from subprocess.py via repo_shape.git_out (:872), bootstrap.py _try_git (:95), checkout_tracking_branch (:115) and _checkout_all_tracking_branches (:349) |
tracking_branch: "a\x00b" |
the same, exit 0 | exit 1, ValueError: embedded null byte |
a leg's branch: "a\ud83db" (tracking_branch: main) |
the same, exit 0 | exit 1, the same UnicodeEncodeError, :349 |
make bootstrap exits 2 for both tracking_branch failing rows (make: *** [Makefile:44: bootstrap] Error 1); it was not run for the leg-branch row. The bootstrap.py frames are the template's own lines on origin/main, copied into the project.
What it should do. Two halves, and the author decides whether both belong in one change:
- Name it.
validate-manifest.pygives atracking_branchand a leg'sbranchthat no argument can carry (a lone surrogate, a NUL) a finding in the style of validate-manifest.py accepts a display name holding a lone surrogate (name: "a\ud83db") and then raisesUnicodeEncodeErrorprinting it, somake validateand shape-doctor.py fail on a traceback instead of a finding while bump-leg.py and update-shape.pyapplypass the same project once #254 lands #280'smanifest-name, so the person who ranmake bootstrapormake validateis told which key and which characters. Whether the value must also be a git ref name (whatgit check-ref-format --branchaccepts) is a wider decision, and scaffold-project.py holds--tracking-branchonly tochecked_value's alphabet, so a name git refuses as a branch (~,a..b,x.lock, a trailing/) passes--dry-runand, against GitHub, dies at the firstgit init -baftergh repo createhas made all three repositories #283 (scaffold's--tracking-branchref names) is where it is being made for the input side. - Survive it. Step (a) treats a branch the platform cannot hand to git as it already treats one git refuses:
_try_gitcatches(Refusal, UnicodeError, ValueError), so the leg printscould not create branch ...; leaving detachedand the run reaches the validators, which name the value once the first half lands. templates/assembly-root/scripts/bootstrap.py and templates/family-root/scripts/bootstrap.py:mainprints the manifest'snamewith a plainprintbefore any step runs, soname: "a\ud83db"(a lone surrogate) endsmake bootstrapin aUnicodeEncodeErrortraceback, exit 1 (make: 2), and the validator that names the problem is never reached; a valid name the stdout cannot encode ends the same way #391's{branch!r}print already spells the value on that line.
How to test. In a scaffolded project (the project fixture), edit tracking_branch and then a leg's branch to "a\ud83db" and to "a\x00b", as bytes. Run validate-manifest.py alone (a FINDING naming the key, exit 1, no traceback, once the first half lands) and scripts/bootstrap.py (exit 1 from the validator, no Traceback, bootstrap FAILED: manifest (exit 1), and under the second half alone, could not create branch on each leg). make bootstrap exits 2. A plain main stays byte-identical.
Not in this issue.
- The first line of the run, which prints the manifest's
name: templates/assembly-root/scripts/bootstrap.py and templates/family-root/scripts/bootstrap.py:mainprints the manifest'snamewith a plainprintbefore any step runs, soname: "a\ud83db"(a lone surrogate) endsmake bootstrapin aUnicodeEncodeErrortraceback, exit 1 (make: 2), and the validator that names the problem is never reached; a valid name the stdout cannot encode ends the same way #391. - A branch git refuses that is encodable (
a\x1bb, a name with a space,..): already handled by step (a); only the validator's wording could change. family-root/scripts/bootstrap.py, which reads no branch.
Activity
Both roots' scripts/bootstrap.py: `main` escapes what stdout cannot e…
brettheap commentedon Oct 15, 2026
CLAIMED — lane openRepoShape-4, session 11c6c0ef-495a-4a05-94cf-811b7b0a1012@Eagle, 2026-10-15T23:06:09Z, for #455
Logged in
lanes/log/openRepoShape-4.mdat6b1715ef47ea9ed7a0ceb0c926631b45565eba38.The three reads (lane-collision-protocol Rule 1):
docs/release-notes/v1.1.0.md: refreshed at main 4cf5fb0 (49 pull requ…
bootstrap.py and validate-manifest.py: a branch holding a NUL or a lo…
siblings.py: the printed move runs as typed past a taken staging name…
repo_shape.py, shape_materialize.py and adopt-project.py: a value the…
bootstrap.py: the L4-124 line calls a branch good only where git take…
validate-manifest.py, bootstrap.py, bump-leg.py and update-shape.py: …
bootstrap.py: step (a) decodes git's output as the system decodes a n…
repo_shape.py strips only YAML's space and tab, so a value a Unicode …