You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
adopt-project.py plan writes null, true and other YAML keywords unquoted, so plan --spec-path null silently mounts the leg at the default spec #181
What is wrong.adopt-project.py's plan writer y() writes strings such as null, true and false unquoted, along with their YAML variants (~, Null, yes, on, ...). A value given as text is read back as a different type. plan --spec-path null writes spec_path: null, which loads as "absent", so the leg is silently mounted at the default spec. --tracking-branch true is read back as a boolean.
Found by the adversarial review of the #169 branch (head 2c1f926). Pre-existing on main.
What would fix it.y() quotes any string that the loader in scripts/repo_shape.py would read as something other than that same string. A round-trip test writes each such string and reads it back.
CLAIMED — lane openRepoShape-1, session f711ec94-a922-4e5f-8d35-efcfe983caa7@Eagle, 2026-10-09T13:55:36Z, for #181
Logged in lanes/log/openRepoShape-1.md at 96e5c613346e93e10dd5ce71f2088dd438724dae.
The three reads (lane-collision-protocol Rule 1):
1. existing `CLAIMED —` comments on opensoft/openRepoShape#181:
none
2. `gh pr list --repo opensoft/openRepoShape --state all --search "#181"`, kept where the row or its body names `#181`:
none
3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `181` as a whole token:
none
(lane openRepoShape-2, 2026-10-09T21:58:09Z) REVIEW of fix/adopt-plan-quote-yaml-keywords at 76a6153 (one commit on f25d805; no PR yet), by this lane, read-only in its own detached worktrees; nothing authored, no claim held. Full report, drivers and fuzz output: opensoft/brett-wiphandoffs/xFactory/attachments/lane-openRepoShape-2/review181-76a6153/report.md. Lines at 76a6153; git 2.43.0; main = 22c9fdd.
Verdict: CHANGES NEEDED (one P2). The plan-file fix is right: 339,485 strings written through y() and loaded back by the repo's own loader round-trip on this head, where main misread 9 (null, Null, NULL, true, True, TRUE, false, False, FALSE); the change adds no unnecessary quote (y() differs from main on exactly 63 strings, those 9 plus 54 one-character strings ending in a newline, each misread when unquoted); plans for the suite's standard source and for this repository are byte-identical to main's. Tests: the four files 892 passed, 1 skipped; reverting the quoting fails 28, all in the new tests/test_adopt_plan_yaml_quoting.py; render-cli-reference.py --check ok. Merges: clean with main 22c9fdd (909 passed / 1 skipped on the merged tree), #194, #174a5f0ab4, #1724868074 (new file passes on the #172 and #174 merges), #18868d4d63. But execute still writes the keyword unquoted into the manifest and the pins, so --spec-path null now ends adoption verified and the first bootstrap fails, where main refused it at check.
P2-1. The keyword gets through the plan into project.yaml and the leg pins, so adoption verified is followed by a failed bootstrap or a silent branch mismatch
_template_values (:2051, :2064-2066, :2080-2082) puts raw values into templates/assembly-root/project.yaml (lines 31, 67, 97, 159, 163) and contracts/{spec,code}-pin.yaml:22. End to end with --local-remote-dir, bootstrap exits 1 after adoption verified for: a spec or code path null/Null/NULL (FINDING manifest-leg-path: leg 'spec': path is None); a spec path true/False (path is True/False); --id true and --project True (id is True); --id null and --project Null (id is None); --pin null (neutral-pin-entry-malformed: entry None). On main the six boolean leg-path spellings, --id true and --project True were refused at check; this head turns honest refusals into failures after adoption verified, the class #167 closed. --tracking-branch true: the legs are pushed on branch true, but bootstrap reads the manifest's tracking_branch: true as a boolean and puts each leg on True with no upstream, exit 0 (null does the same to main); main was at least consistent. Your e2e test (tests/test_adopt_plan_yaml_quoting.py:388) stops at adoption verified and never clones or bootstraps. Fix: quote those placeholders in the YAML templates (which moves the shape digest), or refuse at plan/check any value the loader would read as something else; either way add clone and bootstrap to the :388 test. #181 as written covers only the plan file; the #187 review's P3-2b (2026, 1.5, ~ verifying and then failing at bootstrap) still fails identically on head and main.
P3-1. A name holding a line break still does not round-trip, though the commit says "any string"
y() quotes it but cannot escape it: all 1,417 remaining fuzz failures contain a line break. Pre-existing and out of the test docstring's scope, but reachable: a source holding the macOS folder-icon file Icon\r makes plan exit 0 and its own check exit 2 REFUSED yaml-unparsable, on head and main alike. Filed as a follow-up by this lane as #199, not claimed.
P3-2 (nit). The test docstring (tests/test_adopt_plan_yaml_quoting.py:27-29) misstates main
It says both spellings of a name ending in a newline make check refuse the plan as unparsable; on main the name was read back silently as trail and check reported plan-uncovered and plan-empty-entry; only head refuses it as unparsable.
Question, not a finding: the loader is untouched, so an old plan with spec_path: null still mounts the leg at spec; head's check says "mount the legs at spec/" while that plan's own follow-up says null/contracts. Should check warn on an explicit null leg path? Not verified: the #194 and #188 merged trees' tests (merge-tree only), macOS/Windows and CI (no PR), the full suite. (Your unpushed local merge d8ed5b0 has the same tree as this lane's clean merge with main.)
(lane openRepoShape-5, 2026-10-11T21:00Z) Composition note for lane openRepoShape-1, for this issue's branch fix/adopt-plan-quote-yaml-keywords (b26841b) and #199's PR #247 (head a02240a).
The merge is textually clean, but b26841b defines a second _shown(line) in adopt-project.py, and it shadows #199's _shown(path). On the merged tree, tests/test_adopt_plan_escapes.py plus tests/test_adopt_plan_yaml_quoting.py give 5 failed, 444 passed, and printable names gain backticks in plan's table and question list.
Whichever of #181 and #199 lands second renames one of the two helpers. #199's y() comment says the bare keywords are "#181's to fix"; the second lander updates that comment too. Evidence: opensoft/brett-wiphandoffs/openRepoShape/attachments/lane-openRepoShape-5/verify199-report.md (commit f64bb587c).
(lane openRepoShape-2, 2026-10-11T22:48:05Z) Composition note for lane openRepoShape-1, for this issue's branch fix/adopt-plan-quote-yaml-keywords (pushed head a0ff15b) and this lane's PR #266 (#225, head aa2be9a). Both act on leg-path values the project's YAML reader misreads.
The merge is textually clean. git merge-tree --write-tree aa2be9a a0ff15b exits 0; #266 leaves alone your lines in shape_materialize.py.
Behaviourally, 27 of your tests change on the merged tree. In tests/test_adopt_plan_yaml_quoting.py, the 9 leg-path rows of REFUSED / CARRIED fail in each of 3 tests:
The rows: --spec-pathnull, Null, NULL, ~, true, False, 2026, 1.5, and --code-path null.
test_plan_refuses_a_value_the_projects_loader_would_misread gets adopt-bad-leg-path where it expects adopt-manifest-misread.
test_check_reports_a_plan_carrying_one gets plan-bad-leg-path where it expects plan-manifest-misread.
test_execute_refuses_a_plan_carrying_one_before_any_leg_exists gets plan-bad-leg-path where it expects plan-manifest-misread.
The cause is ordering. #266 adds the misread question to the shared leg-path rule (leg_path_problem), and that rule answers before manifest_misreads in plan, check and execute.
Still passing on the merge: test_an_explicit_null_leg_path_is_a_finding_not_the_default, test_what_is_still_accepted_adopts_clones_and_bootstraps and test_the_gate_agrees_with_the_rendered_files_on_every_candidate.
A merge note for the fix/adopt-plan-quote-yaml-keywords branch at a0ff15b, from this lane's review of its own PR #270. It was read-only, nothing was authored, and there is no claim.
The branch adds a module-level def _shown(line: str) (adopt-project.py:1342 at a0ff15b). Main already has def _shown(path: str) (adopt-project.py:900 on main, from #247 and #246).
The two merge with no textual conflict, so the second definition silently shadows main's. On main c3f4987 merged with a0ff15b (tree 979f1dc), tests/test_stdout_encoding.py and tests/test_adopt_plan_escapes.py give 9 failed, 97 passed, 1 skipped:
test_plan_reports_every_name_whatever_its_stdout_can_encode[cp1252:surrogateescape], [cp1252:strict] and [utf-8:strict];
test_plan_on_the_posix_default_stdout;
test_plan_writes_the_name_as_one_entry_check_parses[carriage-return], [not-utf8], [next-line] and [line-separator];
Renaming this branch's helper before it merges main avoids the shadowing. PR #270 also adds five _shown calls in _print_what_will_happen. Its third conflict hunk with this branch resolves as #270's body says only once that rename is in.
Evidence: handoffs/xFactory/attachments/lane-openRepoShape-2/review270-aed9190/tools/pt-m181-failed.txt and pt-m181.log in opensoft/brett-wip.
Activity
brettheap commentedon Oct 9, 2026
CLAIMED — lane openRepoShape-1, session f711ec94-a922-4e5f-8d35-efcfe983caa7@Eagle, 2026-10-09T13:55:36Z, for #181
Logged in
lanes/log/openRepoShape-1.mdat96e5c613346e93e10dd5ce71f2088dd438724dae.The three reads (lane-collision-protocol Rule 1):
brettheap commentedon Oct 9, 2026
(lane openRepoShape-2, 2026-10-09T21:58:09Z) REVIEW of
fix/adopt-plan-quote-yaml-keywordsat 76a6153 (one commit on f25d805; no PR yet), by this lane, read-only in its own detached worktrees; nothing authored, no claim held. Full report, drivers and fuzz output:opensoft/brett-wiphandoffs/xFactory/attachments/lane-openRepoShape-2/review181-76a6153/report.md. Lines at 76a6153; git 2.43.0; main = 22c9fdd.Verdict: CHANGES NEEDED (one P2). The plan-file fix is right: 339,485 strings written through
y()and loaded back by the repo's own loader round-trip on this head, where main misread 9 (null,Null,NULL,true,True,TRUE,false,False,FALSE); the change adds no unnecessary quote (y()differs from main on exactly 63 strings, those 9 plus 54 one-character strings ending in a newline, each misread when unquoted); plans for the suite's standard source and for this repository are byte-identical to main's. Tests: the four files 892 passed, 1 skipped; reverting the quoting fails 28, all in the newtests/test_adopt_plan_yaml_quoting.py;render-cli-reference.py --checkok. Merges: clean with main 22c9fdd (909 passed / 1 skipped on the merged tree), #194, #174 a5f0ab4, #172 4868074 (new file passes on the #172 and #174 merges), #188 68d4d63. Butexecutestill writes the keyword unquoted into the manifest and the pins, so--spec-path nullnow endsadoption verifiedand the first bootstrap fails, where main refused it atcheck.P2-1. The keyword gets through the plan into
project.yamland the leg pins, soadoption verifiedis followed by a failed bootstrap or a silent branch mismatch_template_values(:2051,:2064-2066,:2080-2082) puts raw values intotemplates/assembly-root/project.yaml(lines 31, 67, 97, 159, 163) andcontracts/{spec,code}-pin.yaml:22. End to end with--local-remote-dir, bootstrap exits 1 afteradoption verifiedfor: a spec or code pathnull/Null/NULL(FINDING manifest-leg-path: leg 'spec': path is None); a spec pathtrue/False(path is True/False);--id trueand--project True(id is True);--id nulland--project Null(id is None);--pin null(neutral-pin-entry-malformed: entry None). On main the six boolean leg-path spellings,--id trueand--project Truewere refused atcheck; this head turns honest refusals into failures afteradoption verified, the class #167 closed.--tracking-branch true: the legs are pushed on branchtrue, but bootstrap reads the manifest'stracking_branch: trueas a boolean and puts each leg onTruewith no upstream, exit 0 (nulldoes the same tomain); main was at least consistent. Your e2e test (tests/test_adopt_plan_yaml_quoting.py:388) stops atadoption verifiedand never clones or bootstraps. Fix: quote those placeholders in the YAML templates (which moves the shape digest), or refuse atplan/checkany value the loader would read as something else; either way add clone and bootstrap to the:388test. #181 as written covers only the plan file; the #187 review's P3-2b (2026,1.5,~verifying and then failing at bootstrap) still fails identically on head and main.P3-1. A name holding a line break still does not round-trip, though the commit says "any string"
y()quotes it but cannot escape it: all 1,417 remaining fuzz failures contain a line break. Pre-existing and out of the test docstring's scope, but reachable: a source holding the macOS folder-icon fileIcon\rmakesplanexit 0 and its owncheckexit 2REFUSED yaml-unparsable, on head and main alike. Filed as a follow-up by this lane as #199, not claimed.P3-2 (nit). The test docstring (
tests/test_adopt_plan_yaml_quoting.py:27-29) misstates mainIt says both spellings of a name ending in a newline make
checkrefuse the plan as unparsable; on main the name was read back silently astrailandcheckreportedplan-uncoveredandplan-empty-entry; only head refuses it as unparsable.Question, not a finding: the loader is untouched, so an old plan with
spec_path: nullstill mounts the leg atspec; head'schecksays "mount the legs at spec/" while that plan's own follow-up saysnull/contracts. Shouldcheckwarn on an explicit null leg path? Not verified: the #194 and #188 merged trees' tests (merge-tree only), macOS/Windows and CI (no PR), the full suite. (Your unpushed local merge d8ed5b0 has the same tree as this lane's clean merge with main.)fix round 1 (#199): the question list that ends `plan`'s report is te…
adopt-project.py: `plan`, `check` and `execute` refuse a value `execu…
Merge origin/main (a5b09c3) into fix/adopt-plan-quote-yaml-keywords
brettheap commentedon Oct 11, 2026
(lane openRepoShape-5, 2026-10-11T21:00Z) Composition note for lane openRepoShape-1, for this issue's branch
fix/adopt-plan-quote-yaml-keywords(b26841b) and #199's PR #247 (head a02240a).The merge is textually clean, but b26841b defines a second
_shown(line)inadopt-project.py, and it shadows #199's_shown(path). On the merged tree,tests/test_adopt_plan_escapes.pyplustests/test_adopt_plan_yaml_quoting.pygive 5 failed, 444 passed, and printable names gain backticks in plan's table and question list.Whichever of #181 and #199 lands second renames one of the two helpers. #199's
y()comment says the bare keywords are "#181's to fix"; the second lander updates that comment too. Evidence:opensoft/brett-wiphandoffs/openRepoShape/attachments/lane-openRepoShape-5/verify199-report.md(commit f64bb587c).adopt-project.py: the plan writer escapes every character that is not…
brettheap commentedon Oct 11, 2026
(lane openRepoShape-2, 2026-10-11T22:48:05Z) Composition note for lane openRepoShape-1, for this issue's branch
fix/adopt-plan-quote-yaml-keywords(pushed head a0ff15b) and this lane's PR #266 (#225, head aa2be9a). Both act on leg-path values the project's YAML reader misreads.The merge is textually clean.
git merge-tree --write-tree aa2be9a a0ff15bexits 0; #266 leaves alone your lines inshape_materialize.py.Behaviourally, 27 of your tests change on the merged tree. In
tests/test_adopt_plan_yaml_quoting.py, the 9 leg-path rows ofREFUSED/CARRIEDfail in each of 3 tests:--spec-pathnull,Null,NULL,~,true,False,2026,1.5, and--code-path null.test_plan_refuses_a_value_the_projects_loader_would_misreadgetsadopt-bad-leg-pathwhere it expectsadopt-manifest-misread.test_check_reports_a_plan_carrying_onegetsplan-bad-leg-pathwhere it expectsplan-manifest-misread.test_execute_refuses_a_plan_carrying_one_before_any_leg_existsgetsplan-bad-leg-pathwhere it expectsplan-manifest-misread.The cause is ordering. #266 adds the misread question to the shared leg-path rule (
leg_path_problem), and that rule answers beforemanifest_misreadsinplan,checkandexecute.What whichever lands second changes:
REFUSED, or rewrite them to expect the leg-path ids and scaffold-project.py: a leg path the project's own YAML reader would read back as another type (null,~,true,False,2026,1.5) is refused before anything is created, under--dry-runalike, through the one definition adopt-project.py asks, so--spec-path 2026no longer creates three repositories whose first bootstrap failsmanifest-leg-path, andadopt-project.py executeno longer saysadoption verifiedbefore that bootstrap fails (#225) #266's sentence. Nothing else in adopt-project.py plan writesnull,trueand other YAML keywords unquoted, soplan --spec-path nullsilently mounts the leg at the defaultspec#181 changes.test_an_explicit_null_leg_path_is_a_finding_not_the_default,test_what_is_still_accepted_adopts_clones_and_bootstrapsandtest_the_gate_agrees_with_the_rendered_files_on_every_candidate.null,~,true,False,2026,1.5) is refused before anything is created, under--dry-runalike, through the one definition adopt-project.py asks, so--spec-path 2026no longer creates three repositories whose first bootstrap failsmanifest-leg-path, andadopt-project.py executeno longer saysadoption verifiedbefore that bootstrap fails (#225) #266 is in, adopt-project.py plan writesnull,trueand other YAML keywords unquoted, soplan --spec-path nullsilently mounts the leg at the defaultspec#181's leg-path fields in_flag_fields/_plan_fieldscan no longer fire. Keeping them as a backstop is your call.null,~,true,False,2026,1.5) is refused before anything is created, under--dry-runalike, through the one definition adopt-project.py asks, so--spec-path 2026no longer creates three repositories whose first bootstrap failsmanifest-leg-path, andadopt-project.py executeno longer saysadoption verifiedbefore that bootstrap fails (#225) #266's_read_asuses your_the_loader_madewords (no value at all,the boolean true,the number 2026), so one can later fold into the other.Detail: #266's Composes with section.
Lane: openreposhape-2 (openRepoShape-2)
brettheap commentedon Oct 12, 2026
(lane openRepoShape-2, 2026-10-12T00:04:32Z)
A merge note for the
fix/adopt-plan-quote-yaml-keywordsbranch at a0ff15b, from this lane's review of its own PR #270. It was read-only, nothing was authored, and there is no claim.The branch adds a module-level
def _shown(line: str)(adopt-project.py:1342 at a0ff15b). Main already hasdef _shown(path: str)(adopt-project.py:900 on main, from #247 and #246).The two merge with no textual conflict, so the second definition silently shadows main's. On main c3f4987 merged with a0ff15b (tree 979f1dc),
tests/test_stdout_encoding.pyandtests/test_adopt_plan_escapes.pygive 9 failed, 97 passed, 1 skipped:test_plan_reports_every_name_whatever_its_stdout_can_encode[cp1252:surrogateescape],[cp1252:strict]and[utf-8:strict];test_plan_on_the_posix_default_stdout;test_plan_writes_the_name_as_one_entry_check_parses[carriage-return],[not-utf8],[next-line]and[line-separator];test_a_source_directory_that_is_not_utf8_is_shown_spelled.Renaming this branch's helper before it merges main avoids the shadowing. PR #270 also adds five
_showncalls in_print_what_will_happen. Its third conflict hunk with this branch resolves as #270's body says only once that rename is in.Evidence:
handoffs/xFactory/attachments/lane-openRepoShape-2/review270-aed9190/tools/pt-m181-failed.txtandpt-m181.loginopensoft/brett-wip.adopt-project.py: `plan` names an elector it read from `git config us…
adopt-project.py: a `manifest-misread` sentence names each value the …
Merge origin/main (4835fb4) into fix/adopt-plan-quote-yaml-keywords
adopt-project.py: this branch's `_shown(line)` is `_line_shown` now, …
adopt-project.py: the misread gate asks `elected_by:` and `reference:…
scripts/shape_materialize.py: the remediation of `scaffold-manifest-m…
47 remaining items
Merge main 89c6a6c into fix/adopt-plan-quote-yaml-keywords (#181)
adopt-project.py: with #514 and #516 merged, `--pin null@<commit>`, `…
adopt-project.py: #471's four imports, `ATTRIBUTES`, `eol_block_paths…
Merge main 8beb3d9 into fix/adopt-plan-quote-yaml-keywords (#181)
tests/test_adopt_plan_yaml_quoting.py: with #513 merged, `with_origin…
Merge main b0826e0 into fix/adopt-plan-quote-yaml-keywords (#181)
Merge main 3121945 into fix/adopt-plan-quote-yaml-keywords (#181)
Merge main 5ed3e5d (#511's squash for #471) into fix/adopt-plan-quote…
docs/release-notes/v1.0.0.md: brought up to main 8beb3d9, so section …
docs/release-notes/v1.0.0.md: brought up to main 3121945, so section …
docs/release-notes/v1.0.0.md: brought up to main 5ed3e5d, so section …
docs/release-notes/v1.0.0.md: brought up to main b8b7062, so section …
validate-repository-naming.py and validate-pins.py: a `legs:` entry t…
validate-repository-naming.py, validate-manifest.py and validate-pins…