Repository navigation
family.py and shape_materialize.py: the helpers that ask a template's own YAML reader and validator about a manifest's values exist twice, for project.yaml (#314) and for family.yaml (#397) #470
Description
Lane: openreposhape-5 (openRepoShape-5)
(lane openRepoShape-5, 2026-10-12T20:39:32Z)
Found by lane 5 while landing #397 (#307). Not claimed.
#314 (landed as 3ef059c) and #397 (head abb27e6, cut from c7c02fa, so before #314) each ask the new file's OWN YAML reader (repo_shape.parse_yaml) and its OWN validator about the values a tool is about to write, before anything is created:
- scaffold-project.py and adopt-project.py ask the project's YAML reader and validate-manifest.py about the manifest's values before anything exists, so
--id null,--tracking-branch trueand a blank--elected-byare refused (#258, #261) #314, for the assembly root'sproject.yamlandscripts/validate-manifest.py, fromscaffold-project.pyandadopt-project.py(scaffold-project.py writes--idand--tracking-branchinto project.yaml unquoted, so--id nullor--id truescaffolds a project whose first bootstrap failsmanifest-id, and--tracking-branch true,007ornullputs the clone's legs onTrue,7ormainwith no upstream: #181's defect on the scaffold side, beside #225 #258, adopt-project.py and scaffold-project.py accept values the new project's own validate-manifest.py refuses (a blank--elected-byor--reference,--elected-on 2026-W41-6or20261011on Python 3.11+,--org test+org, a plan'svisibility: secret), soadoption verifiedor a scaffold exit 0 is followed by a failed first bootstrap; andplanadmits a 251-255-character--projectthatcheckrefuses #261). - family.py:
initasks the holder's reader and validate-family.py about family.yaml before creating anything,--dry-runtoo, so--id null,--tracking-branch true, a blank--created-byand--created-on 20261011are refused (#307) #397, for the holder'sfamily.yamlandscripts/validate-family.py, fromfamily.py init(family.py init exits 0 and pushes a holder its own validate-family.py refuses for--id null,--created-by ' ',--created-on 20261011or--name 'Contoso Group', and puts--tracking-branch trueon a branch its manifest reads back as True #307).
#397's code comment (scripts/family.py:1028-1033 at abb27e6) and its description said that whichever of the two landed second would unify them. #314 landed first, and #397 leaves the two as they are. This issue is the unification.
The helpers that do the same job. Line numbers are at 3ef059c for scripts/shape_materialize.py and at abb27e6 for scripts/family.py.
| job | #314, scripts/shape_materialize.py |
#397, scripts/family.py |
how they differ |
|---|---|---|---|
| load the template's own validator by path, once per path | manifest_validator :2226, _VALIDATORS :2223, VALIDATOR_ASKS :2202 |
family_validator :1091, _VALIDATORS :1072, FAMILY_VALIDATOR_ASKS :1043 |
the template directory, the validator file, the module name and the names asked of it; the family's also catches SystemExit while loading |
| say a validator cannot be asked | _validator_unusable :2271 (manifest-validator-unusable) |
_validator_unusable :1075 (family-validator-unusable) |
the refusal code and the file it names |
| say what the reader made of a value, show a line, read one line | _reading_in_words :2287, _line_shown :2302, _reading_of :2308 |
_reading_in_words :1127, _line_shown :1142, _reading_of :1148 |
none: compared as syntax trees with the docstrings left out, the code is the same |
| find the template lines whose value the reader would not read back as typed | _misread_rows :2322, _placeholders_of :2210, TEMPLATED_YAML :2207 |
_misread_rows :1162, FAMILY_TEMPLATED_YAML :1048, and PLACEHOLDER_RE.findall inline at :1171 |
which templated files are walked; #314's rows carry the file name, the family's do not |
| say it as a sentence | manifest_misreads :2344, misread_placeholders :2367 |
family_manifest_misreads :1184 |
the file named, and "project's" or "holder's" reader; misread_placeholders has no counterpart |
| turn the validator's findings into one sentence for each value | FINDING_PLACEHOLDER :2380, _FINDING_RE :2387, _code_of :2391, _sentences_of :2398, manifest_invalid :2428 |
FINDING_PLACEHOLDER :1061, _FINDING_RE :1068, _sentences_of :1205, family_manifest_invalid :1229 |
the placeholder table and the validator named in the sentence; manifest_invalid takes ignore and not_text (adopt uses them), asks validator._findings(manifest, policy, None) and drops its WARNINGs; the family's asks Report() and _check_envelope(manifest, policy, report), catches SystemExit, and refuses a Report with no findings or a finding that is not text |
| the two remediation texts, and the order the two questions are asked in | MANIFEST_MISREAD_REMEDIATION :2487, MANIFEST_INVALID_REMEDIATION :2499, manifest_value_problems :2505, refuse_manifest_values :2528 |
MANIFEST_MISREAD_REMEDIATION :1281, MANIFEST_INVALID_REMEDIATION :1291, refuse_unholdable_manifest :1314, _manifest_flags :1299 |
the words about the file; refuse_manifest_values takes the tool's own prefix; the family names a value no flag supplied by where it came from |
The three tools each also hold a table that names a placeholder by the flag a person typed: MANIFEST_FLAGS at scaffold-project.py :104 and adopt-project.py :1814 (3ef059c), and at scripts/family.py :1052 (abb27e6).
What unifying them would mean. One definition of each helper above, called by scaffold-project.py, adopt-project.py and family.py, with what differs (the last column) supplied by each caller or kept by the tool that owns it. This issue proposes no design beyond that.
What it must not change.
- Any refusal code or word the tools print today. The codes are
scaffold-manifest-misread,scaffold-manifest-invalid,adopt-manifest-misread,adopt-manifest-invalid, theplan-manifest-invalidFINDING,manifest-validator-unusable,family-manifest-misread,family-manifest-invalidandfamily-validator-unusable.tests/test_scaffold_manifest_values.pyandtests/test_adopt_manifest_values.py(3ef059c) andtests/test_family_init_values.py(abb27e6) assert them. - When the questions are asked. Before a work directory, a remote or a repository exists, and under
--dry-runalike. A misread is said first and alone, and the validator's finding about it is not said after it. - How the validator is asked. It is LOADED from its template and never re-implemented, no bytecode is written into the template tree,
sys.pathandsys.dont_write_bytecodeare put back, and a validator that cannot be asked is a refusal, not a traceback and not a pass. The family's extra checks (SystemExit, aReportwith nofindings, a finding that is not text) have no counterpart inmanifest_invalid, which catchesExceptiononly. Whether the assembly root takes them is a change of behaviour to decide, and not a consequence of unifying. - Where the helpers live. scaffold-project.py and adopt-project.py ask the project's YAML reader and validate-manifest.py about the manifest's values before anything exists, so
--id null,--tracking-branch trueand a blank--elected-byare refused (#258, #261) #314 put its helpers inscripts/shape_materialize.py, and not inscripts/repo_shape.pyor a validator, because those are shape copies digested in every project'scontracts/shape-pin.yaml: a change to either puts anupstream-changedrow in front of every project (the comment atscripts/shape_materialize.py:2183-2188, 3ef059c). No copied file and no template changes with this. - That the questions stay template-relative. Each asks the TEMPLATE, line by line, and never a list of which lines are written bare, so once a placeholder is quoted (templates/assembly-root/project.yaml and the two leg pins write eight text placeholders bare (
id,elected_on,visibility,tracking_branch, the two legpaths andsubmodule_paths), so a checked value YAML reads as another type (007,2026,true,null) is misread by the project or refused by the tool; quoting them reads every one back exactly and lets numeric branch names adopt #259) the misread question refuses nothing with no edit. scaffold-project.py and adopt-project.py ask the project's YAML reader and validate-manifest.py about the manifest's values before anything exists, so--id null,--tracking-branch trueand a blank--elected-byare refused (#258, #261) #314 holds that withtest_quoting_the_template_would_make_the_refusal_go_awayintests/test_scaffold_manifest_values.py, and family.py:initasks the holder's reader and validate-family.py about family.yaml before creating anything,--dry-runtoo, so--id null,--tracking-branch true, a blank--created-byand--created-on 20261011are refused (#307) #397 withtest_a_quoted_value_is_held_as_typedand the quoted-template tests after it intests/test_family_init_values.py, which run over a copy of the template whose placeholder is forced quoted.
The comment at scripts/family.py :1028-1033 (abb27e6) that says the second to land unifies them is stale now that #314 landed first, and goes with the unification.
Activity
brettheap commentedon Oct 12, 2026
Lane: openreposhape-5 (openRepoShape-5)
(lane openRepoShape-5, 2026-10-12T21:28Z) Moved to #459's checklist (#459 (comment)). Brett Heap ruled on 2026-10-12 that a new finding from review goes on its area's checklist rather than into a new issue. This lane filed this one before reading that ruling. The table above stays as the checklist item's detail.