KERNEL — five members (v1, frozen definitions)

Copy Markdown View Source

Durable definitions only. Each is backed by an evidence report named at its foot; the reports carry the version-specific numbers, this file carries the invariants.

A note on shape: Delegation, Observation, and Channel are mechanisms (things a runtime/server does); Cursor is a construct; Interaction Persistence is not a mechanism — it is a substrate contract that Delegation and Cursor each depend on. The five are not five symmetric operations. Do not read Interaction Persistence as something you "invoke."


1. Delegation (mechanism)

The server emits declarative markup that transfers ownership of a browser-native interaction machine to the browser.

Invariants:

  • Browser owns the native interaction state when delegation is patch-safe.
  • Delegated browser-owned state must not be stored in a server-reconciled attribute. (State reflected into an attribute the server template does not carry is stripped by reconciliation.)
  • Structural attributes a browser machine requires must be server-rendered constants. (A client-added structural attribute — e.g. popover — is stripped by reconciliation just like reflected state. The attribute must be static in the server template so the machine keeps its shell.)
  • popover is green. dialog and details are red (see RED_FIXTURES.md).

Evidence: reports/CONFORMANCE_REPORT.md, reports/COMBOBOX_SPIKE_REPORT.md (test 7).

2. Observation (mechanism)

A declarative relay forwards browser-machine events to the server as ordinary LiveView events.

Invariants:

  • Observation is lossy browser-to-server telemetry.
  • It is never authoritative.
  • The server may react to observed events (lazy cleanup, logging, non-gating assigns) but must not derive canonical state or authorization from observed browser state.

The dialog-close-relay evidence shows the signal is lossy in three independent ways (a reconciliation-stripped close fires no event; a disconnected close is dropped; <dialog> has no open event at all), so the non-authoritative rule is not hygiene — it is the only safe reading.

Evidence: ../archive/observation-spike/OBSERVATION_SPIKE_REPORT.md.

3. Interaction Persistence (substrate contract — NOT a peer mechanism)

The condition under which owned interaction state survives a patch. It splits by owner and must not be collapsed into a single "Identity" concept.

Browser-owned tier: DOM node continuity + state-surface non-interference. The same DOM node object must persist and the machine's state surface (attribute or top-layer) must not be overwritten. Node continuity alone is insufficient (dialog keeps its node and still loses open).

Client-owned tier: stable logical identity + explicit userland rebind/re-projection machinery. Not provided by LiveView. The two required mechanisms, both evidenced:

  • child-node replacement → the container hook re-projects presentation by logical id in updated();
  • hook-node (container) replacement → recover state from external storage keyed by the logical container id on remount.

Standing caveat (durable): LiveView node continuity is observed implementation behavior, not a documented framework guarantee. The harness exists to detect when it changes.

Evidence: reports/CONFORMANCE_REPORT.md, reports/CURSOR_REBIND_SPIKE_REPORT.md.

4. Cursor (construct)

Client-owned coordination state over server-rendered, identity-bearing children.

Invariants:

  • Primary strategy is aria-activedescendant (focus stays on a persistent input/container; the active item is a logical-id reference).
  • Roving tabindex is not patch-safe as the default strategy — a focused non-form element is blurred when a patch touches its subtree (LiveView preserves focus for form inputs only).
  • The active descendant must always target a live node, or collapse deterministically (clear/first/nearest, chosen and documented) — it must never point at a removed or stale node.
  • Cursor is a specialization of the Interaction Persistence client tier; it inherits the "stable logical id + explicit rebind" requirement.

Evidence: reports/CURSOR_REBIND_SPIKE_REPORT.md, reports/COMBOBOX_SPIKE_REPORT.md (tests 3–5).

5. Channel (mechanism — a server obligation)

A versioned async query/result exchange between a client-owned input atom and server-owned result content.

Invariants:

  • version-through-render: the client stamps each query with a monotonically increasing version; the server stamps each result render with the version it answers.
  • server-enforced monotonicity is required for construction-grade correctness: the server render path must refuse to render superseded versions. The package ships LiveInteractionContracts.Channel as the reference guard; an application must route result rendering through that guard to inherit the construction-grade claim.
  • client-side stale detection is a secondary guard, not the primary one. The version stamp alone, without Channel.accept/2 on the server render path, is convention — stale results still enter the DOM and are only flagged after the fact.
  • Channel stays in the kernel because Combobox correctness is impossible without it, and the version must round-trip through the server render (coupling it to the pipeline in a way generic app-level versioning is not).

Evidence: reports/COMBOBOX_SPIKE_REPORT.md (test 2 — guard on vs off).


Derivations (not kernel; for orientation only)

  • Dialog = Delegation (red) + Observation. Red fixture.
  • Popover = Delegation (green). Reference machine.
  • Dropdown menu = Popover + Cursor.
  • Combobox = Popover + Cursor + Channel. Proven to compose on one subtree.