From edc9fc719a75c3d1f417ae2eee040e704098572b Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Tue, 20 Oct 2026 16:06:19 +0000 Subject: [PATCH 1/3] scripts/shape_materialize.py and family.py: a `family.yaml` or `project.yaml` the template's own reader makes something other than a mapping is `-manifest-invalid` still, but its remedy says it is a defect in the copy of the standard and names `templates/family-root/family.yaml` or `templates/assembly-root/project.yaml`, and no longer says to choose a value the validator accepts; `manifest_invalid`'s docstring says a line `passed_over` names is a note, not a WARNING for the holder too (#1059) Two notes from the reviews of #1057 (#925), both words only. No refusal code changes. 1. `manifest_invalid`'s docstring said a WARNING of the validator "is a note and never a refusal, exactly as the project's own exit code treats it", which is false for the holder since #1057 (`HOLDER_MANIFEST.passed_over` is empty). It now says a line `manifest_kind.passed_over` names is a note and never a refusal, as that validator's own exit code treats it (the project's WARNING and ` note`, #990), and that the holder passes over none (#925). Its other project-only words are neutral. 2. The not-a-mapping sentence went out as `invalid`, with "choose a value the ... validate-manifest.py accepts; the words after each value are the validator's own". No value reaches that case (RV1057 tried 51), and the words are the reader's. It is a kind of its own now, `KIND_NOT_A_MAPPING`, with a remedy in each manifest's table: the defect-of-the-standard one main's project had before #1057, aimed at the right file. One builder, `manifest_not_a_mapping_remediation`, says it for both manifests, so the holder's and the project's cannot drift. Lane openRepoShape-5 agreed on #473 (issuecomment-6295099581). The refusal codes are kept. `test_a_manifest_that_is_not_a_mapping_keeps_its_kind_and_remedy` (#960's round 1) holds the new remedy, so #960's mutant M2 (the kind moved to `unreadable`) and a swap back to the invalid-value remedy both fail it. The scaffold's row for `project.yaml` holds the same, and two new tests hold the kind, `manifest_judged`'s None and each manifest's own file. Closes #1059 Lane: openreposhape-3 (openRepoShape-3) Co-Authored-By: Claude Sonnet 5.5 --- scripts/family.py | 16 +++- scripts/shape_materialize.py | 103 ++++++++++++++++++------- tests/test_family_init_yaml_words.py | 65 ++++++++++++++-- tests/test_scaffold_manifest_values.py | 41 ++++++++-- 4 files changed, 182 insertions(+), 43 deletions(-) diff --git a/scripts/family.py b/scripts/family.py index 82270793..b6d75c30 100755 --- a/scripts/family.py +++ b/scripts/family.py @@ -197,9 +197,10 @@ # `project.yaml`, asked of `family.yaml` (#925), and the first sentence of # the remedy where the holder's reader refuses it (#929). from shape_materialize import ( # noqa: E402 - FAMILY_TEMPLATED, KIND_INVALID, KIND_MISREAD, KIND_UNREADABLE, - UNREADABLE_CHOICE, TemplateManifest, manifest_invalid, manifest_misreads, - manifest_validator, manifest_value_problems, refuse_manifest_problems, + FAMILY_TEMPLATED, KIND_INVALID, KIND_MISREAD, KIND_NOT_A_MAPPING, + KIND_UNREADABLE, UNREADABLE_CHOICE, TemplateManifest, manifest_invalid, + manifest_misreads, manifest_not_a_mapping_remediation, manifest_validator, + manifest_value_problems, refuse_manifest_problems, ) # How every command this prints for a person to paste spells its paths # (#486), the quoting the holder's `scripts/siblings.py` uses too. @@ -3554,10 +3555,17 @@ def _print_next_steps(args, work: Path, folder: Path | None) -> None: "red from its first commit, because `make validate` and the `validate` " "workflow run that validator first, and `init` cannot be run again over " "a pushed holder: there is no --force.") +#: Where the holder's own reader reads the template's `family.yaml` as +#: something other than a mapping (#1059), no value `init` is handed did it, +#: so the remedy is the defect of the standard, aimed at that file, and it +#: is the project's sentence (`shape_materialize`), said of the holder's. +MANIFEST_NOT_A_MAPPING_REMEDIATION = manifest_not_a_mapping_remediation( + "family-root", MANIFEST, "the holder's own YAML reader") #: The remedy for each kind of problem the questions name. KIND_REMEDIATIONS = {KIND_MISREAD: MANIFEST_MISREAD_REMEDIATION, KIND_INVALID: MANIFEST_INVALID_REMEDIATION, - KIND_UNREADABLE: MANIFEST_UNREADABLE_REMEDIATION} + KIND_UNREADABLE: MANIFEST_UNREADABLE_REMEDIATION, + KIND_NOT_A_MAPPING: MANIFEST_NOT_A_MAPPING_REMEDIATION} def _holder_findings(validator, manifest: dict, policy: NamingPolicy): diff --git a/scripts/shape_materialize.py b/scripts/shape_materialize.py index d7f897cb..d77b3f22 100644 --- a/scripts/shape_materialize.py +++ b/scripts/shape_materialize.py @@ -5038,11 +5038,13 @@ def _placeholders_of(line: str) -> list[str]: #: The kinds of problem `manifest_value_problems` names, each spelled once #: (#708): a value the project's reader reads back as something else, one -#: its validator refuses, and a manifest the reader refuses before the -#: validator can be asked, which `refuse_manifest_values` refuses under the +#: its validator refuses, a manifest the reader refuses before the validator +#: can be asked, and a manifest the reader reads as something other than a +#: mapping (#1059), which no value a person types can make (only a broken +#: template does). `refuse_manifest_values` refuses the last three under the #: code `invalid` still. -KIND_MISREAD, KIND_INVALID, KIND_UNREADABLE = ( - "misread", "invalid", "unreadable") +KIND_MISREAD, KIND_INVALID, KIND_UNREADABLE, KIND_NOT_A_MAPPING = ( + "misread", "invalid", "unreadable", "not-a-mapping") #: The remediation, without the sentence only the caller can write (what was #: or was not created, whether `--dry-run` refuses the same). @@ -5087,11 +5089,38 @@ def _placeholders_of(line: str) -> list[str]: "which refuses the manifest this run would write before its " "validate-manifest.py can be asked, and a project whose manifest it " "refuses is one whose first bootstrap would fail.") + + +def manifest_not_a_mapping_remediation(template: str, manifest: str, + reader: str) -> str: + """The remedy where the template's own manifest is not a mapping to its + reader (#1059), for the manifest `manifest` in `templates/