### A channel's breaks marked in its HLS Media Playlist, and why a delivery took the route it took

- **The cue tags** ([extensions/channel-lineup.md](extensions/channel-lineup.md) §7.4): a packager that writes a
  channel's segments, MPEG-2 transport stream segments among them, marks each break of the `wai.video.channel`
  receipt's schedule, in two forms. `EXT-X-CUE-OUT` with the break's duration goes on its first segment,
  `EXT-X-CUE-OUT-CONT` with the time elapsed and the duration on each later one, and `EXT-X-CUE-IN` on its return.
  For a break whose cue carries its SCTE-35 section, the `EXT-X-DATERANGE` pair of RFC 8216 §4.3.2.7.1 is written
  as well: `SCTE35-OUT` and `PLANNED-DURATION` with the last segment before the break, kept while the window holds
  a segment of it (RFC 8216 §6.2.1), then `DURATION` on its return. A date range's `ID` is the break's id and its
  start, so a break id a schedule repeats on another day names another range. A segment carries the same
  `EXT-X-CUE` lines in every window that holds it. A break whose start or end falls inside a segment is refused
  `cue_unaligned`, and one whose id holds a double quote, a line feed or a carriage return, which no quoted-string
  can hold, `cue_unwritable`. A window's last segment ends before 10000-01-01T00:00:00Z: a break in the window
  starts at the latest where the window ends, so every date the playlist writes has four digits of year.
- **Its verification** (§8.4): a receipt, the cues its import wrote (`cues.json`) and a playlist. Each cue is held
  to its break's id, start and duration, and through its cue id to a `splice_insert()`'s `splice_event_id`
  (`cues_malformed`, `cues_mismatch`). The playlist's window is read back (`playlist_malformed`), and its tags are
  rendered again and compared byte for byte (`playlist_mismatch`). The receipt signs each break's id, start and
  duration, which every tag is written from. It does not sign the section a date range carries, and §12 says so.
- **The reference**: `channel_lineup::cue_tags` (`render`, `read_playlist`, `verify_playlist`), and
  `channel_lineup::import::break_cue`, the cue §4.8 yields for a break.
- **The corpus** [`live-conformance/channels/`](live-conformance/channels/) gains the sample's cues and five more
  channels' receipts or cues. One is the JSON form with brk-1's section left out, whose receipt is the sample's;
  three name brk-1 with a double quote, a line feed and a carriage return, the last a receipt the operator signs
  itself, since an import refuses the id; and one is a channel scheduled at the end of the year 9999. It also
  gains 26 playlist windows and 28 playlist verifications. Eleven windows render playlists, among them one that
  begins inside a break, one at a return, one with no section, and segments of 6.006 seconds, whose spans state
  milliseconds and whose `TARGETDURATION` is 7, 6.006 rounded up. Four more sit at a bound of §7.4: a URI of 2 048
  bytes, a segment of 2^32 − 1 milliseconds, a media sequence number of 2^53 − 1, and a window that ends at
  9999-12-31T23:59:59.999Z where a break starts. Fifteen are refused: a control of each refusal of §7.4, and one
  past each bound. Eight verifications are verified, and each of the others is a control of one step.
  `channel_lineup_verify.py` renders and reads the playlists itself. It catches each of its 18 new checks dropped,
  among them one for each bound and one for each character no quoted-string holds, and 13 new mutated copies.
- **Breaking:** `api:rust:wai::channel_lineup::Reason::CuesMalformed`,
  `api:rust:wai::channel_lineup::Reason::CuesMismatch`, `api:rust:wai::channel_lineup::Reason::PlaylistMalformed`,
  `api:rust:wai::channel_lineup::Reason::CueUnaligned`, `api:rust:wai::channel_lineup::Reason::CueUnwritable` and
  `api:rust:wai::channel_lineup::Reason::PlaylistMismatch`: six reasons, which an exhaustive match over `Reason`
  needs.
- **The delivery-decision record** ([extensions/route-record.md](extensions/route-record.md) §6.3, §7.2 step 10),
  `wai-route-delivery-decision`: why a delivery of a job's output took the route it took. A delivery is routed as a
  job is, from its own request, price book of version 2 and policy, so its candidates are the routes that could
  carry it (an origin, a cache, a bearer), with every limit that removed one. The record restates every route as
  its price book stated it, with its estimates and expected figures. It states the order, the decision and the
  route taken, and in `passed` the key by which each other surviving route was passed over. It names its inputs by
  digest: the delivery's three documents and, as its `parent`, the job's route record, whose served hop's output
  it carries by count and root. Signed by the job's router under its own domain, it is chained: each decision after
  a job's first names the one before it by `prev`, so a decision left out before a later one, moved or out of
  order is refused. The list proves nothing of decisions after its last, since a verifier is not told how many
  there were.
- **Its verification.** A verification document may have `deliveries`, each a delivery's three documents and its
  decision, the job's decisions from the first. Each is read and held to its documents (`request_mismatch`,
  `policy_mismatch`, `pricebook_mismatch`), and its routing is recomputed (`candidate_mismatch`, `removal_mismatch`,
  `rank_mismatch`, `decision_mismatch`). Its route and its passed routes are checked (`delivery_route_mismatch`),
  then its parent (`delivery_parent_mismatch`; a record of version 1, or one no hop served, has nothing to
  deliver). Last comes its chain (`delivery_chain_broken`: its place, its `prev`, a decision before the output
  existed or before the one before it, one delivery decided twice). A form that breaks §6.3 is `delivery_invalid`.
  No route record changes, and a document without `deliveries` reads exactly as before.
- **The reference**: `route_record::delivery` (`seal`, `passed`, `delivered_by`, `form`); the route record's
  candidate form and step 6 are shared with it, unchanged.
- **The corpus.** Routes gain 70 vectors: six accepted and 64 controls, each a control of one defect, refused at its
  own place. Each member that binds a decision to its documents has a control of its own: the request's id,
  operation, capability, fallback, quantities and digest, the policy's name, version and digest, and the price
  book's digest, currency and `issued`. The accepted ones are a delivery to Europe that one cache wins on time to
  first byte over another of one price, two decisions chained, a delivery no route survives, one under a record of
  version 2, one verified without receipts, and an empty `deliveries`. `route_record_verify.py` verifies each from
  the text. It catches each of its 31 new checks dropped and every mutated copy.
- **The registry** lists `wai-route-delivery-decision` as a document kind of route-record §6.3 (REGISTRY.md and
  `codecs/registry.rs`).
- **Breaking:** `api:rust:wai::route_record::Accepted::deliveries`: what the decisions state, `None` when the
  document has none. A struct literal of `Accepted` needs it.
- **Breaking:** `api:rust:wai::route_record::Document::deliveries`: the deliveries' texts, `None` when the document
  has none. A struct literal of `Document` needs it.
- **Breaking:** `api:rust:wai::route_record::Reason::DeliveryInvalid`,
  `api:rust:wai::route_record::Reason::DeliveryRouteMismatch`,
  `api:rust:wai::route_record::Reason::DeliveryParentMismatch` and
  `api:rust:wai::route_record::Reason::DeliveryChainBroken`: four reasons, which an exhaustive match over `Reason`
  needs.
- **Breaking:** `api:rust:wai::route_record::Reason::ALL`: the list of §8's codes holds those four, an array of 29.
  A use that names its length needs the new one.
