# SPEC — live_interaction_contracts (v1, frozen)
This document holds **durable statements only**. No version-specific numbers appear
here; those live in the harness output (`delegation-ledger.json`) and the dated
`reports/*_REPORT.md` evidence files. If a sentence here would change when LiveView ships a
new version, it does not belong in this file.
## Three evidence tiers (kept separate everywhere)
1. **Durable invariant** — true by the architecture's construction, independent of
implementation. Lives in `SPEC.md` / `KERNEL.md` / the `*_CONTRACT.md` files.
2. **Observed version-specific behavior** — what a tested LiveView/browser version
did. Lives in `delegation-ledger.json` (generated) and `reports/*_REPORT.md` (dated).
3. **Conformance result** — pass/fail produced by the harness on each run. Lives in
CI output and the regenerated ledger.
Never copy tier-2 numbers into tier-1 prose.
## Durable project statements
1. **This project is not a component library.**
2. It defines **executable interaction contracts** for Phoenix LiveView and
browser-native state machines.
3. **Components are derivations of contracts**, not the primary artifact.
4. The **conformance harness and delegation ledger are first-class artifacts.**
5. **LiveView DOM node continuity is observed implementation behavior, not a
documented framework guarantee.** The LiveView docs describe `phx-update` with the
verb "replace" and make no promise of DOM node-object persistence.
6. **The harness exists to detect regressions in that observed behavior** — it is the
fuse that converts statement 5 from a footnote into a monitored contract.
## The one cross-cutting invariant
> **A delegated browser machine is patch-safe only when its state does not live in a
> server-reconciled attribute, and any structural attribute it requires is a
> server-rendered constant.**
Both halves are load-bearing and both are evidenced (see `RED_FIXTURES.md` and
`REFERENCE_POPOVER_CONTRACT.md`). This is why popover is green and dialog/details are
red.
## v1 verdict
**Frozen (will not change without the invalidation evidence below):**
- the durable kernel invariants (`KERNEL.md`)
- the delegation-ledger **format** and classification rules (`DELEGATION_LEDGER.md`)
- the conformance harness (`CONFORMANCE.md`)
- **CI-as-fuse** — stable gate + main/edge early-warning (`CONFORMANCE.md`)
- the reference popover / tooltip / menu / select / combobox contracts
- the cursor contract and channel contract, including the shipped
`LiveInteractionContracts.Channel` guard
- anchored `placement` presets for the reference components (zero-JS CSS anchor
positioning, with documented browser-floor degradation)
- the amber dialog-adapter contract (`CONTRACT_DIALOG.md`), 7/7 conformance-gated
**Explicitly NOT frozen:**
- a polished public `<.dialog>` / `<.details>` component API (the dialog *adapter*
contract is an amber reference — `CONTRACT_DIALOG.md` — but no component ships)
- any IME correctness claim (only synthetic events tested)
**Still experimental:**
- native select popup state (not automatable)
- real-device IME behavior (the synthetic no-emit-during-composition rule is frozen;
device coverage is not)
**Evidence that would force a v1 revision:**
- the harness showing a **green machine regress** on any supported LiveView version
(node continuity or top-layer survival changes) → ledger + kernel update
- a **red fixture turning green** (LiveView stops stripping reflected attributes) →
it may graduate out of `RED_FIXTURES.md`
- a delegated machine found whose state is safe **despite** living in a
reconciled attribute, or unsafe **despite** not → the cross-cutting invariant is wrong
- a client-owned coordination need that **cannot** be met by stable-logical-id +
explicit rebind → the Interaction Persistence split is wrong
- real-device IME showing the "no emit during composition" rule is insufficient →
the Channel contract's IME clause needs revision
## Scope of applicability
These contracts pay rent only at the **interaction-primitive boundary** (overlays,
menus, comboboxes, focus/scroll coordination). For ordinary CRUD / forms / navigation
LiveView, the traditional two-runtime model is adequate and this project is silent.