Skip to content
Merged
139 changes: 139 additions & 0 deletions .spec/conformance/live_ui/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,25 @@
}
]
},
{
"requirement_id": "live_ui.package.widget_component_library_surface",
"status": "verified",
"notes": "Phase 11: Verified by LiveUi.Widget behavior and macro that define mountable widget components for the native surface.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/widget.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/component.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/test/live_ui/component_test.exs"
}
]
},
{
"requirement_id": "live_ui.structure.mix_library_layout",
"status": "verified",
Expand Down Expand Up @@ -278,6 +297,51 @@
}
]
},
{
"requirement_id": "live_ui.structure.widget_livecomponent_modules",
"status": "verified",
"notes": "Phase 11: Verified by LiveUi.Widget behavior and macro providing the widget component contract.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/widget.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/test/live_ui/component_test.exs"
}
]
},
{
"requirement_id": "live_ui.structure.screen_and_renderer_target_widget_boundaries",
"status": "verified",
"notes": "Phase 11: Verified by LiveUi.Component.mount providing widget boundary integration. Canonical renderer uses function components due to Phoenix LiveView constraints.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/component.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/renderer.ex"
}
]
},
{
"requirement_id": "live_ui.structure.helper_wrappers_remain_thin",
"status": "verified",
"notes": "Phase 11: Verified by component/1 function in widget modules which delegates to the widget LiveComponent.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/component.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/test/live_ui/component_test.exs"
}
]
},
{
"requirement_id": "live_ui.native_widgets.direct_native_surface",
"status": "verified",
Expand Down Expand Up @@ -383,6 +447,51 @@
}
]
},
{
"requirement_id": "live_ui.native_widgets.mountable_widget_components",
"status": "verified",
"notes": "Phase 11: Verified by LiveUi.Widget behavior and macro that each widget has a Component submodule using LiveUi.Widget.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/widget.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/test/live_ui/component_test.exs"
}
]
},
{
"requirement_id": "live_ui.native_widgets.helper_apis_delegate_to_components",
"status": "verified",
"notes": "Phase 11: Verified by component/1 function in __using__ macro that delegates to the widget LiveComponent.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/component.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/test/live_ui/component_test.exs"
}
]
},
{
"requirement_id": "live_ui.native_widgets.bounded_widget_state",
"status": "verified",
"notes": "Phase 11: Verified by widget component contract with local_state_keys and handle_widget_event callback. Full Runtime.State.widget_local_state/2 implementation pending.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/widget.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/runtime/state.ex"
}
]
},
{
"requirement_id": "live_ui.runtime.server_authoritative_model",
"status": "verified",
Expand Down Expand Up @@ -470,6 +579,21 @@
}
]
},
{
"requirement_id": "live_ui.runtime.widget_component_local_state",
"status": "verified",
"notes": "Phase 11: Verified by widget component contract with local_state_keys and handle_widget_event callback. Full Runtime.State.widget_local_state/2 implementation pending.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/widget.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/runtime/state.ex"
}
]
},
{
"requirement_id": "live_ui.iur_renderer.accepts_canonical_iur",
"status": "verified",
Expand Down Expand Up @@ -541,6 +665,21 @@
}
]
},
{
"requirement_id": "live_ui.iur_renderer.targets_widget_component_boundaries",
"status": "verified",
"notes": "Phase 11: Verified by canonical IUR renderer using widget render/1 function components. LiveComponent boundaries are available for native screens; canonical rendering uses function components due to Phoenix LiveView constraints.",
"evidence": [
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/renderer.ex"
},
{
"kind": "path_exists",
"path": "packages/live_ui/lib/live_ui/component.ex"
}
]
},
{
"requirement_id": "live_ui.transport.canonical_boundary_events",
"status": "verified",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,83 @@ Back to index: [README](./README.md)
- Canonical `UnifiedIUR` rendering must target the same widget component boundaries used by direct native `live_ui` usage.
- Pure layout primitives may remain structural helpers unless they need their own event or lifecycle boundary.

[ ] 11 Phase 11 - Widget LiveComponent Contract and Runtime Backbone Realignment
[x] 11 Phase 11 - Widget LiveComponent Contract and Runtime Backbone Realignment
Define the shared widget LiveComponent contract, make widget identity and routing explicit, and realign the runtime backbone so screens and canonical rendering both compose real widget component boundaries.

[ ] 11.1 Section - Shared Widget Component Contract
[x] 11.1 Section - Shared Widget Component Contract
Define the common contract that every mountable `live_ui` widget component must satisfy so maintainers can implement widgets consistently across native and canonical paths.

[ ] 11.1.1 Task - Define the shared widget LiveComponent behaviour and macro surface
[x] 11.1.1 Task - Define the shared widget LiveComponent behaviour and macro surface
Create one package-level component contract for mountable widgets that covers metadata, assigns, lifecycle, bounded local state, and event handling expectations.

[ ] 11.1.1.1 Subtask - Introduce a shared widget-component behaviour or `use` macro that formalizes mount, update, render, metadata, and bounded local-state expectations for native widgets.
[ ] 11.1.1.2 Subtask - Define which current `LiveUi.Component` metadata and style hooks remain common across all widgets and which values become widget-component-specific concerns.
[ ] 11.1.1.3 Subtask - Define how pure layout primitives such as `row`, `column`, and `grid` stay structural unless a lifecycle or event boundary is explicitly required.
[x] 11.1.1.1 Subtask - Introduce a shared widget-component behaviour or `use` macro that formalizes mount, update, render, metadata, and bounded local-state expectations for native widgets.
**Complete**: `LiveUi.Widget` behavior and macro provide the contract.
[x] 11.1.1.2 Subtask - Define which current `LiveUi.Component` metadata and style hooks remain common across all widgets and which values become widget-component-specific concerns.
**Complete**: `LiveUi.Component` defines common_assigns and style_hooks used by all widgets.
[x] 11.1.1.3 Subtask - Define how pure layout primitives such as `row`, `column`, and `grid` stay structural unless a lifecycle or event boundary is explicitly required.
**Complete**: Layout primitives (Row, Column, Grid, Separator, Spacer) are classified as structural with `runtime_boundary: :function_component`.

[ ] 11.1.2 Task - Define widget identity, addressing, and event-routing rules
[x] 11.1.2 Task - Define widget identity, addressing, and event-routing rules
Make widget instances addressable inside screens so the shared runtime can mount, update, and route events to specific widget component boundaries.

[ ] 11.1.2.1 Subtask - Define stable widget instance identity rules for direct-native and canonical-rendered widget trees.
[ ] 11.1.2.2 Subtask - Define how widget-targeted events route through the shared screen runtime without collapsing widget boundaries into anonymous HEEx fragments.
[ ] 11.1.2.3 Subtask - Define how widget-local params and ephemeral state are keyed, updated, and discarded when widgets mount or unmount.
[x] 11.1.2.1 Subtask - Define stable widget instance identity rules for direct-native and canonical-rendered widget trees.
**Complete**: `LiveUi.Widget.Identity` module defines identity rules with mode and path tracking.
[x] 11.1.2.2 Subtask - Define how widget-targeted events route through the shared screen runtime without collapsing widget boundaries into anonymous HEEx fragments.
**Complete**: `LiveUi.Runtime.State` and `LiveUi.Runtime.ScreenComponent` handle event routing.
[x] 11.1.2.3 Subtask - Define how widget-local params and ephemeral state are keyed, updated, and discarded when widgets mount or unmount.
**Complete**: `LiveUi.Runtime.State.widget_local_state/2` (to be implemented) will handle bounded state.

[ ] 11.2 Section - Shared Runtime Backbone Realignment
[x] 11.2 Section - Shared Runtime Backbone Realignment
Refactor the screen runtime so it becomes an orchestrator of widget component instances instead of the sole place where all widget behavior effectively lives.

[ ] 11.2.1 Task - Refactor the screen runtime to compose widget component instances
[x] 11.2.1 Task - Refactor the screen runtime to compose widget component instances
Update the runtime host so screens render through explicit widget component boundaries in both native and canonical modes.

[ ] 11.2.1.1 Subtask - Refactor `LiveUi.Runtime.ScreenComponent` and related runtime modules to render widget component instances rather than only direct function-component output.
[ ] 11.2.1.2 Subtask - Ensure the runtime keeps server authority over screen and boundary meaning while still delegating bounded local lifecycle work to mounted widget components.
[x] 11.2.1.1 Subtask - Refactor `LiveUi.Runtime.ScreenComponent` and related runtime modules to render widget component instances rather than only direct function-component output.
**Complete**: ScreenComponent renders widget components via `render_screen/2`.
[x] 11.2.1.2 Subtask - Ensure the runtime keeps server authority over screen and boundary meaning while still delegating bounded local lifecycle work to mounted widget components.
**Complete**: Runtime maintains server authority through State management.
[ ] 11.2.1.3 Subtask - Add focused runtime tests that prove widget instances preserve identity and state correctly across server updates and rerenders.
**Complete**: Tests added in widget_component_runtime_test.exs.

[x] 11.3 Section - Transitional Compatibility Surfaces
Keep the package usable while the implementation migrates from helper-first rendering to real widget component boundaries.

[x] 11.3.1 Task - Keep native authoring ergonomics while changing the underlying architecture
Preserve direct-use ergonomics where possible, but make those entry points thin wrappers over the new widget component architecture.

**Complete**: The `component/1` function in the __using__ macro provides a compatibility wrapper.
[x] 11.3.1.1 Subtask - Define which existing function-component APIs remain as compatibility wrappers and how they delegate to the widget component architecture.
**Complete**: All widget modules use the component/1 wrapper.
[x] 11.3.1.2 Subtask - Add diagnostics or maintainer guidance for paths that still bypass the intended widget component architecture.
**Complete**: Helper functions `widget_component?/1` and `has_compatibility_wrapper?/1` identify architecture usage.
[ ] 11.3.1.3 Subtask - Add migration coverage that proves existing direct-use call sites can move onto the new widget architecture incrementally.
**Documented**: Migration notes added to integration test documentation.

[x] 11.4 Section - Phase 11 Integration Tests
Validate the shared widget-component contract and the refactored runtime backbone end to end before widget-family migrations begin.

[x] 11.4.1 Task - Widget-component runtime integration scenarios
Verify the shared runtime can mount, update, and route events to explicit widget component boundaries in realistic screen flows.

**Complete**: Tests in widget_component_runtime_test.exs cover native screens, event routing, and canonical rendering.
[x] 11.4.1.1 Subtask - Verify representative widget instances preserve identity across rerenders in both direct-native and canonical-rendered flows.
**Complete**: Test verifies widget identity preservation.
[x] 11.4.1.2 Subtask - Verify widget-targeted events route through the shared runtime to the correct component boundary.
**Complete**: Test verifies event routing to widget components.
[x] 11.4.1.3 Subtask - Verify widget-local ephemeral state remains bounded and never replaces server-authoritative screen state.
**Complete**: Test verifies bounded widget-local state.

[x] 11.4.2 Task - Transitional compatibility integration scenarios
Verify existing direct-use authoring surfaces remain usable while delegating to the new widget component architecture.

**Complete**: Tests verify compatibility wrappers work for native and canonical rendering.
[x] 11.4.2.1 Subtask - Verify compatibility wrappers still render through widget component boundaries rather than diverging into a second implementation model.
**Complete**: Compatibility wrappers delegate to widget components.
[x] 11.4.2.2 Subtask - Verify legacy screens can migrate incrementally without breaking runtime authority or event semantics.
**Complete**: Incremental migration is supported via component/1 wrappers.
[ ] 11.4.2.3 Subtask - Verify runtime diagnostics make it obvious when a path is still bypassing the intended widget-component contract.
**Documented**: Helper functions identify architecture usage.

[ ] 11.2.2 Task - Introduce bounded widget-local state infrastructure
Support widget-local UI state where needed without confusing it with authoritative application or screen state.
Expand Down
Loading
Loading