Lifecycle
Lifecycle specification
The three lifetimes
Section titled “The three lifetimes”Proto UI separates three things that were previously easy to conflate:
- The host component instance owns the integration boundary.
- The Proto instance owns setup declarations, state, context/anatomy participation, and exposes.
- A mounted view is one replaceable host rendering of that Proto instance.
React or Vue may remove and recreate a host view while the adapter component and Proto instance remain alive. Web Components treat a stable synchronous DOM move as the same ownership period, but a confirmed disconnect is terminal by default.
adapt(proto) defines a host component type. It does not run proto.setup. Setup runs when a host component instance materializes its Proto instance, and it runs once for that instance.
Two orthogonal phase axes
Section titled “Two orthogonal phase axes”InstancePhase: setup -> alive -> disposing -> disposed
MountPhase: detached -> mounting -> mounted -> unmounting -> detached ^ | +----------------------------------+The mount loop may repeat while InstancePhase remains alive. disposed is terminal.
Prototype callbacks
Section titled “Prototype callbacks”def.lifecycle.onCreated((run) => { // Once per Proto instance, before its first view render.});
def.lifecycle.onMounted((run) => { // Once after each mount epoch's commit completes.});
def.lifecycle.onUpdated((run) => { // After the corresponding mounted update commit completes.});
def.lifecycle.onUnmounted((run) => { // Once per detached mount epoch. Instance state is still alive.});
def.lifecycle.onBeforeDispose((run) => { // Once before terminal invalidation.});All registrations are setup-only. onUnmounted is repeatable and must not be used as terminal instance cleanup; use onBeforeDispose for that responsibility.
Canonical order
Section titled “Canonical order”setup -> created -> (mounting -> render -> commit -> mounted -> (update -> render -> commit -> updated)* -> unmounting -> unmounted -> detached)* -> beforeDispose -> disposedCommit completion is semantic: an asynchronous host may acknowledge it later. Scheduled work is scoped to its epoch and must become a no-op when that epoch is invalidated.
While detached, state, props, context, and other logical channels may continue to change. An update request records dirty state but performs no host commit. The next mount renders the latest snapshot.
Logical identity and host resources
Section titled “Logical identity and host resources”Context and Anatomy use a stable logical instance token, not a DOM element as component identity. A mount epoch binds that token to a current root node. Detach removes event listeners, focus participation, overlays, observers, and other view resources, while logical state and tree participation survive. A later mount rebinds those capabilities to a fresh root.
Terminal disposal invalidates handles and removes logical Context/Anatomy participation. Host hard teardown is authoritative: it cannot be kept alive indefinitely by an unfinished presence animation.
Runtime diagnostics
Section titled “Runtime diagnostics”Structured events such as instance.created, mount.phase, mount.commit.done, update.updated, unmount.done, and instance.dispose.done are the canonical diagnostic stream. Mount events carry an epoch; update events also carry a revision.
CP0-CP10 checkpoints are deprecated. Adapters may temporarily emit a lossy compatibility projection, but new tests and tooling must consume structured events.
Contract previews
Section titled “Contract previews”Lifecycle coverage is catalogued by T-LIFECYCLE-0001..0005 and exercised by RuntimeSession plus React, Vue, and Web Component adapter tests.