# live-conformance/compose — live composition The corpus of [`extensions/live-compose.md`](../../extensions/live-compose.md) §11: the layout function and the mixer on their own, `WCD1` composition descriptors, and rooms (a signed `WRD1` descriptor, its `WRG1` grants and its principals' `WEV1` chains) composed at a list of instants, with `WCR1` composition receipts checked against them. **Composition equivalence.** A conforming implementation reaches, for every case, the outcome the case states, rectangle for rectangle and sample for sample: - a **layout** case's `params` (the descriptor's fields, §3.1) and `entrants` (each a `principal`, its `join` order, its `video` as `[width, height]` or `null`, whether it has `audio`, and its `attrs` as `[key, value]` pairs) give the `order`, the `tiles` and the `voices` of §5 and §6, or the refusal `reason`. A tile is its `principal`, its `place` (`grid`, `featured` or `pip`), its `z`, its `tile` rectangle and its `dst` and `src` rectangles (`null` when its video is stopped), each `[x, y, w, h]`; a voice its `principal`, `gain` and `pan`; - a **mix** case's `channels`, `frames` and `inputs` (each its `channels`, `gain`, `pan` and `pcm`, signed 16-bit little-endian samples in hexadecimal) give the mixed `pcm` (§6), or the refusal; - a **descriptor** case's `bytes` read (§3.3) to its `digest` and `fields`, or are refused; - a **composition** case's `room`, `descriptor` and `instants` give the descriptor's `digest` and a frame per instant (§9): its `participants` (each its `principal`, its `grant`, its `join` order, its `attrs`, and its `video` and `audio` sources with their slot, media kind, profile, layers, composed layer, layering, dimensions and `tracks`), its `set_digest` (§4.5), and its `order`, `tiles` and `voices`; or a refusal and where, `at`: `["room"]`, `["room", …]` with the room verifier's own place (live-rooms §9.1), `["descriptor"]` or `["set", t]`; - a **receipt** case's `room`, `descriptor` and `receipt` are accepted (§8.3) with the receipt's `digest` and the `set_digest` it names, or refused, `at` as above or `["receipt"]`. A verifier that reaches another outcome, reason, place, rectangle, sample or digest does not conform. **Provenance.** Generated here: `wai_live_compose_vectors gen` writes every case, room, descriptor, record and receipt from scenes authored in code, from fixed seeds. Each key is SHA-256 of a fixed label and the principal's index, each pure layout case's participant a SHA-256 of a fixed label and an index (a name, not a key), each block of PCM SHA-256 output under a fixed label (it stands for decoded audio and is no recording), each object digest of a receipt SHA-256 of a fixed label (it stands for an object and hashes none), every time is a constant (the room's `t0` is 2026-10-17T00:00:00Z), and Ed25519 signing is deterministic (RFC 8032), so the file is the same bytes on every machine. The generator asserts that each case reaches the outcome it was written to have before it writes it. No recorded data. ## Layout One file, `vectors.json`: - `principals`: the room's keys, by name (informative). - `layouts`, `mixes`, `descriptors`: the cases above, each with `name` and `about`. - `rooms`: by name, each a `descriptor` and `grants` (hexadecimal), `key_log_head` (`null`: the room names no origin) and `chains` (lists of records in hexadecimal). - `compositions`, `receipts`: the cases above, each naming its room. The **studio** room has a director (its role has the direct and compose powers), a performer (camera and music, featured, order 1, gain 5120), a guest (speech only at first, order 3, then exchanged at 5 s for a grant of order 0, gain 2048 and pan −2048, then video at 7 s), a screen-sharing device, an encoder live in the slot `main` under a staged profile of the room's own, a mixer (the compose power; it publishes the composed tracks), and a viewer. The director's video stops at 6 s and the performer leaves at 8 s. Its variants: `studio_bad_order` (the guest's order is `third`), `studio_lifecycle_gap` (the relay's record at 6 s not delivered), `studio_viewer_gap` (the viewer's first chat not delivered) and `studio_refused` (the viewer sends a `control` it may not). Cases: - layouts: `grid_0` to `grid_12`; portrait, square and auto canvases; `fill_fill`, `fill_cover`, `fill_contain`, `fill_default` and extreme aspects; the featured participant alone, of four, on a portrait canvas, kept past the tile limit, first of two, absent, and unread; order by attribute and ties broken by key; stopped video shown and omitted; the tile limit and the voice limit; picture in picture in each corner, static and dynamic, alone, with derived sizes, with stopped video, first of two, and over a featured tile; and attributes that do not read; - mixes: passing through, both widths into both, saturation, pans, gains, ties, silence and five refusals; - descriptors: the room's three and canvases at their limits, and each refusal a descriptor alone can have; - compositions: `grid_session` (every second from 1 s to 9 s), `pip_session`, `participant_gap`, `signer_with_power`, and a refusal for a signer without the power, one not in the room, another room, a bad signature, an instant before `effective`, an attribute that does not read, a lifecycle gap and a refused room; - receipts: `video`, `audio` and `pip_video` accepted, and one refused for each reason a receipt can have. ## Running ``` cd ../../wai-rs cargo run --no-default-features --features live_compose --bin wai_live_compose_vectors -- verify ../live-conformance/compose cargo run --no-default-features --features live_compose --bin wai_live_compose_vectors -- gen ../live-conformance/compose # regenerate cargo test --no-default-features --features live_compose --test live_compose cd ../live-conformance python3 live_compose_verify.py compose ``` `wai_live_compose_vectors verify` and `tests/live_compose.rs` require the file to regenerate byte for byte and `wai-rs` to give every case its outcome; the test also requires every reason of §10 to refuse a case, the cases above to be there, the grid session to change its order at the guest's exchange, and §10 to list exactly the reasons the reference reports. `live_compose_verify.py` is the second implementation, written from the extension's text and sharing no code with `wai-rs`: it verifies each room with `live_rooms_verify.py` and steps through its lifecycle replay to take the room at each instant, gives every case the same outcome, requires the same coverage of reasons, and then mutates copies of the corpus, one defect each (a tile moved, tiles swapped, the PiP window's z, a source or destination rectangle, the order, an entrant's attribute, a parameter, a stated reason, a voice, a mixed or input sample, a pan, a descriptor's byte or digest, a frame's tile, set digest, join order or tracks, an instant, a lifecycle record not delivered, a grant's byte, a receipt's byte or digest, and a stated outcome), each of which must fail. Pass = an exit status of 0 from each.