### `wai.live.cowatch`: watching together in a room, with the sync measured

- **The extension** ([co-watch](extensions/co-watch.md)) registers a record for a room that
  watches one source together. The room authority signs a co-watch policy, `WXP1` (§3): the
  source (a WAI package by its receipt, a sequence of on-demand objects by a digest of their
  content hashes and durations, or a recording by its manifest), its duration, and the bounds of
  every rule below. A policy is replaced by one chained to it; one naming another source starts
  the controlled position again.
- **Controls** (§5): `play`, `pause`, `seek` and `rate`, `WXC1`, as `meta` events, each effective
  at a room-clock instant ahead of its sending by at least the policy's lead and at most its
  horizon, so every viewer applies it at that instant whatever its own latency. Who may control
  is the direct power or the grant attribute `watch_control`, one bit per action, which needs no
  new power bit. Controls apply in a pinned order, by instant, then by sending, then by digest:
  of two for one instant that set the same thing, the one sent later prevails, and the other is
  stated overridden (§5.4). The controls define the controlled position at every instant (§6).
- **Presentation statements** (§7): a viewer's player signs, under its own key and in its own
  chain, the source position it presented at a room-clock instant, its state and its rate, at
  least once a slot. A statement lifted from another chain, signed by another key, about an
  instant after its sending, or naming another source is refused.
- **Skew** (§8): the room clock's skew statement, `WXK1`, states per window, for each viewer, the
  slots due while it was present, the samples it has and those counted (a sample within the
  policy's settle time of a join, a control or a source's start is not), and the 50th
  percentile, the policy's percentile and the greatest of its absolute errors, with a verdict
  against the bound; and the same for each pair of viewers. `held` pins the statements the clock
  had received, so one arriving later changes nothing. A verifier recomputes every entry; a
  viewer with a due slot of no statement is unknown, never in sync; and a window's statements
  together list every viewer of it.
- **Catch-up** (§9): a pinned correction from the controlled state and the player's position:
  the controlled rate within the tolerance, a rate nudged toward the room and held within the
  policy's limits up to the seek threshold, a seek past it, and a seek or a hold while paused.
- **Reference**: the `co_watch` module of `wai-rs` (feature `co_watch`); the corpus
  `live-conformance/cowatch/` (`wai_co_watch_vectors gen`): a watch party with a conflict at one
  instant and a late joiner, a room whose second policy starts another source, a room with a
  viewer out of sync, one unknown, one that leaves and a window stated in two statements, a gap,
  refused vectors for every reason of §12, and catch-up cases; its second implementation
  `live-conformance/co_watch_verify.py`, which recomputes every entry, requires every mutated
  copy to fail and catches each of its own checks dropped.
- **The room service and the page** (`joule-moq-room`, `joule-moq-web`): a co-watch room serves
  its source and carries its viewers' controls and statements in a log, the clock signing each
  viewer's presence and each window's skew statements; the room page has a co-watch mode with
  shared controls and a sync indicator, and the module `web/room/cowatch.js` gives every
  catch-up case of the corpus its correction and writes its controls and statements byte for
  byte.

