Implements #160 (epic #157).
Added
planShellSwitch (TypeScript) / ShellSwitchPlanner.Plan (C#): the pre-flight of switching the application's shell. Default mapping by outlet name, the current primary outlet and content following to the new shell's primary outlet; every outlet of the current shell (and any a screen uses that it lacks) gets a move (keep, primary, unused, unresolved, and the user's moveToPrimary / mapTo / drop passed back as remaps). An outlet that needs a decision is a blocker with profileSlotUnplaced and a message naming the screens and outlets; the candidate's own problems (rootTemplateUnknown, rootTemplateVersionNotSatisfied, rootTemplateNotApplicable, rootTemplateMissingContentSlot, rootTemplateCycle) block too; the blueprint to add and warnings are listed.
findProfileBlockers (TypeScript) / ProfileBlockers.Find (C#): the rules Studio kept in findProfileBlockers (missing packages, version conflicts, dependency cycles, unusable shell, incompatible theme, unavailable default screen template, layouts, screen templates, dialog templates and slots the screens still use), moved into the engine with messages that name what they are about. Studio keeps only the presentation (REN2).
describeUiProfile / UiProfileNodeKind: component descriptors, in the existing format, for the nodes of a UI profile (Application, Shell with root.options.*, Theme with colour scheme and accent, Packages, Sample data), with the choices the application supplies; a theme the packages do not support stays on offer with the reason.
placeableScreenTemplates / ShellPlacement (shared by the resolver and the planner), Engine-owned codes ShellOutletAction and ProfileBlockerCode.
- Shared corpora
shell-switch-fixtures.json (27 cases) and profile-blockers-fixtures.json (20 cases), each asserted byte-for-byte by C# (for_ShellSwitchPlanner, for_ProfileBlockers) and TypeScript (for_planShellSwitch, for_findProfileBlockers), including a regression vector that no message carries an id or an unsubstituted placeholder (the {subject} defect).
- Tests:
for_describeUiProfile (18).
- Docs: "Switching the shell", "What stops a profile from being applied" and "Describing the profile for a designer" in
blueprints/root-template.md.