Repository navigation
adopt-project.py: _verify fails a split whose root project.yaml is not the shape's manifest (adopt-manifest-not-shape), so a plan that gets past check's plan-root-blocks-manifest no longer ends adoption verified over an assembly the doctor calls NOT A SHAPE ROOT (#389) - #722
Merged
Merged
Conversation
…s not the shape's manifest (`adopt-manifest-not-shape`), so a plan that gets past `check`'s `plan-root-blocks-manifest` no longer ends `adoption verified` over an assembly the doctor calls NOT A SHAPE ROOT (#389) `_verify` never asked whether the split's root `project.yaml` is the shape's manifest. `check` finds, and `execute` refuses before any leg exists, a plan that keeps the source's own `project.yaml` in the root (#305), and that refusal was all there was: with it taken away, `execute` wrote the manifest beside the source's file as `shape/project.yaml`, every source blob was in exactly one place, and the run said `adoption verified` (exit 0) over a root the doctor calls NOT A SHAPE ROOT (exit 2). The same held for a kept symlink there that leads nowhere (the manifest written through it), a kept directory `project.yaml/`, and a leg mounted at `project.yaml` (#172). `_accounted_for` now adds `_split_manifest_findings`: a finding when the root's `project.yaml` is the source's own entry (by path and blob, whatever its mode), or when `shape/project.yaml` holds a blob the source did not have at that path. A source's own `shape/project.yaml`, kept where the root's `project.yaml` is the manifest, still verifies, and so do the shape's other copies beside a kept file. Nothing leans on the pin, which does not list the rendered manifest. `plan-root-blocks-manifest` said `execute` "would ... say `adoption verified`"; it now says the run would fail its verification (`adopt-manifest-not-shape`), which is what the run does without the refusal. Tests: tests/test_adopt_verify.py (the `verify` fixture: the manifest beside, the source's own file with and without it, two controls; one `execute` with `_refuse_what_check_finds` taken away, sharing two helpers with #165's test), and tests/test_adopt_root_manifest.py's two text pins. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s own at the root, so a source file that is byte for byte the manifest this run renders, answered `drop`, no longer fails `adopt-manifest-not-shape` after both legs are pushed (#389) #389's review (R1): `_split_manifest_findings` matched the source's own `project.yaml` at the root by blob alone. A source whose own `project.yaml` held exactly the manifest `execute` renders for this project, answered `drop`, passes `check` and verified on main; with the check it failed after both legs and the split were pushed, calling the shape's manifest the source's own file. `_mount_the_legs` `git rm`s every path in `paths_for["drop"]` before the shape writes anything, so a dropped `project.yaml` is gone from the root and what is at that path is the shape's. `_split_manifest_findings` now takes that list and does not count the root's `project.yaml` as the source's own when the plan dropped it. It asks what the split did, not what `check` refused. The manifest beside the root's `project.yaml` is still a finding. Test: `test_a_dropped_project_yaml_is_never_the_sources_own` in tests/test_adopt_verify.py, two cases (the manifest at the root verifies; the manifest beside it is still the finding). Both fail with adopt-project.py as at 3397926. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideStrengthens adoption verification so any split whose root Sequence diagram for failed adoption verificationsequenceDiagram
participant Execute as execute
participant Account as _accounted_for
participant Verify as _verify
participant Doctor as shape-doctor.py
Execute->>Account: _accounted_for(split_tree, before, ...)
Account->>Account: _split_manifest_findings(tree, before, drops)
Account-->>Verify: adopt-manifest-not-shape finding
Verify->>Doctor: Root manifest would be project.yaml
Verify-->>Execute: exit 1 with MANIFEST_DEFECT
Note over Execute,Doctor: adoption verified is not printed
Flow diagram for split manifest verificationflowchart TD
A["_accounted_for"] --> B["_shape_file_findings"]
B --> C["_split_manifest_findings"]
C --> D{"Root project.yaml is source entry or shape/project.yaml is new?"}
D -->|"No"| E["Continue verification"]
D -->|"Yes"| F["FINDING adopt-manifest-not-shape"]
F --> G["MANIFEST_DEFECT"]
G --> H["_verify exits 1; no adoption verified"]
Flow diagram for valid and invalid manifest casesflowchart LR
A["Split root project.yaml"] --> B{"Source entry kept at root?"}
B -->|"Yes"| C["adopt-manifest-not-shape"]
B -->|"No"| D{"New shape/project.yaml manifest?"}
D -->|"Yes"| C
D -->|"No"| E["No manifest finding"]
C --> F["Verification fails"]
E --> G["Continue; valid shape-file merge"]
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
brettheap
marked this pull request as ready for review
October 16, 2026 17:32
|
Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 3 hours and 3 minutes by commenting |
|
brettheap
pushed a commit
that referenced
this pull request
Oct 17, 2026
main gained 25 pull requests since de92614: #634, #699, #671, #719, #701, #717, #700, #702, #722, #720, #725, #721, #728, #705, #727, #718, #744, #743, #749, #740, #737, #734, #742, #751 and #736. No conflict: AGENTS.md, adopt-project.py and docs/cli.md merged as text, and README.md and docs/handbook.html are unchanged by the merge. README.md is 1473 lines, its cap; AGENTS.md 494, its cap; every handbook marker is current; `render-cli-reference.py --check` is ok. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
pushed a commit
that referenced
this pull request
Oct 17, 2026
…es every reason THIS checkout cannot answer, and the notes are current to main bf1f099 with the 25 pull requests since de92614 (#563, #683) - W683 and RV-f's N4 on #742: README's exit-3 list (Keeping a project's shape current, :1208-1220) and its handbook twin (`doctor`) named only a pin whose commit this checkout does not carry. They now say, as shape-doctor.py's EXIT CODES does: a pin's commit it lacks, a partial clone missing what is compared (#683), a read that fails (`update-upstream-unreadable`), a crashed validator of its own (#278, #410), or its own naming policy not loading (#678). +1 line, with tests/readme-cap.d/683.txt; README.md is 1474, its cap (1422 + 2 + 5 + 12 + 22 + 10 + 1). The two `Keeping a project's shape current` markers move: `doctor` text and marker, `current` marker only. - The notes, "What changed since v1.0.1", one entry per pull request from `git log --first-parent de92614..bf1f099`, each from its squash commit and the issues GitHub says it closes: - adopt-project.py: #699, #719, #749, #727, #717, #728 (with #621's hint), #743 + #720 + #718, #722, #721; - update-shape.py, bump-leg.py and a project's own scripts: #702 (with the pinned validators), #634; - scaffold, setup, family and the shared readers: #725, #671, #744; - shape-doctor.py: #742, #701, #737, #751, #736, #734, #700 + #705, #740; - install, CI and the docs: the exit-3 sentence above. - Counts (99 pull requests since bfed143; 109 of 135 milestone issues closed at 10:28Z), the "current to main" sha and the open list (26) are at main bf1f099, still placeholders for tag time. Left for round B: lane 5's eight lines (#630 issuecomment-6227129879), whose pull requests #726, #747, #682, #724, #746, #745 and #738 are open drafts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Lane: openreposhape-1 (openRepoShape-1)
Claim: #389 (comment)
What
_verifynow fails a split whose rootproject.yamlis not the shape's manifest. It reports a finding of its own,adopt-manifest-not-shape, and exits 1 like its other findings, soadoption verifiedis never printed over such a split. This is #389, the second bullet of #305's "What would fix it", which the fix for #305 left out on purpose.It is defence in depth. Through
executeas shipped, no plan reaches_verifywith such a split:checkfinds, andexecuterefuses before any leg exists, every plan known to make one (plan-root-blocks-manifest, andplan-leg-path-collidesfor a leg mounted atproject.yaml). Until now that refusal was all there was._verify's own rule, since #165, is that it does not lean oncheck's refusals.Why (repro on main)
Measured on main
da48256c, through a shared clone of it, with a local source and--local-remote-dir, a stubghfirst on PATH, a bogusGH_TOKEN, an emptyGH_CONFIG_DIR,GIT_CONFIG_GLOBAL=/dev/nullandGIT_ALLOW_PROTOCOL=file. The source heldsrc/app.py,docs/spec.mdandREADME.md, plus what the first column says.executeran in process with_refuse_what_check_findstaken away, astests/test_adopt_verify.pytakes it for #165.checkexecuteon mainexecuteon this branchproject.yaml(name: theirs), answeredroot(#305)plan-root-blocks-manifestadoption verifiedproject.yamlis the source's blob; the manifest is atshape/project.yamladopt-manifest-not-shapeproject.yaml -> missing.yaml, answeredrootplan-root-blocks-manifestadoption verifiedproject.yamlis the source's link; the manifest was written through it, tomissing.yamladopt-manifest-not-shapeproject.yaml/a.md,project.yaml/answeredrootplan-root-blocks-manifestadoption verifiedproject.yaml/a.md; the manifest is atshape/project.yamladopt-manifest-not-shapeproject.yaml; the plan'slegs.code_pathedited toproject.yaml(#172)plan-leg-path-collidesadoption verifiedproject.yaml; the manifest is atshape/project.yamladopt-manifest-not-shapeIn every row both legs were made and pushed, and so was the split branch. With the refusal in place, as shipped, the first row is
REFUSED plan-root-blocks-manifestbefore any leg exists, on main and on this branch.shape-doctor.pyon a recursive clone of the first row's split on main saysNOT A SHAPE ROOT (exit 2), and that clone's rootproject.yamlbeginsname: theirs.How
_split_manifest_findings(tree, before, drops), called by_accounted_forafter_shape_file_findings. It reads the split commit's tree, which_accounted_foralready lists, and the source's tree. It finds a split in either of two ways:project.yamlis the source's own entry, matched by path and blob, whatever its mode. A kept symlink that leads nowhere has the manifest written through it, and the root keeps the link, so a file mode alone would miss it;shape/project.yamlholds a blob the source did not have at that path. The materializer writes the manifest there only when the root already holdsproject.yaml.project.yamlthe plan drops is never the source's own at the root (adopt-project.py_verifynever asks whether the split's rootproject.yamlis the shape's manifest, so the one refusal #305 added before any leg exists is all that keeps the source's own file out of the root, and a plan that gets past it endsadoption verifiedover an assembly shape-doctor.py calls NOT A SHAPE ROOT, where #165's gitlink checks in the same function fail closed #389's review, R1):_mount_the_legshasgit rmed every dropped path before the shape writes, so a source file that is byte for byte the manifest this run renders, answereddrop, whichcheckpasses and main verified, still verifies; the manifest beside it would still be a finding.contracts/shape-pin.yamldoes not list the rendered manifest, and the tests' stand-in pin does.shape/project.yaml, kept where the root'sproject.yamlis the manifest, whichtests/test_adopt_root_manifest.pyalready treats as legal;shape/README.md,shape/Makefile, and so on), which are the designed follow-up merge.project.yaml, with the manifest beside it (adopt-project.pycheckpasses a plan that keeps the source's ownproject.yamlin the root, andexecutewrites the shape's manifest beside it asshape/project.yamland saysadoption verified, so shape-doctor.py calls the adopted assembly NOT A SHAPE ROOT and its firstmake bootstrapfails #305's split);project.yaml, with no copy beside it (the symlink that leads nowhere);shape/project.yamlwith no source entry atproject.yaml(a kept directory, a leg mounted there).MANIFEST_DEFECT, besideROOT_SUBMODULE_DEFECT. Every plan known to reach this is refused before any leg exists, so the split itself is wrong: "do not merge it, and report it"._verify's footer and its exit 1 are unchanged.plan-root-blocks-manifest's sentence. It saidexecute"would write the shape's manifest beside it asshape/project.yamland sayadoption verified". With this check, that run fails its verification instead, so the sentence now says "and fail its verification (adopt-manifest-not-shape)". The symlink form ("either way it would ...") changes the same way. The rest of the finding is byte for byte what it was._verify's docstring is unchanged: nothing it says becomes untrue.Tests
New, in
tests/test_adopt_verify.py: 8 cases. Seven call_verifydirectly through the file'sverifyfixture, which gainssource_files=besideroot_files=. They need nogit filter-repo.test_the_manifest_beside_the_roots_project_yaml_is_a_findingis the issue's (a):root_files={"shape/project.yaml": ...}. It expects exit 1, exactly the new finding, and noadoption verified.test_the_sources_own_project_yaml_in_the_root_is_a_findinghas 2 cases: the source's ownproject.yamlin the root, with the manifest beside it (adopt-project.pycheckpasses a plan that keeps the source's ownproject.yamlin the root, andexecutewrites the shape's manifest beside it asshape/project.yamland saysadoption verified, so shape-doctor.py calls the adopted assembly NOT A SHAPE ROOT and its firstmake bootstrapfails #305's split) and without (the split a kept symlink that leads nowhere makes). Each is countedroot(2 of 4 source paths) and still refused, with one finding.test_what_else_the_root_holds_under_shape_still_verifieshas 2 controls. One is the issue's (c):shape/README.mdbeside a keptREADME.md. The other is the source's ownshape/project.yamlkept, where the root'sproject.yamlis the manifest. Both verify with nothing on stderr.test_a_dropped_project_yaml_is_never_the_sources_own(R1's test, added at6f308bc7) has 2 cases. A sourceproject.yamlthat is byte for byte the root's manifest, answereddrop, verifies with nothing on stderr. With the manifest also beside it, it is still the finding, in its beside wording. End to end at6f308bc7, with r389's probe, a source whose ownproject.yamlis the manifest an ordinary run of this head renders (the same blob), answereddrop, passescheckand endsadoption verified.test_execute_fails_a_source_manifest_the_plan_checks_let_into_the_rootis the issue's (b), shaped like adopt-project.py_verifyskips every root gitlink and compares a kept root.gitmodulesbyte for byte, so any plan that keeps a source submodule or its.gitmodulesin the root ends with exit 1 andadopt-lost#165's test. The source is conftest'sSYNTHETIC_TREEplus aproject.yamlof its own, answeredroot.checkexits 1 withplan-root-blocks-manifest._refuse_what_check_findsmonkeypatched to a no-op,executeprintsbeside shape/project.yamlandbeside shape/README.md, exits 1 with exactly the new finding, and prints noadoption verified.git filter-repo, and is skipped without it, as everyexecutetest is._verifyskips every root gitlink and compares a kept root.gitmodulesbyte for byte, so any plan that keeps a source submodule or its.gitmodulesin the root ends with exit 1 andadopt-lost#165'sexecutetest now shares two helpers with it,checked_planandexecute_past_check, so the two do not duplicate each other. Its assertions are unchanged. The module docstring and theneeds_filter_repocomment now count threeexecutetests.Changed, in
tests/test_adopt_root_manifest.py.test_a_kept_project_yaml_is_a_findingpins the new wording ofplan-root-blocks-manifest, andtest_a_kept_symlink_there_is_a_finding_whatever_it_leads_tonow pins the symlink form's new tail. Itsexecutetests at:307,:330and:350are unchanged and pass. The last of them is the control end to end:project.yamlsent tocodeor dropped still endsadoption verified.Red on main. Against
da48256c'sadopt-project.py, 4 new cases fail: the 3 finding cases with exit 0, and theexecutetest with exit 0 andadoption verified. The 2 controls and #165's test pass there. Of R1's 2 cases,the-manifest-at-the-rootpasses on main andthe-manifest-beside-itfails there (main finds nothing beside it); both fail withadopt-project.pyas at3397926e, this branch's first commit.Revert table. Each row changes
adopt-project.pyalone, in place, over both test files, and after each row the fixed file was restored and its sha256 checked. Rows C1 to C6 ran at3397926e(49 cases, sha256854f2a35…); rows D1 and D2 ran at6f308bc7(51 cases, sha256ce6ed2c4…).3397926e, 0 of 51 at6f308bc7_accounted_forno longer calls_split_manifest_findingsexecutetestkept = False)executetestbeside = False)executetestshape/project.yamlcounted by its path alone, not as a blob the source did not have therethe-sources-own-shape-project-yamlplan-root-blocks-manifest's text back to "and sayadoption verified"test_a_kept_project_yaml_is_a_finding,test_a_kept_symlink_there_is_a_finding_whatever_it_leads_toshape/that the source did not have countsthe-copy-of-a-kept-readme, the two existingexecutetests intest_adopt_verify.py, andtest_an_answer_the_question_offers_adopts_with_the_shapes_manifest[code]and[drop]and not droppedremoved)test_a_dropped_project_yaml_is_never_the_sources_ownproject.yamlwaives the whole checkthe-manifest-beside-itcaseRuns. Every run used
/usr/bin/python3 -m pytest, a stubgh(exit 1) first on PATH, a bogusGH_TOKENand an emptyGH_CONFIG_DIR. Each log names its head with dirty 0 at the start and at the end, and endsEXIT=0.grep -l -E 'adopt-project|adopt_project|\bADOPT\b' tests/*.py(86 files atda48256c,tests/conftest.pyamong them), plustests/test_shape_doctor.pyandtests/test_scaffold_leg_path_collisions.py, which the grep already lists. That is 85 test files and 6,386 tests, run in four shards per mode.PATH=/usr/local/bin:/usr/bin:/bin, with the stub's directory first.6f308bc7(R1's fix) the four files the change touches or the adopt rules name were run in both modes:test_adopt_verify.py,test_adopt_root_manifest.py,test_shape_doctor.pyandtest_scaffold_leg_path_collisions.py.GIT_ALLOW_PROTOCOLwas not set in any run.3397926e, the first commit.6f308bc7changes only_split_manifest_findings(a third argument, and thedropwaiver) and adds one test totest_adopt_verify.py.6f308bc7(this branch now)git filter-repoon PATH6f308bc7a8164b60,6f308bc7with main78fe3fff(treed61f8602, a scratch commit, never pushed)test_adopt_verify.py,test_adopt_root_manifest.pygit filter-repoon PATH3397926e(the first commit)git filter-repoon PATH3397926e3397926etests/test_cli_reference.pygit filter-repoon PATH5057810f, this branch merged into mainabb956e6(tree6a6ed973, never pushed)test_adopt_verify.py,test_adopt_root_manifest.pygit filter-repoon PATH5057810ftest_adopt_verify,root_manifest,e2e,leg_path_collisions,root_shape_paths,ignored_shape_files,late_failure,finding_spelling,root_symlinks,test_shape_doctor,test_scaffold_leg_path_collisionsgit filter-repoon PATHgit merge-tree --write-tree 3397926e abb956e6is clean (tree6a6ed973). Main has since moved to879d8047(#620, which changesadopt-project.py'sadopt-bad-id).git merge-tree --write-tree 3397926e 879d8047is clean too (treeab18664e), and the reviewer's targeted runs on that merge passed in both modes: the four filestest_adopt_verify,test_adopt_root_manifest,test_shape_doctorandtest_scaffold_leg_path_collisions, 558 passed and 3 skipped withgit filter-repoon PATH, 548 passed and 13 skipped hidden; and 12 neighbouring files, 939 passed and 1 skipped on PATH, 813 passed and 127 skipped hidden.At this branch's head
6f308bc7, main is78fe3fff, which changesadopt-project.pyagain since879d8047.git merge-tree --write-tree 6f308bc7 78fe3fffis clean (treed61f8602), and the two changed test files pass on that tree (a8164b60, a scratch commit, never pushed): 51 passed withgit filter-repoon PATH. Main moved tode926142while those runs ended (14:18Z);git merge-tree --write-tree 6f308bc7 de926142is clean too (tree22de4a24). The reviewer ran the four files above on that tree (08417354, a local commit, never pushed): 560 passed and 3 skipped withgit filter-repoon PATH, and 550 passed and 13 skipped with it hidden, none failed.Windows
CI is Linux only since #597.
_verifycases need nogit filter-repo. Their fixture writes every file withwrite_bytes, and nothing reads back a file a helper wrote withwrite_text.executetest writes its source through conftest'smake_source_repo. It names the source's blob bygit rev-parse, and compares only lines of the captured output.shape/project.yaml,shape/README.md,project.yaml) is legal on NTFS.Not in this PR
checkandexecute, andplanno longer offeringrootforproject.yaml: the fix for adopt-project.pycheckpasses a plan that keeps the source's ownproject.yamlin the root, andexecutewrites the shape's manifest beside it asshape/project.yamland saysadoption verified, so shape-doctor.py calls the adopted assembly NOT A SHAPE ROOT and its firstmake bootstrapfails #305.scripts/repo_shape.py, the naming policy,scripts/bootstrap.py,contracts/shape-pin.yaml): adopt-project.pycheckpasses a plan that keeps the source's ownproject.yamlin the root, andexecutewrites the shape's manifest beside it asshape/project.yamland saysadoption verified, so shape-doctor.py calls the adopted assembly NOT A SHAPE ROOT and its firstmake bootstrapfails #305's own follow-up, as adopt-project.py_verifynever asks whether the split's rootproject.yamlis the shape's manifest, so the one refusal #305 added before any leg exists is all that keeps the source's own file out of the root, and a plan that gets past it endsadoption verifiedover an assembly shape-doctor.py calls NOT A SHAPE ROOT, where #165's gitlink checks in the same function fail closed #389 says.checkpasses a plan that keeps the source's ownproject.yamlin the root, andexecutewrites the shape's manifest beside it asshape/project.yamland saysadoption verified, so shape-doctor.py calls the adopted assembly NOT A SHAPE ROOT and its firstmake bootstrapfails #305's optional fourth bullet: the split's FOLLOW-UPS naming every collisionexecuteactually made.Project.yaml(the case twin): see Known limits.materialize_assembly_rootdoes with a collision.docs/release-notes/v1.0.0.mdstill lists adopt-project.py_verifynever asks whether the split's rootproject.yamlis the shape's manifest, so the one refusal #305 added before any leg exists is all that keeps the source's own file out of the root, and a plan that gets past it endsadoption verifiedover an assembly shape-doctor.py calls NOT A SHAPE ROOT, where #165's gitlink checks in the same function fail closed #389 as a v1.0.0 known limit, which stays true of v1.0.0. The v1.1.0 notes are README, AGENTS.md, docs/cli.md and the handbook:pipx install openreposhapeis the second way in and the first on native Windows, git-filter-repo is installed in install.sh's order and never with a barepip install, and a first draft of the v1.1.0 release notes (#563) #630's.Known limits
Project.yamlansweredroot, with the refusal taken away, endsadoption verifiedon Linux.placewrites the manifest atproject.yamlbeside the twin, so the root'sproject.yamlIS the manifest there. By reading the code, not measured (no such disk here): on a macOS or Windows diskplacefinds the twin atproject.yamland writes the manifest toshape/project.yaml, and this check then fails that split.plan-root-blocks-manifestrefuses the twin on every disk, and its sentence ("atproject.yamlonce case is ignored, as a macOS or Windows disk does") describes such a disk. adopt-project.py_verifynever asks whether the split's rootproject.yamlis the shape's manifest, so the one refusal #305 added before any leg exists is all that keeps the source's own file out of the root, and a plan that gets past it endsadoption verifiedover an assembly shape-doctor.py calls NOT A SHAPE ROOT, where #165's gitlink checks in the same function fail closed #389 lists the twin as not in this issue.Closes #389
🤖 Generated with Claude Code
Summary by Sourcery
Fail adoption verification when the assembly root does not contain the shape's manifest.
Bug Fixes:
project.yamlis not the shape manifest, preventing falseadoption verifiedresults for invalid shape roots.Enhancements:
adopt-manifest-not-shapecode.Tests: