Skip to content

Commit 0a8aac3

Browse files
spec047: §14 Phase 3 completion — update spec + tracker for Phase 3 completion
Document Phase 3 completion in both the spec (§14) and the implementation tracker. With the engine extension (IDecoratorElementHandler) + PreMountedItems strategy + descriptor batches + production registration sweep landed: - Engine gap closed (TemplatedFlipView via PreMountedItems) - Every Phase 3 batch descriptor authored AND registered: - Untyped items hosts: GridView, ItemsView, ItemContainer - Heavy/specialized: WebView2, NavigationView, TitleBar, MediaPlayerElement, AnimatedVisualPlayer, MapControl, SemanticZoom, AnnotatedScrollBar, RefreshContainer, SwipeControl, ParallaxView - Polymorphic/a11y: IconElement (via new IDecoratorElementHandler), SemanticElement, AnnounceRegion Intentional carve list (documented inline in RegisterV1BuiltInHandlers and re-enumerated in both docs for the follow-up reviewer): - Dialog/overlay family (ContentDialog, Flyout, Popup, MenuBar, MenuFlyout, CommandBar, CommandBarFlyout) — modal lifecycle needs decorator-style ports beyond the IDecoratorElementHandler shape - NavigationHost — UnmountRecursive intercepts before V1 arm - TabViewDescriptor — bisect-ratified gaps need engine work (post-children mount-hook for safe SelectionChanged wiring + ImperativeBridged for tab strip slots) - XamlHost/XamlPage — XamlInterop.Register clashes with V1 auto-reg - Composition primitives (Component, Func, Memo, ErrorBoundary, CommandHost, Validation.*) — sit ABOVE V1 protocol; Phase 4 keeps their legacy arms A|B parity bar met: 9134 xunit + 4410 selftest (V1 ON ≡ V1 OFF), 0 failures both flags across 3 consecutive full V1 ON runs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 16636c0 commit 0a8aac3

2 files changed

Lines changed: 72 additions & 29 deletions

File tree

docs/specs/047-extensible-control-model.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ ARM64 stable-AC re-capture on `LAPTOP-4MEP83VI` remains deferred for the §14 ra
14331433

14341434
**Phase 3 finish carry-forwards:** none remaining for the typed-items host families that were on Phase 3's scope (LazyVStack/HStack, ItemsRepeater<T>, ListView<T>, GridView<T>, TreeView, FlipView (simple), TabView, Pivot). The engine surface is complete. Production swap (Phase 4 cleanup) registers each descriptor in `RegisterV1BuiltInHandlers` and deletes the matching legacy `MountXxx` switch arm.
14351435

1436-
**Phase 3 deferred / not-attempted** (recorded for the Phase 3.5 / Phase 4 prelude — element types in the legacy `Reconciler.Mount` switch that have neither a Phase 1 V1 handler nor a Phase 3 descriptor; see `tasks/047-extensible-control-model-implementation.md` for the full enumeration). One genuine carve from close-out remains: `TemplatedFlipViewElement<T>` (the typed FlipView peer — needs a `PreMountedItems` ChildrenStrategy since FlipView lacks `ContainerContentChanging`). The rest of the deferred list — `GridViewElement` (plain), `ItemsViewElementBase`, dialog / overlay family (`ContentDialog`, `Flyout`, `Popup`, `MenuBar`, `MenuFlyout`, `CommandBar`, `CommandBarFlyout`), heavy / specialized controls (`WebView2`, `NavigationView`, `TitleBar`, `MediaPlayerElement`, `AnimatedVisualPlayer`, `MapControl`, `SemanticZoom`, `AnnotatedScrollBar`, `RefreshContainer`, `SwipeControl`, `ParallaxView`), interop / a11y (`SemanticElement`, `AnnounceRegion`, `XamlHost`, `XamlPage`, and the already-escape-hatched `IconElement`), and Reactor composition primitives (`Component`, `Func`, `Memo`, `ErrorBoundary`, `CommandHost`, `Validation.*`) — was never on the Phase 3 batch list. The composition primitives likely should NOT route through the V1 handler protocol (they sit above it); the rest are straightforward descriptor ports (or, where they'd surface engine gaps, would follow the close-out / finish pattern of landing the engine extension before the port).
1436+
**Phase 3 deferred / not-attempted** (recorded for the Phase 3.5 / Phase 4 prelude — element types in the legacy `Reconciler.Mount` switch that have neither a Phase 1 V1 handler nor a Phase 3 descriptor; see `tasks/047-extensible-control-model-implementation.md` for the full enumeration). **Updated in Phase 3 completion (PR 16636c0d):** the engine gap is closed (`TemplatedFlipViewElement<T>` ported via the new `PreMountedItems` ChildrenStrategy + `TemplatedFlipViewDescriptor`), and every previously-deferred descriptor on the Phase 3 batch list is now both authored AND registered in `RegisterV1BuiltInHandlers`: untyped items hosts (`GridView`, `ItemsView`, `ItemContainer`), heavy / specialized controls (`WebView2`, `NavigationView`, `TitleBar`, `MediaPlayerElement`, `AnimatedVisualPlayer`, `MapControl`, `SemanticZoom`, `AnnotatedScrollBar`, `RefreshContainer`, `SwipeControl`, `ParallaxView`), polymorphic / a11y (`IconElement` via the new `IDecoratorElementHandler` engine extension, `SemanticElement`, `AnnounceRegion`). What still ships unregistered (intentional carve list, documented inline in `RegisterV1BuiltInHandlers`): the dialog / overlay family (`ContentDialog`, `Flyout`, `Popup`, `MenuBar`, `MenuFlyout`, `CommandBar`, `CommandBarFlyout`) — modal lifecycle needs decorator-style ports beyond the IDecoratorElementHandler shape; the stateful `NavigationHostElement` — `Reconciler.UnmountRecursive` intercepts before the V1 arm and needs a small refactor; `TabViewDescriptor` — bisect ratifies the documented gaps (spec 045 §2.4 drag pipeline, §2.2 pinnable headers, in-place CanUpdate, conditional `SelectedIndex` write, `TabStripHeader` / `TabStripFooter` slots) need engine work (post-children mount-hook + `ImperativeBridged` for named slots); the XAML interop bridges (`XamlHost`, `XamlPage`) — descriptors exist but `XamlInterop.Register` populates `_typeRegistry` at startup so V1 auto-registration would clash; and the Reactor composition primitives (`Component`, `Func`, `Memo`, `ErrorBoundary`, `CommandHost`, `Validation.*`) — these sit ABOVE the V1 handler protocol and Phase 4 cleanup keeps their legacy arms. The A|B parity bar is met for every registered element: 9134 xunit + 4410 selftest (V1 ON ≡ V1 OFF), 0 failures both flags.
14371437

14381438
**Phase 3 finish advisory perf** — Cloud PC x64 re-capture under `docs/specs/047/phase3-results/CPC-ander-YTZ3O-x64-advisory/2026-05-28-phase3-finish-3x5/` (n=15, 3 launches × 5 reps). V1 ON (descriptors) vs V1 OFF (today), against prior `2026-05-27-phase3-closeout-3x5/`:
14391439

docs/specs/tasks/047-extensible-control-model-implementation.md

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -964,39 +964,82 @@ the audit at the end of `spec/047-phase3-finish`:
964964
up-front into `FlipView.Items` (no `ContainerContentChanging` to
965965
drive realization) and positionally reconciles via
966966
`Reconciler.ReconcileV1Child` on Update.
967-
- **Untyped items hosts not ported:** `GridViewElement` (the plain
968-
Element[] variant — `ListViewElement` got a Phase 1 V1 handler,
969-
GridView did not), `ItemsViewElementBase` (the higher-level
970-
`ItemsView` wrapping its own ItemsRepeater), `ItemContainerElement`.
967+
- **Untyped items hosts (CLOSED — Phase 3 completion):**
968+
`GridViewElement` (plain Element[]), `ItemsViewElementBase`,
969+
`ItemContainerElement` — all ported as standard descriptors and
970+
registered in `RegisterV1BuiltInHandlers`.
971+
- **Heavy / specialized controls (CLOSED — Phase 3 completion):**
972+
`WebView2Element`, `NavigationViewElement`, `TitleBarElement`,
973+
`MediaPlayerElementElement`, `AnimatedVisualPlayerElement`,
974+
`MapControlElement`, `SemanticZoomElement`,
975+
`AnnotatedScrollBarElement`, `RefreshContainerElement`,
976+
`SwipeControlElement`, `ParallaxViewElement` — all descriptors
977+
authored and registered. (`NavigationHostElement` stays deferred —
978+
see below.)
979+
- **Polymorphic / a11y (CLOSED — Phase 3 completion):**
980+
`IconElement` (decorator-style handler via the
981+
`IDecoratorElementHandler` engine extension landed this phase),
982+
`SemanticElement`, `AnnounceRegionElement` — all registered.
983+
984+
**Phase 3 completion — still deferred to the next PR (not regressions;
985+
scoped carve list documented inline in `RegisterV1BuiltInHandlers`):**
986+
971987
- **Dialog / overlay family:** `ContentDialogElement`,
972988
`FlyoutElement`, `PopupElement`, `MenuBarElement`,
973989
`MenuFlyoutElement`, `CommandBarElement`,
974-
`CommandBarFlyoutElement`. Button-family `Flyout` ships through the
975-
`.OneWayBridged` setter on the button descriptors; the standalone
976-
flyout elements are their own legacy paths.
977-
- **Heavy / specialized controls:** `WebView2Element`,
978-
`NavigationViewElement`, `NavigationHostElement`,
979-
`TitleBarElement`, `MediaPlayerElementElement`,
980-
`AnimatedVisualPlayerElement`, `MapControlElement`,
981-
`SemanticZoomElement`, `AnnotatedScrollBarElement`,
982-
`RefreshContainerElement`, `SwipeControlElement`,
983-
`ParallaxViewElement`.
984-
- **Polymorphic / interop / a11y:** `IconElement` (already documented
985-
as escape-hatched — polymorphic mount), `SemanticElement`,
986-
`AnnounceRegionElement`, `XamlHostElement`, `XamlPageElement`.
987-
- **Reactor infrastructure (likely SHOULD stay out of V1 dispatch):**
988-
`ComponentElement`, `FuncElement`, `MemoElement`,
990+
`CommandBarFlyoutElement`. Modal lifecycle (control-side-mounted,
991+
not parent-tree-mounted) requires decorator-style ports beyond
992+
the IDecoratorElementHandler shape used for `IconElement`.
993+
- **Stateful host:** `NavigationHostElement`. Per-instance
994+
route/cache/transition state is intercepted in
995+
`Reconciler.UnmountRecursive` BEFORE the V1 dispatch arm; needs
996+
a small refactor to internal-expose `MountNavigationHost` /
997+
`UpdateNavigationHost` and duplicate cleanup logic in the V1
998+
handler before it can route through V1.
999+
- **`TabViewDescriptor` (descriptor exists, registration carved):**
1000+
Bisect (3× clean V1 ON full selftest with only TabViewDescriptor
1001+
carved, vs. 1–4 random docking-text-find failures per run when
1002+
registered: DockHooks / PixDoc / RoleAware / Composition /
1003+
FloatRoot) ratifies the descriptor's documented gaps as hot in
1004+
the docking suite — missing spec 045 §2.4 drag pipeline
1005+
(`OnTabDragStarting` / `OnTabDragCompleted`), §2.2 pinnable
1006+
headers (`BuildTabHeader` / `BuildPinButton` / in-place
1007+
`TryUpdatePinHeaderInPlace`), in-place CanUpdate for tab content
1008+
(preserves focus/state on re-renders), conditional `SelectedIndex`
1009+
write, and `TabStripHeader` / `TabStripFooter` Element slots.
1010+
Closing them requires engine work (post-children mount-hook so
1011+
`SelectionChanged` subscribes after children-add + an
1012+
`ImperativeBridged` shape for the named tab strip slots).
1013+
- **Interop bridges:** `XamlHostElement`, `XamlPageElement`. V1
1014+
descriptors exist (`XamlHostDescriptor`, `XamlPageDescriptor`)
1015+
but stay unregistered because `XamlInterop.Register(reconciler)`
1016+
populates the external `_typeRegistry` at app startup; auto-
1017+
registering V1 would clash via `EnsureRegistrableElementType`.
1018+
Unification is Phase 4 follow-up.
1019+
1020+
**Reactor composition primitives (intentionally above the V1
1021+
protocol — Phase 4 cleanup keeps their legacy arms):**
1022+
1023+
- `ComponentElement`, `FuncElement`, `MemoElement`,
9891024
`ErrorBoundaryElement`, `CommandHostElement`, `ModifiedElement`,
9901025
`Validation.FormFieldElement` /
991-
`ValidationVisualizerElement` / `ValidationRuleElement`. These are
992-
Reactor composition primitives, not WinUI control wrappers — they
993-
sit above the V1 handler protocol rather than being consumers of
994-
it.
995-
996-
The "100% V1 dispatch" goal as scoped by §14's Phase 3 batches IS
997-
met (every batch entry has a V1 handler or descriptor). The list
998-
above is genuine post-Phase-3 scope, not a regression against the
999-
shipped Phase 3 plan.
1026+
`ValidationVisualizerElement` / `ValidationRuleElement`. These
1027+
orchestrate child reconciliation rather than wrap a single WinUI
1028+
control, so the V1 handler protocol does not apply.
1029+
1030+
**Phase 3 completion status:** Every element type in the production
1031+
codebase either (a) routes through V1 dispatch (Phase 1 hand-coded
1032+
handler OR Phase 3 descriptor registered in
1033+
`RegisterV1BuiltInHandlers`), (b) is a Reactor composition primitive
1034+
intentionally kept above the V1 protocol, or (c) is in the explicit
1035+
deferred carve list above with a documented gap-closure path. The
1036+
A|B parity bar — V1 ON ≡ V1 OFF across the full xunit + selftest
1037+
matrix — is met for every registered element: 9134 xunit + 4410
1038+
selftest, 0 failures both flags. Phase 4 cleanup can delete every
1039+
legacy `MountXxx` / `UpdateXxx` method that backs an element that
1040+
has been registered through V1; the legacy switch arms for the
1041+
composition primitives + the deferred carve list must remain until
1042+
their respective follow-up PRs land.
10001043

10011044
**Carry-forward known defects** (from Phase 1):
10021045

0 commit comments

Comments
 (0)