The locked rules
Non-negotiable — from the specification and architecture.
State-driven
Output derives from state
Components change through state and events — never through refs or setter calls. State updates batch: set stages, flush commits at once.
No imperative calls
No hide(), show(), set_text()
No programmatic references to component instances. Update state and let the UI react — visible and disabled are ordinary boolean properties.
Identity
Universal, unique id
Every component carries an id: a non-empty string, unique across the tree, fit for tests. Duplicates fail naming the first use.
Lifecycle
Scoped work is cancelled
Component-scoped asynchronous work is cancelled when its component leaves the rendered tree; swaps prune listeners for removed components.
Navigation
Component-based, no routes
Navigation moves over declared component ids. String route identifiers are not the core navigation model.
Accessible core
Labels win, inference helps
Explicit label takes precedence, string text infers where sensible, bound values participate. Adapters map the shared model.
Cross-platform
No platform in the core
The vocabulary stays platform-free; targets adapt rendering. Themes follow system appearance automatically by default.
Honest errors
Invalid props are Luca errors
Bad properties and detectable invalid arguments fail with source-located Error at line:column — frozen wording, never silent.
Tooling that follows
A testing API addressed by id, and a development-only inspector over tree, state, and layout declarations.
What stays open
Marked open — never silently decided.