# .WAI™ — Web AI Media Transport & Execution Status: **Draft Standard**. `1.0` is the wire version of the `WAI1` envelope, carried in the manifest's `wai` member, and `1.1` that of the `WAI2` envelope (§7.1); neither is a release of this document. Reference implementation: `wai-rs/` (Rust lib + cdylib + staticlib, C FFI). Two paths open every conforming file: - the **neural condition** — the sink regenerates the media from a compact conditioning payload against a *shared ambient prior* (a model). The model is a **requirement of existence**, never transported in the envelope that decodes against it, exactly as `.mp3` does not ship its decoder. Its identity MAY be pinned: the manifest MAY carry a *pin*, the SHA-256 of the whole parameter set the payload was coded against (§3.1), and a sink whose parameter set does not match the pin does not decode against it (§4, §7.1). The pinned set's wire form MAY be declared ([prior-carriage](extensions/prior-carriage.md)). - the **zeroth condition** — a *menu of registered standard codecs* (AVIF, JPEG XL, PNG, Opus, FLAC, AV1, zstd, XZ and the others §5 registers), each decoded by the sink with the library it already has. WAI dispatches registered standard codecs and also defines WAI-native capability classes (§5): integer codecs, worlds, scores, films and the other extensions, each with its own payload format and conformance criterion. The capability a file requires is *named*, not supplied. Sinks that have the named capability use it; sinks that don't fall back to a declared `fallback` capability. Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119. --- ## 1. Scope and model WAI is a **container + capability dispatch standard**. It is media-general; its floor and recommended set are royalty-free. Its substance is the envelope, the dispatch rules and the registry's classes: a standard codec is dispatched to a sink's existing decoder, not re-implemented. A WAI file declares (in its manifest): - what media it carries, - what *capability* a sink must have to decode it, - a fallback capability the sink can use if it lacks the primary, - the conditioning bytes for that capability, - and, OPTIONALLY, for a capability that decodes against a parameter set, the pin of the set the payload was coded against (§3.1). Conforming sinks MUST implement the container envelope (§2), the manifest schema (§3), the capability-dispatch algorithm (§4), and at least the **mandatory floor** capabilities (§5). Other capabilities are OPTIONAL; §5 says which are RECOMMENDED. --- ## 2. Container ``` +--------+----------------+-------------------+----------------+-----------+ | "WAI1" | u32 man_len | manifest (JSON) | u32 payload_len| payload | | 4 B | little-endian | man_len bytes | little-endian | bytes | +--------+----------------+-------------------+----------------+-----------+ ``` - Bytes 0..4 MUST be ASCII `WAI1`. A reader MUST reject any file whose first 4 bytes differ. - `man_len` and `payload_len` are unsigned 32-bit little-endian. - The manifest is UTF-8 JSON, serialized with no insignificant whitespace, preserving key insertion order. Readers MUST NOT depend on key order for *semantics*; encoders SHOULD preserve order so files round-trip byte-identically. - Member names are unique within each object of a manifest, at any depth: a manifest that names a member twice in one object is malformed, and a reader rejects it as it rejects any manifest that does not parse. Names compare after their escapes are read. - An integer member of a manifest, or of any JSON this specification or its extensions define, is a JSON number written as an integer: digits, with a minus sign only before a non-zero value, and no fraction or exponent. `-0`, `1.0` and `1e0` are not integers, whatever their value, and a member that must be an integer and is written so has the wrong type. - The payload is opaque codec bytes whose interpretation is fully determined by the manifest's `model_requirement.capability` and, for a capability that decodes against a parameter set, by that set, which the manifest MAY pin (§3.1). All WAI multi-byte integers are little-endian unless stated otherwise. **Reader limits.** A reader MUST NOT refuse a manifest for its length, its nesting or the number of its values while it is at most 134 217 728 bytes (`man_len` ≤ 2²⁷), its arrays and objects nest at most 127 deep, the manifest object itself counting as one, and it holds at most 4 194 304 JSON values (2²²), counting the manifest object and every value nested in it at any depth; a member's name is not a value. It MAY refuse a longer or deeper manifest, or one that holds more values. The limits hold the largest manifest a conforming layer has: a `prev` ([staged-delivery](extensions/staged-delivery.md) §3) that names a different producer for each of the 2²⁰ units a `WIR1` layer may cover (staged-delivery Appendix A.3, `n_units` ≤ 2²⁰) is about 94 MB, and three values a run (the run, its `producer` and its `count`), 3·2²⁰ and a few more in all. A reader that refuses one past the length limit does so from `man_len` alone, before it reads or requests the manifest (`manifest_too_large`). A reader that refuses one past the value limit does so while it counts the values, before it builds anything from the manifest (`manifest_too_many_values`). The reference readers refuse all three. The same limits apply to the `WAI2` manifest (§7.1), whose `renditions` lists no more entries than its table holds. They move no byte of the layout above, which stays frozen (§8). Since a conforming encoder emits only containers every conforming sink can read (§7), a conforming encoder writes no manifest past any of these limits; the reference writers refuse one past any of them. Together the length and value limits bound what parsing a manifest takes, which the length limit alone does not: a parsed value takes more memory than its text, and many small values can take many times their length. The reference readers count a manifest's values before they build anything from it, then build each array and object at the size counted, and on a 64-bit target allocate at most 128 bytes for each value and one for each byte of the manifest, with, for a `WAI2`, a rendition entry of 768 bytes for each it lists: at most 640 MiB for a `WAI1` manifest at both limits, whatever its shape, and 48 MiB more for a `WAI2`'s entries (informative; `SECURITY.md`). A `wai.text.zstd` or `wai.text.xz` payload (§5) has reader limits of its own, since neither stream format bounds what a payload may ask of its decoder. A reader MUST NOT refuse one for the length it decodes to, or for the history its decoder must keep, while it decodes to at most 134 217 728 bytes (2²⁷) and every frame or block of it declares at most 2²⁷ bytes of history: for Zstandard the frame's window size, which for a single-segment frame is its content size (RFC 8878 §3.1.1.1); for XZ the LZMA2 dictionary size. It MAY refuse one that decodes to more (`text_decoded_too_long`) or declares more (`text_window_too_large`). A reader that refuses for length does so when its output would pass the limit, in a buffer it never sizes past the limit; where a Zstandard frame declares a content size past the limit, it does so from the declaration, before it decodes anything. A reader that refuses for the history does so from the declaration, before its decoder allocates it. The reference readers refuse both. A decode then takes its output, at most the length limit, the decoder's history, at most the other, and the decoder's fixed state. As for a manifest, a conforming encoder writes no payload past either limit, and the reference writers refuse one; bytes longer than the length limit are carried as more than one object. A picture, audio or video payload of the mandatory floor or the recommended set (§5) has reader limits too, since its format bounds what it may ask of a decoder loosely or not at all. A reader MUST NOT refuse a picture (a `wai.image.png`, `wai.image.jpeg`, `wai.image.avif` or `wai.image.jxl` payload, or a frame of a `wai.video.av1` or `wai.video.av1.lossless` one) for its size while it is at most 65 536 pixels wide and tall and holds at most 134 217 728 pixels (2²⁷, a 16 384 × 8 192 picture). It MUST NOT refuse a `wai.audio.flac` or `wai.audio.opus` payload for its length while it decodes to at most 134 217 728 samples (2²⁷), counting every channel: 46 minutes of one channel at 48 kHz. It MUST NOT refuse a `wai.video.av1` or `wai.video.av1.lossless` payload for its length while its framing header (§5, *Payload framing*) declares at most 1 048 576 temporal units (2²⁰), 4.9 hours at 60 frames a second. It MAY refuse one past any of these: a picture (`image_too_large`), audio (`audio_decoded_too_long`) or video (`video_too_large`). A reader that refuses a picture does so from the size its payload declares, before it decodes a pixel: the PNG `IHDR`, the JPEG frame header, the `ispe` property of each image item of an AVIF, the JPEG XL size header, the AV1 framing header's `h` and `w`. One that refuses audio does so when its output would pass the limit, in a buffer it never sizes past the limit, and where a FLAC `STREAMINFO` declares a total past the limit, from the declaration, before it decodes. One that refuses video does so from the framing header. A picture or audio decode then takes its output and the decoder's state; a video decode that hands on each frame as it decodes takes one frame and the decoder's reference frames, whatever the payload's length. (A reader that keeps every frame at once needs n · h · w pixels; the reference library's whole-output entry points refuse a payload past a budget, 4 GiB by default, and decode one frame at a time otherwise; informative, `SECURITY.md`.) As for text, a conforming encoder writes no payload past these limits, and the reference writers refuse one; longer audio and video are carried as more than one object. An envelope delivered over HTTP is one object of the proposed media type `application/wai`, named by its receipt content hash, and fetched whole or, for a `WAI2`, one verified component at a time ([http-delivery](extensions/http-delivery.md)). --- ## 3. Manifest schema ```json { "wai": "1.0", "media": "image" | "audio" | "video" | "text" | "volumetric" | "haptic" | "metadata" | "interactive" | "binary", "intent": "replicate" | "create" | "improve" | "...", "model_requirement": { "capability": "", "fallback": "" | null }, "conditioning": { "kind": "", "prior": { ... } }, "security": { "encryption": "" | "none", "kid": }, "refines": { ... }, "frame": { ... }, "target": { ... } } ``` - `wai` — the envelope's wire version. This document defines `"1.0"` (a `WAI2` envelope's is `"1.1"`, §7.1). Unknown major → reject. Unknown minor → accept. A reader ignores a member it does not understand, whatever the minor (§8). - `media` — media class; informational. The capability is authoritative. The values are the registry's media classes (`codecs::capability_media`; [`registry/capabilities.json`](registry/capabilities.json)): `image`, `audio`, `video`, `text`, `volumetric` (meshes, point clouds, Gaussian splats), `haptic`, `metadata` (data applied with another payload), `interactive` (worlds, feeds, avatars) and `binary` (anything else). A reader MUST accept a value it does not know: the field is informational, and a MINOR revision may add a value (§8). - `intent` — generative intent. `replicate` (reconstruct the source) is the only intent with normative reconstruction semantics in this document. What it promises is set by the capability's registry class (§7, *Replicate-soundness*): a byte-exact reconstruction — every conforming sink that decodes the payload produces the same bytes (decode-equivalence) — where the capability's reconstruction is specified exactly; and, for a standard codec whose named standard holds decoders to a criterion around a reference rather than to identical output (Opus's thresholds, RFC 6716 §6, are one), no more than that standard's decoder conformance, so conforming sinks' reconstructions may differ as far as that criterion allows; for a standard codec §7 has not yet classified, what its standard's decoder conformance states, which the registry does not assert is byte identity. For a **neural** capability, `replicate` promises decode-equivalence and is sound only under the integer-entropy contract (§7), with a pin (§3.1, §7): a capability whose decode runs float, or whose entropy decode alone is integer, MUST NOT claim it. That is WAI's rule, and this revision applies it to `wai.image.jpegai` as well; it is not a finding that JPEG AI's standard leaves the reconstruction unbounded (§7, `NeuralEntropyExact`). - `model_requirement.capability` — the capability string a sink MUST resolve. See §5 for the registered set. - `model_requirement.fallback` — a second capability the sink MAY use if it lacks the primary, or if the envelope's pin does not resolve for the primary at the sink (§4 step 3). `null` means the file is inert without the primary. An encoder whose primary capability decodes with a module a sink obtains apart from the envelope does not write `null` (§4). - `conditioning.kind` — short codec id matching the capability. Helps multiplexers route bytes without parsing the full capability string. - `conditioning.prior` — OPTIONAL. The pin (§3.1) of the parameter set the payload was coded against. It applies to whichever of `model_requirement.capability` and `model_requirement.fallback` decodes the payload (§4), where that capability decodes against a parameter set. Absent, or `null`, the key is not written, and a decode through such a capability is unpinned: it runs against whatever parameter set the sink holds, and it cannot back `intent = replicate` over a `NeuralIntegerExact` capability (§7). An encoder SHOULD write it wherever such a capability decodes the payload, whatever the intent (§3.1, *Pin by default*). - `security` — OPTIONAL. Absent, `null`, or `encryption: "none"` ⇒ the payload is plaintext (the default). Otherwise the payload is encrypted and MUST be recovered before dispatch; see §6. The capability, media, and conditioning fields always describe the **plaintext** codec. - `refines` — OPTIONAL. Carried exactly when `model_requirement.capability` is refinement-only (§5, *Refinement capabilities*): what the payload refines, by content hash ([staged-delivery](extensions/staged-delivery.md) §3). A manifest that carries it has a `null` `fallback`. - `frame` — OPTIONAL. Carried exactly when `model_requirement.capability` is a frame capability (§5, *Frame forms*): the frame's index in its group and the content hash of the frame before it, and, where its publisher states them, its sequence number in its stream and its capture time ([frame-stream](extensions/frame-stream.md) §2). A manifest that carries it has a `null` `fallback`. - `target` — codec-specific reconstruction parameters (dimensions, sample rate, duration, frame count). Informational; the payload is self-describing per the codec's own format. ### 3.1 Parameter-set pin (`prior`) A capability **decodes against a parameter set** when its registry class (§7) is `NeuralIntegerExact`, `NeuralEntropyExact`, `NeuralFloat` or `GenerativeDeterministic`. Its **parameter set** is every byte, other than the payload, that its decode reads and that its output depends on: networks, entropy tables, normative constants. The sink supplies it; the envelope never carries it (§1). §5 registers each such capability's parameter set as **one file** or **several files**; a capability registered with neither, and a capability this revision does not register, is treated as several files. A manifest names the parameter set a payload was coded against with a **pin**. One capability is the exception: the payload of `wai.generate.spectral` names its own parameter set, the model file, by SHA-256, and an envelope that names it carries no pin (§5, *Payload of `wai.generate.spectral`*). The payload of `wai.avatar.face` names, by SHA-256, the identity prior its frames are generated from, an input of the decode as the payload is; a pin names its parameter set, the generator, and covers no identity prior ([avatars](extensions/avatars.md) §7.4). ```json "prior": { "id": "", "sha256": "<64 lowercase hexadecimal digits>", "determinism": "", "form": "", "tier": "decode-equivalence", "supersedes": { "sha256": "<64 lowercase hexadecimal digits>", "form": "" } } ``` | member | presence | meaning | |---|---|---| | `id` | REQUIRED, string | A name for people and logs. A sink MUST NOT select, resolve or accept a parameter set by it. | | `sha256` | REQUIRED, string | The SHA-256 (FIPS 180-4) of the parameter set in its form (below), as 64 lowercase hexadecimal digits. | | `determinism` | REQUIRED, string | How the decode is made reproducible, in words. Informative, except where §7 reads it for a pin without `tier`. | | `form` | OPTIONAL, string | A registered prior form (§5; [prior-carriage](extensions/prior-carriage.md)). | | `tier` | OPTIONAL, string | The reproducibility tier ([determinism-tiers](extensions/determinism-tiers.md) §2) the sender claims for the decode, from a closed vocabulary: `decode-equivalence`, `entropy-consistency`, or `none` for neither. | | `supersedes` | OPTIONAL, object | Informative. The parameter set this one replaces, named as a pin names one: its `sha256` (REQUIRED) and, if it is pinned in a declared form, that `form`. | A `prior`, or a member of it, whose JSON type is not the one given makes the manifest malformed, and a reader rejects it as it rejects any manifest that does not parse. A mistyped member is never read as absent: a `form` dropped that way would turn a set-form pin into a form-less one, which a single file can satisfy. `null` in an OPTIONAL member is the same as the member being absent. A member this section does not define is ignored (§8). An optional member that is absent is not written, so a pin written without it keeps its bytes. **What the digest covers.** A pin identifies the whole parameter set. - With `form` absent, `sha256` is the SHA-256 of the one file that holds the set. That is admissible only for a capability registered with a one-file set. - With `form` present, `sha256` is the SHA-256 of the set serialized in exactly that form ([prior-carriage](extensions/prior-carriage.md) §2). The form `wai.prior.set` serializes a set of one or more files as its **listing**, so a pin in that form covers every file of the set: - The listing has one line for each file: the file's SHA-256 as 64 lowercase hexadecimal digits, two spaces (0x20 0x20), the file's path, and a line feed (0x0A). - A path names the file below the set's root: one or more segments joined by `/` (0x2F). A segment begins with one of `A`–`Z`, `a`–`z`, `0`–`9`, `_` and `-`, continues with any of those and `.`, and does not end with `.`. - The lines are in strictly ascending order of their paths compared as byte strings. No two paths are equal once `A`–`Z` are mapped to `a`–`z`, and no path followed by `/` begins another path. - The listing is its lines concatenated. It has at least one line and nothing else: no header, no byte-order mark, no carriage return, no blank line. A listing is the text common checksum utilities write and check, so a third party can check a set against its listing, and a listing against a pin, without WAI software. **Verification.** A sink that is to decode through a capability, for an envelope whose pin applies to that capability, MUST verify the pin first. A pin applies to a capability that decodes against a parameter set, and to a capability this revision does not register when the sink advertises it (such a string is dispatchable, §4): such a capability is verified as several files, so a form-less pin over it is refused (`form_required`). The pin **resolves** when the sink holds a parameter set for the capability whose digest, in the pin's form, equals `sha256`: in the form `wai.prior.set`, a listing whose SHA-256 is `sha256`, together with every file the listing names below the listing's root, each with the SHA-256 its line gives. Nothing else satisfies a pin: not a matching `id`, not a set that `supersedes` names or that names this one, and not a set in another form whose unpacked parameters compare equal. A sink MAY hold several parameter sets for one capability; the pin resolves when one of them satisfies it. A pin that does not resolve is refused with one reason. The checks run in this order, and the first that fails is the reason reported: 1. `pin_malformed`: `sha256` is not 64 lowercase hexadecimal digits. 2. `form_not_registered`: `form` names no registered prior form. 3. `form_unreadable`: `form` is registered and the sink has no reader for it. This is the sink's gap, and it is never reported as a mismatch. 4. `form_required`: `form` is absent and the capability is not registered with a one-file set. 5. `prior_revoked` or `prior_not_authorised`: the sink holds a key log ([jwp-receipts](extensions/jwp-receipts.md) §7), and it refuses the set this pin names, which it identifies by the pin's `sha256` in the pin's `form`. The reason is `prior_revoked` when that digest is in the `revoked_modules` of the head the sink reaches from any anchor it holds, or, where none can be reached, of that anchor revision (§7.9 check 5). A revocation needs no grant, status or clock, so this part runs for every capability a pin applies to, and whichever check of §7.9 a grant fails first. Where the sink also holds the capability's pinned parameter sets to §7.9 (§4, *Module authorisation*), §7.9 authorises the set as a decoder module, and the reason is `prior_not_authorised` when §7.9 does not hold it for any other reason — no grant from one of the sink's module origins, a granting key §7.4 does not confirm, no fresh status because the sink is offline or has no clock it trusts, a grant outside its window or for another capability — or the sink holds no grant for the set. The sink reports §7.9's check and reason with it. A sink that holds no key log skips this check. Check 5 covers every identity of the bytes the decode reads, not only the pin's: once checks 6 to 8 have found the set, the sink runs this check again over each digest a pin over those bytes could name — the listing of the files the decode reads, and, for a capability registered with a one-file set, that file's SHA-256 — so a set refused under one identity is not reached through a pin that names it by another (a set-form pin over a listing of one revoked file, or a listing that adds a file the decode does not read). Authorisation needs one of them to be held; the pin's own digest, which passed above, is one. 6. `prior_not_held`: the sink holds no parameter set for the capability whose digest, in the pin's form, equals `sha256`; a file the sink cannot read is not held. A sink that holds the set a well-formed `supersedes` names — a file when `supersedes.form` is absent, a listing when it is `wai.prior.set` — reports `digest_superseded` instead, so that its operator can tell it holds the set this one replaces. 7. `set_malformed`: in the form `wai.prior.set`, the listing whose SHA-256 is `sha256` breaks a rule above. 8. `part_mismatch`: in the form `wai.prior.set`, in every copy of that listing the sink holds, a file the listing names is missing, cannot be read, or has a SHA-256 other than its line gives. These checks read the envelope, the registry, the forms the sink can read and the bytes it holds, and nothing that depends on how the sink was built, so two conforming sinks that read the same forms and hold the same bytes report the same reason. Check 5 also reads what the sink holds under jwp-receipts §7.9 and its clock, so two sinks that hold the same key-log material and agree on the time report the same reason there. Refusal reasons are snake_case; tier names and class labels are kebab-case. **Decoding against a verified set.** A pinned decode MUST read its parameters only from the set it verified. A decode that needs a file the verified set does not contain is refused with `set_incomplete`; the sink presents no output from it, and dispatch treats it as a pin that did not resolve. A file a model names for part of its own data, such as the file an ONNX tensor stored as external data names, is a file the decode needs: when the decode cannot take it from the verified set, it is refused the same way. A sink SHOULD decode from the very bytes it verified: one that reads a file again after verifying it can decode bytes it did not verify. **A refused pin** makes its capability **unsupported for that envelope** at that sink. It is not a decode error and not a reason to decode anyway, as [capability-constraints](extensions/capability-constraints.md) §2 treats an unmet constraint. Dispatch continues as §4 and §7.1 state. A sink MUST NOT decode a payload through a capability whose pin it refused. **Tier.** `tier` is the sender's claim, from the registered vocabulary `decode-equivalence`, `entropy-consistency` and `none`. An encoder MUST write a registered token. A sink reads a token this revision does not register as `none`, and a verifier reports it (`tier_unregistered`). The tier a registry class gives is `decode-equivalence` for `NeuralIntegerExact`, `entropy-consistency` for `NeuralEntropyExact`, and `none` for every other class. With the tiers ordered `none` < `entropy-consistency` < `decode-equivalence`, a `tier` above the class's does not conform (`tier_exceeds_class`): the `replicate` verdict (§7) does not rest on it, and a verifier reports it. The decode itself is unaffected. A `tier` at or below the class's is honoured as stated. **Updates.** `supersedes` is informative: it records that the set a pin names replaces another, changes no decision, and changes only the reason check 6 reports. A `supersedes` whose `sha256` is not 64 lowercase hexadecimal digits or equals `sha256`, or whose `form` is not a registered prior form, is malformed: a verifier reports it (`supersedes_malformed`), and a sink ignores the member and so never reports `digest_superseded` for that pin. Content coded against a set pins that set, and a successor never satisfies its predecessor's pin, so content coded against a predecessor decodes at a sink exactly as long as that sink still holds the predecessor. A sink can hold both without a second copy of the files they share, by keeping the predecessor's listing beside the successor's. An update delivered as a change to an earlier set, such as an NNC incremental update, is not a parameter set and is never pinned; the self-contained set it yields is ([prior-carriage](extensions/prior-carriage.md) §2). **Where a pin sits.** In a `WAI1` manifest, `conditioning.prior` (§3). In a `WAI2` manifest, a rendition entry's `prior`, which pins that entry's capability and is part of the entry's identity (§7.1). A pin where no capability it would apply to decodes against a parameter set, and every such capability is registered, means nothing: an encoder MUST NOT write one, a verifier reports it (`prior_not_applicable`), and a sink ignores it. **Pin by default.** A pin is OPTIONAL in `1.x`, and only `replicate` over a `NeuralIntegerExact` capability requires one (§7). Elsewhere an unpinned decode runs against whatever parameter set the sink holds, and a set other than the one the payload was coded against gives plausible output, not an error (§4). So: 1. An encoder SHOULD pin the parameter set a payload was coded against wherever a capability that decodes the payload — `model_requirement.capability`, `model_requirement.fallback`, or a `WAI2` entry's capability — is registered as decoding against one, whatever the envelope's `intent`. `wai.generate.spectral` is the exception above: its payload names its set. 2. An envelope that pins nothing there conforms, unless §7 requires the pin (`replicate_unpinned`). A sink decodes it as before. 3. A verifier reports it (`prior_unpinned`). The report is informative: it is not a finding that the envelope does not conform, and it is made whatever else the verifier finds. A capability this revision does not register is not reported, since this revision does not know what it decodes against. 4. A sink that records a decode names the parameter set it read, pinned or not, by the digest a pin over those bytes names ([jwp-receipts](extensions/jwp-receipts.md) §2.4.12, a decoder entry's `pin`), so that a decode against another set is visible after the fact. **Sinks of earlier revisions.** A sink that implements an earlier text of this specification may do one of two things with a pin (§8). It may reject the envelope as carrying a member it does not understand, which fails closed. Or it may ignore `prior`, and then the pin fails open: such a sink may decode a pinned payload against another parameter set. The rules of this section bind sinks that implement this revision; an encoder that must not be decoded against another set at an earlier sink has no means to require that within `1.x` other than a capability string earlier sinks do not advertise. **Envelopes these rules make non-conforming.** The rules enforce the definition of `prior` as it was made — a lowercase hexadecimal SHA-256 of the artifact that determines the decode's output, which a `replicate` over an integer-exact neural capability requires — and change no payload format and no role (§8). Each of these envelopes but the last still parses, and does not conform: - one whose pin's `sha256` is not 64 lowercase hexadecimal digits (the reference implementation compared digests without regard to case or length); - one whose pin has no `form` for a capability registered with several files: its digest covered one file of the set or, where the registered artifact was a directory, nothing a sink could hash; - one that carries a pin where no capability it would apply to decodes against a parameter set; - one with `intent = replicate` whose decode capability is `NeuralIntegerExact` and which pins no parameter set for it, or pins one that does not declare `decode-equivalence` (§7); the reference implementation already refused these; - one that carries a member this revision defines — `conditioning.prior` or a rendition entry's `prior`, a pin member, or a rendition entry's `id`, `sha256` or `companion_of_id` (§7.1) — with a JSON type other than the one defined. A reader of an earlier revision may have ignored the member; a reader of this one rejects the manifest as malformed, so this envelope no longer parses. §8 states this as the one exception this revision makes to the `1.x` freeze. --- ## 4. Capability dispatch A conforming sink MUST implement this algorithm: 1. Read the manifest. If `wai` major version is unknown → reject. 2. Let `cap = model_requirement.capability`. 3. If `cap` is dispatchable (below), the sink advertises `cap` — holding under jwp-receipts §7.9 any module it obtained apart from the envelope to decode `cap` (*Module authorisation*, below) — and, when a pin applies to `cap` (§3.1) and the manifest carries `conditioning.prior`, the pin resolves at the sink for `cap`, decode `payload` via the codec registered for `cap` (§5), against the verified set, and return. A pin that does not resolve makes `cap` unsupported for this envelope: keep its reason and continue at step 4. 4. Else, let `fb = model_requirement.fallback`. 5. If `fb != null`, `fb` is dispatchable and the sink advertises `fb` on the same terms, and, when a pin applies to `fb` and the manifest carries `conditioning.prior`, the pin resolves at the sink for `fb`, decode via `fb`'s codec and return. A pin that does not resolve: keep its reason. 6. Else the file is **inert at this sink** — return an error to the calling application that names why: the reason kept at step 3, else the one kept at step 5, else `missing_capability`. `conditioning.prior` pins the parameter set the payload was coded against, so it applies to whichever capability decodes the payload. A pin that does not resolve is never a reason to decode against another parameter set: a learned decode against the wrong parameters yields plausible output, not an error. An encoder that needs an alternative for sinks that hold another parameter set carries one pinned rendition per set in a `WAI2` envelope (§7.1). **The unit that runs a decode.** Which unit of the sink's device runs a learned capability's networks — a neural processor, a GPU or the CPU — is the sink's choice, made once this algorithm has chosen the capability, under the tier the decode needs: a path that computes in floating point never runs a decode that needs `decode-equivalence` ([neural-dispatch](extensions/neural-dispatch.md) §3). The choice changes no step above, and a sink states it in the report of neural-dispatch §5. **Energy order.** Steps 3 and 5 are tried in the **energy order**, which a sink applies unless its deployer configures another. It is an order over what the sink advertises, and never a reason to advertise or not: what a sink advertises is decided as above (in a web page, by the object's route, below). Each capability ranks, lowest first: 1. `first`: classical decode the sink's platform answers supported, smooth and power-efficient (a page's Media Capabilities `decodingInfo()` once WebCodecs `isConfigSupported()` has answered supported; a native platform's own decoder query; [platform-decode](extensions/platform-decode.md) §2, §3). In a page the answer counts only for an object routed to the user agent's decoder (browser-sink §4.7). `powerEfficient` is the user agent's hint: it orders, and is never an energy figure or evidence of hardware; 2. `smooth`: classical decode the platform answers smooth, not power-efficient; 3. `classical`: any other classical decode the sink can make, every classical capability of a sink with no platform to ask among them; and a learned capability whose decode the sink holds a qualifying measurement of (below); 4. `learned-without-budget`: a learned capability — one whose replicate class (§7) is not one of the three standard classes, or a string this revision does not register — with no such measurement. Where `fb` ranks before `cap`, the sink takes steps 4 and 5 before step 3, and step 3 only if step 5 does not decode; otherwise it takes them as listed. So a learned capability without a qualifying measurement is never decoded above a classical fallback the sink can decode, and a decode the platform answers smooth or power-efficient comes before a software one. The order never makes inert an envelope either capability could decode, and it changes nothing else: an inert envelope reports the reason kept at step 3, else the one kept at step 5, whichever was tried first. A sink whose deployer configures the manifest's order instead takes the steps as listed, and says so wherever it reports a decode (a capability report, a receipt's notes, its logs). A manifest states no energy, and a figure in a receipt is the producer's (encode) energy, not the sink's decode, so the order reads neither. **The measurement a learned capability needs** is a sink-metered figure of its decode on this sink, signed by the sink's meter with its class, its declared uncertainty, its coverage and the fabrics it covers, in the shape of [browser-sink](extensions/browser-sink.md) §6's energy entry. It qualifies when it reads under §6 there with the class `OnChipCounter` or `CalibratedInstrument` and the coverage `Whole`. The order reads only whether such a figure is held, never its value: a figure changes no route and steers no choice (browser-sink §6). A deployer MAY set a policy of its own that also compares the figure, per decode, with a ceiling; the default sets none. The reference dispatcher applies the order in `Wai::dispatch_verified` and `WaiMulti::pick`, takes another through `dispatch_with` and `pick_with`, and ranks with `energy_order::DispatchPolicy`. A capability is **dispatchable** unless this revision registers it as something a sink does not decode on its own: a candidate (§5, *Candidate capabilities*), a companion-only capability (§5, *Companion-only capabilities*), a refinement-only capability (§5, *Refinement capabilities*), a record or a derivation (§5, *Kinds of registered string*). A sink MUST NOT take step 3 or step 5 with a capability that is not dispatchable, whatever it advertises. A string this revision does not register is dispatchable: a later MINOR revision may register it (§8), and a sink that has a codec for it says so by advertising it. A `WAI1` whose `cap` is companion-only does not conform and is inert: its payload is companion data, so step 5 is not taken either (§5). A WAI **payload always corresponds to exactly one capability**. No payload multiplexes several codecs. Dispatch goes by `cap`: a `WAI1` whose `cap` is not refinement-only is dispatched as above whatever else its manifest carries, a `refines` member included, which such a manifest MUST NOT carry and a sink ignores ([staged-delivery](extensions/staged-delivery.md) §3). A sink never takes step 3 or step 5 with a capability §5 registers as **refinement-only**, and a `WAI1` whose `cap` is refinement-only takes neither: its payload refines the output of a base, and [staged-delivery](extensions/staged-delivery.md) §4 processes it. A sink that does not implement that extension finds the capability unsupported, and the envelope is inert. If the manifest declares `security.encryption` other than `"none"` (§6), the sink MUST recover the plaintext payload before step 3 and run this algorithm on the plaintext; see §6.4. **Module authorisation.** A module is code a sink obtains apart from the envelope and runs to decode a capability, or to rebuild a reconstruction from what a decoder produced: a decoder or reconstruct module ([`extensions/jwp-receipts.md`](extensions/jwp-receipts.md) §7.9). A sink that decodes `cap` with one MUST hold it under §7.9 for the envelope before it runs it, from one of the sink's module origins (§7.9): the origins its relying party names, and the origin under which it confirmed the envelope's delivery. A module that is not held — not granted by a module origin, revoked, or not checkable because the sink is offline or has no clock it trusts — leaves `cap` not advertised for that envelope at steps 3 and 5. A sink that holds a key log refuses a parameter set whose digest the key log revokes (§3.1 check 5, `prior_revoked`). A sink MAY also hold the parameter sets envelopes pin to §7.9, by its relying party's choice per capability; for such a capability §3.1's check 5 also refuses a pinned set §7.9 does not hold (`prior_not_authorised`). A refused pin does not resolve. An envelope that pins no set is decoded against the set the sink holds for `cap`, and a sink that holds a key log runs check 5 over that set too, identified by each digest a pin over it could name: it does not decode `cap` for that envelope when any of them is revoked, or, for a capability it holds to §7.9, when §7.9 holds the set under none of them. It then decodes from the bytes check 5 ran over alone, as a pinned decode reads only what its pin verified (§3.1): read once, so a file changed after the check is not what the decode reads, and, for a capability it holds to §7.9, only the part §7.9 holds (the set, the files a held listing names, or one held file); a file the decode needs outside them is `set_incomplete`. Either way the algorithm above runs unchanged, so a sink MUST NOT report a file inert because of module authorisation while a fallback it can decode without that module remains, and an encoder emitting a capability whose decode needs a module MUST declare such a fallback (§3). A sink configured with no key log holds no module under §7.9, so it runs no module obtained apart from an envelope, and it does not run check 5. The reference dispatcher in `wai-rs` runs no module obtained apart from an envelope; it runs check 5 when the sink is configured with a key log (`key_log::SinkKeyLog`, feature `key_discovery`, given to `pin::verify_with`, to `int_payload::resolve` (which runs it for a pinned decode and over the files an unpinned integer decode reads) or to `neural::ModelRegistry::with_key_log`, which also runs it before an unpinned decode, over the bytes that decode then reads, read once: an integer decode's members, and otherwise the registered file of a one-file set, or every file below the directory the decoder reads from, identified by the listing `pin::listing_of_dir` derives, each file's digest and each listing beside them that matches): the revocation part for every capability a pin applies to, and §7.9's authorisation for the capabilities the sink holds to it. `wai-web` and the C ABI take no key log. **A sink in a web page** answers step 3's "the sink advertises `cap`" for an object with the object's route ([browser-sink](extensions/browser-sink.md) §4): to the user agent's own decoder, put only codec strings the WebCodecs Codec Registry lists and taken only where its output holds the tier the object needs; to a native host's decoder; or to WAI's own WebAssembly decoder, which depends on nothing the device must ship. It advertises `cap` for that object when the route is not `none`. It evaluates the capability's constraint sets ([capability-constraints](extensions/capability-constraints.md)) before dispatch, reports a measured figure per decode beside the user agent's own power-efficiency answer, which stays the user agent's, and binds every frame it decodes to the receipted object it came from (browser-sink §7). Where it holds several objects that are alternatives of one content (a `WAI2` envelope's entries, or a `WAI1` envelope's capability and fallback), it decodes the one the energy order above puts first among those it can route, the order sitting inside the routing and changing no route (browser-sink §4.7). The algorithm above is unchanged. --- ## 5. Registered capabilities (the zeroth menu) WAI registers the following capabilities. Each names a standard codec or a WAI-native class. The mandatory floor and the recommended set are royalty-free; every payload and companion capability carries a licence class (see the end of this section), and one that is not royalty-free is never a default. The "payload format" column is the on-the-wire payload bytes. For a standard codec it is the canonical bytes that codec normally emits (a JXL file, an Opus stream, etc.) — WAI does not wrap or re-frame them. For a WAI-native class it is the format the class's registration or extension defines; for the WAI-native integer codecs, the format *Payloads of the WAI-native integer codecs* (below) pins. The registry is also published in machine-readable form, generated from the reference implementation: [`registry/capabilities.json`](registry/capabilities.json) and its schema, with the policy that governs it in [`REGISTRY.md`](REGISTRY.md). Where the two differ, this section is normative and the generated files are wrong. **Kinds of registered string.** Every string this section registers has one kind: - a **payload** capability: an envelope's `capability`, `fallback` or `WAI2` rendition names the codec its payload is decoded with; - a **companion** capability: companion-only (*Companion-only capabilities*, below), carried only as a `WAI2` companion; - a **refinement** capability: refinement-only (*Refinement capabilities*, below), applied to the output of the stage below it and never decoded on its own; - a **derivation** operation (`wai.derive.*`): an operation on samples another capability decoded, which names no payload format; - a **record**: a signed record a WAI tool emits and verifies (a receipt kind, a delivery record, or a record of one of the extensions this section registers; [REGISTRY](REGISTRY.md) lists every one, kind `record`), which names no payload format. Only payload, companion and refinement capabilities have a media class, a fidelity tier, a replicate class and a role. A derivation or record string is not a payload capability and is not dispatchable (§4): step 3 does not take an envelope's `capability` that names one, and step 5 may still take a usable fallback. A row of the tables below that registers a record says what the record attests, not a payload format. Named sub-identifiers this section uses — `wai.det.fixed64`, `wai.det.amp64`, `wai.world.sim.feed0`, `wai.world.sim.skeletal0` — name parts of a capability's definition and are not capabilities. ### Mandatory floor Every conforming sink MUST implement: | capability | payload | role | |---|---|---| | `wai.image.png` | PNG (W3C Recommendation, *Portable Network Graphics (PNG) Specification*, Third Edition) | universal lossless image | | `wai.audio.flac` | FLAC (RFC 9639) | universal lossless audio | | `wai.text.zstd` | Zstandard (RFC 8878) | universal compressed bytes | These three guarantee that any sink with the standard system codec libraries can open a file in the image, audio and text classes. The floor has no video capability. ### Recommended modern set Every conforming sink SHOULD implement: | capability | payload | role | |---|---|---| | `wai.image.jxl` | JPEG XL (ISO/IEC 18181) | lossless + lossy | | `wai.image.avif` | AVIF (the AOM AVIF specification: an AV1 image format based on HEIF, conforming to MIAF) | lossy (AV1-based) | | `wai.image.jpeg` | JPEG (ITU-T T.81) | compatibility with existing JPEG decoders | | `wai.audio.opus` | Opus (RFC 6716) | lossy speech and music | | `wai.video.av1` | AV1 (AOMedia) | lossy | | `wai.video.av1.lossless` | AV1 (AOMedia), `quantizer=0` | mathematically lossless YUV (lossy in RGB due to color conversion) | | `wai.text.xz` | XZ/LZMA2 | maximum classical text ratio | **Payload framing.** A `wai.image.*` payload is one file of its format as the named specification defines it, and a reader decodes it as that format only: PNG bytes are not a `wai.image.jpeg` payload. A `wai.audio.flac` payload is a FLAC stream (RFC 9639), its `fLaC` marker and `STREAMINFO` first. A `wai.audio.opus` payload is an Ogg Opus stream (RFC 7845); its `OpusHead` input sample rate is informational (RFC 7845 §5.1), so a reader decodes at a rate of its own choosing when the declared one is not an Opus rate. A `wai.video.av1` or `wai.video.av1.lossless` payload is five `u32` little-endian values, `n`, `h`, `w`, `fps_num` and `fps_den` (the number of temporal units, the largest frame's height and width, and the frame rate as `fps_num` / `fps_den` frames a second), then each temporal unit as a `u32` little-endian length and its bytes: the temporal unit in the low-overhead bitstream format (AV1 §5), every OBU with its size field. A payload holding more temporal units than `n`, or a frame larger than `h` × `w`, is malformed. [packaging](extensions/packaging.md) §7 writes its floor objects in this framing. A sink decodes AV1 in any profile, layout and depth AV1 allows. ### Neural capabilities (OPTIONAL, sink advertises if its ML runtime supports them) Each names a model the sink MAY have installed. Payload is a compact conditioning representation specific to the capability (latent tokens, prompt embeddings, etc.). The standard does not specify the byte layout of these payloads — the capability owner does — except where this section pins one: the integer codecs' payloads are pinned below (*Payloads of the WAI-native integer codecs*). Each row names the model and the operating point its own publication reports (bitrate, sample rate) or the property WAI's integer construction gives it; this section states no comparison between models or with the zeroth codecs. The decode route for each is implemented in the reference sink (see the `source` column / `neural/*.rs`); the model weights are sink-supplied. A capability that decodes against a parameter set (§3.1) is registered with that set's shape. **One file:** `wai.neural.int_synth` (its model specification, `int_synth.json`); `wai.neural.int_mlicpp` (its `WMB1` bundle, read from a set as `model.wmb`); `wai.audio.int_codec` (its `WAM1` synthesis, read from a set as `model.wam`); `wai.splat.int_codec` (its `WHM1` synthesis, read from a set as `g_s.whm`); `wai.avatar.face` (its generator, `WFG1`, [avatars](extensions/avatars.md) §7.2); `wai.video.int_cond` and `wai.video.int_cond.frame` (their `WCB1` bundle, read from a set as `model.wcb`, [integer-payloads](extensions/integer-payloads.md) §17.3); and `wai.neural.encodec32`, `wai.neural.encodec24`, `wai.neural.encodec48`, `wai.neural.dac`, `wai.neural.dac16`, `wai.neural.dac24`, `wai.neural.mimi`, `wai.neural.wavtokenizer`, `wai.neural.snac` and `wai.neural.video_bmshj2018` (a self-contained ONNX model; one that keeps tensors in external files is several files). **Several files:** every other capability that decodes against a parameter set; `wai.neural.int_hyper` and `wai.video.int_hyper` read `g_s.whm`, `h_s.whm` and `entropy.json` from theirs. `wai.audio.int_codec` and `wai.splat.int_codec` were registered as several files until this revision named their one-file formats. A later revision MAY register a capability of several files as one file when it defines a one-file format that holds the whole set; that widens the registration and makes no conforming envelope non-conforming (§8). *Audio:* | capability | model | operating point | source | |---|---|---|---| | `wai.neural.encodec24` | EnCodec at 24 kHz, mono, causal | 24 kHz; 2, 4, 8, 16 or 32 codebooks of 1024 at 75 Hz (1.5, 3, 6, 12 or 24 kbps) | EnCodec (arXiv 2210.13438) and its open release; payload: *Payloads of the neural audio codecs*, below; `neural/audio.rs` | | `wai.neural.encodec32` | EnCodec at 32 kHz, 4 codebooks | 32 kHz; 4 codebooks of 2048 at 50 Hz (2.2 kbps) | EnCodec (arXiv 2210.13438) | | `wai.neural.encodec48` | EnCodec at 48 kHz, stereo, non-causal, in one-second chunks overlapping by 1% | 48 kHz, two channels; 2, 4, 8 or 16 codebooks of 1024 at 150 Hz (3, 6, 12 or 24 kbps) | EnCodec (arXiv 2210.13438) and its open release; payload: *Payloads of the neural audio codecs*, below; `neural/audio.rs` | | `wai.neural.dac` | DAC at 44.1 kHz | 44.1 kHz; 9 codebooks at 86 Hz (about 8 kbps) | DAC (arXiv 2306.06546) | | `wai.neural.dac16` | DAC at 16 kHz | 16 kHz; 1 to 12 codebooks of 1024 at 50 Hz (6 kbps with all 12) | DAC's open release 0.0.5 and its training configuration `conf/final/16khz.yml`; payload: *Payloads of the neural audio codecs*, below; `neural/audio.rs` | | `wai.neural.dac24` | DAC at 24 kHz | 24 kHz; 1 to 32 codebooks of 1024 at 75 Hz (24 kbps with all 32) | DAC's open release 0.0.4 and `conf/final/24khz.yml`; payload: *Payloads of the neural audio codecs*, below; `neural/audio.rs` | | `wai.neural.mimi` | Mimi, 12.5 Hz frame rate | 24 kHz; 8 codebooks of 2048 at 12.5 Hz (1.1 kbps), real-time speech | Mimi (arXiv 2410.00037) | | `wai.neural.wavtokenizer` | WavTokenizer single-codebook VQ | 24 kHz; one codebook at 40 or 75 tokens per second (under 1 kbps) | WavTokenizer (arXiv 2408.16532) | | `wai.neural.snac` | SNAC multi-resolution RVQ (hierarchical code levels, own sample rate) | hierarchical code levels at the model's own sample rate | SNAC (arXiv 2410.14411), `neural/snac.rs` | | `wai.neural.soundstream` | SoundStream — a **candidate** (*Candidate capabilities*, below): the publication's models were not released, and the open-source speech codec built on its architecture ships its own models (not ONNX; 16 kHz, 3.2 to 9.2 kbps) and its own packet, which the reference route does not read; no payload format and no parameter set are pinned | 24 kHz; one model with residual vector quantization across 3 to 18 kbps (its publication) | SoundStream (arXiv 2107.03312); no decoder | *Image:* | capability | model | operating point or property | source | |---|---|---|---| | `wai.neural.bmshj2018` | bmshj2018-factorized + rANS (byte-exact CompressAI port) | about 0.26 bpp at 29 dB PSNR (quality 3) | CompressAI | | `wai.neural.mbt2018_mean` | mean-scale hyperprior (Gaussian-conditional entropy) | the conditional-entropy family (arXiv 1809.02736) | `neural/hyperprior.rs` | | `wai.neural.int_synth` | integer fixed-point synthesis (all-i64 transposed-conv, no float/ONNX) | bit-identical on every machine — soundly backs `intent = replicate` | payload and set: [integer-payloads](extensions/integer-payloads.md) §13; decoded through its lowering, [integer-operators](extensions/integer-operators.md) §13.1 (`int_synth/1`); `int_synth.rs` (integer weights sink-supplied; the reference tools make them by training in float, then quantising after training with per-layer shifts calibrated on measured activations, `tools/wai_int_synth_train.py`. Of the committed vectors only `photo` comes from a trained model, `tools/wai_int_synth_real.py`; `gradient`, `bloom`, `facade` and the cross-architecture golden use seeded integer weights) | | `wai.neural.int_hyper` | integer fixed-point **conditional** codec — whole bitstream→image path integer (integer hyper-decoder σ → integer-σ entropy → integer synthesis) | the integer-entropy contract fully assembled: a PTQ of mbt2018_mean, bit-identical on every machine, whose integer decode CI holds within 1 dB of the same model's float decode on a pinned photograph; its cost against the float model at all eight published qualities, and its decodes and the float model's compared across platforms, are measured in [determinism-tiers](extensions/determinism-tiers.md) §7 | payload `WIH1`; `int_hyper_synth.rs` (tables sink-supplied). Payload: [integer-payloads](extensions/integer-payloads.md) §4; its networks decoded through their lowering, [integer-operators](extensions/integer-operators.md) §13.2 (`whm1/1`) | | `wai.neural.int_mlicpp` | integer fixed-point **MLIC++ entropy topology** — `K` channel slices of the latent, each decoded as a checkerboard anchor pass then a non-anchor pass, with an entropy network over concat[latent decoded so far, hyper] re-run before every pass to give σ‖μ; hyper-decoder, entropy network and synthesis all integer | the channel-autoregressive × checkerboard entropy model at **decode-equivalence**: the encoder and every decoder compute the same σ, so the same distribution for every element, at any thread count; bit-identical on every machine. The committed conformance vector has synthetic weights, so it demonstrates decode-equivalence and states no quality figure | `int_mlicpp.rs` (one-file model bundle sink-supplied; `tools/wai_int_mlicpp_export.py`). Payload and bundle: [integer-payloads](extensions/integer-payloads.md) §14; its networks decoded through their lowering, [integer-operators](extensions/integer-operators.md) §13.4 (`wmb1/1`) | | `wai.image.jpegai` | JPEG AI (ISO/IEC 6048-1:2025) codestream → RGB — integer entropy front end (mANS, with an integer scale-index derivation) + 16-bit-PTQ integer hyper-decoder, context-model and synthesis networks + dequantisation, latent refinement, post-filters (the eICCI CNN among them) and colour conversion in IEEE-754 float with a fixed evaluation order. Scope: one configuration — 256×256 4:4:4, `model_id` 0 (tools_0), `beta_displacement_log` 0, the high-operation-point synthesis, the eICCI model pair the weight bundle carries, and the other header conditions in [determinism-tiers](extensions/determinism-tiers.md) §5; both decode paths refuse any other codestream. Within it, a sink without the integer weight bundle, or in a non-default floating-point environment, takes a float ONNX decode instead; a refusal of the exact decode (`model_mismatch` or `stream_exhausted`, [integer-operators](extensions/integer-operators.md) §13.6.1, or `field_range`, §13.6.2) is reported, not replaced by the float decode. Only checkpoint constants are sink-supplied | **entropy-consistency** (registry class `NeuralEntropyExact`): the entropy decode, including the scale-index derivation, is integer on both decode paths, so the decoded symbols reproduce on every machine. The exact decoder also pins one reconstruction to RGB, reproducible across machines under the build and floating-point conditions in [determinism-tiers](extensions/determinism-tiers.md) §5–§6 (it checks the floating-point environment before decoding) — a property of that decoder, not of the capability, so `wai.image.jpegai` does not back `replicate` (§7). On one reference codestream the exact decoder stays within max\|Δ\| ≤ 2 of the reference decoder (recorded max\|Δ\| = 1 on ~4.4% of samples); evidence in [determinism-tiers](extensions/determinism-tiers.md) §6. **Downgraded in v0.4.0:** this row previously claimed decode-equivalence, and the registry classed the capability `StandardDefined` | `jpegai_decode.rs` (+ `jpegai_{bitstream,mans,pipeline,synthesis,icci}.rs`); its integer stages decoded through their lowering `jpegai-int/1` ([integer-operators](extensions/integer-operators.md) §13.6, `jpegai_ops.rs`): the scale path and entropy decodes (§13.6.1), and the hyper decoders, context stages and synthesis (§13.6.2) | | `wai.generate.spectral` | deterministic integer GENERATIVE synthesis (`intent=create`) — prompt+seed → integer-LUT spectral composition, no float/ONNX | byte-identical on every machine, pinned to (model, prompt, seed, steps); the create-side of "conformance is a hash" (generation-equivalence). Payload: the instruction object of form v0, which names the model by its SHA-256 and lists every size a sink makes, each output checked by its SHA-256 (*Payload of `wai.generate.spectral`*, below) | `generate.rs` (small pinned model bundle) | | `wai.neural.elic` | checkerboard context model (hyperprior + 2-pass spatial context) | the checkerboard-context entropy class (arXiv 2203.10886) | `neural/context.rs` | | `wai.neural.mlicpp` | MLIC++ multi-reference entropy (channel-AR slices + checkerboard + global attention) | the multi-reference entropy model (arXiv 2307.15421) | research code, `neural/mlicpp.rs` | | `wai.neural.mlicv2` | MLICv2 / MLICv2+ (2025), MetaFormer transform | shares the mlicpp route | research code, `neural/mlicpp.rs` | | `wai.neural.cmic` | Content-Adaptive Mamba (ICLR 2026), SSM transform + SCCTX entropy | shares the mlicpp route | arXiv 2508.02192, `neural/mlicpp.rs` | | `wai.neural.glc` | Generative Latent Coding — categorical / VQ entropy | ultra-low-bitrate image coding | research code, `neural/glc.rs` | | `wai.image.ieee1857_11` | IEEE 1857.11-2024 neural-network-based image coding — a **candidate** (*Candidate capabilities*, below): the standard is not openly readable, and its open reference software writes a picture header with no start code, from a working draft, so no payload format is pinned | `NeuralFloat`: no integer decode is shown, and the open text that states what its decoders must reproduce asks for a cross-check by re-running a decoder, not identical output | `format_probe::nic` reads the reference software's picture header ([format-probes](extensions/format-probes.md) §10); no decoder | | `wai.semantic.clip` | a CLIP-embedding package regenerated by any conforming sink generator (the generative-semantic path, `semantic.rs`) | conforms by similarity above a declared threshold, never by bytes (`Behavioral`, tier `Perceptual`); generators are sink-supplied | `semantic.rs` | | `wai.semantic.perco2` | PerCoV2 ultra-low-bitrate generative image coding | as `wai.semantic.clip`; its model licence is non-commercial (CC BY-NC-SA), so it is licence-flagged and never a default | `semantic.rs` | *Video:* | capability | model | operating point or property | source | |---|---|---|---| | `wai.neural.video_bmshj2018` | per-frame bmshj2018 | per-frame image coding; decodable in a browser on WebGPU | CompressAI | | `wai.neural.dcvc_rt` | DCVC-RT (2025), inter-frame with reference-feature propagation | inter-frame neural video; its paper reports real-time 1080p and 4K decode on a GPU | research code, `neural/video_dcvc.rs` | | `wai.neural.dcvc_fm` | DCVC-FM (feature modulation), wide single-model quality range (RGB + YUV) | a wide single-model quality range; shares the inter-frame route | research code, `neural/video_dcvc.rs` | | `wai.neural.dcvc_rt.frame` | ONE FRAME of `wai.neural.dcvc_rt` an object, the reference feature carried from object to object and started at zero by each group's intra frame | the frame form of `wai.neural.dcvc_rt` for live carriage; its frames are the clip decode's, frame for frame | payload `WNF1`: [frame-stream](extensions/frame-stream.md) §4; `neural::DcvcFrames`, the frame step of `neural/video_dcvc.rs` | | `wai.neural.dcvc_fm.frame` | ONE FRAME of `wai.neural.dcvc_fm` an object, as `wai.neural.dcvc_rt.frame` | the frame form of `wai.neural.dcvc_fm`; shares its route | payload `WNF1`: [frame-stream](extensions/frame-stream.md) §4; `neural::DcvcFrames` | | `wai.neural.dcvc` | DCVC (NeurIPS 2021): conditional coding, with a context drawn from the decoded frame — a **candidate** (*Candidate capabilities*, below) | `NeuralFloat`: its published decoder runs float inference; it decodes a motion latent beside the contextual one, and takes the contextual latent's entropy parameters from the hyperprior, a temporal prior and an autoregressive spatial context | arXiv 2109.15047; no decoder | | `wai.neural.dcvc_tcm` | DCVC-TCM: temporal contexts at several scales, mined from features propagated frame to frame — a **candidate** | `NeuralFloat`: a motion latent beside the contextual one, whose entropy parameters come from the hyperprior and a temporal prior | arXiv 2111.13850; no decoder | | `wai.neural.dcvc_hem` | DCVC-HEM (ACM MM 2022): a hybrid spatial-temporal entropy model — a **candidate** | `NeuralFloat`: a motion latent; entropy parameters from the hyperprior, the previous frame's latent, a temporal prior and a spatial prior of two passes | arXiv 2207.05894; no decoder | | `wai.neural.dcvc_dc` | DCVC-DC (CVPR 2023): diverse temporal and spatial contexts — a **candidate** | `NeuralFloat`: a motion latent; entropy parameters from the hyperprior, the previous frame's latent, a temporal prior and a spatial prior of four passes | arXiv 2302.14402; no decoder | | `wai.neural.dcvc_uf` | DCVC-UF (CVPR 2026): a chunk of frames coded as one latent, its frames decoded together — a **candidate** | `NeuralFloat`: entropy parameters from the hyperprior, a temporal prior and a spatial prior of several passes | arXiv 2606.04410; no decoder | | `wai.video.nnvc` | NNVC, neural-network-based video coding: the exploration of the Joint Video Experts Team of ITU-T and ISO/IEC, whose reference software (NNVC, built on the VVC test model; tagged releases up to NNVC-8.0, and release candidates of 9) adds neural-network in-loop filtering and intra prediction to a VVC codec — a **candidate**: no standard is published, and the software's bitstream changes between its releases, so no payload format is pinned | `StandardUnclassified`: no published text states what its decoders must reproduce | no decoder | | `wai.video.int_motion` | DETERMINISTIC INTEGER inter-frame — I-frame + integer block motion-compensated P-frames + integer-quantized residual over rANS, no float/ONNX; motion is whole-pel or **half-pel** (`mv_precision`), the latter predicting at the half-grid by integer bilinear interpolation (`(a+b+1)>>1`, `(a+b+c+d+2)>>2`) so real footage — which pans a non-integer number of pixels per frame — costs fewer residual bits while staying byte-exact | byte-identical frame-by-frame on every machine (*frame-state-equivalence*, a per-frame portable hash); the temporal extension of the integer contract, where a float inter-frame decode desyncs down the GOP | payload `WIV1`, keyframe 0; `int_video.rs` (the encode tools write a JSON form a converter reads). Payload: [integer-payloads](extensions/integer-payloads.md) §3; decoded through the integer operator set's stage operators, [integer-operators](extensions/integer-operators.md) §13.5 (`rans64_decode`, `mc_predict`, `residual_step`), with no graph | | `wai.video.int_hyper` | NEURAL-KEYFRAME inter-frame — the I-frame is the LEARNED integer codec `int_hyper` decoded byte-exact, the P-frames are integer block-MC residuals on top | a learned keyframe you can put in a receipt + integer inter-frames; whole decode integer, byte-identical everywhere | payload `WIV1`, keyframe 1 (a nested `WIH1`); `int_video::decode_pframes_typed` ∘ `int_hyper_synth::decode_conditional_checked`. Payload: [integer-payloads](extensions/integer-payloads.md) §3, its keyframe §4; the keyframe's networks decoded through their lowering, [integer-operators](extensions/integer-operators.md) §13.2 (`whm1/1`), and the P-frames through the operator set's stage operators, §13.5 | | `wai.video.int_motion.frame` | ONE FRAME of `wai.video.int_motion` an object: a group's intra frame carries the group's residual table, `q` and `offset` and frame 0 predicted from grey; each inter frame its motion vectors and its residual symbols in a stream of its own, decoded against the previous decoded frame of its group | each frame decodes to the frame `wai.video.int_motion`'s clip decode gives it, byte for byte (frame-state-equivalence); a frame names its predecessor by content hash, so a sink refuses a lost or altered frame instead of decoding past it | payload `WIF1`, keyframe 0: [integer-payloads](extensions/integer-payloads.md) §16; carried and checked by [frame-stream](extensions/frame-stream.md); `frame_stream::IntFrames` over `int_video::decode_unit_typed`, through the stage operators of [integer-operators](extensions/integer-operators.md) §13.5 | | `wai.video.int_hyper.frame` | ONE FRAME of `wai.video.int_hyper` an object: a group's intra frame is the learned `int_hyper` keyframe (a nested `WIH1`) with the group's residual table, `q` and `offset`; its inter frames are the integer P-frames, one an object | as `wai.video.int_motion.frame`, with a learned keyframe; whole decode integer | payload `WIF1`, keyframe 1: [integer-payloads](extensions/integer-payloads.md) §16, its keyframe §4; [frame-stream](extensions/frame-stream.md); `frame_stream::IntFrames`; the keyframe's networks through `whm1/1` ([integer-operators](extensions/integer-operators.md) §13.2) | | `wai.video.int_cond` | CONDITIONAL inter-frame coding at the integer tier — each frame's latent is coded given a temporal context, the previous frame's decoded feature (the zero feature for frame 0): an integer context network over that context gives every latent element's scale and mean, each element is decoded against its scale's table, and an integer conditional decoder and synthesis turn the latent and the context into the frame and the feature the next frame reads | byte-identical frame by frame on every machine (frame-state-equivalence): every scale, table choice, feature and frame is an integer function of the payload and the set, the encoder's on every decoder | payload `WIC1`, a clip of `WCF1` frames; one-file set `WCB1` (`model.wcb`): [integer-payloads](extensions/integer-payloads.md) §17; `int_cond_video::decode_clip`; its four networks through `wcb1/1` ([integer-operators](extensions/integer-operators.md) §13.4a); the reference vector's networks trained and quantised by `tools/wai_int_cond_export.py` | | `wai.video.int_cond.frame` | ONE FRAME of `wai.video.int_cond` an object: a group's intra frame decodes against the zero feature, each inter frame against the feature its predecessor left | each frame decodes to the frame `wai.video.int_cond`'s clip decode gives it, byte for byte; a frame names its predecessor by content hash | payload `WCF1`: [integer-payloads](extensions/integer-payloads.md) §17; [frame-stream](extensions/frame-stream.md); `int_cond_video::CondFrames` | | `wai.video.manifest` | ATTESTED PER-SESSION MANIFEST — the OTT delivery layer, not a codec: a personalised HLS manifest (ads stitched at `EXT-X-DISCONTINUITY`, blackouts + geo enforced) rendered as a **pure function of the session *class*** `(content, entitlement, geo, blackout set, ad pod, window)` rather than the viewer, and sealed in an Ed25519 receipt that binds the JCP grant (capability, joule ceiling, `funds_ceiling` = ad budget), the composition, the stitched ads and the policy applied. A receipt over a WAI playlist MAY carry `render` and `extras`, the rendering parameters and per-segment lines that playlist adds, both bound through `manifest_hash` and through a render digest the signature covers ([http-delivery](extensions/http-delivery.md) §8.6) | **manifest-equivalence**: `manifest_hash == hash(render(segments))` and `session_class_hash` are recomputable by anyone holding the bytes, so the ads, blackouts and compose-work stop being dashboard claims; class-determinism means one generation serves every viewer of the class, and `uj_per_viewer` is the amortised energy that a 1:1-unique generator cannot report below its per-viewer cost. Only the measurement — `joules_micro`, its acquisition class and the class's evidence — is measured-attested: signed, and not re-measurable | `wai_video_manifest.rs` | | `wai.video.ssai` | ATTESTED SERVER-SIDE AD INSERTION — a **deterministic** ad decision (greedy by price within the avail duration and the funds remaining) plus a per-impression Ed25519 receipt binding the candidate pod, the manifest it belongs to, the served `creative_hash`es and the VAST quartile each reached. The receipt has two forms: form 1, stitched, names an avail of an attested manifest; form 2, break ([live-ads](extensions/live-ads.md) §8), names a break of a room's schedule, the viewer's session and offset into it, and the asset list served, signed under its own domain so that every form-1 receipt keeps its bytes | **spend-equivalence**: `budget_spent_micros` is recomputed from the *billable* impressions and rejected if it exceeds the grant's `funds_ceiling` — an overspent receipt fails verification; every creative and quartile is checkable, so a buyer and seller reconcile impressions from the same bytes instead of two logs that only a dashboard joins. In form 2 the decision is recomputed from the bound pod, avail, slots and funds, and the spend of every receipt of a room together is held to the decider grant's ceiling. Only the measurement — `joules_micro`, its acquisition class and the class's evidence — is measured-attested: signed, and not re-measurable | `wai_video_ssai.rs` | | `wai.video.keys` | ATTESTED CONTENT-KEY RELEASE — the DRM licensing decision as a record: every key release, and every refusal, is an Ed25519 receipt binding the KID, the DRM system, the entitlement demanded and the window enforced, with a BLAKE3 `key_commit` proving *which* key was released without carrying it. The receipt has two forms: form 1, this row's; form 2, the proxy form ([key-release](extensions/key-release.md) §8), signed by a proxy in front of any licence server under its own domain, which adds the scheme, the key delivery, the CPIX document's digest, the entitlement and the device's proof, and the licence server's answer. It is one of Lane A's records (§6.5): it covers the release decision, never a frame the key opens | **decision-equivalence**: `verify()` re-runs the release policy over the receipt's own `(grant capability, entitlement, issued, expiry)` and rejects any misreported outcome, and enforces granted-iff-committed — so "keys went only to entitled, unexpired sessions" is checkable against the signed log, not asserted. In form 2 the decision is recomputed from signed inputs over the proxy's whole log, and each `key_commit` is checked against the key holder's commitment list. Only the measurement — `joules_micro`, its acquisition class and the class's evidence — is measured-attested: signed, and not re-measurable | `wai_video_keys.rs` | | `wai.video.package` | DETERMINISTIC PACKAGING + ATTESTED SEGMENTMAP — a source sliced into content-hashed segments on GOP boundaries; the ordered `(index → content_hash)` map is a signed Merkle commitment, and identical content (ads, bumpers, replays, simulcast overlap) dedups to one stored/encoded copy | **map-equivalence + verifiable dedup**: `segment_map_root` lets a `wai.video.manifest` reference be checked against the package that produced it, and `verify()` recomputes `unique_segments`/`stored_bytes` from the segments so the storage/encode saving cannot be overstated; `uj_per_unique_segment` is the encode-once energy. Only the measurement — `joules_micro`, its acquisition class and the class's evidence — is measured-attested: signed, and not re-measurable. Version 2 ([packaging](extensions/packaging.md) §9) binds the policy digest and one stage index per component, names each object by its jwp-receipts §2.1 content hash, and covers every media class a packager packs; the string keeps `video` for history | `wai_video_package.rs`, `package.rs` | | `wai.video.channel` | VIRTUAL LINEAR / FAST ASSEMBLY — a continuous schedule of assets over wall-clock time, sliced into attested playback windows; windows chain via `parent_receipt_hash`, so a channel's history is a hash chain of program-as-run records | **schedule-continuity + recomputable program-as-run**: `verify()` rejects a schedule with a gap or overlap (no dead air, no double-booking) and recomputes `aired` from the schedule and the window, so what actually aired is checkable by a licensor, advertiser or regulator against the signed chain rather than an operator-held play-out log. Only the measurement — `joules_micro`, its acquisition class and the class's evidence — is measured-attested: signed, and not re-measurable | `wai_video_channel.rs` | **Sink-architecture note:** the inter-frame neural video codecs (DCVC-RT, DCVC-FM) decode through `ort` and are **CPU-capable** for native sinks — their real-time figures come from GPU execution, but a GPU is not required to decode. They are heavier than per-frame image codecs (a temporal net plus reference-feature state), so a browser sink that cannot host the temporal net should declare only `wai.neural.video_bmshj2018` (or another browser-decodable neural video codec) for the `video` media class. The choice is the deployer's, advertised per sink — the envelope is identical. **Frame forms.** Five rows above are the **frame forms** of an inter-frame capability: `wai.video.int_motion.frame`, `wai.video.int_hyper.frame`, `wai.video.int_cond.frame`, `wai.neural.dcvc_rt.frame` and `wai.neural.dcvc_fm.frame`, each carrying one frame of its base's bitstream an object ([frame-stream](extensions/frame-stream.md)). Each is a capability of its own, as `wai.audio.opus.packet` is of Opus, because it frames its base's bitstream differently and a registered string's payload format is fixed (§8). Its payload is pinned with its registration: `WIF1` ([integer-payloads](extensions/integer-payloads.md) §16) for the frame forms of `wai.video.int_motion` and `wai.video.int_hyper`, `WCF1` (integer-payloads §17) for that of `wai.video.int_cond`, `WNF1` (frame-stream §4) for the two neural forms. Frames come in groups: a group's intra frame resets the decoder state, and each later frame of it is decoded against the state the frames before it left. Every envelope of a frame capability carries the manifest member `frame` (§3), which names the frame before it by content hash, and a sink decodes an inter frame only when that frame is the last it decoded (frame-stream §5). Each frame form has its base's registry class, fidelity tier, licence class and parameter set: the integer forms reproduce on every machine given their chain; the neural forms run floating point, and reproduce on one build. A MoQ track declares a frame stream in its catalog ([moq-streaming-format](extensions/moq-streaming-format.md) §4.3). **The inter-frame route and the DCVC family.** `neural/video_dcvc.rs` decodes a payload of its own layout: each frame's latent is entropy-decoded with the parameters the hyperprior alone gives, then the sink's temporal decoder turns it and the reference feature into the frame and the next reference feature. `wai.neural.dcvc_rt` and `wai.neural.dcvc_fm` decode through that route, with a sink-supplied temporal decoder in its contract. The family's published decoders do not take that form: each takes the latent's entropy parameters from a temporal context as well, most also from a spatial prior of two or four passes; DCVC, DCVC-TCM, DCVC-HEM, DCVC-DC and DCVC-FM decode a motion latent beside it; and DCVC-UF codes several frames as one latent. So no published checkpoint of the family decodes through the route unchanged, and the five members registered beside `dcvc_rt` and `dcvc_fm` are candidates, each coding its own bitstream through research code that pins no format. **Scope of the neural rows.** A neural image or video capability is an option a deployer may declare and a sink may advertise; none is in the floor or the recommended set, and none is a default. Each capability owns its payload format. Decoder implementations (Python source-side, ONNX-export, browser onnxruntime-web) live in `tools/wai__*.py` and `wai-web/demo/`. New neural capabilities are added by registration; the WAI envelope is unchanged. See [`extensions/jwp-receipts.md`](extensions/jwp-receipts.md) for the receipt-chain sub-spec covering per-object content hashes, per-group Merkle roots, Ed25519 group signatures, and cross-hop preservation; an object's figure, acquisition class and origin bound into its Merkle leaf, and a group total's class signed under a labelled group payload; the typed receipt classes beside delivery (`energy`, `lawful-basis`, `log-inclusion`, `measurement`, `operating-point`, `stage`, `delivery-gap`, `reconstruct-session`) carried as `claim` receipts; one receipt chain per publisher key and track, and an object not delivered accounted for by its receipt, verified by inclusion; and a second, weaker binding class (a registry-named soft binding with a resolution endpoint) whose recovered receipts attest the ancestor, never the object in hand. See [`extensions/energy-measurement.md`](extensions/energy-measurement.md) for how a receipt's `joules_micro` is acquired: the required acquisition class (`CalibratedInstrument` / `OnChipCounter` / `ModelBased` / `Estimator`, with the legacy `HwShunt` still accepted when read), the declared uncertainty — a standard relative uncertainty and its integration window, never less than the `0.5/√3` µJ (≈ 0.289 µJ) that rounding the figure to whole microjoules adds, so `joules_micro × relative_ppm ≥ 288 676` — that both hardware classes must carry, the counter filtering state and calibration reference that distinguish them, the bracketed marginal protocol (a burst whose window opens from rest, divided by the work the window paid for, from brackets in which the power reader's rail was live), the attribution-quality rule that decides whether a figure may be published at all, the signed measurement report that publishes a figure's bracket, build and power reader beside the receipt it names, and how the receipt families that sealed a figure before the class existed carry it as an optional signed label that leaves every issued receipt's bytes unchanged. A `joules_micro` of `0` is the unmetered marker, never a figure of zero joules. See [`extensions/confidentiality.md`](extensions/confidentiality.md) for the end-to-end encrypted rooms behind §6: objects sealed as MoQ secure objects (`draft-ietf-moq-secure-objects-01`, SFrame RFC 9605 on an MoQ object) under keys from one MLS group (RFC 9420) per room. See [`extensions/reconstruction-binding.md`](extensions/reconstruction-binding.md) for the reproducible-reconstruction binding: a C2PA / JPEG-Trust hard binding over the *deterministically decoded pixels* of a neural-coded asset (SHA-256 over the canonical RGB plus the descriptor that pins the reconstruction) — the reconstruct-side companion to `provenance`, applicable to the byte-exact `wai.neural.int_*` codecs and, over the exact decoder's pinned reconstruction only, to `wai.image.jpegai`. See [`extensions/energy-binding.md`](extensions/energy-binding.md) for the companion energy assertion: the joules a reconstruction cost, bound to that reconstruction, with the acquisition class and coverage C2PA 2.4's `c2pa.environmental-sustainability` has no field for. ### Prior artifacts, general tensors and derivation operations | capability | payload | status · extension | |---|---|---| | `wai.prior.nnc` | a trained network's parameters as an ISO/IEC 15938-17:2024 (NNC, 2nd edition) bitstream | a registered wire form a pin MAY declare (`prior.form`); its digest then covers the coded bitstream. Optional, not recommended: royalty status is not established, and cross-decoder exactness of the reconstruction is not established, so a `replicate` over a neural capability cannot rest on a prior read out of it. The reference reads and writes a subset — integer tensors under the standard's arithmetic coding and raw 32-bit floats — measured against an open implementation of the standard, and refuses quantised payloads by name. As a payload it takes the replicate class of a standard whose decoder conformance the registry has not checked · [prior-carriage](extensions/prior-carriage.md) | | `wai.prior.set` | the listing of a parameter set of one or more files: each file's SHA-256 and path (§3.1) | a registered wire form a pin MAY declare (`prior.form`), and the form in which a set of several files is pinned: the pin covers the listing, and each line covers one file. Reading a set through its listing compares digests and hands the decoder each file's bytes unchanged, so the registry lists it as established exact, and a `replicate` MAY rest on a pin in it. WAI-native, royalty-free; as a payload its output is its own bytes (`StandardDefined`) · [prior-carriage](extensions/prior-carriage.md) | | `wai.prior.safetensors` | a parameter set as one safetensors file: an 8-byte header length, a JSON header naming each tensor's type, shape and bytes, then the tensors' bytes | a registered wire form a pin MAY declare (`prior.form`); its digest covers the whole file, which a reader requires canonical, so one set of tensors has one digest. Reading it hands the decoder each tensor's bytes as the file holds them, so the registry lists it as established exact. A prior in the integer-quantised profile `wai-int/1` loads, bit for bit, into the native artifact an integer kernel reads. Royalty-free (the layout is published with its reference implementation under Apache-2.0); as a payload `StandardDefined` · [prior-carriage](extensions/prior-carriage.md) | | `wai.prior.gguf` | a parameter set as one GGUF version 3 file: key-value metadata, tensor descriptions, aligned tensor data | as `wai.prior.safetensors`: a registered wire form, its digest over the whole canonical file, established exact, and in the profile `wai-int/1` a prior that loads bit for bit into the integer kernels. Royalty-free (published under MIT); as a payload `StandardDefined` · [prior-carriage](extensions/prior-carriage.md) | | `wai.prior.sealed` | a one-file set encrypted under a key its origin releases (`WSK1`): the inner form, the key's identifier, the counter block, the plaintext's SHA-256, the set's usage statement, then the set under AES-128 in counter mode | a registered wire form a pin MAY declare (`prior.form`); its digest covers the sealed bytes, so any server may serve them and a sink checks them before it holds the key. A sink without the key does not hold the set (`prior_not_held`, `set_key_absent`); opened, the plaintext is checked against the SHA-256 the header states, and is a set in an admitted one-file form, so the registry lists it as established exact. WAI-native, royalty-free; as a payload `StandardDefined` · [prior-carriage](extensions/prior-carriage.md) §18.2 | | `wai.prior.tree` | the head of a chunk tree over a one-file set (`WTR1`): the inner form, the set's length, SHA-256 and BLAKE3 hash, and the BLAKE3 chaining value of each piece of 1024 · 2^g bytes | a registered wire form a pin MAY declare (`prior.form`); its digest covers the head, so a sink fetches the set by range from any peers and checks each piece as it arrives, refusing a changed piece at that piece, then checks the whole set against the SHA-256 the head states. It hands over the set it names, so the registry lists it as established exact. WAI-native, royalty-free; as a payload `StandardDefined` · [prior-carriage](extensions/prior-carriage.md) §19 | | `wai.tensor.nnc` | general tensorial data (split-inference feature maps, 3D/4D scene parameters) coded with NNC | **candidate**: general-tensor coding is in an unpublished amendment, so the payload format is not fixed and MUST NOT be emitted until pinned (*Candidate capabilities*, below) · [prior-carriage](extensions/prior-carriage.md) | | `wai.tensor.weft` | one WFT1 frame of the WeftCodec format 1.0: a plaintext (`RAW`), a tensor's row-major little-endian elements (`TENSOR`), or a floating-point tensor whose exponents are coded with a canonical Huffman code and whose signs and mantissas are packed raw (`FLOAT_TENSOR`) | registered with its decode route, `codecs::weft` (*WFT1 tensor frames*, below). Lossless: its header binds the plaintext by a BLAKE3 content hash, and a decoder that does not reproduce it refuses the frame, so its class is `StandardDefined`. Royalty-free: the format's text is published under CC BY 4.0 and its reference implementation under Apache-2.0 · corpus `tensor-conformance/` | **WFT1 tensor frames.** A `wai.tensor.weft` payload is one frame of the WeftCodec format 1.0 — WEFTCODEC-FORMAT v1.0.0 for the frame, and WEFT-AI-CODEC v1.3.0 for its tensor modes, as published with weftcodec 1.2.0, the edition this registration carries (§8) — in one of three modes: `RAW` (0), whole or in a table of chunks each with its hash; `TENSOR` (6); and `FLOAT_TENSOR` (9); in the payload domain, and naming no dependency, so the payload decodes on its own. A sink that advertises the capability decodes every such frame, checks it in the order the format gives, and refuses one it cannot decode with the format's own error class: `Malformed`, `Corrupt`, `UnsupportedVersion`, `UnsupportedMode`, `UnsupportedFeature`, `LimitExceeded` or `NonCanonical`. A frame of another mode is refused as `UnsupportedMode`, as the format requires of a decoder that does not implement a mode, and an envelope whose `wai.tensor.weft` payload is one is non-conforming (it still parses). The format's resource limits are a sink's defaults, and a sink MAY lower any of them. The output is the frame's plaintext (for a tensor mode, its elements' bytes, every bit kept, NaN payloads and signed zeros among them); the header binds it by `H("weft/chunk/v1", plaintext)`, BLAKE3 over a domain, and a decode that does not reproduce it is refused, so every conforming sink gives the same bytes. The reference is `codecs::weft` (feature `weft`), which also writes the three modes byte for byte as the format's own encoders do. The corpus is `tensor-conformance/`: the format's frozen vectors, each with the outcome a sink of this capability gives it, and frames each with one planted defect; `weft_verify.py` is its second implementation. The ten derivation operations of ISO/IEC 23001-16:2021 (derived visual tracks) are registered as `wai.derive.*` strings, each with a per-operation determinism tier. They are **not payload capabilities**: an operation acts on samples another capability decoded. WAI does not composite; the registration states what a reproducibility claim over a derived sample needs. The geometric conditions a tier lists for each operation are read from the operation's title: clause 8 of ISO/IEC 23001-16, which defines each operation, was not read · [derived-tracks](extensions/derived-tracks.md). An edge that derives — `wai.edge.derivation`: an edge evaluates one of these operations over 8-bit RGB samples, rebuilds an object at a lower rung for a sink that lacks its capability (a frame of a `wai.video.int_motion` clip written as a `wai.image.png` still, or as a `wai.image.jpeg` picture), or re-packages one without decoding it (a `WAI2` component exploded into its `WAI1` envelope, §7.1). It never alters what it received: it publishes each output as a new object, in a group of its own track under its own key, and signs a derivation record that names each input by its content hash, the group receipt that carries it and the record that derived it where another edge did; the derivation and its parameters; the output by its content hash and receipt; and the energy the derivation took, with its acquisition class. The record's check is `replicate` when every step is pinned (the inputs' reading, an operation exact under derived-tracks §2, and the still writer of packaging §5 or this section's explode), so any verifier holding the inputs re-executes it and compares the output byte for byte; it is `attest` otherwise (a JPEG encode, a resampling), and the attested step rests on the edge's signature. A sink follows its object hop by hop back to the publishers it subscribed to, refusing a hop it cannot follow, a hop that passes an edge's output off as a source object, an output that does not match its recomputation and an edge its source's origin does not list with `edge/derive`; its policy may refuse attested hops, require every replicate hop to be re-executed, or require every hop to be authorised. Every record carries forward, by digest, the provenance its inputs had (the claims about them, the C2PA Manifest Stores bound to or embedded in them, and what the records below it carry), each item in a system or a personal compartment, and an AI-origin label that may rise along a chain and never fall; a hop that strips an item or lowers a label is refused: [`extensions/deriving-edge.md`](extensions/deriving-edge.md). ### Interactive, temporal & computed content (extensions) Media that consumes input, moves over time, or is *computed* from a compact instruction set. Each registers its own payload format and a deterministic `*-equivalence` conformance criterion over the `wai.det.fixed64` fixed-point floor — the reconstruct half of the standard. See the linked extension for each. | capability | payload | conformance · extension | |---|---|---| | `wai.world.scene` / `wai.world.replay` / `wai.world.live` | WWLD container (op log) | replay-equivalence · [interactive-worlds](extensions/interactive-worlds.md) | | `wai.world.model` | generative-world transport: a signed **action trace** (the world CausalOp log) + a declared `model_id` (`world_model.rs`) | the wire carries the *action trace*, not the pixels — it replays under canonical total order to one **session hash** on every machine (replay-equivalence), the generated frames vouched for by a signed, joules-accounted provenance receipt. The neural sibling of `.replay`; with an `int_*` renderer the frames hash-converge too (a generative interactive world you can put in a receipt). The integer renderer (`int_world.rs`) renders through its lowering, [integer-operators](extensions/integer-operators.md) §13.5 (`world/1`, informative: no payload text yet binds a trace to a renderer's set, so the capability carries no `ops` member) | | `wai.mesh.glb` | glTF 2.0 Binary (Khronos) | asset, content-addressed (decoder sink-supplied) | | `wai.splat.spz` | SPZ (an open-source Gaussian-splat format) | asset, content-addressed; presentation only | | `wai.audio.scene` | WSCN scene (objects + trajectories) | mixdown-equivalence · [spatial-audio](extensions/spatial-audio.md) | | `wai.audio.score` | WSCR container (note events) | music as instructions; sink synthesizes, mixdown-equivalence · [score](extensions/score.md) | | `wai.audio.int_codec` | `WIA1` — a LEARNED 1-D transform codec: integer transposed-conv synthesis + integer IGDN over a factorized-rANS latent (`tools/wai_int_audio_export.py` writes the model and a JSON form a converter reads) | **sample-equivalence**: int16 PCM byte-identical on every machine (a portable PCM hash); the audio analog of `wai.neural.int_hyper`, where a float learned-audio decode desyncs on ~1e-5 round-off. Pure i64, no float/ONNX (`int_audio.rs`). Payload: [integer-payloads](extensions/integer-payloads.md) §5; decoded through its lowering, [integer-operators](extensions/integer-operators.md) §13.3 (`wam1/1`) | | `wai.haptic.signal` | WHAP envelope (intensity/sharpness keyframes) | sample-equivalence · [haptics](extensions/haptics.md) | | `wai.feed.state` | WWLD, sim `wai.world.sim.feed0` | replay-equivalence · [state-feeds](extensions/state-feeds.md) | | `wai.avatar.pose` | WWLD, sim `wai.world.sim.skeletal0` | pose-equivalence · [avatars](extensions/avatars.md) | | `wai.avatar.face` | `WFK1`, a segment of a keypoint track, which names its identity prior (`WFI1`) and its generator (`WFG1`) by SHA-256; the generator is the parameter set, one file | **face-equivalence**, a case of generation-equivalence (§7, `GenerativeDeterministic`): the driver's integer warp and keypoint maps, then the generator's network as one graph of [integer-operators](extensions/integer-operators.md) (`face-int/1`), so every sink generates the same frames; each segment is signed by the participant who drives the face and carries an origin claim of class `synthesized` · [avatars](extensions/avatars.md) §6 to §13 | | `wai.splat.4d` | W4DS container (per-Gaussian keyframed tracks) | frame-state-equivalence · [volumetric](extensions/volumetric.md) | | `wai.splat.int_codec` | `WIS1` — a LEARNED Gaussian-splat ATTRIBUTE codec: a learned transform over the `[14,S,S]` attribute image (pos/scale/rot/color/opacity), integer synthesis (int_hyper machinery, 14 channels) over a factorized-rANS latent (`int_splat.rs`; `tools/wai_int_splat_export.py` writes the model and a JSON form a converter reads) | **splat-equivalence**: the decoded attribute tensor is byte-identical on every machine (a portable cloud hash) — the int_hyper of 3D, where a float splat-attribute decode desyncs. The float rasterizer stays sink-supplied presentation; the *attributes* are the contract. Pure i64, no float/ONNX. Payload: [integer-payloads](extensions/integer-payloads.md) §6; decoded through its lowering, [integer-operators](extensions/integer-operators.md) §13.2 (`whm1/1`) | | `wai.field.int_grid` | `WIG1` — an integer neural field: a multi-resolution integer feature grid, each level read through a direct index or a spatial hash, and a small integer network, in one payload with the view it is presented at; the coarsest levels carried, the rest declared and read as zero until each arrives as its own refinement, `wai.field.int_refine` (*Refinement capabilities*, below), so the coarse field is presented first (`int_field.rs`; `tools/wai_int_field_export.py` writes them) | **field-equivalence**: the sink computes the content, the field's density and colour at any point and its frame at any view by integer ray marching with pinned samples, stop and compositing, and every conforming sink computes the same bytes, so a frame digest can be signed and checked where the frame is presented. Integer arithmetic only, no parameter set · [neural-fields](extensions/neural-fields.md) | | `wai.film.linear` | WFLM container (sealed world + camera track + frame schedule) | film-equivalence · [linear-film](extensions/linear-film.md) | | `wai.film.reel` | WREL container (sealed world + a sequence of shots = camera track + schedule each) | reel-equivalence (film-equivalence with cuts) · [linear-film](extensions/linear-film.md) | | `wai.ternary.tt` | WQTT container (balanced-ternary MPS cores — packed trits + integer per-column scales) | a **quantum-inspired** (tensor-network) transform ported from the ternary/MPS fabric with ONE change: the per-column scale is an **integer**, so the whole decode is `i64`/`i128` and the reconstruction is byte-identical on every machine — **reconstruction-equivalence** (a portable recon hash), receiptable. Scope: a **provenance** transform, measured at 13.3 dB SNR for 3.8× with six residual layers (`Lossy` tier; the extension's §5). Encoder-side float SVD only · [ternary-tt](extensions/ternary-tt.md) | | `wai.quantum.circuit` | WQC container (gate op-log — Clifford+T + dyadic phase) | the wire carries a **circuit** (kilobytes, linear in gate count), the sink CLASSICALLY simulates it in a fixed-point **complex** floor (`Amp` = i64 re/im), and the reconstructed `2^n`-amplitude statevector is byte-identical on every machine — **statevector-equivalence** (a portable statevector hash); measurement is sampled by the pinned `splitmix64` so a shot histogram at a pinned `(seed, shots)` converges too (**shot-histogram-equivalence**). The dyadic phase ladder transports the **QFT** ("quantum FFT") as a circuit, reconstructed byte-exact; the phase table is frozen as existing content was made with it, so `P(k)` deviates from the ideal phase for k ≥ 8 and applies none for k ≥ 19, and new content uses `wai.quantum.circuit2`. No quantum hardware — NISQ noise breaks the determinism the standard rests on; this makes a quantum *computation* transportable + receiptable, with **no** speedup claimed · [quantum-sim](extensions/quantum-sim.md) | | `wai.quantum.circuit2` | WQC container under magic `WQC2` (the same gate op-log) | the successor of `wai.quantum.circuit`, with the same statevector- and shot-histogram-equivalence: a correctly rounded phase table (each component of every `P(k)` within half a unit of 2^30·e^{2πi/2^k}), so the dyadic phase ladder gives the **QFT**; a byte-canonical contract; an op-log that ends exactly after its last op. A new capability, not a change to the old one, because a registered capability's payload format is fixed (§8): a reader that predates it rejects a `WQC2` payload at the magic · [quantum-sim](extensions/quantum-sim.md) | | `wai.quantum.wasmq` | WAI1 envelope whose payload is a `WQM1` bundle: an OpenQASM 3 program of Clifford gates, the WebAssembly modules its `extern`s call and their priors, each pinned by BLAKE3 in a canonical contract | **result-equivalence** · [quantum-wasmq](extensions/quantum-wasmq.md) §6.4: every conforming runner gives an envelope the same result bytes, the same fuel for every callout and the same fault, on every host and engine. A run is whole-number arithmetic throughout: a stabilizer tableau, outcomes from an integer stream, and modules held to a deterministic profile (Lime1, nothing imported, memory and stack bounded, NaNs canonical, fuel counted on the module as written), sealed in the job receipt | *Scene carriage* ([scene-carriage](extensions/scene-carriage.md)) maps a world (`WWLD`), an audio scene (`WSCN`), the assets a world names and timed media items onto ISO/IEC 23090-14 scene description (a glTF 2.0 document with `MPEG_media`, `MPEG_buffer_circular`, `MPEG_accessor_timed`, `MPEG_audio_spatial` and `MPEG_texture_video`) and onto a USD layer of the USD Core Specification v1.0.1, in both directions. It registers no capability: a document carries the WAI payloads exactly beside the presentation its format's players read, reading it back gives the same bytes or is refused, and a document WAI did not write becomes new WAI bytes only where every value carries exactly. The contract of a `wai.quantum.circuit2` payload names its arithmetic `wai.det.amp64`: complex amplitudes as `i64` pairs at scale `2^frac`, each product exact and then rounded half up, each sum exact. Inside a `wai.quantum.circuit` contract, `wai.det.fixed64` names that same arithmetic at frac 30. [quantum-sim](extensions/quantum-sim.md) §2.1 defines both. *Payloads the quantum-sim reader rules make non-conforming* (their envelopes still parse). [quantum-sim](extensions/quantum-sim.md) §2 and §2.1 state reader rules that enforce the registration of `wai.quantum.circuit` as it was made (§8). A sink refuses, when it decodes it, a `wai.quantum.circuit` payload whose contract does not carry the registered `ext`, `numeric`, `frac` and `gateset`, a `wai.quantum.circuit2` contract among them; whose `n_qubits` is not an unsigned integer of at most 255; that carries a known section kind more than once; that has a section whose bounds overflow; or whose contract or measurement repeats a member name within one object, holds a noncharacter, or holds a number of magnitude 2^1024 − 2^970 or more that an earlier reader's float parser let through. No payload a reference writer wrote is among them; [quantum-sim](extensions/quantum-sim.md) §8 lists them with the rules. And the verify half — a signed, energy-accounted lineage for opaque captured content WAI does **not** reconstruct (content-addressing + receipts + measured joules): [`extensions/provenance.md`](extensions/provenance.md) (`wai.asset.provenance`). And an envelope's provenance in C2PA's own form — `wai.asset.c2pa`: a C2PA Manifest Store bound to one stored `WAI1` or `WAI2` envelope, the envelope a C2PA asset and not one of its bytes changed. The store is served beside the object (`.c2pa`, `application/c2pa`), never inside it, so the object's content hash, its receipts and its head proof stay as they were. Its hard binding is a `c2pa.hash.data` over every byte of the envelope with nothing excluded, and its WAI assertion names the envelope's content hash, the capabilities it carries, and the JWP group receipt it was delivered under by link hash with that receipt's publisher key; the store, its claim, its EdDSA signature and its claim signer's certificates are live provenance's profile. A verifier checks the claim and its signer's chain, the data hash over the envelope, the content hash and capabilities against the envelope, the receipt by its link hash and signature and its publisher against the assertion, and the envelope's object receipt under it: [`extensions/c2pa-binding.md`](extensions/c2pa-binding.md). The same verify half, specialized to **quantum operations** — a signed, content-addressed, joule-metered, grant-authorized receipt of a calibration run (`wai.quantum.calibration`) or a dispatched QPU job (`wai.quantum.job`), where a job binds the exact calibration state it ran under and `verify()` enforces the grant's joule ceiling (gate ⊗ meter ⊗ receipt in one object). WAI owns the receipt; the sink's control system runs the hardware: [`extensions/quantum-ops.md`](extensions/quantum-ops.md). The same verify half, for **live events** — `wai.live.events`, a signed, timeline-bound event track: timed metadata, ad and chapter cues, chat, reactions, polls, markers, remote-control commands, captions, moderation decisions and room lifecycle, each one `WEV1` record signed by its principal, hash-chained to that principal's previous event, stamped with the room clock and optionally anchored to one media object, so a delivery gap is told apart from corruption and a poll's tally replays as `wai.feed.state` cells. The same bytes ride an MSF event timeline, an `EXT-X-DATERANGE` tag, a version 1 `emsg` box, a data channel and a recording: [`extensions/live-events.md`](extensions/live-events.md). And for the **rooms** those events belong to — `wai.live.room`: the signed room descriptor whose digest is the room id, fixing the room's authority, its clock and `t0`, the roles a principal may hold, its limits, the slots several publishers may stand behind, its publish profiles, and its review and recording policies (with a region pin for data residency); and the signed room grant under which one principal takes part, carrying its capabilities, a window of at most fourteen days, a single-use nonce, the event policy it is held to, its joule and funds ceilings and its composition attributes. A grant is exchanged at a tick of the room clock and revoked through the authority's key log; a room verifier replays every principal's events under the grant in effect at each instant. The grant maps onto existing token formats rather than defining one, and its seek power decides who may fetch a track below its live edge, from a relay's DVR window: [`extensions/live-rooms.md`](extensions/live-rooms.md). And for a **take** recorded in a room — `wai.capture.take`: a device's full-quality master recording, made on the device beside a live call of lower quality, bound to the room while it is captured. Every commit interval of the room's recording policy the device emits a `take_commit` event in the room's event track, carrying the take id (derived from the director's `record_start`), the chunks it adds, the root of a Merkle tree over every chunk so far with a consistency proof that it extends the last, and the device's offset to the room clock, so the room clock stamps each commitment and every participant holds it. The master is uploaded by chunk hash under the store's signed receipts, and the device signs a take manifest listing the chunks, their root, every commitment and the consent of each subject, a guardian's for a minor, revocable through the key log. A verifier checks it against the room's events and gives each claim its verdict: `single-take` (one continuous take, every chunk committed while it was captured, every part uploaded the chunk committed at its index), `aligned` (capture began at the count-in's instant), `complete`, and `publishable` for each purpose. The take maps onto C2PA live video output: [`extensions/capture-binding.md`](extensions/capture-binding.md). And for the **composition** of a room — `wai.live.compose`: a signed composition descriptor, by the room authority or a principal whose grant has the compose power, that fixes a canvas (at most 1920 pixels an edge and 1920 × 1080 pixels, at 1 to 60 frames a second), a background, and a layout: a grid, with a featured participant above the others, a gap, a tile aspect, a fill mode (fill, cover or contain), an order by attribute and stopped video shown or omitted; or the same grid under a picture-in-picture window in a corner, of a set or derived size, static or dynamic. The participant set at each instant follows from the room's lifecycle replay: who publishes, each one's source and its dimensions, the attributes of its grant in effect and its join order. The layout is a pure integer function of the descriptor and the set, laid out again at every lifecycle event and grant exchange, and the mix a saturating integer function of decoded PCM, so every sink composes the same rectangles locally; a server compositor under the compose power signs a receipt naming the descriptor, the set and the input and output objects, which anyone checks against the same function. Its ad frames (a squeeze, the program in a window with an ad in the L around it, or a double box) fix the ad's region as an integer function of the descriptor; a session's own ad, decided by a stitched-presentation record of that session, is shown there on the session's ad track, bound to the frame by an ad-track binding, `WAT1`, that the record's signer signs, and a binding whose record is shared, is another session's or states another frame is refused (`ad_track_mismatch`): [`extensions/live-compose.md`](extensions/live-compose.md). And for a room session **recorded** whole — `wai.live.recording`: a finished session as one package, a directory of files and its listing (§3.1), whose components are the room (its descriptor, grants and key-log head), its events (each principal's chain whole), one take of each participant and, optionally, the composite, each named as §7.1 names a component, by an `id` and the SHA-256 of its files' listing. A recording manifest signed by the room authority, or by a principal that held the record power at every instant of the session's span, names every component with that span on the room clock and where the package is kept, and a verifier gives `complete` (every take of the session held, each whole, and no event missing) and `publishable` for each purpose. A **clip** of a recording, a span of one take or one window of several aligned on the room clock, is a signed clip record carrying the covered chunks' descriptors and an RFC 6962 audit path taken over their run of leaves against a commitment the device made while it captured, so a verifier holding the clip, the take's commitments, the device's key and the room descriptor knows the clip's bytes are exactly those bytes of the take, without the take. The mapping of a recording onto HLS and LL-CMAF and the addressing of its chunks for a MoQ FETCH are field semantics. A relay may keep a **DVR window** of a room's tracks, with their receipts, for at most 24 hours: it answers a FETCH from it in the requested order, so a viewer checks a recorded object exactly as a live one, marks what it evicted as unknown rather than absent, withholds what a moderation decision restricts, keeps nothing of an end-to-end encrypted room, and checks every object it kept again after a restart: [`extensions/live-recording.md`](extensions/live-recording.md). And for the **captions** of a room — `wai.text.timed`: timed text, as cues in a closed set of styling (italic runs, line breaks, six anchors) that WebVTT and the IMSC1 Text Profile both express, so that a cue maps onto each exactly, and onto the two MoQ caption timelines, CTA-608 (pop-on and roll-up on CC1) and HLS; where a target cannot hold a cue, the mapping refuses it with a named reason. A live caption is a `caption` event of `wai.live.events`, unchanged; a machine caption is revised in place, each revision a new `caption` event followed by a `WTX1` annotation that supersedes the revision before it by digest, states whether the text is final and how much of it is stable, and carries the anchor and italics. The event's origin and model digest are the disclosure label, carried through every mapping (an HLS media characteristic, C2PA's AI disclosure and digital source type, a WebVTT class, IMSC1 attributes) or, where a target cannot hold it, in a sidecar: [`extensions/timed-text.md`](extensions/timed-text.md). And for the **access services** of a room session — `wai.access.services`: figures about a caption track that any verifier recomputes from its signed revisions. Its latency is each cue's first display on the room clock less the capture instant of the speech it carries, placed through a take's opening commitment or as an aligner states it; its stability, the revisions after first display and the words they changed; its accuracy, the word errors of the first revision shown against a reviewed final revision or a signed reference transcript; all in integer arithmetic over one fixed word alignment, so a quality figure a vendor states is checked by recomputing it. An audio description track is a signed script of timed descriptions, the ducking of the programme audio under each, and its voicing on a separate track or by the sink, each labelled human or machine; its voice is held to the synchronisation bounds of the Dubbing and Audio description Profiles of TTML2, and it maps onto a document of that profile. A sign language track, an avatar pose stream or the video of a person signing, is bound by digest to the final caption revisions it translates, with a reviewer's optional sign-off. A completeness claim states that each access track a session declares was delivered complete and in sync, against tolerances it names, and a verifier checks it against the records: [`extensions/access-services.md`](extensions/access-services.md). And for what a room session **cost** — `wai.live.metering`: every hop that carried the session (a relay, a compositor, an ingest gateway) signs one per-hop session record, `WMH1`: per track and direction the objects and bytes it carried and the objects it dropped by reason, with those whose receipts it forwarded; its subscriber sessions' time by layer class; the events it delivered; its own energy with its acquisition class, or the unmetered marker; and the root of a ledger of the grants its sessions ran under, with their ceilings. The record holds nothing per object or per viewer, so its size is bounded by what the room published, whatever the audience. The room authority, or a key its origin's key log lists with `live/meter`, signs the room-session receipt, `WMR1`, naming the records, the takes and the composition receipts it aggregates and stating publisher-seconds, subscriber-seconds by layer class, composition-seconds, events sent and delivered and recorded-seconds (and, in a receipt of version 2, the bytes its hops sent the session's sessions, priced per byte), every hop's joules with its class and a total per class, never one across classes, and each grant's consumption against its joule and funds ceilings, a hop's joules attributed to grants by the bytes each moved, an accounting convention and not a saving any grant made; a verifier recomputes every number from the records. The reference relay signs its own energy read from the host's counter (its process's per-task energy on macOS, the CPU packages' on a Linux host it runs alone), `OnChipCounter` with its uncertainty, where the counter was live and the relay served the room alone, and the unmetered marker otherwise. Clients' QoE observations ride the CMCD event timeline, and only a cell of at least fifty sessions reaches the receipt. The receipt maps onto C2PA's `c2pa.environmental-sustainability` assertion where one class covers the session whole: [`extensions/live-metering.md`](extensions/live-metering.md). And for the protocols standard encoders and players already speak, a binding onto a room's tracks rather than a record: WHIP (RFC 9725) into them through a gateway that admits a publisher by its room grant, carries each frame as one envelope on a MoQ track, places it on the room clock within a stated bound, and signs every group's receipts as the first hop; WHEP (`draft-ietf-wish-whep-05`) out of them, every object verified against its receipt before a player gets it; SRT; and, as a mapping, Enhanced RTMP v2 multitrack: [`extensions/live-ingest.md`](extensions/live-ingest.md). And for **contribution over UDP with retransmission** — `wai.live.contribution`: SRT (`draft-sharabayko-srt-01`), as a listener and a caller, and RIST (VSF TR-06-1:2020 Simple Profile, VSF TR-06-2:2024 Main Profile), each admitted by a one-time session a publisher obtains under its room grant, its MPEG transport stream demultiplexed into the room's tracks as one envelope an access unit with first-hop receipts. The gateway signs the **link record**, `WLK1`, part by part: every sequence number delivered at the first try, recovered within the receive window, dropped, or outstanding when the link ended, the retransmission requests, the round trips and the recovery times, each part chained to the one before and naming the head of every media track's receipt chain; a verifier recomputes every sum from the record and checks the chain: [`extensions/live-contribution.md`](extensions/live-contribution.md). And for **the health of an input** — `wai.live.signal_health`: a monitor's signed record (`WSH1`) of one input over a window, with up to six checks: black and frozen pictures from the decoded luma, silence in 10 ms blocks of the decoded samples, when captions and cues were last seen and the longest gap without one, and the first-priority transport-stream indicators of ETSI TR 101 290 (sync lost and bad sync bytes, PAT, continuity, PMT and referred-PID errors). Each check states its thresholds, its integer values, the digest of the media it read and its verdict. A verifier holds every verdict to its values and thresholds and every threshold to the profile it expects without the media (`signal_health_verdict_inconsistent`, `signal_health_profile_mismatch`), and recomputes every value from the media where it holds it; an input switch carries the first input, in its order, whose latest record by a monitor it trusts is fresh and states no fault: [`extensions/signal-health.md`](extensions/signal-health.md). And for **which pathway** delivers a room's stream to each client — `wai.live.steering`: the operator signs a steering policy, `WSP1`, naming the pathways (CDNs, relay trees, an origin path, and their clones), the hops of each, the quality floor, the latency ceiling, each pathway's capacity and minimum share, and the window over which the hops' per-hop records are read. A steering server derives each pathway's joules per delivered byte, or per delivered second at the floor tier, from those records with their acquisition class, compares figures only within a class, ranks a pathway whose energy is not known (an unmetered hop, two classes, stale records) after every pathway whose energy is, holds a client against a figure within a margin, and signs a steering decision, `WSD1`, naming the records, the client's report, its own inputs and the output, which a verifier recomputes. The figure is the hops' own energy averaged over their delivery, not the network's, which is largely flat against the traffic it carries: a pathway chosen by it spends what its hops spend, and no claim is made that moving a client lowers a network's energy. The output is the steering manifest HLS and DASH players already read, written byte for byte, with the decision's URI in one member players ignore: [`extensions/energy-steering.md`](extensions/energy-steering.md). And for **what nobody watches** — `wai.live.termination`: a sink signs a stream log, `WSL1` records chained by digest under a key it makes for its playback session, for each stream it receives. The log opens with the stream, how it started (by the viewer's activation or by autoplay, the viewer's autoplay setting recorded beside the platform's answer), the sink's termination policy, its display declaration and the ladder it was offered; it holds a receipt for each segment, stating the rendition, how it matched the panel and each hop's joules with their acquisition class (the unmetered marker where a hop was not measured, never 0 J); the observations of the document's visibility, occlusion, the display's power and the viewer's interaction; and a termination with its reason (hidden, occluded, display off, idle, autoplayed with no interaction, stopped, ended), the media time and the joules of each hop up to it, a total per hop and class. A verifier checks the chain, that nothing follows the termination, that the reason is one the log's observations support, that every rendition was admissible under the panel and the totals, and states what was delivered while the stream was unseen. The display declaration — resolution, refresh rate, bit depth, dynamic range and physical size — is [capability-constraints](extensions/capability-constraints.md) §4: no rendition above it is sent, and where none is within it, the least alone: [`extensions/stream-termination.md`](extensions/stream-termination.md). And for **what decoding cost at the sink** — `wai.sink.energy`: a sink signs a **decode table**, one measured figure per registered capability, decode path and sink energy profile, from an odd number of bracketed rounds (at least seven), with every round's values in the record and every counter reading in a readings file it binds by digest; a **segment receipt** per segment of each stream it decodes, chained, whose figure is measured over the segment's own decode, taken from the sink's own table (`ModelBased`) or another key's (`Estimator`), estimated from processor time, or stated as unmetered with its reason; and a **session receipt** that splits one viewing session over the four hops a stream log names — its origin, its relay (a hop's per-hop record, restated only where the session was the hop's sole user), its decode and its display (an estimate from the panel's declared on-mode power and its luminance setting) — each hop a figure with its own acquisition class, the unmetered marker where it took place unmeasured, or absent where the sink states nothing, never a zero. The counters, their scopes, their idle baselines and their windows are the sink profiles of energy-measurement §9: [`extensions/sink-energy.md`](extensions/sink-energy.md). And for the **moderation** of a room — `wai.live.moderation`: the room authority signs a review policy, `WMP1`, that keeps the room descriptor's review field and refines it: which event kinds and media are held for review before delivery or reviewed after it, by which reviewers, each one's deadline, the fallback at the deadline (allow, deny or hold), the trusted flaggers it recognises, and the reason codes in use, each with its ground (illegal content, or incompatible with the terms), the provision or clause it rests on and its category. A moderator's verdict is a `decision` event of `wai.live.events`, unchanged, followed by a `WMS1` statement that names its target (an event, or a media object such as a recorded chunk by its leaf), the decision it supersedes, its basis (own initiative, a notice, a complaint, or the policy's fallback), its use of automated means, and its ground, explanation and facts. Decisions on one target form a line by digest, so an appeal's outcome is a decision too; the room's clock signs each fallback the policy applies. Anyone can sign a notice, `WMN1`, about an item, and anyone affected a complaint about a decision. A restricted item is withheld, never replaced: a gap it leaves in its author's chain is explained by the moderators' signed statements, and a clip over a redacted chunk keeps its range proof and withholds the chunk's bytes. Each restricting decision maps, byte for byte, onto one statement of reasons in the format of the database the European Commission keeps under Regulation (EU) 2022/2065 (Article 24(5)), with no personal data: [`extensions/live-moderation.md`](extensions/live-moderation.md). And for the **confidentiality** of a room — `wai.live.e2ee`: the room authority signs a confidentiality record, `WRE1`, stating that a room is end-to-end encrypted, with which secure-objects and MLS ciphersuites, and that it is never recorded. Every object of the room's media tracks is sealed by its publisher as an MoQ secure object (`draft-ietf-moq-secure-objects-01`), its Key ID among the object's Immutable Properties, so relays route, cache, meter and receipt ciphertext alone; the keys come from one MLS group (RFC 9420) per room, whose credentials are the principals' Ed25519 room keys, whose one external sender is the room's clock, proposing an Add for each join under a grant that may receive or publish and a Remove for each leave, revocation or expiry, and whose committer every member computes alike, the member at the lowest leaf the commit does not remove. Each epoch's application secret is an MLS export, from which each publisher's track base key and KID (the epoch and its leaf index) follow, so a receiver selects the one key that opens an object; a receiver refuses, each with a named reason, an object of an epoch it never joined, one after its own removal, a Key ID naming no member, a sender that is not the track's owner or was removed since, a replay, a bad tag and a plaintext that does not read or does not match its sealed inner digest. Receipts bind the sealed bytes. A browser page is a member through the same code built for WebAssembly, sealing each encoded frame before it publishes it and opening each object before it decodes it; a room service may carry the group's messages in one order, and a member reached so applies its own create or commit only when the service returns it in that order (confidentiality §15): [`extensions/confidentiality.md`](extensions/confidentiality.md). And for **messaging** in a room — `wai.live.message`: a conversation is an end-to-end encrypted room whose authority signs a conversation statement, `WMC1`, with its bounds. Its clock records membership rather than presence: a member stays a member while its device is offline, and leaves when it leaves or the authority removes it. Each member publishes its messages on a messages track of its own, each message one object sealed under the room's MLS group and signed into the member's receipt chain; the plaintext is a message record, `WMG1`, signed by its author, of one of five kinds: a text, a reply in a thread, a reaction, an edit and a retraction, the last four naming the message they concern by its link hash. Any member may commit, the room service's log ordering the commits, and after each the clock signs an epoch statement, `WME1`, naming the epoch's roster, so an offline verifier holds each member to the epochs it was in. Members acknowledge delivery and reading, `WMA1`, in the clear. A history store keeps the conversation's log, ciphertext, receipts and signed records only, takes a message only from a member of the latest epoch sealed in it, and serves each principal only the entries of the epochs it was a member of, so a member that was offline catches up and a removed member reads nothing sent after its removal. A verifier states every message accepted, sealed or refused with its reason, keeps an edited message's original and an edit's current text, and keeps a retracted message in verification, stated retracted. And for **calls** — `wai.live.call`: a call is a room with a call descriptor, `WCT1`, the authority's, naming its caller and invitees; the caller signs an invitation, `WCI1`, held in each callee's inbox at the room service and verified before a device rings; each invitation ends with a signed answer, `WCA1`: accept, decline, cancel, or a missed call the room's clock signs at its deadline; and the media is the room's own audio and video tracks: [`extensions/live-messaging.md`](extensions/live-messaging.md). And for **forensic watermark sessions** of a room's Lane A delivery (§6.5) — `wai.live.watermark`: the edge that chooses, segment by segment, which of the ETSI TS 104 002 A/B variants a viewer's session receives signs a session record, `WWS1`, when the session ends: the room and the content, the span, the KIDs of the content keys the variants were encrypted under, the TS's watermark token by its digest (the token, a CWT that may carry a viewer's identifiers and can be presented again until it expires, travels beside the record only to those who check it), the positions of the pattern it sequenced with the variant at each, and a salted commitment to the session's grant and principal. The record names no grant, principal or viewer; only the room authority, to which the edge gives each opening, can link a session to one, and the edge keeps records within the room's region pin and its retention bound. A claimant that recovers a variant sequence from a copy signs it, `WWQ1`, with its erasures; a session agrees with it when it sequenced every stated position with the stated variant, and a match is the one session that agrees, the TS leaving detection's statistics and thresholds to its vendors. For a matched session the authority signs a disclosure, `WWD1`, opening that one commitment, which a third party checks against that record and the grant without learning other sessions. A room that is end-to-end encrypted has no edge that can mark it, and a record for one is refused: [`extensions/forensic-watermark.md`](extensions/forensic-watermark.md). And for the **ads** of a room — `wai.live.ads`: server-guided ad insertion that keeps the manifests shared. The room authority signs an ad policy, `WAP1`, naming the grant its ad decider runs under, whose funds ceiling is the room's ad budget, and how breaks are presented (slots, an avail for a break opened with no planned duration, a preload window, skip and jump restrictions, a skip control, snapping, and the base URIs of asset lists and creatives). A room's breaks are its signed `cue` events of `wai.live.events`, unchanged: an out and its in, or a break of known duration, and a post-roll that a `WAB1` annotation in the cue author's chain marks; a verifier refuses overlapping breaks, an in with no out, a break of no duration, an in that misstates its duration and any cue after the post-roll, and the room refuses a cue by a principal whose grant does not permit one. Each break maps, as a pure function of the signed records, onto one interstitial date range of HLS (`draft-pantos-hls-rfc8216bis-22` Appendix D, its closing tag at the in, and a preload range of Appendix F) and one alternative-presentation event of DASH (ISO/IEC 23009-1:2026, replace for a mid-roll and insert for a post-roll), with an `ID` derived from the opening cue's digest, so every edge writes the same bytes. Each viewer's decision is made behind the one URI a break names: the asset list (an HLS asset list, or a DASH list MPD importing each ad's MPD), filled by `wai.video.ssai`'s deterministic decision over the viewer's pod and what remains of the break for a viewer who joins it running, and sealed in that capability's receipt of form 2, which binds the break, the session, the decision's inputs and the asset list served. A verifier recomputes the fill and the asset list, refuses a second receipt of one session for one break, and holds the spend of every receipt together to the decider grant's ceiling: [`extensions/live-ads.md`](extensions/live-ads.md). And for the **presentation** of a room's ads — `wai.live.ad_presentation`: a player's signed claim, `WPC1`, that it presented one impression of a break. The player makes a key for each playback session of a room, from which the session its receipts name is derived, and signs with it: the impression (the break, the session, the slot), the content hashes of the creative's media objects it presented, whose ordered list the creative's hash digests; spans of the creative's media time, each with the least fraction of pixels it observed in view and whether the ad was audible, measured over the ad's pixels, the player's area or a television's full screen; a count of rendered frames where the platform has one; and optionally a device attestation, a Privacy Pass token (RFC 9577) whose challenge is a digest of this impression and this key, verified as RFC 9578 §6.4 verifies its publicly verifiable type. An ad policy of version 2 names a viewability rule (at least half the ad's pixels, or every pixel, for two continuous seconds, as the video and cross-media measurement guidelines state them), and can require a claim for each impression, an audible run and an attestation. A verifier then gives each claim a verdict: the claim reads, is signed by the key its session is derived from, is the impression's first, presented the creative's own objects, reaches the quartile the receipt states, and is viewable under the rule, with its token when one is required; and the spend it holds to the decider grant's ceiling counts only the impressions whose claim does. Without an attestation a claim is its key holder's statement, which a modified player can make falsely; the attestation bounds that to a device its attester vouched for, one token per impression: [`extensions/ad-presentation.md`](extensions/ad-presentation.md). And for the presentation of ads **another party stitched** into a stream — `wai.video.stitched_presentation`: a player's signed claim, `WSC1`, that it presented one ad written into an HLS or DASH stream, in its segments or as an interstitial. The claim names the ad by the marker the stream carries for it (an `EXT-X-DATERANGE` tag's `ID` and `START-DATE` with the ad identity an attribute of it carries; an interstitial's date range and the asset of the asset list the player was served; or a DASH event's scheme, value and `id`), in the manifest whose SHA-256 it states, and carries ad-presentation's spans, viewability rules, quartile and attestation under a session key of its own. Beside it, the stitcher or a proxy in front of the ad server signs a pod-input record, `WSI1`, for each decision: the digest of the ad server's response (a VAST document, a VMAP document, or a form-1 `wai.video.ssai` receipt), the chosen ads with their markers, creatives and prices (from the response's CPM `Pricing`, a winning bid bound by digest, or stated), the avail, the session it was decided for or none for a break every viewer is shown, the measurement terms, and the frame: the full picture, or a squeeze or double box whose ad region is an integer function of live-compose's ad frames. A verifier checks each record against its response, judges each claim against its record and the manifest's bytes, and recomputes each ad's presentations, the quartiles they reached and the spend that counts, by currency; an ad whose segments were fetched ahead of its break and never presented has no claim and counts nothing. A composited break whose ad region shows each session its own ad is decided by a record of each session, under the room's ad frame (live-compose's ad-track binding): [`extensions/stitched-presentation.md`](extensions/stitched-presentation.md). And for a **linear channel's lineup and guide** — `wai.video.lineup`: the channel operator's signed lineup, `WLU1`, of one `wai.video.channel` schedule, bound to it by the schedule root: each programme asset's title, description, categories, rating, artwork by content hash, the countries it may be shown in and its rights holder, and where each programme of the guide begins. A channel as operators exchange it (an XMLTV schedule, Media RSS catalogues or a JSON form of both, with the SCTE-35 date ranges of its HLS Media Playlist as its ad breaks) is imported into the schedule's receipt, whose signed bytes are unchanged, the lineup, and a live-events `cue` for each break. The import reads bounded documents over an XML subset that defines no entity, and refuses, each with its reason, a gap, an overlap, a programme with no stop, a time zone named by letters, a break outside its programme and a window outside the schedule. The guide, an XMLTV document or a now/next document for a player's guide row, is rendered from the receipt and the lineup and names both, so a verifier recomputes it and compares, and states of each of its programmes whether the receipt's program-as-run says it aired. A Media Playlist of the channel marks each break of the receipt's schedule where it places it, with `EXT-X-CUE-OUT` and its duration, `EXT-X-CUE-OUT-CONT` and `EXT-X-CUE-IN`, and with RFC 8216's date ranges carrying its SCTE-35 section, so the playlist of the channel's segments, MPEG-2 transport stream segments among them, carries the schedule's ad markers; a verifier given the receipt, the cues and the playlist recomputes every tag and compares: [`extensions/channel-lineup.md`](extensions/channel-lineup.md). And for **watching together** in a room — `wai.live.cowatch`: people in different places watching one source in sync, with the sync measured. The room authority signs a co-watch policy, `WXP1`, naming the source (a WAI package, a sequence of on-demand objects, or another room's recording) and the bounds. A principal whose grant holds the direct power, or whose grant attribute `watch_control` allows the action, sends controls, `WXC1` (`play`, `pause`, `seek`, `rate`), as `meta` events of `wai.live.events`, each effective at a room-clock instant at least the policy's lead after it is sent and at most its horizon; the controls apply in a pinned order, the one sent later prevailing at one instant, and define the controlled position of the source at every instant. Each viewer's player signs, at least once a slot, a presentation statement, `WXS1`: the source position it presented at a room-clock instant, under its own key, carried in its own chain. The room clock signs a skew statement, `WXK1`, per window: for each viewer and each pair of viewers, the 50th percentile, the policy's percentile and the greatest of the errors from the controlled position, with a verdict against the policy's bound; a verifier recomputes every entry from the statements, a viewer with a slot of no statement is unknown and never in sync, and a window's statements list every viewer. A viewer off the position corrects by a pinned catch-up rule, a rate nudge within limits or a seek past a threshold: [`extensions/co-watch.md`](extensions/co-watch.md). And for a **remote desktop** in a room — `wai.live.remote`: one principal's screen shared into a room and controlled from it. A host, a principal whose grant attribute `remote_host` is `true`, publishes its screen as the room's `screen` track, each frame one object with its receipts, and signs a screen statement, `WDS1`, as a `meta` event of `wai.live.events`: what it captures (a display, a window or a region, with the rectangles it blanks), the frame size every input's coordinates are in, the actions it injects, whether it keeps a floor, and the encoder that made the frames with its version, which no rule reads. A principal whose grant attribute `remote_control` carries the classes of its actions (pointer, keys, touch, clipboard) sends input statements, `WDI1`; the host decides each by nine pinned rules at the input's place in the room's merged order, injects all of its actions or none, and signs an outcome, `WDO1`, for every input it receives: applied, anchored on the first frame it captured after the injection, or refused with the rule's number. A verifier recomputes every outcome and refuses a host that applied what a rule refuses. A host that states a sealing key, an X25519 public key, in its screen statement takes key, text and clipboard actions sealed to it: their fields go into one HPKE ciphertext a statement (RFC 9180; DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM), which the host alone opens, and each such action keeps in the clear the type it seals, its instant, a clipboard text's length and a salted commitment binding its fields, its order and its author; pointer, wheel and touch actions stay in the clear. A viewer verifies every outcome from the commitments, and a verifier given the host's opening key opens every seal and checks every commitment. Control passes by grant exchange, or by floor statements, `WDF1`, that request, give, release and take back a host's floor; a floor statement the floor's rules refuse is stated and changes nothing, so a race on the wire leaves a session that verifies. A viewer that presents the frame an outcome names signs a latency record, `WDL1`: the action's instant and the frame's presentation, both on its own estimate of the room clock, from which a verifier states the latency and its three legs, the two that cross estimates with the uncertainty of the round trips the estimates rest on: [`extensions/remote-desktop.md`](extensions/remote-desktop.md). And for a **shared world** in a room — `wai.live.world`: people in different places acting in one world, each tab replaying the same world from the same ops. The room authority signs a world statement, `WLW1`, naming the world the room's operations replay in (for `wai.world.model`, its model header) and the bounds of an operation and of an object. A principal whose grant holds the attribute `world` with the value `act` publishes a world track, `[room, principal, "world"]`, whose groups are op batches, each signed into the principal's receipt chain as a room's media track is; a relay accepts that track only from that principal's grant and holds it to that principal's key. The room's clock records each actor joining when its world track appears. Every participant subscribes to every actor's track, one that enters late fetches each from its first group, and each checks every op's signature, owner, kind, Lamport order and equivocation, then replays the merged ops under the canonical order to one session hash. In an end-to-end encrypted room the world tracks are sealed, and each member carries the ops it holds into every epoch it reaches, so a member that joins later replays the world from its start: [`extensions/live-worlds.md`](extensions/live-worlds.md). And for the **provenance** of a room's CMAF tracks and a device's CMAF take — `wai.live.provenance`: the live video provenance of the C2PA Technical Specification, version 2.4, §19, written as it defines it. A room track packaged as CMAF travels under `draft-ietf-moq-cmsf-01`, each MoQ group one segment and each object one chunk, and a segment is its C2PA boxes followed by its group's objects and nothing else, so the segment's C2PA hard binding and the group's JWP receipt commit to the same chunks. Under the per-segment C2PA Manifest Box method each segment's manifest holds a `c2pa.hash.bmff.v3` over the segment, the live video segment assertion naming the stream and the manifest before it, and the link hash and root of its group's receipt; under the Verifiable Segment Info method each segment carries an `emsg` with a segment-info map signed by a session key delivered in a manifest, rotated in a segment's manifest, and the same key signs the group's receipts. The claim signer's X.509 chain and its profile, the session keys' binding to it, and every object's receipt are checked together. A stream labelled machine-made carries C2PA's digital source type and AI disclosure for its model in every manifest, as timed text does for a caption model, and a compositor's output names its inputs' labels. Manifest identifiers are derived from the stream and the segment and every signature is deterministic, so packagers sharing a key write the same segment and packagers that do not chain across a failover, as C2PA 2.4 has dynamically packaged content; and a registered initialization manifest carries C2PA's repository receipt, whose proof is an RFC 9942 receipt of inclusion in the repository's RFC 9162 log. The C2PA boxes of each segment ride a provenance track beside the media track: [`extensions/live-provenance.md`](extensions/live-provenance.md). And for the **origin** of any media — `wai.media.synthesis`: an origin claim says of one object, one group or one track that it is captured, reconstructed (a codec, neural or not, rebuilding what was captured), assistive (an edit that does not substantially alter its input) or synthesized (generated). It names each input by the link hash of the input's own claim, and its class is the greatest of its step's and its inputs', so the class rises along every chain of derivations and never falls; a generator's own envelope (a `GenerativeDeterministic` or `Behavioral` capability, or `intent` `create`) cannot be claimed as anything else. The claim's IPTC digital source type and its C2PA statement (the actions, and one `c2pa.ai-disclosure` assertion per trained model) are functions of it; a codec's step is a conversion, which asserts no source of its own, as a decode does under energy-binding §6.1. An assistive claim over one of two pinned integer derivations (a 2× upscale and a 3 × 3 denoise) is proved by recomputing the output from the input's decoded samples; any other assistive step can only assert it. The signed claim is the first of two marking layers; the second is a watermark whose payload is the claim's class and the head of its link hash, and a detection that disagrees with the claim is refused. The registered watermark, `wai-mark:tent64`, marks the luma of pictures and video by a pinned integer derivation: a tent pattern on a 64 × 64 grid that follows the picture through a rescale, each bit of a shortened BCH codeword carried by 16 cells, each given the least amplitude up to 12 that meets its margin. A verifier holding the unmarked frames recomputes the marked ones, so the mark carries its payload and nothing else (no viewer or session identifier can ride on it), and a sink that generates content marks it as part of the reconstruction its tier holds. Anyone reads it with no key, in any quarter turn or mirror, with a false-positive bound of 2^−61.39 derived and checked against unmarked pictures; a detection is run again on the frames it names, and a payload a conversion carries agrees with the conversion's claim by inheritance. An attack battery of integer attacks (re-encoding with the crate's own codecs, rescaling, crops, rotations, noise, brightness, contrast, a local blur) measures what it survives, and it claims no more: no crop and no small rotation. The marking's C2PA statement and the mark itself are the signposts to the detection solution, and a well-known path resolves the scheme's definition. A second registered watermark, `wai-mark:tent64s`, lays the same mark out in four tiles that each hold the whole layout, embedded and recomputed alike; its detector, integer throughout, finds the tile lattice again from the mark's own period and reads it after crops from every side, small rotations and a simulated capture of a screen, with a false-positive bound of 2^−60.80 over all its decodes, and the battery measures what it claims. A room's AI participant, marked in its grant, states its machine origin in its chat, reactions and captions, and labels every track it publishes. A review signed over one exact reconstruction is presented only by a player whose decode path holds the review's tier and whose output is that reconstruction, so one review holds for every viewer of exact output. A label policy says when a label is due (first exposure, after each interruption, at an interval), with the EU icons pinned by digest, and a player's signed log shows whether it was shown: [`extensions/synthesis.md`](extensions/synthesis.md). And for **pictures a sink makes** — `wai.media.upscale`: a sink that presents a picture at a higher resolution than it received runs `wai-upscale:sr2` (or `wai-upscale:sr4`, the same twice): the pinned upscale of integer-operators §5E E11 plus a detail an integer network of `wai-ops/1` computes from the picture, under a `WSR1` prior the sink holds by its SHA-256 (§3.1, one file). The network is one `WHG1` graph that loads under `acc64` with its bounds certificate, and under `acc32` where the certificate meets it, so every sink, on a CPU or on a 32-bit fabric, presents the same bytes, and anyone holding the transmitted picture and the prior recomputes them; an assistive claim over the upscale is proved that way (synthesis §4). Because the sink's upscale is known exactly, the origin can send a residual against it, a `WIR1` payload of staged-delivery Appendix A with the identity predictor, and sign an upscale record that states the picture it aimed at and the bound within which the sink's output lies: 0 for the target itself. A prior an origin overfits to one title is carried by digest like any other, and is worth sending only when the bytes it saves exceed its own. A sink's presentation statement counts, for a span, the frames and pixels it presented that were transmitted, derived exactly, edited by a step no one can recompute, or generated, each held to its origin claim; a generated frame names the model that made it: [`extensions/exact-upscale.md`](extensions/exact-upscale.md). And for **AI usage preferences** and the agents that consume media — `wai.ai.usage`: a usage statement carries, verbatim and each in its own member, the AI usage preferences of `draft-ietf-aipref-vocab-08` in its Structured Field form, the TDM Reservation Protocol's `tdm-reservation` and `tdm-policy`, and the entries of a `cawg.training-mining` assertion (Training and Data Mining Assertion 1.1), with no category of WAI's own. The manifest member `ai_usage` carries it inside the envelope, where the object's receipt signs it with the content, so an object whose statement is removed or altered fails its receipt (`usage_unbound`); a room usage record, `WAU1`, signed by the room authority and chained by the instant it takes effect, carries a room's; and a grant's attribute `ai_usage` carries the terms one principal is granted. An origin writes `draft-ietf-aipref-attach-05`'s `Content-Usage` field and the TDMRep fields from the signed statement, a MoQ catalog states it as `wai_ai_usage`, and a field or catalog that contradicts the signed statement is refused. One rule decides a use: a grant's terms, then the signed statements, the most restrictive governing, then unsigned statements where nothing is signed. An agent signs a consumption claim, the jwp-receipts class `consumption`, under its `did:key`: the objects by content hash, the term it acted under in each vocabulary, the statements it saw and its grant; a verifier checks it against the objects, their statements and the room, and refuses a use they disallow (`usage_disallowed`), and a relay or gateway MAY require claims before it serves an agent: [`extensions/ai-usage.md`](extensions/ai-usage.md). And for **who contributed what** to media people and models make together — `wai.media.contribution`: a tool signs a session naming its parties, people by key (each countersigning its own membership, so no one is enrolled without its signature) and models by digest, and every act is a signed step in a hash chain whose steps are the leaves of a Merkle tree: a person authors or edits samples inside a region, a model generates, proposes candidates or inpaints a region a person marked, a party selects one candidate, transforms a state with a pinned derivation (deriving-edge's crop, rotation and mirror, synthesis's upscale and denoise, a per-sample colour table), composes layers, or rejects an output. Each act has a dependency rule, so re-executing the steps gives every sample of the output the parties whose act produced its value (`made_by`) and those whose choices conditioned it (`directed_by`): an authorship map computed, not declared, encoded with a palette and run-length rows and bound to the output's samples by its digest. A verifier checks that an edit or an inpainting changed nothing outside its region, that a selection is a member of its committed set and that every candidate regenerates from its seed under `wai.generate.spectral`, that each transform recomputes, that the map recomputes, and that the output's origin claim is synthesized wherever a model made any sample. A creator may disclose some steps with inclusion proofs and keep prompts as salted commitments; the outcome is `recomputed`, `checked` or `stated`, the shares are exact sample counts per party, and a sample no disclosed, pinned rule fixes is `unknown` or `undisclosed`, never credited to anyone. WAI decides no legal question: the record states facts a reader applies its own rule to: [`extensions/contribution.md`](extensions/contribution.md). And for **settling delivery** on what the party that received it signed — `wai.delivery.settlement`: the downstream party of a delivery, a next hop or a sink, signs an acknowledgement, `WDA1`, of what it received in a window: per object class (live, fetch, fill, ancillary), the objects by content hash under jwp-receipts §2.2's tree, the byte range of each, and their byte count, each acknowledgement chained to the one before it for the same upstream. A relay acknowledges upstream and is acknowledged downstream over the same content hashes, and a hop's billable bytes are exactly the bytes its downstream parties signed for. A hop whose downstream does not sign declares that delivery in the same record signed by itself, counted apart as unacknowledged: never as zero, never as acknowledged; a unidirectional bearer settles under unidirectional-delivery §4. A range proof, `WBR1`, shows that given bytes are a range of an object over BLAKE3's chunk tree without the rest of it, and answers an audit of an acknowledged item. A retrieval that costs money (a fetch below the live edge, a recording fetch, a fill past a cache) is billed only to a room grant whose proof of possession, `WRP1`, the request carried; an ungranted retrieval is free. Per party and per period, a settlement statement, `WSS1`, states the acknowledged bytes by class and payer, the declared bytes, the party's joules by acquisition class from its per-hop records, never summed across classes, and the amount under a declared tariff in integer micro-units; a verifier recomputes every figure from the acknowledgements and refuses a statement that does not recompute. Acknowledgements map onto CDNI logging records (RFC 7937), whose fields carry no counter-signature, and a statement's attribution lines pay a party that is not a hop, the owner of a work that conditioned an output, from that output's acknowledged deliveries under a basis influence verifies. A sink acknowledges the objects of an HTTP service that delivers no WAI envelopes too, each named by the plain SHA-256 of its content, from an upstream named by the digest of its origin, which signs nothing: [`extensions/settlement.md`](extensions/settlement.md). And for **invoicing from receipts**, invoice lines a customer can recompute from those records — `wai.delivery.ledger`: a seller and a buyer both sign a tariff, `WLT1`, one currency and one price for every unit the records state (a room session's publisher-, subscriber-, composition- and recorded-seconds and its events; the acknowledged bytes of each object class, carried over MOQT or HTTP; a package's packages, entries and stored bytes, or, in a tariff of version 4, its work units and its stored bytes by the days they are held, beside a room's bytes out; an ad decision's impressions, presented under the players' claims or billable on beacons, or presented in a stream another party stitched), and the scope of rooms, delivering parties, packagers, and ad deciders and stitchers it bills. Each source is verified by the extension that defines it, a room-session receipt or a settlement statement that states a tariff must state this one, and the seller signs an invoice, `WLI1`, for a period: every record it was computed from, one line per source and unit whose amount is its quantity at its price rounded down once, each line citing the records it came from by a citation digest, and the joules those records state per scope and per acquisition class with the largest declared uncertainty among them, never summed across classes or scopes. Invoices under one tariff chain, and no record is billed twice. A verifier recomputes every line and refuses an invoice that does not recompute; beside it, the ledger states the ad decisions reconciled against the presentation claims, and each delivering party's acknowledged, free and declared bytes with the bytes two parties were acknowledged for by one receiver. No payment and no tax: [`extensions/receipt-ledger.md`](extensions/receipt-ledger.md). And for **sharing a channel's ad revenue with the owners of its programmes**, statements an owner can recompute from the public records — `wai.delivery.revenue_share`: an operator and every owner it names sign a share contract, `WRC1`: its period and currency, its channel and the key that signs the channel's program-as-run (`wai.video.channel`, whose receipt it reads in a JSON carriage that writes out its signed bytes unchanged), the rooms and stitchers whose ad evidence is the channel's, the map from each asset to a split of integer millionths among owners and the operator, and the rule for a break between programmes (the programme before it, the one after it, or a between split). The operator signs a statement, `WRS1`, for one party and one period: the invoices of `wai.delivery.ledger` it rests on, each verified by the ledger, the program-as-run windows it places impressions in, and one line per split and class (presented under the players' claims, billable on a decider's beacons, or presented with no time a marker states), each with its impressions, the revenue its invoices' tariffs priced them at, the party's part of it by the largest-remainder rule, so that the parts of a split sum to its revenue exactly, and a citation digest of the records it came from. A verifier refuses an impression outside every aired window, an asset the contract does not map, a contract an owner did not countersign, two contracts that overlap, an impression two invoices bill, a split whose shares do not sum, and a line no record covers. No payment and no currency conversion: [`extensions/revenue-share.md`](extensions/revenue-share.md). And for **checking a platform's reported figures against the opportunities a channel's own records prove** — `wai.delivery.opportunity`: an opportunity report, `WOR1`, states for one party of a revenue-share contract and one period the ad breaks that aired in the programmes of the splits it shares in, each from the signed cues of a room the contract names (the schedule `wai.live.ads` makes of them, its slots those an SCTE 35 placement opportunity in the cue's section states, or the room policy's) or from an ad entry of the channel's signed program-as-run that no cue covers, placed at its start on the window that aired it and attributed to the programme on air; per split and class it states the breaks, their seconds and their slots, with a citation digest of the cues, policy and runs they came from. A reported statement, the platform's own figures in a documented JSON or CSV form, is read and never treated as evidence. A statement check, `WCK1`, sets them side by side for the period, each day and each programme: the opportunities, the reported impressions and revenue, impressions and revenue per slot, flags for a figure no break stands behind and for one far from the period's own rate, and, where the operator's signed revenue-share statement of the same party and period is given, its impressions and revenue beside the reported ones. A verifier refuses a cue whose section its summary contradicts, a break no window places, two rooms' breaks at once, and a report or a check that does not recompute. No parser of any platform's own format: [`extensions/opportunity-report.md`](extensions/opportunity-report.md). And for **a routed media job**, what a router considered and why it chose — `wai.route.record`: a job names an operation of WAI's catalogue, a capability and a fallback, the quantities it expects, hard limits (regions and data residency, no training on its inputs, zero retention, generally available endpoints only, consent on file, a price per unit and a spend ceiling) and soft preferences (a time to first byte, a quality floor, a sort by price, speed, energy or quality); a price book states what each endpoint offers and costs for each operation, and, in its version 2, how often its hops failed, what their failures were billed and how long they took, over a stated basis; and a named, versioned routing policy orders the survivors and bounds the attempts, the three pinned by SHA-256 over their RFC 8785 forms. From those three documents alone come the candidates, every limit that removes one (a value the price book does not know counted as the most restrictive), the ranking (by what one served job is expected to cost and take, failures included, the job paying the list price), the order and the first key on which the first two survivors differ; the router signs a route record of them and of every attempt, each with its hop's OER/2 job receipt and whether it was billed, the receipt of the hop that served naming the outputs it delivered. The attempts follow the order and only the last may serve; a failed hop, and a hop that served after the deadline the job declared, is not billed. A verifier recomputes the record from the three documents, holds each attempt to its receipt, and refuses a record whose choice they do not give. A delivery of the job's output is routed the same way, from its own request, price book and policy, and its signed decision record states every route considered, the route taken and the key each other route was passed over by, names the job's record and the delivery decided before it, and is refused when its route is not the rule's or its chain is broken. A decision of version 2 also states its offer, the route's entry in a price book of version 3 with its energy figure's uncertainty and grade, and the route's receipt is held to it: its grade no higher, and a figure more than that uncertainty above the offer's flagged `price_exceeded`. No transport and no payment: [`extensions/route-record.md`](extensions/route-record.md). And for **auditing a stream another service delivers** — `wai.delivery.audit`: a content owner's players, with nothing asked of the service that packages and delivers the stream over HTTP. For each playback session a player makes a fresh key and signs with it settlement acknowledgements of every playlist and segment it fetched, by plain SHA-256, one chain per origin and window; a presentation claim, `WPC1`, for each ad an `EXT-X-DATERANGE` marks, named by the marker's digest, its creative the acknowledged segments the ad covers; and a session record, `WAS1`, binding them with the spans it presented, each with the least fraction of its pixels in view and whether it was audible, its start time and stalls, which its delivery-telemetry log recomputes, its sink energy per role with each figure's acquisition class or the unmetered marker, and how it ended. The player sends its CMCD version 2 Event-mode reports to the owner's collector as it plays and the session's bundle when it ends; the collector verifies the bundle, stores it once per session, and serves a channel report it signs: time presented, in view and audible, ads presented and the quartile each reached, start time and stalls once 50 sessions hold them, acknowledged bytes per origin and object class, and joules per role and class, never summed across classes. Anyone holding the bundles recomputes the report byte for byte. No price, tariff or amount: [`extensions/stream-audit.md`](extensions/stream-audit.md). And for **an organisation's fleet** — `wai.delivery.fleet`: the organisation signs an enrolment, `WFE1`, for each node it runs, naming it by its signing key with its role (a relay, a compositor, an ingest gateway, a room service, a ledger or an audit collector), a label and the span it holds. Each node contributes the records it already signs, as it signs them: a relay's session summaries, one line of its summary file each, and every hop's per-hop records (`WMH1`) with their ledgers, placed in time by the room descriptors whose digests they name. Each is verified against its node's enrolled key, placed in a period by its instant, and counted once. For a period, the organisation signs a fleet report, `WFR1`: one line per node, with its client sessions, its hop links to other relays and their bytes, and its per-hop records and their bytes, never added to the first; one line per room, with its hops, subscriber sessions and time, and bytes; the totals; and for each line and the totals the energy its records state, per scope (the sessions' figures, the hops' figures) and per acquisition class with the largest declared uncertainty, never summed across either. Every unmetered figure is counted as unmetered, never as zero joules, so a total over measured and unmetered figures says it is partial, and a node that signed nothing in the period is listed as silent. Each line cites the records it came from, by the identity the receipt ledger gives a per-hop record. A verifier given the report with its enrolments and records, a bundle, recomputes every line. No accounts, no billing: [`extensions/fleet.md`](extensions/fleet.md). And for **a native host's player** — the native sink: an application that plays through its platform's own player, which decodes on the platform's media engine, routes the player's requests through the sink, which verifies a media playlist against its playlist receipt and the chain of its live revisions, holds every object whose URL states its content hash to that hash, and withholds from the player whatever does not verify; it signs what stream-audit has a player sign under a fresh key per session, ends a session nobody can see, and states the sink decode as the unmetered marker where the platform's decoder is outside every counter an application reads. One C interface, `wai_sink_*` in `include/wai.h`, serves every native platform: [`extensions/native-sink.md`](extensions/native-sink.md). And for **influence**, who conditioned an output and their share of what it earns — `wai.media.influence`: an owner, any key (a person, a collective, a label), publishes a work (a style or reference image, a voice model, an adapter or another prior, a taste prior, or a catalogue, a signed set of works) with signed terms: a `wai.ai.usage` statement and the acts of generation it allows, a per-use price or a revenue share, and the tier a use must reach. A tool that conditions a generation, candidates or an inpainting of a contribution session signs a conditioning record beside the step, naming every work by digest with its owner's terms in force, its weight and its use; a use the terms disallow is refused (`usage_disallowed`). The pinned conditioned generator, `wai-influence:spectral-blend`, blends `wai.generate.spectral`'s picture with every reference image and adapter by weight in integers, so the step regenerates only from the works it names (`conditioning_mismatch` otherwise). Re-executing the steps gives every sample the steps that made it, and the declared rule `wai-influence:share/1` divides the output in integer units among the people who made samples, the owners of what conditioned the model and of the model itself, works no one owns, `unknown` and `undisclosed`; the shares sum to the whole (`shares_not_whole`), units no pinned rule fixes are never credited (`unknown_attributed`), and a training-time estimate stays beside the shares with its class (`estimate_mixed` otherwise). A settlement statement pays each owner an attribution line recomputed from the output's acknowledged deliveries, its units and its tariff, rounded down once per bucket, and the statement's party reports to each owner the outputs its works conditioned and what it was paid, without the other owners' figures. WAI decides no legal question: [`extensions/influence.md`](extensions/influence.md). logging records (RFC 7937), whose fields carry no counter-signature, and a line kind is reserved for a payee that is not a hop: [`extensions/settlement.md`](extensions/settlement.md). And for the **takedown** of an item across every rendition and cache — `wai.media.takedown`: a service signs a takedown of a source (an object by its content hash, a group, a track or a take) in answer to a signed notice or order, or of its own initiative, under a policy that names its stores and the clocks it runs under, read by identifier from a registry of regime clocks (`registry/takedown-clocks.json`, each entry citing its instrument and provision; no duration is fixed in the text). The takedown covers the source's derivation closure: every object, group and track a deriving-edge record or a synthesis origin claim derives from it, transitively (a re-package, a rebuild, a crop, a scaling, a transcode, an upscale, a generated group, a live track), with each group it reaches expanded from its delivery receipts; a verifier computes the closure exactly from the records and refuses a stated set that leaves a derivative out or claims one no record derives. A copy made outside every WAI derivation is out of the closure's reach, while every copy of the same bytes is in it by its content hash; a perceptual match is a class of its own, never counted as exact. Each holder of a covered subject (the policy's stores, each edge that derived from it, each party that claimed to, each publisher of a covered group, and each party a delivery-settlement acknowledgement shows served it or, as a hop, received it) signs a purge, and the time from the clock's start to the last purge required is held to the clock: a holder's missing purge is `purge_missing`, a late removal `deadline_missed`, and a removal inside a reply window `window_not_observed`. A service's signed counts per clock, ground, category and source recompute from its takedowns, beside its statement-of-reasons records by their `puid`. The reference relay's DVR store honours a signed takedown: it forgets what it covers in every room, never stores an identical copy again, and signs its purge. WAI decides no legal question: it computes what was removed, where and when: [`extensions/takedown.md`](extensions/takedown.md). And for **co-performance**, people and AI participants performing together in a room with an audience joining in — `wai.live.coperformance`: the room authority signs a co-performance policy, `WPP1`, and everything else rides in the room's events as `meta` payloads its authors sign. A participant announces an intent, `WPI1`, ahead of the instant it plays: the material by digest, or as notes, a text line or a camera move; a pinned rule compares what played with what was announced, and a room key's fidelity statement, `WPF1`, which a verifier recomputes, states per participant how many intents it kept, diverged from or missed. A turn schedule, `WPT1`, gives the floor in turns of microseconds or of bars at a stated tempo, solo or as call-and-response pairs, and a handover, `WPH1`, passes a turn; the relay refuses an object published out of turn, or the room clock marks it, `WPM1`, as the schedule states, and an object later than its grant's latency budget is marked and never mixed unmarked. An audience member whose grant carries the audience-input power sends inputs, `WPA1`, to a selection window, `WPW1`; the clock commits to the eligible inputs, `WPK1`, once the window closes, and a selection, `WPS1`, recomputes from the commitment under the window's rule (a plurality vote, the top inputs by reactions, or a draw from a seed committed before the window opened), with a credit for every input it picks. A relay withholds an input the rules refuse, or one naming a window already committed, and a room clock that is a session of its own on the relay logs each object as it takes it and signs its marks, commitments, selections and fidelity statements from the room it holds, so that a verifier given the room and that log recomputes each: [`extensions/co-performance.md`](extensions/co-performance.md). And for **content ratings and admission by age** — `wai.age.assurance`: a rating claim says, of an object, a track, a span of a track or a room, what it is rated under one or more rating schemes, each named by its vocabulary URI and stating the minimum age its value means, with no scheme of WAI's own; a derived object's claim names its inputs' claims, and a derivation that drops or lowers a scheme an input is rated under is refused (`rating_dropped`), so a rating rises along a chain and never falls, and a rating that rises for a span holds from its first group. A room's age policy, signed by its authority, names the Privacy Pass issuers it admits by, each with one key per threshold, so a token of RFC 9578's publicly verifiable type says "at or over *T*" and nothing else; a relay serves a track only to a session whose threshold is at least the track's age, and learns the issuer and the threshold alone. Over MOQT a token's challenge carries the room's one scope (live-rooms §10.4); over HTTP the room's service is the token's origin (RFC 9577), and states the threshold in the grant it issues; a rating claim reaches a relay as the MOQT property `WAI_RATING`. With no return path the rating is a predicate the sink evaluates against a credential it holds, and nothing leaves the device. An admission receipt counts admissions per window, issuer and threshold, every count under 50 suppressed, and carries no member a session's identity could ride in (`receipt_identifies`). A room in which a minor's publishing grant takes effect meets the minors' profile: no record or seek power, no `chat` or `reaction` from a principal that publishes nothing, never recorded, and no DVR window kept: [`extensions/age-assurance.md`](extensions/age-assurance.md). And for **a person's direction of generated or edited video** — `wai.media.direction`: a director, a person by an Ed25519 key, signs records at four levels of control: a storyboard (the shots, each with its duration, its subjects by reference picture and the framing it opens on, and optionally their order: the shot and sequence levels); keyframes (at stated frames of a shot, each subject's box on screen relative to the subject, its size class, screen position and angle, and a camera window over the shot's plate, with a pinned integer interpolation between keys: the frame level; and regions of frames held to a reference picture: the pixel level); and a sequence (which shots, which part of each, in which order, cut or dissolved). Each record states the levels it sets. The tool that made the video signs a directed output naming the records, the layout of every frame of every shot, the timeline as made and the frames by digest. Where the frames are the pinned integer render of the extension over layers `wai.generate.spectral` regenerates or the verifier holds, every frame recomputes, and the checks are exact: each cut falls on its directed frame, each duration and the order are the directed ones, each subject is where its keyframes and their interpolation put it under a pinned framing measure, and each held region holds; where a model made the frames in floating point the same checks run on the tool's stated layout and the outcome is attested with its class, never exact. Every directed element governs the frames that show what it directed, and the record states them: a per-frame map of who directed each frame at each level, a `direct` step of the contribution record for each element, and a C2PA action with frame ranges for each. WAI decides no legal question: the records state facts a reader applies its own rule to: [`extensions/direction.md`](extensions/direction.md). And for the **bearer** a group travels over — `wai.bearer.receipts`: one receipt on every bearer. A publisher's group and object receipts are the same bytes on a two-way relay chain, IP multicast and a broadcast with no return path, and a sink holding the bytes verifies them the same way on each. The bearer is declared beside the receipt, not in it, in a jwp-receipts claim of class `transmission` signed by the group's key and naming the group by its link hash: the bearer's class (`bidirectional`, `multicast` or `unidirectional`), the instance, and the transmission's energy with its acquisition class, or none where it was not metered; it attests transmission, never delivery. A sink later signs, out of band, a claim of class `reconciliation`: a bitmap of the objects it received and a root over their leaves under the group's own Merkle tree, checked against the publisher's root without the objects, never a hop and never the publisher's. A verifier states a group `published`, `transmitted` or `reconciled`, counts each sink key once per instance, refuses a group presented as delivered that no sink reconciled whole (`delivery_not_reconciled`), sets aside declarations that contradict each other and reconciliations over an instance nobody declared, and states each receiver's share of a shared transmission's energy only as an upper bound, the figure over the distinct keys that reconciled, rounded up, tightening as reconciliations arrive. A sink with no return path confirms keys under anchors provisioned in advance, and a key log that reaches it over the bearer is held and anchors nothing (`anchor_on_bearer`). The extension maps the carriage onto FLUTE, DVB multicast ABR, DVB-I, ATSC 3.0, 3GPP MBMS and 5G broadcast, MoQ over multicast and the applications of hybrid broadcast receivers: [`extensions/bearer-receipts.md`](extensions/bearer-receipts.md). And for **when** each object passes on a bearer with no return path — `wai.bearer.carousel`: a publisher's signed schedule, a jwp-receipts claim of class `schedule` beside the group receipt and the instance's transmission claim, that names for each object its forward error correction (RaptorQ, RFC 6330; Raptor, RFC 5053; or Compact No-Code, RFC 5445) with that code's object transmission information, the repair symbols each pass adds, whether a later pass repeats its symbols or sends new ones, and the times and count of its passes. A verifier holds the parameters to each code's bounds and the entries to the group, its objects' content hashes and, where it holds them, their lengths; sets aside schedules that contradict each other, or whose instance is undeclared or two-way; and derives, for a loss bound stated in parts per million, the pass after which a receiver whose losses stay within it holds each object, whatever symbols it loses: a RaptorQ block at K′ + h distinct symbols, the count RFC 6330 states its decoding-failure bound at, a Raptor block at K and a margin this text sets by measurement, with no bound, as RFC 5053 states none, and a symbol a repeating pass missed counted as missed again. That is the deadline a one-way bearer can promise, checked with no receiver; a statement that an object or a group is held by an instant holds or is refused (`availability_after_deadline`, `availability_not_within_schedule`, `object_not_scheduled`). A receiver derives the passes it must listen to, and when its radio may be off: [`extensions/carousel.md`](extensions/carousel.md). And for **who holds what** near a receiver — `wai.delivery.holdings`: a node's signed record (`WHD1`) of which objects of which groups it holds now, for its neighbours: per group, its link hash, its leaf count and either `whole` or a bitmap, in one canonical form, signed under SPEC §7 *Signatures*, with an instant it states them at and one it expires at. Exact, so a neighbour is never sent after an object its holder lacks, and a bit an object where objects are held as groups are delivered. A verifier holds a record to its instant and to the group receipts it has (`holdings_leaf_count_mismatch` refuses it whole), keeps a holder's latest record and sets aside two of one instant that differ, answers whether a record holds an object, and derives which wanted objects each neighbour holds, in the asker's order, and which must come from the origin. An object a neighbour serves is verified under its receipts like any other; a record is never evidence of bytes: [`extensions/holdings.md`](extensions/holdings.md). And for **when** an object is still worth delivering — `wai.delivery.timeliness`: a publisher's signed statement, a jwp-receipts claim of class `timeliness` beside the group receipt and one for every bearer, of each object's instant of use, its deadline, how its value falls after it (a stated piecewise-linear function in parts per million, floored) and the renditions a receiver presents in its place, a ladder of separate objects derived from it in order of falling value. A verifier holds the statement to its group and objects, refuses one for a staged layer, sets aside two that differ, and judges each object for each holder from holdings records, as a sink that decides at the deadline would present: on time, replaced, held only after its deadline at a value it shows at least, or not shown (`deadline_not_stated` where nothing is stated). An asker plans which of its sources, in its own order, delivers each object in time, and a sink runs its plans against its own clock; the deadline maps onto MoQ's delivery timeout, CMCD's `dl`, DVB's target acquisition latency, ATSC's entry-package load time and a bundle's lifetime: [`extensions/timeliness.md`](extensions/timeliness.md). And for **what delivering a rung costs** — `wai.delivery.rung_price`: a seller's signed list (`wai-rung-prices`) of prices per direction, bearer class, footprint of regions delivered to, ceiling of the rung's rate and unit, each unit at the divisor of the ledger field that bills it, in route-record's amounts with the energy the seller states; the latest of a seller's lists stands alone, and one that lapses revives none. rung-price §2 is WAI's one region code (ISO 3166-1 alpha-2 or ISO 3166-2, in capitals), held by a footprint that lists it or, for a subdivision, its country. A comparer's request removes what its limits remove (a `null` is most restrictive, units are never converted, and the least ceiling that covers a rate prices it) and ranks the rest by a cost per receiver: a shared transmission's is held to its pass rate and divided by the audience the comparer states or by one, never by an assumed one, and the plan states the audience at which sharing is no dearer. A list is a quote, billed only at a tariff the buyer signed: [`extensions/rung-price.md`](extensions/rung-price.md). And for **who served** what a node holds, and on whose authority — `wai.delivery.cache`: the role `cache/serve`, which a node's operator gives in its key log to the caches and peers it runs, and the class authority `cache-transmission`. Under the role a key signs its holdings records and its declarations, and is the upstream its receivers acknowledge; neither lets it author, transform or sign a publisher's statement. A verifier places a server key by the heads its relying party names, in jwp-receipts' three levels, and a placement never changes a verdict. The `cache-transmission` claim (jwp-receipts §2.4.18), beside the group receipt, declares a multicast or unidirectional instance of the node's own and the objects it sent over it from what it held, with a root under the publisher's tree checked without the bytes; receivers' reconciliations over it count, the node credited per instance and only for what it says it sent, and it never makes a group transmitted. Of a population of receiver keys a relying party states for a region (rung-price §2's codes), fixed by its digest, a verifier derives how many held an object by a deadline (stated, or a timeliness entry's), on their own signed word: acknowledgements, counted reconciliations and holdings records, read as timeliness' held-at statements, with any before the group's start set aside. The miss rate is in parts per million, rounded up and held to a target, each hit credited to the publisher or the nodes its evidence names, and every unknown a miss: [`extensions/cache-authority.md`](extensions/cache-authority.md). And for **where a programme may be shown** — `wai.video.audience`: a decider's signed audience decision (`wai-audience-decision`) of whether the sessions in one region may be shown a programme over a span, under the blackouts in force, each named by the id a session class carries and listing its regions in rung-price §2's codes, with the programme shown in its place, if any. A session's location is aggregated in the session, before it leaves it, to the one listed code that holds it, to outside, or to unresolved; the decision carries that and nothing else of where a session is, and is refused when its evidence holds more (`audience_location_not_aggregated`) or a region its blackouts do not list (`audience_region_not_in_set`). The blackouts that apply (every one, for an unresolved session), the verdict (`show`, `withhold` or `alternate`) and the programme shown in place follow, and a verifier recomputes them; a session class of the programme carries the blackouts that apply as its own, and a verifier given both states the class's hash. And `wai.delivery.territory`: a publisher's signed territory statement (`wai-territory`) of where its content may be shown, everywhere, only in some regions or everywhere but some; the latest stands alone and one that lapses revives none. It is reported beside a server key's placement (cache-authority's), which it never changes, and a statement that would name a server, an origin or a role is refused (`territory_scopes_serving`): [`extensions/audience-decision.md`](extensions/audience-decision.md). And for a condition **evaluated on the sink**, on any bearer and on one with no return path — `wai.delivery.sink_predicate`: a source's signed predicate (`wai-sink-predicate`) travelling beside a programme, carrying its blackouts and its ad slots, each slot a list of candidate ads in the order the source prefers them, with the regions each is shown in and its frequency caps, and the state classes it reads declared (`location`, `exposures`). A sink evaluates it from its own state alone: the programme's verdict is the blackouts' at its location (unresolved when it holds none, and every blackout then applies), and it fills each slot itself, taking in order the candidates shown at its location whose caps its own exposures have not reached in their windows and that fit the avail. The evaluation causes no request, and nothing about the device leaves it. A predicate holding a member by which its evaluation would send something away or count across devices is refused (`predicate_needs_report`), and a sink's log that presents a candidate whose cap was reached is refused (`predicate_cap_breached`): [`extensions/sink-predicate.md`](extensions/sink-predicate.md). And for **exploration** with the exact generator, and **taste** as a declared, owned objective — `wai.media.exploration`: six integer descriptors over a picture's `RGB8` samples (mean luma, chroma, detail, palette diversity and the luma centroid's two coordinates) place it without judging it. An archive is MAP-Elites over a declared grid of descriptors, run over `wai.generate.spectral` by a pinned schedule from a declared search seed, through the prompt and the modifiers a person declares: every elite names its genome and regenerates, and the archive replays bit for bit (`archive_replay_mismatch` otherwise). A prompt's default set is seeds 0 to 15 at four steps, and a work's default-distance from it, in descriptors and in samples (0 exactly when the work is a default), is a signed measurement for the exact generator and an estimate, never a measurement, for any other; an unknown figure is never written as 0. A collection statement gives a gallery's, a room's or a session's descriptor coverage and pairwise distances. A taste prior is an integer ranking model over the descriptors, a one-file parameter set pinned as §3.1 pins one, signed by its owner (`taste_not_owner` otherwise) and carrying the owner's `wai.ai.usage` statement; a ranking under it reproduces. Every archive, ranking and pick that an aesthetic or reward model steered names it by digest or states `none`; a policy may require the disclosure of every pick, a pick from an archive a prior steered names that prior, and no default objective exists: [`extensions/exploration.md`](extensions/exploration.md). And for **quality of experience the service receives only as sums** — `wai.telemetry.aggregate`: a sink reports each session's measures, the session metrics of delivery telemetry cast as Prio3 measurements (`draft-irtf-cfrg-vdaf-22`: Prio3SumVec for the start outcomes and the durations, Prio3Sum for the stalls, Prio3Histogram for the video start time), through the Distributed Aggregation Protocol (`draft-ietf-ppm-dap-20`): each measurement is secret-shared between a leader and a helper aggregator and each share encrypted to its aggregator, the two check its range proof without either seeing it and refuse an out-of-range one, and neither learns a measurement as long as one of them follows the protocol. A task's `task_info` names its measure, its scope (a room id for a room's, an impression catalogue's digest for measure 5) and the keys of its two aggregators and its collector, so every report is bound at upload to who aggregates it; a task's minimum batch size is at least fifty, and each aggregator refuses to release a share of a smaller batch. Each aggregator signs a statement of its aggregate share with the batch's task, count and checksum, `WQS1`; the collector's aggregate receipt, `WQA1`, carries the task, both statements and the result, and a reader recomputes the result and refuses a receipt with one aggregator, a batch below the minimum, statements that disagree, or a batch whose reports were uploaded to another task. A room's quality-of-experience cell is computed from its tasks' receipts. Delivery telemetry classes every CMCD key it writes as `delivery` or `measurement`, with what each reveals, and a delivery-only Request mode carries the delivery class alone: [`extensions/telemetry-aggregation.md`](extensions/telemetry-aggregation.md). And for **ad presentations counted over a bearer with no return path** — `wai.delivery.impressions`: a receiver judges each ad of a shared pod-input record it presented by stitched-presentation's rules, and reports each presentation once through the Distributed Aggregation Protocol, to a task of `wai.telemetry.aggregate`'s measure 5, as a Prio3Histogram measurement whose one set element is its creative, region and quartile, with the hour in DAP's own report time; the shares, statements and receipt are that record's. A catalogue fixes the vector's meaning and is the task's scope; a receiver accepts a task only from a task file whose signer its pinned key log lists with the authority `aggregate/task`, generates each report once and re-sends its bytes over whatever path it later has, and the leader holds each collection for a stated delay so late reports count. With attestation each report carries a Privacy Pass token bound to its task and report id. A reader recomputes, per batch, each creative's and region's presentations and quartile counts: a lower bound of what receivers reported, never an audience: [`extensions/impression-aggregates.md`](extensions/impression-aggregates.md). And for **robustness evidence** — what a soft binding survives, measured so anyone recomputes it — `wai.media.robustness`: a corpus document names pictures or clips each by the SHA-256 of its samples, and itself by the SHA-256 of its JCS; an attack battery is a list of registered transforms, each an integer function of the frames with exact parameters and a seed (the battery of synthesis §7.5.7 with its parameters free, and a gamma computed in integers); and a robustness record, signed by the party that measured, names the algorithm by term and definition digest, the corpus, the battery, the harness, and per attack the items that survived out of the corpus and the negatives read as marked, with the survival, false-positive and balanced-accuracy rates and the true-positive rate at 1% false positives as exact fractions in lowest terms, never floating point (`rate_not_exact`). A verifier that holds the corpus reruns the battery and the detector and gets the table bit for bit (`table_irreproducible` otherwise); one that does not states the record. A robustness claim — what an algorithm claims to survive — holds only where a record it cites shows every item of its corpus survived the attack and no negative read as marked; a claim with no record (`claim_unevidenced`) or above one (`claim_exceeds_evidence`) is refused. `wai-mark:tent64` carries records over its measurement sets and a claim that is exactly synthesis §7.5.8's list. A soft binding may also cover a span of a track, its media time and the groups or objects that carry it, a recovery through which attests the span and nothing outside it (jwp-receipts §2.6.4): [`extensions/robustness-evidence.md`](extensions/robustness-evidence.md). And for **Gaussian splats in glTF**, and frames that are the same everywhere — `wai.splat.exact`: a `wai.splat.int_codec` object travels in a glTF 2.0 asset (ISO/IEC 12113:2022) as the draft compression extension `EXT_gaussian_splatting_compression_wai`, nested in a mesh primitive's `KHR_gaussian_splatting` object: a buffer view holds the object's `WAI1` envelope, and the extension states its content hash and its parameter set, which the asset carries or a sink holds by digest. The decode is integer, so the attribute planes are the same bytes on every machine, and they map onto the base extension's attributes. The renderer `wai-splat-render:i1` is integer too: a fixed-point camera and projection, an order by squared camera distance with the Gaussian's index breaking ties, alpha compositing with every rounding stated, a 3σ cut-off, and 16 × 16 tiles whose order does not change the frame. The origin signs a commitment to the object, its set, the digest of its decoded attributes and the digest of the frame at each of its canonical poses, so a viewer recomputes what the scene looks like from each of them bit for bit; a sink signs a view statement for a frame it presented at a pose, under a session key. A view is a conversion of the splat set under synthesis's class lattice, so it is never labelled lower than the splat set. Against a floating-point renderer of the same model, the integer frames differ by a few levels of a byte, at about 60 dB PSNR and above on the corpus's scenes: [`extensions/splat-exact.md`](extensions/splat-exact.md). And for **signatures that stay verifiable after Ed25519 can be forged** — hybrid signatures: a record carries an ML-DSA-65 signature (FIPS 204) beside its Ed25519 one, the two combined as the composite `id-MLDSA65-Ed25519-SHA512` of `draft-ietf-lamps-pq-composite-sigs-19`, so it verifies only while both hold and stands on either. A group receipt is signed over the labelled payload's third version, `moq-jwp:group-sign\x03`, which carries the publisher's ML-DSA key; a claim, and every JSON record an extension signs as `wai:\x01 ‖ JCS`, carries `pq_suite`, `pq_key` and `pq_sig`, checked by one shared rule. A key log lists an entry's ML-DSA key and may have a hybrid root, committed to before it signs; a relying party may pin an anchor that requires hybrid, under which only hybrid-signed revisions count. A verifier may require hybrid of every item (`hybrid_required`), and refuses a classical-only item signed by a key its origin lists as hybrid (`hybrid_downgrade`), so stripping the post-quantum half never yields a valid classical record. A classical publisher's bytes are unchanged: [`extensions/pq-signatures.md`](extensions/pq-signatures.md). And for **cues from broadcast automation** — `wai.live.injection`: SCTE 104 (ANSI/SCTE 104 2023) into a room's signed cues. A gateway is the automation system's injector: it answers the API connection's initialisation, heartbeats and requests with SCTE 104's responses and result codes, translates each splice, time-signal and splice-null request and its descriptor requests into the SCTE 35 section it asks for (ANSI/SCTE 35-1 2023r2, the program's 90 kHz clock the room clock), and derives the request's cues: an out and an in from a splice insert, an in an auto-return implies at the end of its break, and outs, ins and chapters from a time signal's segmentation descriptors of breaks, placement opportunities and chapters. It signs each cue when its splice instant comes, so a cancel or an early return that arrives in time leaves nothing signed to undo, and it holds its own chain to live-ads' break rules. Before each cue its chain carries an injection record, `WIJ1`, in the `meta` kind: the SCTE 104 message verbatim, when it arrived and the parameters it was translated with, from which a verifier recomputes the cue, its section and its instant (`injection_mismatch` otherwise). Built from the request whose fields are SCTE 35-1's sample of §14.1, the section is that sample byte for byte: [`extensions/cue-injection.md`](extensions/cue-injection.md). And for the **release of content keys** by a proxy in front of a licence server — the proxy form of `wai.video.keys`: a signing proxy signs one receipt for every licence request it answers, a release or a refusal, naming each key's encryption scheme (ISO/IEC 23001-7's `cenc`, `cbc1`, `cens` and `cbcs`, or an HLS method of `draft-pantos-hls-rfc8216bis-22` §4.4.4.4), the key delivery (an HLS key file, W3C Clear Key, or a content protection system by its DASH-IF system ID) and the SHA-256 of the CPIX document (DASH-IF CPIX 2.3, ETSI TS 103 799) the keys came in. The key holder signs a commitment list, `WKL1`, derived from that document's key material, and the proxy copies each `key_commit` from it, so it holds no key; a key a client receives in the clear is answered with a release ticket, `WKT1`, that a key server redeems once, so the proxy never relays one. A list of version 2 also states the content's release time, `not_before`, and a request decided before it is refused `DeniedNotReleased` whatever its entitlement grants. The viewer's entitlement, `WKE1`, is signed by the operator's entitlement authority and bound to a key the device holds, which signs each request. The decision is a pure function of those signed inputs, the proxy's clock and its earlier receipts — freshness, replay, the release time, and key periods under rotation, offline licences and their renewals, each bounded by the entitlement — and a verifier recomputes it over the proxy's whole log. Form 1 keeps its bytes: [`extensions/key-release.md`](extensions/key-release.md). ### Payloads of the WAI-native integer codecs This revision pins a payload format to each WAI-native integer codec whose row named its decoder and no byte layout. The rows of `wai.video.int_motion`, `wai.audio.int_codec` and `wai.splat.int_codec` also named the tool that wrote a bitstream, a JSON document, which this section's opening called the bytes the codec normally emits; those of `wai.neural.int_hyper` and `wai.video.int_hyper` named their decoders only. The pin completes these registrations as §8 permits (*Completing a registration*). [integer-payloads](extensions/integer-payloads.md) §3–§6 defines each layout and its decode, §7 the checks a sink makes, and §8 the closed list of codes it refuses with. The rows above keep their headings. | capability | payload format | parameter set | |---|---|---| | `wai.video.int_motion` | `WIV1`, keyframe 0 | none | | `wai.video.int_hyper` | `WIV1`, keyframe 1 (a nested `WIH1`) | several files: `g_s.whm`, `h_s.whm`, `entropy.json` | | `wai.neural.int_hyper` | `WIH1` | several files: `g_s.whm`, `h_s.whm`, `entropy.json` | | `wai.audio.int_codec` | `WIA1` | one file: `model.wam` | | `wai.splat.int_codec` | `WIS1` | one file: `g_s.whm` | From this revision on, the format of each is fixed as §8 states. The JSON the encode and export tools write is a converter input ([integer-payloads](extensions/integer-payloads.md) §10), never a payload: an encoder MUST NOT carry it under these strings, and a sink refuses it (`bad_magic`). *Envelopes the pin makes non-conforming* (they still parse): a `WAI1` whose `capability` or `fallback` is one of these strings and whose payload is not that string's format, a tool's JSON form among them; and a `WAI2` with a component of one of these strings whose bytes are not its format. A sink refuses such a payload when it decodes it, and does not try the fallback ([integer-payloads](extensions/integer-payloads.md) §11). ### Payload of `wai.generate.spectral`: the instruction object (form v0) This revision completes the registration of `wai.generate.spectral` as §8 permits (*Completing a registration*): its row named the generator, `generate.rs`, and no byte layout. Its payload is an **instruction object**, form v0: one JSON object (RFC 8259) in UTF-8 with exactly the five members below, written in ascending byte order of their names, with no whitespace, and with each integer in decimal, without sign, fraction or exponent. Nothing precedes or follows the object. ```json {"model":"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e","prompt":"a calm spectral horizon","seed":7,"sizes":[[256,128],[640,320],[1280,720],[1920,1080]],"steps":4} ``` | member | value | |---|---| | `model` | `sha256:` followed by the SHA-256 of the model file the reference generator reads, as 64 lowercase hexadecimal digits | | `prompt` | 0 to 256 bytes, each from 0x20 to 0x7E other than `"` (0x22) and `\` (0x5C), so the string holds no escape | | `seed` | an integer from 0 to 2³² − 1 | | `sizes` | 1 to 16 pairs `[w, h]`, each side from 1 to 4096 and `w·h` at most 2²³, in strictly ascending order of `w` and then `h` | | `steps` | an integer from 1 to 64 | These rules leave one serialization for each object, so two objects that say the same thing are the same bytes, and an envelope's content hash names the instructions. A sink MUST refuse a payload that is not exactly that serialization of such an object — a member added, missing, repeated or out of order, whitespace, an escape, a value out of range — and make nothing from it. The model file is the generator's parameter set (§3.1), and `model` is its identity: the object names it, so the envelope does not. An envelope that names `wai.generate.spectral`, as a `WAI1`'s `capability` or `fallback` or as a `WAI2` component, carries no `prior` pin, not even one over the file `model` names; a sink MUST refuse one that does, whatever the pin names, and make nothing from it. A sink checks the model file it holds against `model` alone. (This revision registers no one-file shape for this parameter set, so §3.1 would refuse a form-less pin over it with `form_required` in any case, and a pin in the form `wai.prior.set` would name the same file twice.) A sink makes the picture at a listed size `[w, h]` with the reference generator, `generate(model, prompt, seed, steps, h, w)`: `h·w·3` bytes of `RGB8` as [reconstruction-binding](extensions/reconstruction-binding.md) §2 defines it. It MUST NOT make one with a model file whose SHA-256 is not `model`, or at a size the object does not list. It MAY decline a listed size it cannot afford to make, and then presents nothing for that size. Conformance is generation-equivalence (§7) at each listed size: every conforming sink makes the same bytes. A publisher MAY state each size's SHA-256 beside the payload; a sink that holds such a digest MUST NOT present a picture whose SHA-256 differs from it, and MUST NOT accept one on a 64-bit FNV-1a alone (§7, *Digests*). The `intent` of an envelope that names `wai.generate.spectral` is `create`: a generator has no source to replicate (it does not back `replicate`, §7) or to improve. The conformance vector is `wai-rs/tests/vectors/generate/instr-v0.json`: the object above and the SHA-256 of each of its four listed sizes; objects at each inclusive bound above, which a sink MUST accept, each with the SHA-256 of its first listed size; and objects a sink MUST refuse, each with the rule the reference reader finds broken first (informative: a sink refuses each, and says why in its own words). `wai generate` is the reference: `--instr` makes a listed size from an object, and `--write-instr` writes one. *Envelopes this makes non-conforming* (they still parse): a `WAI1` whose `capability` or `fallback` is `wai.generate.spectral` and whose payload is not an instruction object of form v0, whose `intent` is not `create` or which carries a `prior`, and a `WAI2` with a component of that string whose bytes are not one, which carries a `prior`, or in an envelope whose `intent` is not `create`. ### Payloads of the neural audio codecs `wai.neural.encodec24`, `wai.neural.encodec48`, `wai.neural.dac16` and `wai.neural.dac24` carry the codebook indices of their model's residual vector quantizer. This section pins their payload, the decoder a sink holds for each (its parameter set, one ONNX file), and the decode. All integers are little-endian. | capability | channels | model codebooks `Q` | codebooks a payload carries, `q` | hop | samples a decoder gives for `t` frames | chunks | |---|---|---|---|---|---|---| | `wai.neural.encodec24` | 1 | 32 | 2, 4, 8, 16 or 32 | 320 | `t`·320 | none | | `wai.neural.encodec48` | 2 | 16 | 2, 4, 8 or 16 | 320 | `t`·320 | 150 frames; starts 47,520 samples apart | | `wai.neural.dac16` | 1 | 12 | 1 to 12 | 320 | `t`·320 − 8 | none | | `wai.neural.dac24` | 1 | 32 | 1 to 32 | 320 | `t`·320 − 8 | none | Every codebook has 1024 entries. DAC's decoders give eight samples fewer than the frames' 320 each: their upsampling by 5 gives `5L − 1` samples for `L`, which the layers after it multiply by 8. **Payload, a model with no chunks.** `q` (u32), `t` (u32, the frames, at least 1), `n` (u32, the samples the decode outputs), then `q`·`t` codes (u16), codebook by codebook, each codebook's frames in order. `q` is one the table allows, every code is below 1024, and 1 ≤ `n` ≤ the samples the decoder gives for `t` frames. This is the layout the reference sink reads for `wai.neural.encodec32`, `wai.neural.dac`, `wai.neural.mimi` and `wai.neural.wavtokenizer` too; this section pins it, with its checks, for `wai.neural.encodec24`, `wai.neural.dac16` and `wai.neural.dac24`. **Payload, `wai.neural.encodec48`.** `q` (u32), `t` (u32, the frames of the last chunk, 1 to 150), `n` (u32, the samples per channel the decode outputs), `c` (u32, the chunks, at least 1), then `c` scales (IEEE 754 binary32, one a chunk, each finite and above 0), then each chunk's codes as above: `q` codebooks of 150 frames for every chunk but the last, and of `t` frames for the last. The last chunk starts `s` = 47,520·(`c` − 1) samples in, and `s` < `n` ≤ `s` + `t`·320: an encoder starts a chunk only for samples it has left to code, and may code the last chunk as a whole chunk of 150 frames (zero padding) or as the frames its samples need. **Decoder.** One ONNX file: inputs `audio_codes` (int64, `[1, 1, Q, T]`) and `audio_scales` (float, `[1]`), output `audio_values` (float, `[1, channels, samples]`, the samples the table gives for `T` frames). Row `i` of `audio_codes` holds codebook `i`'s codes; a row that holds 1024 is a codebook not used, and adds nothing to the quantized latent, as the model's own decode does when it is given fewer codebooks. The output is the model's decode times `audio_scales`. `tools/wai_neural_audio_export_onnx.py` writes it from each model's released weights and checks it: at each operating point it tested, the file's output and the model's own decode with the first `q` codebooks differed by at most 1.5·10⁻⁵ (2026-11-09). **Decode.** A sink refuses, before it runs the decoder, a payload whose `q` the table does not allow, whose length is not what its header gives, with a code of 1024 or more, with an `n` outside its bounds or, for `wai.neural.encodec48`, with no chunk, a last chunk of no frames or more than 150, or a scale that is not a finite number above 0. Otherwise it runs the decoder once for each chunk (once for a model with no chunks): `audio_codes` holds the chunk's `q` rows and `Q` − `q` rows of 1024, and `audio_scales` holds the chunk's scale (1 for a model with no chunks). For `wai.neural.encodec48` the chunks' outputs `y₀ … y_(c−1)` are joined by the model's linear overlap-add: with `L₀` the length of `y₀` and `w(j) = ½ − |(j + 1)/(L₀ + 1) − ½|`, sample `i` of each channel is `Σ w(j)·y_k(j) / Σ w(j)` over the chunks `k` that cover it, `j = i − 47,520·k`. The output is the first `n` samples of each channel; two channels are interleaved by sample. `neural/audio.rs` is the reference; the decode runs float inference, so the class is `NeuralFloat` and conforming sinks' outputs need not be identical. **Vectors.** `wai-rs/tests/vectors/neural_audio/` holds an envelope of each capability, pinned to a small decoder with the model's geometry and contract (not its network), and the decode computed apart from the reference by `tools/wai_neural_audio_vectors.py`; the reference's output is within 10⁻⁵ of it (`tests/neural_audio_vectors.rs`). ### Immersive audio, cinema, volumetric, haptics, HDR (registered, sink-supplied) The same "name the capability, the sink supplies the decoder" pattern extends to the standard carriers of the immersive / theatrical / volumetric media a full distributor needs. Each names an open reference where one exists; the proprietary and SEP-pool entries are flagged, never defaults. Payload is the named standard's canonical bytes. | class | capabilities | |---|---| | immersive audio | `wai.audio.iamf` (IAMF, royalty-free) · `wai.audio.ac4` (AC-4, ETSI TS 103 190, proprietary) · `wai.audio.ivas` (3GPP IVAS, SEP-pool) · `wai.audio.mpegh` (MPEG-H 3D Audio, SEP-pool) · `wai.audio.avs3` (AVS3-P3 / Audio Vivid, SEP-pool) — the last two with the broadcast codecs below | | cinema mastering | `wai.image.jp2` · `wai.video.j2k` (JPEG 2000 / DCP, OpenJPEG) | | mezzanine and contribution | `wai.image.jxs` · `wai.video.jxs` (JPEG XS, ISO/IEC 21122; SEP-pool; *JPEG XS*, below) | | volumetric / 3D | `wai.mesh.draco` (royalty-free) · `wai.pc.gpcc` (G-PCC, ISO/IEC 23090-9) · `wai.pc.vpcc` (V-PCC, ISO/IEC 23090-5) — MPEG point clouds · `wai.splat.sog` (Gaussian-splat compression; a **candidate**, no payload format pinned — *Candidate capabilities*, below) | | haptics | `wai.haptic.mihs` (MPEG-I Haptics, ISO/IEC 23090-31; its 23090-33 ships bit-exact conformance vectors) | | HDR dynamic metadata | `wai.meta.hdr10plus` (SMPTE ST 2094-40 dynamic metadata, royalty-free) · `wai.meta.dovi` (SMPTE ST 2094-10 dynamic metadata, proprietary) · `wai.meta.st2094_50` (SMPTE ST 2094-50:2026-08 dynamic metadata, Application #5, patent-pool) — **companion descriptors** to a video payload, not standalone media | | HDR gain maps | `wai.meta.gainmap` (an ISO 21496-1:2025 gain map: its metadata and its gain map image, patent-pool) — a **companion** to an image payload, not standalone media | | projection | `wai.meta.projection` (the `WPJ1` projection descriptor, [projection](extensions/projection.md), royalty-free) — a **companion descriptor** to a video payload: rectilinear, equirectangular, half-equirectangular or fisheye pictures, one view or two views packed or in layers | **HDR renditions at a display's headroom.** The payload of `wai.meta.gainmap` is a `WGM1` frame: ISO 21496-1:2025's binary metadata as written, and the gain map image as a PNG of 8-bit samples, one channel or three. The payload of `wai.meta.st2094_50` is a `WD50` frame: one or more metadata sets in the binary encoding of SMPTE ST 2094-50:2026-08 Annex C, each with the frames of its base it applies to. A sink makes from the base, the companion and its display's headroom the rendition it presents. The standards state that computation in real numbers, and two sinks that evaluate it in their own floating point present different pixels; the derivations `wai-tonemap:gainmap` and `wai-tonemap:st2094-50` pin it in integer arithmetic (a fixed-point `log2` and `exp2`, an sRGB table, one rounding rule), so every sink at a headroom, an integer in units of 1/10000 of a stop, presents the same `RGB16` bytes, and a verifier recomputes them. A rendition is a `convert` of its inputs under the synthesis extension's lattice: it rebuilds what the base and the companion hold and generates nothing. And for the **renditions a sink presents** — `wai.media.tonemap`: a rendition record names the base, the companion, each headroom and the digest of each rendition, and a verifier holding the envelope recomputes them: [`extensions/exact-tonemap.md`](extensions/exact-tonemap.md). ISO 21496-1:2025 was not read for this registration; what the extension states of it is marked there. **Point clouds: what the two registrations name.** `wai.pc.gpcc` names G-PCC, ISO/IEC 23090-9, and `wai.pc.vpcc` names V-PCC, ISO/IEC 23090-5; each payload is a bitstream of the part it names. A bitstream of another part of MPEG-I is not a payload of either unless it is also a bitstream of that part. Enhanced G-PCC, ISO/IEC 23090-38, is such another part, with its own conformance part, so it would be registered, if at all, under a capability string of its own (§8). Neither registration names an edition, so each carries the edition of its part current when it was registered, on 2026-06-17 (§8, *Editions*). Which edition that was is unresolved: the research registry records it as open, as it does whether `wai.pc.vpcc` carries the V3C bitstream of MIV. Until a revision records the edition, what either registration admits beyond the tools of its part's first edition is unspecified: a sink that advertises either capability is not known to decode a bitstream that uses a later tool, and an encoder that emits one makes no claim a sink can rely on. The amendments in preparation that add Gaussian splats to both parts were not published on the registration date, so each needs a capability string of its own (§8). Whether V-DMC, which the fourth edition of ISO/IEC 23090-5 makes a V3C application, is admitted turns on the unresolved edition. **JPEG XS.** A `wai.image.jxs` payload is one JPEG XS codestream (ISO/IEC 21122-1), `SOC` to `EOC`. A `wai.video.jxs` payload is five `u32` little-endian values, `n`, `h`, `w`, `fps_num` and `fps_den`, then `n` codestreams, each preceded by its length as a `u32` little-endian value: the framing of `wai.video.av1` (*Payload framing*, above), with a codestream for a temporal unit. A sink that advertises either decodes at the strict conformance point of ISO/IEC 21122-4 (Annex B.2: decoded images bitwise identical to the reference images), not only at its relaxed point, so the class of both is `StandardDefined`; the measurements behind it, and RFC 9134's and SMPTE ST 2110-22's carriage of the payload, are [format-probes](extensions/format-probes.md) §3. Each is tiered `Lossy` (its role is mezzanine compression; its lossless mode is signalled in the codestream, as for AVIF). Its essential patents are licensed through a pool, so its licence class is `patent-pool`. **Candidate capabilities.** A *candidate* is a registered capability string whose payload format no revision has pinned. The candidates are `wai.tensor.nnc` (general-tensor coding is in an unpublished NNC amendment; *Prior artifacts* above), `wai.splat.sog` (registered for a family of Gaussian-splat formats; no specification of the format is cited), `wai.image.ieee1857_11` (IEEE 1857.11-2024 is not openly readable, and its open reference software writes a header with no start code from a working draft; *Neural capabilities*, above), `wai.neural.soundstream` (the publication's models were not released, and the open speech codec built on it has its own models and packet, which no revision has registered; *Neural capabilities*, above), the five members of the DCVC family registered beside `wai.neural.dcvc_rt` and `wai.neural.dcvc_fm` (`wai.neural.dcvc`, `wai.neural.dcvc_tcm`, `wai.neural.dcvc_hem`, `wai.neural.dcvc_dc` and `wai.neural.dcvc_uf`: each codes its own bitstream through research code that pins no format, and none fits the inter-frame route; *Neural capabilities*, above) and `wai.video.nnvc` (neural-network-based video coding, an exploration with no published standard, whose reference software's bitstream changes between its releases). A conforming encoder's payload is the canonical byte stream of its capability (§7), and a candidate has none. So, until a revision pins a candidate's payload format: - an encoder MUST NOT emit it: not as a `WAI1` `capability` or `fallback`, and not as a `WAI2` component in either role; - a sink MUST treat it as unsupported: it takes neither step 3 nor step 5 of §4 with a candidate, and §7.1's selection never picks a component of one. The revision that pins a candidate states its payload format, and §8 fixes that format from that revision on. This rule enforces the candidate registrations as they were made (§8); it changes no payload format and no role. It makes non-conforming a `WAI1` envelope that names a candidate as its `capability` or its `fallback`, and a `WAI2` envelope with a component of a candidate; such envelopes still parse. The reference implementation lists the candidates in `codecs::is_candidate`, reports such envelopes from `Wai::check_candidates` and `WaiMulti::check_candidates`, and never dispatches or selects a candidate: `Wai::dispatch_verified`, `WaiMulti::pick`, `WaiMulti::primary` and the C `wai_envelope_select` take only a capability `codecs::is_dispatchable` accepts (§4's dispatchable). Its `wai wrap` tool, its C envelope packers (`wai_envelope_pack`, `wai_envelope_pack_multi`) and its browser writers (`pack`, `packMulti`) refuse to write one. ### Refinement capabilities (staged delivery) | capability | staged form | payload | registry class | |---|---|---|---| | `wai.image.int_refine` | residual | `WIR1` ([staged-delivery](extensions/staged-delivery.md) Appendix A.1), units RGB8 | StandardDefined | | `wai.video.int_refine` | residual | `WIR1`, units RGB8 frames | StandardDefined | | `wai.audio.int_refine` | residual | `WIR1`, units `i16` PCM | StandardDefined | | `wai.splat.int_refine` | residual | `WIR1`, units attribute tensors | StandardDefined | | `wai.field.int_refine` | level | `WIL1` ([neural-fields](extensions/neural-fields.md) §7.2), one grid level of a field | StandardDefined | | `wai.image.int_cond_refine` | conditioned residual | `WCP1` ([staged-delivery](extensions/staged-delivery.md) Appendix B), units RGB8 | StandardDefined | Each residual refinement decodes a unit through the integer operator set's stage operators, with no graph ([integer-operators](extensions/integer-operators.md) §13.5): `rans64_decode`, one stream per unit; the prediction, `up2_predict` for up2 and `rate_predict` for rate; and `residual_step` on the element range. Its registry `ops` member names the set and the stream's modes (§11). `wai.field.int_refine` decodes no stream: its payload is one level of the field it refines, which applies only as that field's next level, and the next stage is the field with that level held ([neural-fields](extensions/neural-fields.md) §7.3, §7.4; [staged-delivery](extensions/staged-delivery.md) §6.2), so it carries no `ops` member. `wai.image.int_cond_refine` predicts a unit from the stage below (identity, or `up2_predict`) and from the **side planes** its `refines` names: pictures the sink holds exactly, each the output of an object of its own (a G-buffer of rendered content, carried as an exact component) or the frame the sink renders itself from a `wai.splat.int_codec` object at a pinned pose with `wai-splat-render:i1` ([staged-delivery](extensions/staged-delivery.md) §3.1). An integer network carried in its payload, one graph of the operator set lowered by `wcp1/1`, adds a correction, and a residual decoded as `WIR1`'s corrects the result (staged-delivery §6.3). With no side plane over a base at a lower resolution, it is the detail stream of a dual stream. A side plane a sink does not hold, or that is not exact, refuses the layer (staged-delivery §4.1 step 4). Its registry `ops` member names the set, the profile `acc64`, the lowering `wcp1/1` and the stream's modes. Each is **refinement-only** (§8): its payload is applied, in a declared order, to the output of the stage below it, bound to that output's producer by content hash, and never decoded on its own. It is carried only as a `WAI1` with `refines` (§3), or as a `WAI2` component with `role: "refinement"` (§7.1). It is never a `capability` or `fallback` that §4 dispatches, a selectable rendition or a companion. Each is royalty-free and WAI-native, its payload format is pinned by this registration, it reads no parameter set, and its tier is `Lossy`: its residual, or its level's features, are quantised. Its next stage is exact given the stage below, and for `wai.image.int_cond_refine` given the side planes, which a sink holds only when they are exact, so its class is StandardDefined and its output is as exact as the base it refines ([staged-delivery](extensions/staged-delivery.md) §5). ### Base admission A capability applied to the output of a base — a refinement-only capability, or an enhancement layer — applies only over the bases listed for it here. A later revision MAY add a base, which widens the capability (§8). | capability | admitted bases | |---|---| | `wai.image.int_refine` | `wai.neural.int_hyper`, `wai.neural.int_mlicpp`, `wai.neural.int_synth`, `wai.image.png` | | `wai.video.int_refine` | `wai.video.int_motion`, `wai.video.int_hyper`, `wai.video.av1` (a grain-free stream, at `decode-equivalence`: [platform-decode](extensions/platform-decode.md) §6) | | `wai.audio.int_refine` | `wai.audio.int_codec`, `wai.audio.flac` | | `wai.splat.int_refine` | `wai.splat.int_codec` | | `wai.field.int_refine` | `wai.field.int_grid` | | `wai.image.int_cond_refine` | `wai.neural.int_hyper`, `wai.neural.int_mlicpp`, `wai.neural.int_synth`, `wai.image.png` | | `wai.video.lcevc` | `wai.video.avc`, `wai.video.hevc`, `wai.video.vvc`, `wai.video.evc`, `wai.video.evc.baseline`, `wai.video.vp9`, `wai.video.av1`, `wai.video.av1.lossless` (*Enhancement layers (LCEVC)*, below) | | `wai.audio.opus.dred` | `wai.audio.opus.packet` (*Opus deep redundancy*, below) | | `wai.audio.opus.dred.int` | `wai.audio.opus.packet` (*Opus deep redundancy*, below) | A refinement is admitted over a base when its `refines.base` names an envelope that a sink decoded through one of these capabilities. Over `wai.video.av1`, whose class promises a criterion and not the output (§7), it is admitted only where the base step holds `decode-equivalence`: the stream signals no film grain in any sequence header, and its frames are the reference decode's or those of a platform decoder whose probe matched (platform-decode §6.2); the base's units are the frames converted by platform-decode §6.3. The reference implementation holds this table once (`codecs::BASE_ADMISSION`, with `codecs::admission_needs_exact_base` for the tier), and every admission check reads it. ### Broadcast and streaming codecs (registered, sink-supplied) The elementary video and audio bitstreams that terrestrial and satellite broadcast, streaming, real-time communication and device playback carry. Registering them lets one envelope name the bitstream a distribution chain already holds, and dispatch it with a declared fallback or a sibling rendition. Every entry is **sink-supplied** — the reference implementation bundles no decoder for any of them — and **none is in the mandatory floor or the recommended set**: registration never makes a capability a default. Payload is the named standard's canonical elementary bitstream in the framing given; WAI does not re-frame it. | capability | standard | payload (canonical bytes) | licence | |---|---|---|---| | `wai.video.av2` | AV2 (AOMedia) — AV2 Bitstream & Decoding Process Specification v1.0.0, 28 May 2026 | the length-delimited bitstream of that specification's Annex B (each OBU preceded by its `leb128` byte length) | royalty-free | | `wai.video.vvc` | VVC — ITU-T H.266 \| ISO/IEC 23090-3 | H.266 Annex B byte stream | SEP-pool | | `wai.video.hevc` | HEVC — ITU-T H.265 \| ISO/IEC 23008-2 | H.265 Annex B byte stream | SEP-pool | | `wai.video.mvhevc` | MV-HEVC — ITU-T H.265 \| ISO/IEC 23008-2, Annexes F and G | the H.265 Annex B byte stream of a multiview bitstream: a Multiview Main or Multiview Main 10 layer over a Main or Main 10 base (*Multiview video*, below) | SEP-pool | | `wai.video.avc` | AVC — ITU-T H.264 \| ISO/IEC 14496-10 | H.264 Annex B byte stream | SEP-pool | | `wai.video.vp9` | VP9 Bitstream & Decoding Process Specification | VP9 frames in the IVF frame container (FourCC `VP90`) | royalty-free | | `wai.video.vp8` | VP8 — RFC 6386 | VP8 frames in the IVF frame container (FourCC `VP80`): a 32-byte file header, then a 12-byte header before each frame, as for `wai.video.vp9` | royalty-free | | `wai.video.evc` | EVC — MPEG-5 Part 1, ISO/IEC 23094-1, any profile | raw bitstream file storage format, ISO/IEC 23094-1 Annex B | SEP-pool (Main-profile tools) | | `wai.video.evc.baseline` | EVC, Baseline profile only | as `wai.video.evc`, Baseline-conformant | royalty-free by design | | `wai.video.avs3` | AVS3 video — AVS3-P2, T/AI 109.2-2021, IEEE 1857.10 | AVS3-P2 elementary bitstream | SEP-pool | | `wai.video.lcevc` | LCEVC — MPEG-5 Part 2, ISO/IEC 23094-2 | LCEVC enhancement as the ISO/IEC 23094-2 Annex B byte stream (start-code-delimited NAL units) — **companion-only**, see below | SEP-pool | | `wai.audio.mpegh` | MPEG-H 3D Audio — ISO/IEC 23008-3 | MHAS packet stream (MPEG-H 3D Audio Stream) | SEP-pool | | `wai.audio.avs3` | AVS3 audio / Audio Vivid — AVS3-P3, T/AI 109.3-2023; GY/T 363-2023; GB/T 46271-2025 | AVS3-P3 elementary bitstream | SEP-pool | | `wai.audio.aac` | AAC-LC, HE-AAC, HE-AAC v2 — ISO/IEC 14496-3 | ADTS stream (ISO/IEC 13818-7 / 14496-3); Extended HE-AAC is not this capability | SEP-pool | | `wai.audio.ac3` | AC-3 — ATSC A/52:2018 §5 \| ETSI TS 102 366 | AC-3 syncframes back to back, each from its sync word `0x0B77`, of `bsid` 0 to 8 | proprietary | | `wai.audio.eac3` | E-AC-3 — ATSC A/52:2018 Annex E \| ETSI TS 102 366 Annex E | an E-AC-3 bit stream: syncframes back to back, each access unit independent substream 0 first (an AC-3 syncframe may be it) and its dependent substreams after it | proprietary | | `wai.audio.opus.packet` | Opus — RFC 6716 | one Opus packet (RFC 6716 §3), its TOC byte first, with no container (*One Opus packet*, below) | royalty-free | | `wai.audio.opus.dred` | Opus deep redundancy (DRED) — draft-ietf-mlcodec-opus-dred-07 | one DRED extension payload (draft §3), for the Opus packet it accompanies — **companion-only**, an enhancement layer (*Opus deep redundancy*, below) | patent-pool | | `wai.audio.opus.dred.int` | DRED through its integer profile `dred-int/1` ([opus-dred](extensions/opus-dred.md)) | as `wai.audio.opus.dred` — **companion-only**, an enhancement layer (*Opus deep redundancy*, below) | patent-pool | *SEP-pool* means the standard's essential patents are licensed for royalties — through patent pools, a single standard-essential-patent licensor, or FRAND holders; it is the `patent-pool` licence class (*Licence classes*, below). Per-entry sources and caveats are in the research registry linked below. Each is tiered `Lossy` (its distribution role; the lossless modes some of them have are signalled in the bitstream, as for AVIF). No model WAI runs is involved in any of them. For replication (§7) they fall in three classes: - **`StandardDefined`** — AVC, HEVC, MV-HEVC, VVC and VP9. Each standard's decoder conformance requires every sample a conforming decoder outputs to equal the value its decoding process produces (H.264 §C.4; H.265 and H.266 §C.5.1, and for every output layer of a multilayer bitstream H.265 §F.13.5.1; VP9 §8.1), so every conforming decoder outputs the same cropped decoded pictures. The guarantee stops at those pictures: film-grain synthesis an SEI message signals, colour conversion and other post-decoding processing are outside it. - **`StandardTolerance`** — AV2 and the Opus packet. As for AV1, AV2's output is identical unless the payload signals film grain; then grain synthesis is held only to the absence of "perceptually significant differences" from the reference (AV2 v1.0.0 §7.1). `wai.audio.opus.packet` is held to Opus's conformance (RFC 6716 §6), as `wai.audio.opus` is (§7). - **`StandardUnclassified`** — VP8, EVC (both entries), AVS3 video, LCEVC, MPEG-H 3D Audio, AVS3 audio, AAC, AC-3 and E-AC-3. Their conformance documents were not read for this revision (for VP8, RFC 6386's decoder-conformance text), so the registry promises no byte identity for them; VP8 shares VP9's framing, not its class. For AAC, three decoders on one host gave three different PCM streams from one ADTS stream. ATSC A/52 lets an AC-3 or E-AC-3 decoder fill a mantissa coded with no bits with "any reasonably random sequence" (§7.3.4), so two conforming decoders need not output the same samples. LCEVC's decoding process includes a signalled dither step (ISO/IEC 23094-2, clause 8.11). Any of them moves to `StandardDefined` only with the conformance clause that fixes its output. The clauses behind each class, what was not read, and the cross-decoder measurements are in the research registry. **Multiview video.** A `wai.video.mvhevc` payload is an H.265 Annex B byte stream whose VPS extension signals multiview scalability with at least two views, and which holds a layer above the base (ITU-T H.265 (V11) Annexes F and G). A sink that advertises it outputs every output layer of the target output layer set. Its base layer is an HEVC bitstream, so `wai.video.hevc` is a usable fallback (§4, step 5): a sink without multiview decode presents the base view. The views' arrangement and the viewer geometry travel in a projection descriptor (`wai.meta.projection`, *Immersive audio, cinema, volumetric, haptics, HDR*, above). **Header probes.** [format-probes](extensions/format-probes.md) defines a header probe for `wai.video.vvc`, `wai.video.hevc`, `wai.video.mvhevc`, `wai.video.lcevc`, `wai.audio.mpegh`, `wai.video.avs3` and `wai.audio.avs3` (and for `wai.image.jxs`, `wai.video.jxs`, `wai.image.ieee1857_11` and `wai.meta.projection`): it identifies a payload as the format its capability names and reads the parameters its headers state, or refuses it with a code. A probe decodes no sample, so it does not change any class above. Where the capability is not known, [media-identify](extensions/media-identify.md) says what a file is from its bytes alone, with the offsets that say so, and runs these probes among its readings. **One Opus packet.** A `wai.audio.opus.packet` payload is one Opus packet (RFC 6716 §3), its TOC byte first, with no container: the per-packet form streaming carries, where a live track sends one packet per object. A sink decodes it with an Opus decoder (RFC 6716 §4) of one or two channels, at any rate that decoder supports. How consecutive objects of one live track are decoded is the rule of the live binding that uses it ([live-ingest](extensions/live-ingest.md)). An envelope of it carries no pre-skip and no output gain: those are Ogg Opus's (RFC 7845 §5.1), and `wai.audio.opus`, an Ogg Opus stream, remains the capability for a stored stream. It is a capability of its own because it is a different framing of the same bitstream, and a registered string's payload format is fixed (§8); `wai.video.av1.lossless` is the precedent for a suffixed string. Like every entry of the table it is sink-supplied: the reference implementation's native sink decodes `wai.audio.opus` and does not advertise the packet form. **Opus deep redundancy.** draft-ietf-mlcodec-opus-dred-07 carries, in an Opus packet's padding, a compact neural latent of the speech before the packet, from which a receiver rebuilds the acoustic features of packets that were lost. Its payload means nothing without the encode it was made with, so both strings are companion-only **enhancement layers**, bound by the rule of *Enhancement layers (LCEVC)* (below) to exactly one selectable rendition of their one base, `wai.audio.opus.packet`, where the envelope aligns the DRED payload with its packet. As LCEVC, DRED is carried embedded (the extension in the base packet's padding, under the base capability, with no DRED component) or separately (a `WAI2` companion whose payload is one DRED extension payload for frame 0 of the packet in the same envelope). `wai.audio.opus.dred` is the draft's decoding, held to the draft's conformance test, which admits features within its thresholds of the reference; it is `StandardTolerance` (§7). `wai.audio.opus.dred.int` is the same decoding through the integer profile of [opus-dred](extensions/opus-dred.md): the draft's network and its weights file, pinned by SHA-256 as the capability's one-file parameter set, lowered to `wai-ops/1` graphs ([integer-operators](extensions/integer-operators.md)) whose feature sequence is the same integers on every conforming sink; it is `NeuralIntegerExact`, its decoded output the feature sequence (the draft leaves the vocoder to the implementation), and its `ops` member names the lowering `dred-int/1`. Both are classed `patent-pool` until the royalty status the draft's IPR disclosure states becomes established. Like every entry of the table they are sink-supplied: the native sink advertises neither, and the reference implementation's `dred_exact` module (feature `dred_exact`) is the reference for the integer profile's feature decode. **Dispatch.** These dispatch exactly as §4 describes. Because none is a floor or recommended capability, no sink can be assumed to hold one: an encoder addressing sinks it does not control SHOULD ship such a payload in a `WAI2` envelope (§7.1) together with a recommended-set rendition of the same content, and that rendition is what keeps the file from being inert at a conforming sink. A v1.0 `fallback` alone does not: dispatch step 5 decodes the *same* payload with the fallback's codec (§4), so a fallback helps only where that codec's decoder accepts the primary's bitstream (`wai.video.evc.baseline` → `wai.video.evc` is such a pair; an HEVC, VVC or AV2 bitstream is not an AV1 bitstream). A deployer that must not ship pool-licensed decode filters on the licence class below, not on a hand-kept list. **Encoding (`wai.video.encode`).** WAI writes no AVC or HEVC encoder. A sink or a packager that needs an AVC or HEVC rendition encodes it with an encoder the device already has: the operating system's media framework and its hardware media engine, a GPU's encode engine through the video acceleration API or through the GPU driver's own encode interface, or a software AVC library the user obtains separately and names at run time, each loaded at run time. The encoder's output is held to one shape before it is recorded: an Annex B byte stream of one access unit per picture, an IDR access unit with its parameter sets at exactly the planned pictures and no other random access point, 8-bit 4:2:0 progressive, a single layer, no reordering. The record `wai.video.encode` is a signed statement of who made the stream (the interface, the encoder and its version, whether a hardware engine coded it, the device and the driver, and for a library the SHA-256 of the file loaded), from what source, with which settings, and at what measured energy with its acquisition class and coverage. A signer that decoded the stream also states `quality`: the SHA-256 of the decoded pictures, each plane's sum of squared differences against the pictures the encoder was handed, and the luma structural similarity in Q32, the figures integers; a signer that did not measure states `null`. A verifier holds the stream to its digest and its shape, and the source to its digest, and with the pictures recomputes each figure exactly, its verdict naming whether it decoded them from the stream; it never re-encodes, and no tier or `replicate` claim covers the encoded pictures, since no encoder is a pure function of its input. An encode over a package's pieces is framed as one floor object per piece, each naming its encoder in `derived_from` and binding its device and driver through the render settings, and the record binds the package receipt and every object: [`extensions/platform-encode.md`](extensions/platform-encode.md). **AV2 placement.** AV2 is licensed royalty-free by its standards body (footnote ⁶ of the research registry records third-party assertions), with a published specification and a reference decoder (AVM v1.0.0). It is registered here and **not** in the recommended set, because that set states what every conforming sink SHOULD implement, and in September 2026 that is not yet a reasonable ask: AVM is a reference model, a production software decoder is still in development, and hardware decode in shipping devices is not confirmed. Promotion to the recommended set is a MINOR revision (§8) once deployable decode exists; the capability string and its payload framing do not change. Until then an AV2 payload SHOULD travel in a `WAI2` envelope with a `wai.video.av1` rendition of the same content. **Enhancement layers (LCEVC).** An LCEVC enhancement is not a picture: it holds residuals that an LCEVC decoder adds to the upscaled output of **one specific base encode**. This registration names its **base codecs**: AVC, HEVC, VVC, EVC, VP9 and AV1, as the capabilities that name those bitstreams — `wai.video.avc`, `wai.video.hevc`, `wai.video.vvc`, `wai.video.evc`, `wai.video.evc.baseline`, `wai.video.vp9`, `wai.video.av1` and `wai.video.av1.lossless` — and not AV2, AVS3, JPEG 2000 or the WAI-native integer codecs. The list is WAI's, not the LCEVC standard's: ISO/IEC 23094-2:2021 takes its decoded base picture from "a base decoder" (definition 3.17) and names no base codec among its normative references. A later revision MAY add a base, which widens what the enhancement layer applies to (§8). WAI carries it one of two ways. - **Embedded.** The enhancement rides inside the base bitstream (SEI / registered user data). The payload is the base codec's bytes, under the base capability; a sink without LCEVC decodes the base and ignores the enhancement under the base codec's own rules. No `wai.video.lcevc` component exists. - **Separate.** The enhancement, in the byte-stream framing given below, is a `WAI2` companion (§7.1): `role = "companion"`, `companion_of` naming the base capability. This is the shape of LCEVC's dual-track storage in ISO/IEC 14496-15, where an enhancement track refers to exactly one base track, and the companion mechanism fits it with one added rule that binds in both directions: `companion_of` MUST name one of its base codecs and resolve to **exactly one** selectable rendition of it in the envelope, and that rendition MUST NOT be the base of any other enhancement layer. `companion_of` names a capability, not a component, so with two renditions of the base capability it cannot say which encode the residuals belong to; and a sink applies every companion bound to the rendition it picks (§7.1), so two enhancement layers on one base would add two sets of residuals to one picture. Either way the picture is corrupted. Such an envelope does not conform; a sink MUST NOT apply its enhancement layers, and MAY still present a base rendition. The separate carriage's payload is the enhancement in the byte-stream form of ISO/IEC 23094-2 Annex B, where a start code prefix (`0x000001`) precedes every NAL unit. ISO/IEC 23094-2 defines an LCEVC bitstream as either a NAL unit stream or a byte stream (definition 3.2); the byte stream is the form that delimits its own NAL units, so it is the one `wai.video.lcevc` names. A NAL unit stream without start code prefixes (for example with each NAL unit preceded by its length) is not a `wai.video.lcevc` payload; carrying that form would need its own capability string (§8). **Companion-only capabilities.** `wai.video.lcevc`, `wai.audio.opus.dred`, `wai.audio.opus.dred.int`, the HDR dynamic-metadata descriptors `wai.meta.hdr10plus` and `wai.meta.dovi` and the projection descriptor `wai.meta.projection` are **companion-only**: their payload means nothing without the base it accompanies. An HDR descriptor or a projection descriptor applies to a rendition whose payload is video (§7.1, rule 2), `wai.video.lcevc` to one rendition of one of its base codecs (above), and the two DRED strings to one `wai.audio.opus.packet` rendition (*Opus deep redundancy*, above). Every other registered capability is **standalone media** and is never carried as a companion (§7.1). A companion-only capability MUST NOT be a v1.0 `capability` (a `WAI1` carries one payload, so there is nothing for it to accompany) or a v1.0 `fallback` (dispatch step 5 would decode it on its own), nor a v1.1 selectable rendition; a sink never dispatches it standalone. A `WAI1` naming one as its `capability` is inert: its payload is companion data. A `WAI1` naming one only as its `fallback` does not conform, and a sink MUST NOT take dispatch step 5 with it; step 3 is unaffected, so a sink that advertises the envelope's `capability` still decodes it (§4). The reference implementation checks these rules in `Wai::check_component_roles` (v1.0) and `WaiMulti::check_component_roles` (v1.1: the companion rules of §7.1, including both enhancement-layer rules above), dispatches `WAI1` envelopes through `Wai::dispatch_verified`, which applies both sentences above, never returns a companion-only component from `pick` / `primary`, and its `wai wrap` tool refuses to write an envelope that fails either check. Parsing stays format-agnostic: a non-conforming envelope still parses, and the check is what reports it. The companion binding carries no per-picture timing. The framing above fixes the bytes of a separately carried enhancement stream, not how its access units align picture by picture with its base outside a timed container; this revision does not pin that alignment, so the embedded form is the unambiguous one until it does. **Licence classes.** Every payload and companion capability carries a licence class — `codecs::capability_license(cap)` ∈ {royalty-free, patent-pool, proprietary, non-commercial}, with `is_royalty_free(cap)` as the predicate. It is a registry property (not a per-file manifest claim — a codec's licence can't be honestly asserted in an envelope's header), so a deployer can audit a title or a whole catalogue in code: encode only to royalty-free capabilities, or flag every pool/proprietary one. The classification is exhaustive with no default class: a capability registered without an explicit class is a registry defect the reference tests reject, so no codec becomes royalty-free by omission. Where a capability's royalty status is not established, it is classified conservatively (patent-pool), never royalty-free; a candidate's class is provisional until a revision pins its payload format. The same tests hold that every floor and recommended-set capability is royalty-free. See [`research/media-codec-registry.md`](research/media-codec-registry.md) for the per-capability standard / spec number / verified royalty status / reference library, what each named standard's decoder conformance fixes (§7), and the remaining spec follow-ups. --- ## 6. Confidentiality (OPTIONAL — encrypted payloads / private channels) By default a WAI payload is **plaintext**: any sink that advertises the named capability (§4–§5) can decode it. This is correct for public media — a shared world, a broadcast film. Some channels are instead **private**: only an intended group may recover the content, and any relay or multiplexer that carries it MUST be able to route, meter, and attest the bytes **without** reading them. Confidentiality is an OPTIONAL layer that is **orthogonal to the capability**. It wraps the payload bytes; the capability still names how to decode the *plaintext* once recovered. A sink decrypts first, then runs capability dispatch (§4) on the plaintext. §6.1–§6.4 define that layer. §6.5 sets it beside hardware-protected content: the two lanes protected content travels in, and what a WAI record covers in each. ### 6.1 Manifest field A manifest MAY carry a `security` object: ```json "security": { "encryption": "", "kid": 0 } ``` - `security.encryption` — encryption scheme id. Absent, `null`, or `"none"` ⇒ the payload is plaintext (the default; §1–§5 unchanged). `"mls-sframe"` named the construction of `draft-jennings-moq-e2ee-mls`, an individual Internet-Draft that has expired, under which an envelope's payload alone was sealed. That construction is withdrawn: no revision defines it, and a sink refuses an envelope that names it as an unsupported scheme (§6.4 step 2). - `security.kid` — the key id of the scheme named. In a room, confidentiality is at the MoQ object, not in the manifest ([confidentiality](extensions/confidentiality.md) §4): the whole object payload, a WAI envelope or a media frame, is sealed, so an envelope travels inside the ciphertext and carries no `security` member, and once opened it is plaintext. What a relay routes by stays in the clear: the track's name, the object's Group ID, Object ID, priority and Immutable Properties (the Key ID among them), and each publisher's catalog track, whose codec, dimensions and rates describe the **plaintext** — confidentiality protects the *content*, not the *shape*. This revision registers no scheme that seals an envelope's payload on its own. ### 6.2 Keys are a requirement of existence Exactly as the model behind a neural capability is never transported (§1), the **group key is never transported**. A room's MLS group is formed and changed by the room's lifecycle; each member exports each epoch's application secret (`MLS-Exporter("wai live e2ee", room_id, 32)`) and derives every sender's keys from it ([confidentiality](extensions/confidentiality.md) §5.7). A sink that is not a member of the epoch holds no key, and the object is **inert at that sink** — the confidentiality analog of a missing capability. This is the content key. Checking a receipt needs no content key, only the signer's verifying key, which the receipt itself carries (`signer_pubkey`): where a signer publishes its verifying keys, and how a verifier confirms whose a key is, is [`extensions/jwp-receipts.md`](extensions/jwp-receipts.md) §7. ### 6.3 Relay transparency and attestation A WAI relay or multiplexer that carries an encrypted payload MUST treat it as opaque: it MUST NOT require the plaintext to route, meter, or attest, and MUST NOT attempt capability dispatch on ciphertext. The JWP receipt chain ([`extensions/jwp-receipts.md`](extensions/jwp-receipts.md)) commits over the **ciphertext** content hash, so each object's integrity, and its delivery under the publisher's signature, are attested end-to-end without any relay holding the content key. Each object's figure, class and origin are signed where its leaf is labelled, and the group total, its class, its coverage and the parent link are signed under the labelled group payload (jwp-receipts §2.2–§2.3). An object's figure and origin beside a legacy leaf are the publisher's statement, unsigned beside the signed bytes; such an object's figure is signed only where an `energy` claim restates it (jwp-receipts §2.4.5). A legacy group payload signs the total, but no class, coverage or parent link. Content secrecy (secure objects keyed by MLS) and delivery attestation (JWP) are independent layers over the same bytes and compose: a relay forwards the exact sealed bytes and their receipts unaltered, signs nothing in the publisher's name (jwp-receipts §4.3), and never learns what the bytes say. Checking the attestation needs the publisher's verifying key, which the receipt carries, never the content key; whose key it is, jwp-receipts §7 confirms. ### 6.4 Decrypt-then-dispatch A confidentiality-aware sink MUST, before running §4: 1. If `security.encryption` is absent / `null` / `"none"`, proceed to §4 on the payload unchanged. 2. Else, if the sink does not implement the named scheme, or holds no key for `security.kid`, the file is **inert at this sink** — return a clear "no key / unsupported encryption" error. It MUST NOT feed ciphertext to a codec. (The reference dispatchers in `wai-rs` implement no scheme and report `unsupported_encryption`, for a `WAI2` envelope against every entry; this revision defines no scheme of the manifest, §6.1.) 3. Else recover the plaintext payload via the named scheme, then run §4 on the recovered plaintext. A sink that does not implement confidentiality at all MUST refuse an envelope whose manifest carries a non-`none` `security.encryption` cleanly, rather than mis-decode ciphertext. A receiver of a room's sealed objects opens each object first, through the checks of [confidentiality](extensions/confidentiality.md) §6, and only then reads the envelope inside and runs §4 on it; an object that does not open is never fed to a decoder. The sealing, the key schedule, the MLS binding (per-sender keys in rooms where several principals publish, membership following the room's grants and lifecycle) and the receiving checks are specified there. The reference implementation is open and in this tree: the `secure_objects` module of `joule-moq` (feature `secure-objects`) and the `joule-moq-mls` crate. ### 6.5 Protected content: two lanes Content whose licence requires protection travels in one of two lanes. They keep the content from different parties, and a WAI record covers different things in each. A sink, a receipt, a tier claim or a status text MUST NOT present content in one lane as being in the other. **Lane A: hardware-protected content.** The media is a bitstream of a capability whose registration names its standard (§5), encrypted for a platform's protected media path: a content decryption module (in a browser, the one the W3C Encrypted Media Extensions interface reaches) and a decoder whose output the application cannot read. Decryption and decode happen inside that path. - This revision registers no `security.encryption` value for Lane A, so no WAI envelope carries Lane A media: it travels in the form its protection system defines, and WAI carries records about it. An envelope that names an encryption the sink does not implement is inert at that sink (§6.4 step 2). - WAI attests about a Lane A title only through its records, among them the manifest a session was served (`wai.video.manifest`), the package's segment map over the bytes it sliced (`wai.video.package`), each key-release decision, which binds the released key by commitment and never carries it (`wai.video.keys`), the ad decision and the per-impression receipts that bind each served `creative_hash` and the quartile it reached (`wai.video.ssai`), a channel's program-as-run windows (`wai.video.channel`), the records of the edges that chose a session's forensic A/B variants (`wai.live.watermark`), and the content hash of each WAI object delivered (jwp-receipts §2.1). None of them covers a decoded frame or sample. - A capability that synthesises output from parameters (grain, an enhancement layer, a generative stage) MAY apply to Lane A content only inside the protected path, in a decoder that the protection system certifies. WAI does not certify that decoder and cannot read its output, so such synthesis has no tier and no output digest, and a record about it states at most which capability the sink declared it ran. **Lane B: end-to-end encryption at the application layer.** Each object of a room's media tracks is sealed under its sender's key from the room's MLS group (§6.1–§6.4, [confidentiality](extensions/confidentiality.md) §4–§6). A member's application opens it and runs §4 on the plaintext, so any decoder a sink has can decode it: native code, WebAssembly, or a neural decoder. - The sink that holds the key decodes the plaintext, so the capability's tier over its decoded output ([determinism-tiers](extensions/determinism-tiers.md) §2) and the output digests it states in a `reconstruct-session` claim ([jwp-receipts](extensions/jwp-receipts.md) §2.4.12) hold as they do for plaintext, and the receipt chain covers the ciphertext (§6.3). Not every record carries over: staged-measurement counts no encrypted object and publishes no byte figure for one ([staged-measurement](extensions/staged-measurement.md) §3, *Only a checked format is counted*, code `encrypted`), and a verifier of a `reconstruct-session` claim that holds no key checks none of the rules that need a payload, which stay the signer's statement (jwp-receipts §2.4.12, rule 3). The reference dispatchers implement no scheme (§6.4 step 2), so nothing in the reference states a tier, an output digest or a binding for Lane B content. - **Lane B is not a protected-path robustness level.** It keeps the content from relays and from anyone outside the group (§6.2, §6.3). It does not keep it from a member's device: the base key, the plaintext and the decoded output are in the application's memory, readable by the application and by anything that can read that memory. A publisher MUST NOT offer Lane B to meet a licence term that requires a hardware-protected path, and a sink or a receipt MUST NOT describe Lane B content as hardware-protected. **What the exact tier covers.** `decode-equivalence` covers the medium a sink emits and can hash ([determinism-tiers](extensions/determinism-tiers.md) §2), on the fabrics determinism-tiers §5 lists: native CPU and WebAssembly in this revision (on WebAssembly, a module a sink holds at the integer level of the WAISM™ profile, [waism](extensions/waism.md) §6), and, for a decoder's `wai-ops/1-i32` graphs, the GPUs and backends listed there, with no NPU decoder: on a neural processor only the operator vectors of `wai-ops/1-npu` have run (integer-operators §9.5). It never covers output the application cannot read. A sink MUST NOT state a tier, an output digest, a reconstruction binding or an energy binding for output decoded inside a protected media path, and a `reconstruct-session` claim (jwp-receipts §2.4.12), whose every presentation carries the SHA-256 of its output, lists no presentation whose output its sink could not hash. In Lane B the tier holds as it does for plaintext; in Lane A there is no output for it to cover. --- ## 7. Conformance - A **conforming sink** MUST: implement the container (§2), capability dispatch (§4), and the mandatory floor (§5). - A **conforming encoder** MUST emit containers (§2) that any conforming sink can read; the payload MUST be the canonical byte stream for the registered capability. - A decode is conformant by the criterion its capability's registry class (below) sets. A `StandardDefined` or `NeuralIntegerExact` capability is verified by **bit-exact decode-equivalence**: against the in-crate decoder or wrapped reference library for the capabilities the reference implementation decodes (`codecs::sink_capabilities()` and the in-crate neural and WAI-native decoders), and against the named standard's own conformance bitstreams and decoded outputs for a sink-supplied codec. A `GenerativeDeterministic` capability is verified by bit-exact generation-equivalence at its pin. A `StandardTolerance` capability conforms by its named standard's own decoder-conformance criterion around a reference, not by bit-exact equality with one library's output; a `StandardUnclassified` capability conforms by its named standard's criterion, which this revision has not classified; WAI adds no bit-exact requirement to either. A `NeuralEntropyExact` capability conforms, as WAI registers it, at the entropy-decoder output (for `wai.image.jpegai`, the criterion its named standard sets on the reconstruction is not read in this revision). `NeuralFloat` capabilities make no claim that their reconstruction is bit-exact across sinks, and `Behavioral` ones conform by similarity. The WAI Rust reference impl in `wai-rs/` ships a test suite that carries every registered capability through the full WAI envelope (`cargo test --lib`, `tests/carriage.rs`). - A **conformance result**, the outcome of running one of WAI's conformance corpora against an implementation, is the signed record `conform-result/1` of [conformance-results](extensions/conformance-results.md) §2. A verifier checks its signature and that its summary and its verdict are what its cases say ([conformance-results](extensions/conformance-results.md) §4). A party that admits an implementation on one, a sink among them, also requires that its run passed, against the corpus the party holds (§4.1 there). `wai conform` writes such records, and `wai verify` checks them (`--conformant`: admits them). ### Replicate-soundness — the integer-entropy contract (normative) `intent = replicate` promises the reconstruction the capability's registry class fixes (the classes are below). For every class that backs it except two, that is a **byte-exact reconstruction**: every conforming sink that decodes the payload produces the same bytes of the medium (*decode-equivalence*, [determinism-tiers](extensions/determinism-tiers.md) §2). The two exceptions are the standard codecs whose named standard fixes less than the bytes (`StandardTolerance`) or has not been checked (`StandardUnclassified`); over those, `replicate` promises that standard's decoder conformance and no more (*What `replicate` promises over a standard codec*, below). For a **neural** capability `replicate` promises decode-equivalence, and this revision does not substitute a standard's decoder conformance for it. The one registered neural capability with a named external standard is `wai.image.jpegai` (ISO/IEC 6048-1:2025). That standard's conformance part may set a criterion on the reconstruction — an overview of the standard says the part "considers the possibility that a decoder is conformant to the standard without having bit-exact reconstruction" — but this revision has not read it, so holding `wai.image.jpegai` to the neural rule is a conservative choice pending that reading, not a finding that its standard leaves the reconstruction unbounded (`NeuralEntropyExact`, below). Decode-equivalence is only sound if the decode is byte-identical on every machine — and that is **not** automatic. A learned codec's entropy decode desyncs the instant the decoder's scale-bucket / σ computation drifts from the encoder's by one float ULP: the bucket assignment flips and the rest of the stream corrupts. So a neural decode that runs **float** inference through a runtime — which chooses kernels, accumulation order, vector width and fused multiply-adds per device — is reproducible only on the *same build*, never guaranteed across hardware. IEEE-754 basic operations are themselves correctly rounded. Float reproduces across machines only when one implementation fixes everything a runtime leaves free: the operations and their order, their precision, no contraction or reassociation, no library function whose last-place error can reach the output — and runs in the default floating-point environment (round-to-nearest-even, no flush-to-zero, no denormals-are-zero), which a host process can change. These are properties of one build and one process that neither the envelope nor the registry can state, which is why the rule below requires integer arithmetic. Therefore a neural capability MAY back `intent = replicate` **only** if its entire decode path — entropy parameterization *and* synthesis — is integer / fixed-point, with no float operation anywhere (the **integer-entropy contract**). That is the only construction by which a neural capability is registered at `decode-equivalence`. Two weaker properties MUST NOT back `replicate`: - **`entropy-consistency`** — the entropy decode (the decoded symbols, and the parameters they are decoded with) reproduces on every machine, but later stages run float, so the reconstruction may differ between conforming sinks. It is necessary for a sound neural `replicate` — without it the decode desyncs — and not sufficient, because `replicate` promises the reconstruction, not the symbols. - **A reconstruction pinned by one implementation** — float stages in a fixed evaluation order, reproducible across machines only under that implementation's build and the process's floating-point environment. Those conditions are the ones the envelope and the registry cannot state, so a `replicate` resting on them promises something no sink can check from what it received. No tier lies between these: a reconstruction kept within a bound of the exact one between points at which it is made exact again is no tier and backs nothing, a reduced-precision decode of a `NeuralIntegerExact` capability is not a decode of it, and a clip digest covers only frames each decoded at `decode-equivalence` ([determinism-tiers](extensions/determinism-tiers.md) §3, *No tier between the two*). The reference impl factors the halves of the contract into ORT-free, pure-i64 modules a codec composes: `int_entropy` (the deterministic scale→bucket step that removes the float-σ desync), `int_synth` (integer synthesis), and the integer rANS — assembled into a full conditional decode by `int_hyper_synth` (`wai.neural.int_hyper`: factorized rANS-decode `z` → integer hyper-decoder `h_s` → σ,μ → integer-σ bucket → rANS-decode residual → `y_hat = r + μ` → integer synthesis — both bitstreams entropy-coded, no float anywhere). This is a property of the capability, classified in the registry as `codecs::capability_replicate_class(cap) -> ReplicateClass`: - **`NeuralIntegerExact`** — integer by construction; byte-identical on every machine; registered at `decode-equivalence`, and the only neural class that backs `replicate`. (`wai.neural.int_synth` is synthesis only; `wai.neural.int_hyper` is the full conditional codec — σ source, entropy, and synthesis all integer; `wai.neural.int_mlicpp` is the channel-autoregressive × checkerboard entropy model on integer networks, so the σ it re-derives before each of its `2·K` passes is integer too; `wai.video.int_cond` codes each frame conditionally on the previous frame's decoded feature, through integer context, conditional-decoder and synthesis networks; `wai.video.int_hyper`, `wai.audio.int_codec` and `wai.splat.int_codec` are integer throughout as well; `wai.audio.opus.dred.int` is the DRED feature decoder of [opus-dred](extensions/opus-dred.md), whose decoded output is the feature sequence.) A capability of this class whose networks decode through the integer operator set names it in the registry, in its `ops` member ([integer-operators](extensions/integer-operators.md) §11): the lowering its sets are lowered by, the profile every conforming set's certificate meets, and the modes of its stage operators. A set whose certificate does not meet that profile is refused. In this revision: `wai.neural.int_synth`, `wai.splat.int_codec`, `wai.audio.int_codec`, `wai.neural.int_hyper`, `wai.video.int_hyper`, `wai.neural.int_mlicpp`, `wai.video.int_cond` and its frame form, and `wai.audio.opus.dred.int`. - **`NeuralEntropyExact`** — the entropy decode is integer by construction, so the decoded symbols are byte-identical on every machine; later stages run float. Registered at `entropy-consistency`. An encoder MUST NOT emit `intent = replicate` for one of these. (`wai.image.jpegai`: integer mANS entropy decode and integer scale-index derivation on both reference decode paths; float dequantisation, latent refinement, post-filters and colour conversion. What its exact decoder pins, and under which conditions, is stated in [determinism-tiers](extensions/determinism-tiers.md) §5. This class is the neural rule applied to it, not a statement about its standard's conformance on the reconstruction, which this revision has not read; see *`wai.image.jpegai` and the standard classes*, below.) Its integer stages decode through the integer operator set, named in its `ops` member ([integer-operators](extensions/integer-operators.md) §11, §13.6): the lowering `jpegai-int/1`, the profile `acc64`, which every graph of a conforming bundle meets, and the role profile `acc32` for the scale graphs `hs_y` and `hs_uv`, the stages the class covers with its two entropy decodes; a bundle whose certificate does not meet them is refused. Its hyper decoders, context stages and synthesis (§13.6.2) are integer too, from inputs the float stages give, and lie outside the class's claim. - **`GenerativeDeterministic`** — the *create*-side of byte-exact conformance. A generator (`intent = create`) whose entire pipeline is integer/fixed-point and pinned to `(model, prompt, seed, steps)`, so the **generated** content is byte-identical on every machine. There is no original to reconstruct, yet the output hash is portable and receiptable — *generation-equivalence*. The fixed-point sampler is mandatory: a float RNG or float sampling step desyncs the stream exactly as a float σ does. (`wai.generate.spectral`: a pure-integer spectral synthesis — prompt+seed draw integer-LUT sinusoid components by a `splitmix64` PRNG; the float `sin()` that bakes the LUT runs once at model-build, never at generation. `wai.avatar.face`: a talking head generated from a keypoint track and an identity prior by an integer warp and one integer graph, [avatars](extensions/avatars.md) §7; its graph decodes through the integer operator set, and its `ops` member names the lowering `face-int/1` at `acc64`.) Distinct from `Behavioral`, which conforms by similarity and never reproduces bytes. It generates rather than reconstructs, so it does not back `replicate`. - **`NeuralFloat`** — runs float inference; exact only on the same build. An encoder MUST NOT emit `intent = replicate` for one of these; `perceptual` / "exact on this build" is the honest claim. The registry claims no determinism tier for these. - **`StandardDefined`** — the reconstruction is specified exactly: by the named standard, for the lossless formats whose decoded output it determines (`wai.image.png`, `wai.audio.flac`, `wai.text.zstd`, `wai.text.xz`) and for the video codecs whose decoder conformance requires every output sample to equal the specified decoding process's (`wai.video.avc`, `wai.video.hevc`, `wai.video.vvc`, `wai.video.vp9`; clauses in the table below), or by the WAI extension that defines the capability's `*-equivalence` over integer / fixed-point state (world, score, film, quantum, ternary, the haptic signal, the integer inter-frame codec and the other WAI-native capabilities). `replicate` promises the same bytes on every conforming sink. `wai.video.int_motion` and the four residual `int_refine` capabilities decode through the integer operator set's stage operators alone, with no graph and so no parameter set or profile; their `ops` member ([integer-operators](extensions/integer-operators.md) §11, §13.5) names the set and the modes of their entropy decode. An extension's equivalence holds given its inputs: where it composes other capabilities' decoded output (a `wai.audio.scene` source decoded through `wai.audio.opus`, say), it is only as exact as those capabilities' classes. `wai.audio.scene` is the one registered capability whose output depends on envelopes it references rather than carries, so the reference registry does not report it byte-exact from the capability alone (below). No neural decode is in this class, and a capability enters it only with a recorded basis — the conformance clause or extension that fixes its output (the reference registry tests pin one per member); without one, a standard codec is `StandardUnclassified`. - **`StandardTolerance`** — a standard codec whose named standard, for at least some conforming payloads, holds decoders to a criterion around a reference rather than to identical output. For Opus and JPEG XL the clauses read state it as numeric thresholds. For JPEG and JPEG 2000 the text read points to a criterion without stating its bound (T.81 leaves the accuracy of dequantisation and IDCT to its Part 2, which was not read; only the table of contents and terms of ISO/IEC 15444-4 were read), so this revision states none. For IVAS, an implementation based on its floating-point reference code whose output is not bit-exact is tested by a non-bit-exact procedure instead: a per-frame loudness-difference corridor for stereo and immersive operation, and for mono operation the procedure of TS 26.444, which was not read (3GPP TS 26.252 §7.2.1). For AV1, AVIF and AV2 when film grain is signalled it is the absence of "perceptually significant differences" from the reference grain synthesis, which the AV1 specification leaves undefined (§7.2: its definition "is beyond the scope of this specification") and the AV2 specification leaves to others to define (§7.1). `replicate` promises what that conformance promises: every conforming sink reconstructs within the standard's criterion — for film-grain AV1 and AV2, a criterion no document WAI cites quantifies. It does not promise byte identity across sinks. - **`StandardUnclassified`** — a standard codec whose named standard's decoder-conformance clauses this revision has not checked. `replicate` promises what that conformance promises; the registry does not say whether that is byte identity. - **`Behavioral`** — a sink-generator path that conforms by similarity, not bytes (`wai.semantic.*`). #### What `replicate` promises over a standard codec A standard codec's reconstruction is what its named standard's decoder conformance fixes, in that standard's own output domain; `replicate` promises that and no more. The registry classes each one by what the standard fixes (the clauses cited are the ones read; the evidence, and what was not read, is in [`research/media-codec-registry.md`](research/media-codec-registry.md)): | class | capabilities | what the named standard fixes | |---|---|---| | `StandardDefined` | `wai.image.png`, `wai.audio.flac`, `wai.text.zstd`, `wai.text.xz` | the decoded output exactly: lossless formats (PNG, W3C Recommendation, Third Edition — its filters are exact integer operations; FLAC, RFC 9639) and lossless byte formats | | | `wai.prior.set` | its bytes exactly: a listing (§3.1) is its own output | | | `wai.video.avc`, `wai.video.hevc`, `wai.video.vvc` | every sample of every cropped decoded picture a conforming decoder outputs equals the value the specified decoding process produces (ITU-T H.264 (V16, 06/2026) §C.4; H.265 (V11, 01/2026) §C.5.1; H.266 (V4, 01/2026) §C.5.1); processing an SEI message only signals, such as film grain synthesis, is outside that decoding process | | | `wai.video.vp9` | output frames "identical in all respects", in the same order, to those of the specified decoding process (VP9 Bitstream & Decoding Process Specification v0.6 §8.1) | | | `wai.video.mvhevc` | every sample of every cropped decoded picture of every output layer equals the value the specified decoding process produces (ITU-T H.265 (V11, 01/2026) §F.13.5.1) | | | `wai.image.jxs`, `wai.video.jxs` | decoded images bitwise identical to the reference images, at the strict conformance point (ISO/IEC 21122-4:2022 §6.3 and Annex B.2, read in its public preview), which the registration requires of a sink; its relaxed point, held to PSNR bounds, is not enough ([format-probes](extensions/format-probes.md) §3) | | | `wai.tensor.weft` | its plaintext exactly: the frame's header binds it by a BLAKE3 content hash, and a decoder that does not reproduce it refuses the frame (WEFTCODEC-FORMAT v1.0.0 §2.1, §12) | | `StandardTolerance` | `wai.audio.opus`, `wai.audio.opus.packet` | output within `opus_compare`'s thresholds of the reference decoder, with the same final range-decoder state (RFC 6716 §6) | | | `wai.audio.opus.dred` | decoded features within the draft's thresholds of its reference features (draft-ietf-mlcodec-opus-dred-07 §4.1: `total ≤ 0.5`, `max ≤ 0.15`, `pitch ≤ 0.02`); the vocoder that renders them is not normative (§4.2 there) | | | `wai.image.jpeg` | decoding "with appropriate accuracy", the accuracy of dequantisation and IDCT specified in Part 2 (ITU-T T.81 §7, A.3.3); Part 2 (ITU-T T.83) was not read, so the bound is not stated here | | | `wai.image.jxl` | decoded samples within per-test peak-error and RMSE thresholds of reference images (ISO/IEC 18181-3 §4.1–§4.3) | | | `wai.image.jp2`, `wai.video.j2k` | decoded components compared with reference components by error metrics, and a reversible path its definitions describe as lossless (ISO/IEC 15444-4); only the table of contents and terms of its public preview were read, so the metrics and thresholds are not stated here | | | `wai.video.av1`, `wai.video.av1.lossless`, `wai.image.avif` | identical output frames, unless the payload signals film grain; then identical frames before grain synthesis, and output frames that "do not have perceptually significant differences" from the reference grain synthesis, a criterion whose definition the specification places outside its scope (AV1 §7.2) | | | `wai.video.av2` | as AV1: identical output unless film grain is signalled, then one of the same two options (AV2 v1.0.0 §7.1) | | | `wai.audio.ivas` | output bit-exact to the test sequences, or, for an implementation based on the floating-point reference code whose output is not, a non-bit-exact procedure: TS 26.444's for mono operation, a per-frame loudness-difference corridor for stereo and immersive operation (3GPP TS 26.252 V19.2.0 §7.1, §7.2.1) | | | `wai.audio.iamf` | its substreams include Opus (above), and renderers are out of its scope | | `StandardUnclassified` | `wai.video.vp8`, `wai.video.evc`, `wai.video.evc.baseline`, `wai.video.avs3`, `wai.video.lcevc`, `wai.audio.mpegh`, `wai.audio.avs3`, `wai.audio.ac4`, `wai.audio.ac3`, `wai.audio.eac3`, `wai.mesh.draco`, `wai.pc.gpcc`, `wai.pc.vpcc`, `wai.splat.sog`, `wai.haptic.mihs`, `wai.meta.hdr10plus`, `wai.meta.dovi`, `wai.meta.projection`, `wai.prior.nnc`, `wai.tensor.nnc`, `wai.video.nnvc` | not checked in this revision (all sink-supplied; `wai.splat.sog`, `wai.tensor.nnc` and `wai.video.nnvc` are candidates, with no payload format pinned — §5) | | | `wai.audio.aac` | not checked in this revision; three decoders on one host gave three different PCM streams from one ADTS stream, so it is not placed where byte identity would be promised | | | `wai.mesh.glb`, `wai.splat.spz` | the payload bytes pass through intact; what a sink decodes from them is not classified here (a glTF binary may carry JPEG images in its buffer and compressed geometry through extensions, and glTF 2.0 specifies an asset format, not a decoder conformance over what is rendered; SPZ stores quantised attributes) | A conversion a sink applies after the standard's decode is not part of the promise. A standard fixes its decoded samples at their own depth, layout and colour representation, and none of those above fixes a conversion to another: PNG sample-depth reduction (the PNG specification gives more than one method), YUV→RGB for AV1 and AVIF, JPEG's colour space (outside T.81's scope, §4.1), rendering an IAMF mix to a loudspeaker layout. The reference sink returns `RGB8` images and f32 PCM, so its output buffers include such conversions; they are the reference implementation's, and this revision does not specify them. #### `wai.image.jpegai` and the standard classes `wai.image.jpegai` has a named standard, ISO/IEC 6048, but its registry class (`NeuralEntropyExact`) comes from the neural rule above, not from what that standard's decoder conformance fixes. What this revision has established, and what it has not: - JPEG AI sets its bit-exact conformance point at the entropy-decoder output, and one codestream may be reconstructed through up to three synthesis transforms, which a profile or the encoder can restrict (an overview of the standard, arXiv 2510.13867; [determinism-tiers](extensions/determinism-tiers.md) §1). - The same overview says the conformance part, ISO/IEC 6048-4, "specifies the requirements for generating a JPEG AI-compliant reconstruction" through a testing suite for each profile and level pair, and "considers the possibility that a decoder is conformant to the standard without having bit-exact reconstruction", which it also calls "the possibility of standard compliance with a certain leeway"; outputs of the processes after entropy decoding "may diverge slightly from the reference". Read together, these passages point to a criterion on the reconstruction around a reference, the kind `StandardTolerance` records. The overview does not state such a criterion. - ISO/IEC 6048-4 itself has not been read (the overview describes it as a draft when it was written), so this revision does not state whether it sets such a criterion, of what form, or how wide. Classing `wai.image.jpegai` as `NeuralEntropyExact`, so that `replicate` over it is refused, is therefore a conservative choice pending a reading of Part 4. It is not a finding that the standard leaves the reconstruction unbounded. If Part 4 states a criterion on the reconstruction, `wai.image.jpegai` is a candidate for `StandardTolerance`, over which `replicate` would promise that criterion; moving it there would also take an exception to the neural rule above, which admits a neural capability to `replicate` only by the integer construction. This is not the choice made for the standard codecs. Over a `StandardUnclassified` codec, whose conformance clauses are unread, and over AV1 or AVIF with film grain, whose criterion the AV1 specification leaves undefined, `replicate` is honoured, with its promise narrowed to the standard's conformance. Those capabilities keep the behaviour they had before this revision. `wai.image.jpegai` had been registered at `decode-equivalence`, which its float stages do not meet, and it was moved to a class that does not back `replicate`. The two treatments differ because of those choices, not because of anything the standards' texts were found to say. **Registry change in v0.4.0 — a downgrade.** `wai.image.jpegai` was classed `StandardDefined`, and §5 listed it at `decode-equivalence`. Its decode has float stages, and a sink without the integer weight bundle decodes it through a float ONNX Runtime path, so neither held as a property of the capability. It is now `NeuralEntropyExact`, registered at `entropy-consistency`, and it no longer backs `replicate`; before, the reference strict check passed a `replicate` envelope over it whenever the prior declared an integer contract. **Registry change in v0.4.0 — the standard codecs.** Every standard codec was classed `StandardDefined`, and the first form of this revision's §3 promised the same bytes on every conforming sink over all of them. The previously registered capabilities in the `StandardTolerance` and `StandardUnclassified` rows above are now in those classes. `replicate` over them is still honoured; what it promises is narrower — the named standard's decoder conformance, not byte identity across sinks. No other previously registered capability changes class. The broadcast and streaming codecs this revision registers (§5) enter with the classes in the table. A conforming sink that receives `intent = replicate` for a capability whose class is `NeuralEntropyExact`, `NeuralFloat`, `GenerativeDeterministic` or `Behavioral` MUST refuse the replicate claim (decode as perceptual or reject). The capability is the one it decodes through: `model_requirement.capability`, or the fallback when it decodes via §4 step 5, or, in a `WAI2` envelope, the capability of the rendition it picks (§7.1). **The pin under `replicate`.** Over a `NeuralIntegerExact` capability a conforming sink MUST also refuse the replicate claim unless a pin applies to that capability (§3.1), declares `decode-equivalence`, and declares no form other than one the registry lists as established exact ([prior-carriage](extensions/prior-carriage.md) §5). A pin declares a tier by `tier`. A pin without `tier` declares `decode-equivalence` exactly when its `determinism`, compared in ASCII lower case, contains `int`, `fixed` or `integer` and none of `f32`, `f64` and `float`, and declares no tier otherwise. That legacy reading exists so that a pin written before `tier` keeps its verdict. It reads a declaration and can misread one (a contract naming `fp16` contains no float token); the registry class, checked first, is what guarantees the arithmetic, so a misread declaration cannot admit a float decode. An encoder SHOULD write `tier`, and SHOULD write a `determinism` that this reading classes the same way, so that a sink of an earlier revision reaches the same verdict. The refusals are named `replicate_unregistered` (the capability is not registered), `replicate_class` (its class cannot back `replicate`), `replicate_unpinned`, `replicate_tier` (the pin does not declare `decode-equivalence`) and `replicate_form_not_exact`. They read only the manifest and the registry, so a sink MAY make them before it verifies the pin; refusing the claim does not excuse the pin, which every decode of a pinned payload verifies (§3.1). The reference impl checks this per-envelope in `decode_envelope_strict` (`codecs::replicate_refusal`) in two steps. First the capability's registry class: only `NeuralIntegerExact` and the three standard classes pass, whatever the envelope declares (`ReplicateClass::replicate_promise` states what each promises). Then, for a `NeuralIntegerExact` capability, the pin: it must be present and declare `decode-equivalence` (`Prior::declared_tier`), and a pin that declares a form passes only if the registry lists that form as established exact ([prior-carriage](extensions/prior-carriage.md) §5): `wai.prior.set` is listed, and no coded form is. The prior check reads the sender's declaration; the class check is what ties it to the capability, so an envelope whose prior declares an integer contract over a float or entropy-only capability is refused. `decode_envelope_strict` applies the rule to the capability it decodes through — `model_requirement.capability`, or the fallback when dispatch reaches step 5 — and, when the rule refuses every capability the sink could decode through, refuses before it verifies a pin or reads a file; `decode_multi_strict` considers only the renditions this rule admits, and reports each one it leaves out with that rendition's `replicate_*` reason (§7.1 step 5). On the encoder side, `wai wrap`, which pins no prior, writes `intent = replicate` only where that check accepts it unpinned — over the three standard classes — for the capability and for any fallback it declares, or, in the `WAI2` companion form (§7.1), for the base payload's capability and each companion's, and otherwise refuses unless given another intent (`codecs::unpinned_envelope_intent`). The registry class is also the *static* audit of the same property: `wai capabilities` prints it per row and reports the count of neural integer-exact capabilities, so a deployer can require "dispatch `replicate` only to a cross-hardware-sound decode", or only to a capability whose output is the same bytes on every conforming sink (`codecs::is_cross_decoder_exact`), in code, exactly as it audits royalty status. The class's promise (`ReplicateClass::replicate_promise`) and `is_cross_decoder_exact` say the same about byte identity for every registered capability but one. A capability whose output is computed from other envelopes' decoded output (`codecs::composes_decoded_sources`: `wai.audio.scene`) has the class `StandardDefined` and the promise `ReplicatePromise::ByteExact`, because its mix is exact given the PCM its sources decode to; `is_cross_decoder_exact` answers from the capability alone and is false for it, because a source decoded through `wai.audio.opus`, say, may decode differently on two conforming sinks. A deployer auditing for the same bytes uses `is_cross_decoder_exact`, not the promise. Once the capabilities of the envelopes a scene references are known, `codecs::is_cross_decoder_exact_with_sources` is true when the scene's class and every source's promise the same bytes; it answers false when it cannot tell — no source given, or a source outside `wai.audio.*`, which a scene may not reference. The `replicate` check above covers one envelope, so `replicate` over a scene is honoured and promises the same mix only given the same source PCM; each source is an envelope of its own, checked by its own class. That promise covers the output the standard or extension specifies, before any conversion a sink applies afterwards (above), so a hash over a converted output is portable only between sinks that also agree on the conversion. The classification is exhaustive with no default class: a capability registered without one has no class, and the registry tests reject it. This makes the cross-hardware property explicit per capability: a neural capability whose decode is *integer all the way down* can put its reconstruction in a receipt that verifies on another machine, and the registry records which capabilities are. Reproducibility is a **spectrum**, not a single point, and the `ReplicateClass` values above span it. The neural classes map onto the two tiers [`extensions/determinism-tiers.md`](extensions/determinism-tiers.md) names. `NeuralIntegerExact` capabilities are registered at **`decode-equivalence`** — the whole decode to the final medium reproduces on every conforming sink, so the rendered result has a portable hash; this is the tier `replicate` over a neural capability promises, and the precondition for a hard [reconstruction binding](extensions/reconstruction-binding.md). `NeuralEntropyExact` capabilities are registered at **`entropy-consistency`** — the entropy decode reproduces across devices (integer entropy arithmetic or explicit parameter transmission), the tier at which JPEG AI sets its bit-exact conformance point; it does not back `replicate`. `NeuralFloat` capabilities claim neither tier. A pin MAY state its decode's tier (§3.1, `tier`); a stated tier above the class's does not conform. ### Digests (normative) WAI names one digest algorithm for each purpose: - **Parameter-set identity** — a pin's `sha256` and `supersedes.sha256`, and each line of a listing (§3.1): SHA-256 (FIPS 180-4), written as 64 lowercase hexadecimal digits. - **Component identity** — a `WAI2` entry's `sha256`, the digest of its payload bytes (§7.1): SHA-256, written the same way. The content hash a receipt chain takes over a whole envelope ([jwp-receipts](extensions/jwp-receipts.md) §2.1) is a different object. - **Decoded output in conformance material** — a digest of the decoded output of a capability that decodes against a parameter set (§3.1), or of a standard codec (§5), in a published conformance vector or corpus, in a golden a conformance test compares with, or in a reconstruction or energy binding ([reconstruction-binding](extensions/reconstruction-binding.md) §2, [energy-binding](extensions/energy-binding.md)): SHA-256 over the capability's canonical output buffer, written as 64 lowercase hexadecimal digits. - **Receipt content and WAI-native state** — an envelope's content hash in a receipt chain, and, for a WAI-native capability that decodes against no parameter set, its state hash and the digests of its rendered output: the algorithm the defining extension names ([jwp-receipts](extensions/jwp-receipts.md) §2.1; the extensions §5 links). A conformance vector or corpus that states a digest of decoded output in the third purpose MUST state its SHA-256 and MUST name the buffer it covers: - an image, or one frame of video: `RGB8` as [reconstruction-binding](extensions/reconstruction-binding.md) §2 defines it; - audio: the samples as signed 16-bit little-endian integers in output order, channels interleaved; - a sequence of frames: each frame's digest, and a clip digest, the SHA-256 of the frames' 32-byte SHA-256 digests concatenated in output order; - any other output (an attribute tensor, an intermediate stage): the buffer the vector's documentation names, with its element type, byte order and layout. A vector MAY state other digests of the same buffer, such as a 64-bit FNV-1a or a domain-separated BLAKE3, to locate a divergence. A verifier MUST NOT accept a decode on such a digest alone. A hash a capability uses as a step of its own algorithm (the prompt fold of `wai.generate.spectral`) is part of that capability, not a digest of its output, and this rule does not reach it. A frozen digest SHOULD be re-derived on more than one instruction-set architecture before it is published. ### Signatures (normative) Every Ed25519 signature (RFC 8032, pure Ed25519) that WAI or one of its extensions defines is verified strictly: on a receipt of any family, a claim, a key-log document, a module grant or status, an op, and a world's seal. A verifier MUST refuse a signature unless each of these holds, in this order: 1. **The key is canonical.** The public key `A` is the one encoding of its point that RFC 8032 §5.1.3 allows: `y` < p, and no sign bit when `x` is 0. A decoder that reduces `y` modulo p, or reads the sign bit beside `x` = 0, reads a second spelling of a point; that key is refused. 2. **The key is not of small order.** `A`'s order does not divide 8. Under such a key the equation can hold for a signature made without any private key: under the identity, `(R, S) = (B, 1)` verifies over every message. 3. **`S` < L**, the order of the base point B (RFC 8032 §5.1.7). 4. **`R` is not of small order.** `R` decodes to a point whose order does not divide 8. 5. **The cofactorless equation holds.** `[S]B − [k]A`, with `k = SHA-512(R ‖ A ‖ M) mod L` over the bytes of `R` and `A` as the signature and the key give them, encodes to `R` byte for byte; an `R` that is not its point's canonical encoding never does. A key that fails step 1 or 2 is a defect of the key, and an extension MAY report it apart from a defect of the signature (jwp-receipts §3.1 step 3: `bad_signer_key` and `signature_verify_failed`). The rule fixes what RFC 8032 leaves to the verifier, so every conforming verifier accepts the same signatures. OER/2 is the one exception: oer-receipts §5 settles its chain signature, which refuses a key by steps 1 and 2 and checks `R` as RFC 8032 does. A record **MAY** carry a second, post-quantum signature beside its Ed25519 one ([pq-signatures](extensions/pq-signatures.md)): ML-DSA-65 (FIPS 204) under the composite `id-MLDSA65-Ed25519-SHA512`. Its Ed25519 half is verified by the rule above, over the composite's message representative rather than over the record's bytes (pq-signatures §4.2), and its ML-DSA half by FIPS 204 Algorithm 3; the record verifies only if both do. A record without one is verified by the rule above alone, as before. ### Machine-checked totality (informative) The cross-architecture matrix establishes byte-exactness by **sampling**: it decodes fixed vectors on every OS/arch leg of the byte-equality matrix (`.github/workflows/wai-byte-equality.yml`). `wai-verify/` supplies the complementary half by **reasoning** — a model checker (Kani/CBMC) over the same `#[path]`-included sources, for every input in a bounded window. What it discharges is the property the byte-exactness claim rests on: **arithmetic totality**. Rust integer overflow *panics in debug and wraps in release*, so an overflowing decoder is not one implementation but two, and which one a sink runs depends on how it was compiled. A decode proved free of overflow, out-of-bounds access and non-termination is a decode whose bitstream denotes exactly one symbol sequence. `matmul`'s accumulation is total for fixed-point operands of realistic magnitude (±2^31 at Q16). This one is a *conditional* result and is stated as such: the product is formed in i128 then truncated to i64 and accumulated with a plain `+=`, which genuinely does overflow for large enough operands. Nothing in the signature constrains magnitude, so callers inherited that safe-operating range silently; the harness turns it into a written, checked precondition rather than reporting an unstated contract as a defect. Currently proved for the integer transformer kernels (`int_transform`): `softmax` is total over the whole fixed-point path (ln2 reduction, i128 polynomial, shift, division) and its output **sums to exactly `2^PROB_FRAC`** with no negative probability — the normalisation the entropy stage depends on, since a denormalised distribution becomes a denormalised CDF. The checker also shows the degenerate uniform fallback to be *unreachable*; that branch would violate the same invariant if it ever fired, so the property currently holds by unreachability rather than by construction, and the code says so at the site. Currently proved for the scale→bucket primitive (`int_entropy`): `det_build_index` always returns an index addressing a real scale-table entry, and is **monotone in σ** — a larger σ never selects a smaller bucket. The monotonicity is proved for an *arbitrary* edge table rather than only an ascending one, so it does not rest on a precondition a caller might not maintain; it is the property the bucketing exists to guarantee, and a non-monotone bucketing would mis-order the table without ever panicking. Currently proved for the integer rANS coder: `RansDecoder::new` is total for every input slice; `decode_categorical` is total and returns an in-alphabet symbol for all admissible CDFs and all streams in the window; and `decode`'s bypass escape is total. Each harness carries a `kani::cover` obligation, so a proof cannot pass vacuously on assumptions that admit no state. This is not redundant with the matrix. The matrix decodes *well-formed* vectors and therefore cannot see defects only a malformed stream reaches; four such defects in the bypass escape — a stream-controlled shift distance, two saturating-arithmetic gaps, an unbounded read — were found this way and fixed, with the conformance vectors confirming the fix changed nothing a conforming encoder can produce. The `wai.video.ssai` decision policy is **test-backed, not proof-backed**: the natural theorem — that `decide` never proposes a fill exceeding the funds, the avail duration or the slot count — did not close (three configurations, up to 900s each). The obstacle is that the decision sorts on a heap-allocated key, so the model carries `memcmp` and the allocator machinery rather than the budget arithmetic. Stubbing that away would prove a property of the stub. What *is* proved there is narrower: a fresh decision bills nothing until its beacons arrive, so a fill cannot be mistaken for delivery. `layernorm` closes only at ±2^10 — *below* realistic Q16 activation magnitude (at ±2^20 it did not close in 25 minutes). Its guarded divide and surrounding arithmetic are therefore established for small operands only, not over the kernel's working range. The obstacle is `isqrt` over a symbolic u128, which is a limit of bounded model checking rather than a property of the code. `attention`, `linear`, `igdn` and the composed `TransformerBlock` are **not covered at all**. The technique does not reach everything, and this section records where it stops rather than listing only what it reached. **Scope, stated plainly:** these are *bounded* proofs — small symbolic CDFs, fixed-length symbolic streams, explicit unwind limits — not universal ones, and they cover the stream-controlled paths rather than the whole crate. A CDF supplied by internal tables is still assumed well-formed. The verification claims what it checks and no more. --- ## 7.1. Multi-rendition envelope (v1.1 extension) The v1.0 single-payload envelope is sufficient when one source produces one rendition for one capability. v1.1 adds an OPTIONAL multi-payload form for cases where the source emits the SAME content in multiple renditions and lets the sink pick — typically because the sink's compute budget, bandwidth budget, or runtime preference (browser- native vs WebGPU vs WebNN vs native ML) differs at decode time. The `model_requirement.fallback` field in v1.0 is **declarative** — it names a capability the sink CAN look for. v1.1 makes fallback (and multi-rendition selection generally) **executable** by carrying every declared capability's payload in one envelope. ### Self-contained-ecosystem note In a controlled-deployment ecosystem (every sink ships from one authority and therefore has a known capability set) the multi-rendition form is NOT a "graceful fallback for missing capability" — every sink has every required capability. Renditions exist for **policy selection**: high-quality on a desktop sink with WebGPU; low-quality on a phone sink; quality-vs-latency by bandwidth headroom; native vs WebNN by which runtime is initialized. The sink picks by deployer-defined policy, not by which capability happens to be installed. ### v1.1 wire format ``` +--------+----------------+-------------------+----------------+----...---+ | "WAI2" | u32 man_len | manifest (JSON) | rendition table| payloads | +--------+----------------+-------------------+----------------+----...---+ ``` - Magic is `WAI2` (distinct from v1.0's `WAI1`; sinks dispatch by magic). - Manifest is JSON with a single `renditions` array of self-contained rendition entries, in deployer-preferred order: ```json { "wai": "1.1", "media": "audio", "intent": "replicate", "renditions": [ { "capability": "wai.neural.encodec32", "kind": "encodec_tokens" }, { "capability": "wai.audio.opus", "kind": "opus" } ], "target": { "sr": 48000, "dur": 5.0 } } ``` Each entry has its own `capability` (the dispatch key) and `kind` (the codec id matching the bytes in the corresponding payload). The manifest MAY carry `security` (§6.1), which covers every payload: a sink applies §6.4 before step 2 of the selection below, and an encoder writes only a security object there. An entry MAY carry `prior`, the pin (§3.1) of the parameter set its payload was coded against. Two entries MAY name one capability with different pins: the same content coded against two parameter sets, such as a set and its successor: ```json "renditions": [ { "capability": "wai.neural.int_mlicpp", "kind": "int_mlicpp", "prior": { "id": "int_mlicpp/b", "sha256": "", "determinism": "int-rans/p16+int-mlicpp/i64", "tier": "decode-equivalence", "supersedes": { "sha256": "" } } }, { "capability": "wai.neural.int_mlicpp", "kind": "int_mlicpp", "prior": { "id": "int_mlicpp/a", "sha256": "", "determinism": "int-rans/p16+int-mlicpp/i64", "tier": "decode-equivalence" } }, { "capability": "wai.image.avif", "kind": "avif" } ] ``` A sink that holds `A` decodes the second entry; one that holds `B`, the first; one that holds neither, the third. - **Component identity.** An entry MAY carry an `id`, a string of 1 to 64 of `a`–`z`, `0`–`9`, `_` and `-`, unique within the envelope (it contains no `.`, so it never equals a capability string), and a `sha256`, the SHA-256 of the entry's payload bytes as 64 lowercase hexadecimal digits. A component's identity is its `id`, its payload digest `sha256` and its parameter-set pin `prior` (§3.1). These are one construct: no extension defines another per-component digest, and a later mechanism that addresses a component (a staged layer, a byte-range or referenced rendition, a per-rendition track) addresses it by `id` and verifies it by `sha256` and `prior`. A sink MUST check an entry's `sha256` against the entry's payload bytes before it decodes or applies the entry: a selectable entry that does not match is skipped (`component_digest_mismatch`), as an entry whose pin is refused is, and a companion that does not match is not applied. An entry whose `id`, `sha256` or `companion_of_id` is not a string (`null` is the same as absent) makes the manifest malformed, as a mistyped pin member does (§3.1), and the reader rejects the envelope. An entry's `capability` names a payload format: a capability §5 registers as a record or a derivation (*Kinds of registered string*) names none, so an entry of one, in any role, does not conform (`record-or-derivation-as-component`). - **Exploding a component.** The exploded envelope of entry *i* is the `WAI1` envelope (§2) whose payload is entry *i*'s rendition bytes. Its manifest is the entry's `envelope_manifest` when it carries one, written exactly as it is in the `WAI2` manifest; otherwise it is `{"wai":W,"media":M,"intent":I,"model_requirement":{"capability":C,"fallback":null},"conditioning":{"kind":K[,"prior":P]}[,"security":S][,"refines":R][,"target":T]}`, with no other bytes, where `W`, `M`, `I`, `S` and `T` are the `WAI2` manifest's `wai`, `media`, `intent`, `security` and `target`, and `C`, `K` and `P` the entry's `capability`, `kind` and `prior`, each written exactly as it is in the `WAI2` manifest; `R` is the entry's `refines` (*Refinement components*, below) with each component id replaced by the content hash of that entry's exploded envelope, written as [staged-delivery](extensions/staged-delivery.md) §3 orders its members (`base`, `prev`, `layer`, `span`; a run's `producer`, then `count`) with no whitespace. A bracketed part is present exactly when its member is present and not `null`. A component and its exploded envelope are the same object for every rule that names an object by content hash ([jwp-receipts](extensions/jwp-receipts.md) §2.1). An entry MAY carry `envelope_manifest`, a JSON object: the exact manifest of the entry as a `WAI1` envelope. Its `model_requirement.capability`, `conditioning.kind` and `conditioning.prior` MUST equal the entry's, its `refines` MUST be the entry's with each id replaced as above, or both absent, and, where the entry's capability is refinement-only, its `model_requirement.fallback` MUST be `null` (`component-manifest-mismatch`). A `WAI1` envelope packed into a `WAI2` with its manifest copied verbatim into `envelope_manifest` explodes back to the same bytes, and so keeps its content hash, when its manifest has no bytes before or after its JSON value (whitespace around a member's value is not part of it, so an explode cannot write it back) and nothing follows its payload; a packer refuses any other envelope, and refuses an output that does not explode back to its sources (one whose manifest, nested in the `WAI2` manifest, passes §2's nesting limit). Entry *i*'s exploded envelope is defined by entry *i* and the entries its `refines` names, so an entry that cannot be exploded leaves every entry that does not name it intact. A tool that re-serialises a `WAI2` manifest may change these bytes, and with them the content hashes of the exploded envelopes. - Rendition table: `u16 n_renditions | n × (u32 offset, u32 length)`, offsets relative to the start of the payloads block. The table's i-th entry corresponds to `renditions[i]` in the manifest. - Payloads block: the rendition byte ranges, packed contiguously. - `n_renditions` MUST equal the manifest's `renditions.length`. - The bytes from offset 0 to the end of the rendition table are the envelope's **head**. They give every component's byte range and, with each entry's `sha256`, its digest, so a sink can fetch and verify one component without the others ([http-delivery](extensions/http-delivery.md) §7). ### Selection algorithm A v1.1-aware sink MUST: 1. Read the manifest and take its ordered `renditions` entries. 2. Walk the entries in order, and pick the first that is not a companion (below), whose capability is dispatchable (§4), that the sink either advertises OR whose declared backend the sink prefers under its deployer policy, whose `sha256`, when present, matches its payload bytes, and whose `prior`, when the entry carries one and a pin applies to its capability (§3.1), resolves at the sink. An entry whose payload digest does not match, or whose pin is refused, is skipped as if the sink did not advertise its capability, and the sink keeps the reason. Without a deployer policy, the sink walks the entries in §4's energy order: the entries step 2 may pick, by §4's ranks, table order within a rank, each taking one of those entries' places in the table; an entry step 2 never picks (a companion, a refinement, a capability that is not dispatchable) keeps its own place. A deployer policy MAY reorder or restrict the entries the sink considers; it MUST NOT pick an entry skipped for its digest or its pin. 3. Read the corresponding rendition's bytes from the payload block. 4. Dispatch as in v1.0 §4, with the entry's `capability` and `prior` in place of `model_requirement.capability` and `conditioning.prior`, and no fallback. A decode refused with `set_incomplete` (§3.1) is handled as a skipped entry: continue at step 2 with the next entry. 5. If no entry is picked, the envelope is inert at this sink: return an error that names, for each entry, its index and why it was skipped: `not_selectable` (a companion, or a capability that is not dispatchable, which step 2 never picks), `missing_capability`, `component_digest_mismatch`, a pin reason (§3.1), or, where a deployer policy restricts step 2 to the entries §7's `replicate` rule admits, the `replicate_*` reason the rule gives for an entry it leaves out; an envelope inert under §6.4 step 2 names that reason for every entry. A sink MUST NOT decode one entry's payload against the parameter set another entry pins. The envelope's `intent` applies to the rendition the sink picks, and §7's `replicate` rule reads that entry's capability and pin; a deployer policy that serves only sound `replicate` claims MAY restrict step 2 to the entries that rule admits. A v1.0 sink that encounters a `WAI2` envelope MUST refuse it cleanly (unknown magic, §2). No silent fallback to the first payload — that would hide the version mismatch. ### Companion components (descriptors bound to a payload) A `WAI2` component carries an OPTIONAL `role`. Absent ⇒ `"rendition"` (a selectable alternative of the same content — the default above). `"companion"` marks a component **applied *with* the chosen rendition, not instead of it**, naming the capability it binds to in `companion_of`. It carries the payloads that are not standalone media — the capabilities §5 registers as **companion-only**: the HDR dynamic-metadata descriptors `wai.meta.hdr10plus` / `wai.meta.dovi` / `wai.meta.st2094_50` (SMPTE ST 2094), which describe a video payload; the HDR gain map `wai.meta.gainmap` (ISO 21496-1), which describes an image payload; the enhancement layer `wai.video.lcevc`, which adds residuals to a video one; and the enhancement layers `wai.audio.opus.dred` and `wai.audio.opus.dred.int`, which carry the redundancy that rebuilds the speech of one Opus packet's lost predecessors. Carried as companions, the companion and its base ride in the **same envelope**, so the binding is intrinsic — not a spoofable sidecar. This revision registers no capability for immersive-audio mix metadata; `wai.audio.iamf` carries its own audio substreams, so it is standalone media and travels as a rendition. Selection: a sink picks a rendition among the `role != "companion"` entries by the algorithm above, then applies every companion bound to the chosen component — by `companion_of_id` when the companion carries one, otherwise every companion whose `companion_of` names the chosen component's capability (e.g. the HDR10+ block for the AV1 video the sink picked). `pick`/`primary` never return a companion, nor a component whose capability is not dispatchable (§4): a companion-only capability, a candidate, a record or a derivation. A component whose capability this revision does not register may be picked when the sink advertises it. Static HDR characteristics (ST 2086 mastering display, HLG transfer) stay in-band in the video bitstream / a manifest color field and need no companion. A component with `role = "companion"` conforms only if: 1. its capability is companion-only, or is not registered in this revision. A capability registered in any other kind (§5, *Kinds of registered string*) is not a companion: a payload capability is standalone media — its payload decodes on its own — and MUST be carried as a rendition, and a record or a derivation is no component in any role (*Component identity*, above); 2. `companion_of` is present and names a capability the companion applies to. An HDR dynamic-metadata descriptor, registered as a companion to a video payload, applies to a registered capability whose payload is video — the `video` media class (§3), as the capability's registration places it: every `wai.video.*` capability that is not companion-only, the neural video codecs `wai.neural.video_bmshj2018`, `wai.neural.dcvc_rt` and `wai.neural.dcvc_fm` (§5, *Video:*), and the films `wai.film.linear` and `wai.film.reel` ([linear-film](extensions/linear-film.md) gives a linear film's `media` the value `"video"`, and a reel is a film with cuts). A capability registered as video in a later revision joins that class. `wai.meta.st2094_50` is such a descriptor. The gain map `wai.meta.gainmap`, registered as a companion to an image payload, applies to a registered capability whose payload is an image: the `image` media class (§3), as the capability's registration places it (the registry's `media` column, [REGISTRY](REGISTRY.md)), every `wai.image.*` capability that is not refinement-only, the neural and generative image codecs and the semantic paths, which regenerate an image. `wai.video.lcevc` applies to one of the base codecs §5 lists for it, and `wai.audio.opus.dred` and `wai.audio.opus.dred.int` to `wai.audio.opus.packet` (§5, *Base admission*). No companion applies to a companion-only capability. This revision constrains no base for a companion whose capability it does not register, nor an HDR descriptor's or a gain map's base whose capability it does not register; 3. a selectable rendition of that capability is present in the envelope — for an **enhancement layer**, exactly one, the base encode its residuals were produced against, and that rendition is the base of no other enhancement layer (§5). Several descriptor companions MAY bind to one base, and a descriptor MAY bind to several renditions of one capability. A companion MAY carry `companion_of_id`, the `id` of the one entry it binds to. That entry MUST exist, MUST have the capability the companion's `companion_of` names, and MUST be a selectable rendition; the companion then binds to exactly that entry, and rule 3's "at most one enhancement layer per base" is checked by entry. `companion_of` keeps its meaning, so a sink that does not read `companion_of_id` binds by capability: for an enhancement layer over two renditions of one base capability it finds the base not unique, and does not apply the layer. An envelope with a companion that breaks any of these does not conform (the reference `WaiMulti::check_component_roles` reports the first break). A sink MUST NOT apply a companion that breaks rule 1 or 2, nor one whose capability it does not recognise; a companion that breaks rule 3 binds to nothing, or, for an enhancement layer, is handled as §5 states. The sink MAY still present the rendition it picked. ### Refinement components A component with `role: "refinement"` is a layer of a stage set ([staged-delivery](extensions/staged-delivery.md)). It carries `refines` (§3), whose `base` and producers are the `id`s of entries in the same envelope (§7.1, *Component identity*); its exploded envelope carries the same `refines` with those ids replaced by the content hashes of the named entries' exploded envelopes (*Exploding a component*, above), so it is the same object as the layer carried on its own. - **Placement.** A refinement component MUST follow every selectable entry in `renditions`. - **Selection.** Selection never picks one (step 2: it is not selectable). A sink picks a rendition as above, then offers to staged-delivery §4, in `renditions` order, the exploded envelopes of the refinements whose `refines.base` is the picked entry's `id`, up to the stage its deployer policy chooses. It offers them only from an envelope every component of which conforms — each refinement below, each companion (*Companion components*), each `id` (*Component identity*) and each capability in the role §5 gives it (the reference `WaiMulti::check_component_roles`, which reads the manifest alone): an envelope one component of which breaks a rule offers none of its refinements. It MAY still present the rendition it picked. A refinement whose payload does not match its `sha256` is not offered. A refinement's exploded envelope a sink receives on its own, as a `WAI1` object ([staged-delivery](extensions/staged-delivery.md) §9), is a separate delivery, which staged-delivery §4 processes as any layer, whatever the envelope it was exploded from. - **Conformance.** A refinement component conforms only if, in this order: its capability is refinement-only (§5); it carries `id` and `sha256`; its `refines` is well formed (staged-delivery §3, with ids in place of hashes); it carries no `side` (`null` is absent): a layer that reads side planes travels as a `WAI1` object (staged-delivery §3.1); `refines.base` names a selectable entry, which carries `id` and `sha256`; its capability admits that entry's (§5, *Base admission*); every producer in `prev` names a selectable entry or a refinement before it, each carrying `id` and `sha256`; and no selectable entry follows it. No other component carries `refines`, and a refinement-only capability is carried with no other role. The reference `WaiMulti::check_component_roles` reports the first break. A sink of an earlier revision does not advertise a refinement-only capability, so it never picks a refinement by capability; and since refinements follow every selectable entry, a sink that picks the first entry it can decode picks a base. If it picks one by another policy, it finds the capability unsupported and the component inert. ### Derived renditions A `WAI1` manifest (§3), or a rendition entry, MAY carry `derived_from`. It states that its payload presents another object, the **motif**, and was made from it by a named renderer or encoder: ```json "derived_from": { "motif": "<64 hex>", "motif_capability": "", "renderer": "@", "settings": "<64 hex>" } ``` - `motif` is the motif's content hash ([jwp-receipts](extensions/jwp-receipts.md) §2.1), 64 lowercase hexadecimal digits. - `motif_capability` is the motif's capability, and `renderer` the renderer or encoder that made the payload; each a non-empty string. - `settings` is `BLAKE3("wai:render-settings\x01" ‖ JCS(settings))`, over the settings the renderer was run with as RFC 8785 canonical JSON, 64 lowercase hexadecimal digits. A sink MUST NOT present such a payload's output as meeting the motif's equivalence criterion, its tier or a `replicate` intent: the payload presents the motif; it does not reconstruct it. A verifier checks `motif` against a motif it holds and reports every other member as the producer's statement, except where a profile fixes them: [packaging](extensions/packaging.md) §7 fixes a supplied floor's `renderer` and `settings`, and a package's verifier holds them to it. A value of another form makes the member malformed; the envelope still parses (§8). A reader of an earlier revision ignores the member and loses only that statement. [packaging](extensions/packaging.md) §7 writes it on every floor object. ### v1.0 compatibility v1.0 envelopes (`WAI1`) remain valid and their format is unchanged, except that a `WAI1` naming a companion-only capability as its `capability` or `fallback` does not conform (§5; below). Encoders SHOULD emit `WAI1` when only one rendition is present (simpler form, wider sink support). `WAI2` is for sources that genuinely benefit from shipping multiple renditions per file. ### Envelopes the companion rules make non-conforming The companion rules of §5 and this section change no capability's payload format and no capability's role (§8). Each enforces something fixed before the rules were stated: - **a registration.** `wai.meta.hdr10plus` and `wai.meta.dovi` were registered as companion descriptors to a video payload, not standalone media. `wai.video.lcevc` was registered companion-only, with its base codecs, in the same revision as these rules. `wai.meta.st2094_50`, a descriptor of a video payload, `wai.meta.gainmap`, a companion of an image payload, and the enhancement layers `wai.audio.opus.dred` and `wai.audio.opus.dred.int`, each bound to one `wai.audio.opus.packet` rendition, were registered companion-only after these rules, under them. Every other registered capability is standalone media. - **the definition of a companion.** When this section introduced `role = "companion"`, it defined a companion as a component applied with the chosen rendition and naming, in `companion_of`, the component it binds to. Before these rules were stated, the text rejected none of the envelopes below, and the reference implementation had no check that reported them (its `pick` and `primary` could select an HDR descriptor). These do not conform: - a `WAI1` that names an HDR descriptor as its `capability` or `fallback`, carrying it as standalone media (§5); - a `WAI2` that carries an HDR descriptor as a selectable rendition instead of with `role = "companion"`. `pick` and `primary` no longer select it (*Selection*, above); - a `WAI2` that binds an HDR descriptor to a registered capability outside the `video` media class (rule 2) — an audio, image or text payload, or any other registered capability rule 2 does not list, a volumetric or world payload among them; - a `WAI2` that marks a registered standalone capability as a companion (rule 1). This includes `wai.audio.iamf` carried as immersive-audio mix metadata: the earlier text of this section named immersive-audio metadata beside the HDR descriptors as a payload that accompanies another, and a reference test carried `wai.audio.iamf` that way. That use did not follow the registration — `wai.audio.iamf` was registered as an immersive-audio carrier, standalone media, and no capability for mix metadata alone is registered — and rule 1 follows the registration; - a `WAI2` with a companion, of any capability — one this revision does not register included — that has no `companion_of`, or whose `companion_of` names no selectable rendition in the envelope (rules 2 and 3). The first four enforce the registrations; the last enforces the definition of a companion. Each still parses, and §5 and the rules above state what a sink does with it. No earlier revision registered `wai.video.lcevc`; this one registers it with these rules. An envelope that used that string while no revision registered it is covered by §8's rule for a new registration, as is an envelope that uses any string a later revision registers. --- ## 8. Versioning - The `wai` manifest field is `MAJOR.MINOR`. A reader MUST reject an unknown MAJOR. A reader MUST accept an unknown MINOR by ignoring fields it does not understand, provided MAJOR matches. - A reader MUST ignore a manifest member it does not understand, whatever the MINOR. Earlier text required this only for an unknown MINOR, so a reader of an earlier revision may instead reject an envelope that carries such a member, which fails closed. Or it ignores the member, and then a pin fails open (§3.1). - The container format (§2) is frozen for all of `1.x`. The manifest schema (§3, and a §7.1 rendition entry) is frozen for all of `1.x` in this sense: no member is removed or renamed, none changes type or meaning, and none becomes REQUIRED. A MINOR revision MAY define an OPTIONAL member, at the top level or inside an existing object, whose absence leaves every envelope's bytes and meaning as they were, and the revision states what it means for a reader of an earlier revision (above). This revision defines `conditioning.prior`, a rendition entry's `prior`, `id`, `sha256` and `companion_of_id`, and the pin's members `form`, `tier` and `supersedes` this way (§3.1, §7.1); envelopes that use them keep `wai` `"1.0"` or `"1.1"`. The reference implementation wrote `prior`, with `id`, `sha256`, `determinism` and `form`, before this revision defined it; an envelope written that way keeps its bytes and its meaning, except as §3.1 lists. - **The one exception to the freeze.** This revision makes one exception to the sentence above, deliberately. A member it defines, carried with another JSON type, makes the manifest malformed rather than being ignored, because a reader that ignored a mistyped pin member could decode against a set the pin excludes (a mistyped `form`, read as absent, turns a set-form pin into a form-less one). The rule covers every member listed above, the rendition entry's `id`, `sha256` and `companion_of_id` included, so one rule decides whether a manifest parses. An envelope that carried such a value before the member was defined, and parsed then, does not parse now; §3.1 lists it. Nothing in the envelope signals the change: its `wai` value is the same, so a reader of this revision rejects the whole envelope where an earlier reader ignored the member. - This revision defines the manifest's `frame` (§3, [frame-stream](extensions/frame-stream.md) §2) as an OPTIONAL member under the MINOR rule above: an envelope that does not carry it keeps its bytes and its meaning, and it is carried only under the frame capabilities (§5, *Frame forms*), which a reader of an earlier revision does not advertise, so it finds such an envelope inert. The exception does not cover it: an envelope whose `frame` is malformed still parses, and frame-stream §5 refuses it as a frame (`frame_link_malformed`). The same holds for `frame`'s OPTIONAL `number` and `capture_ms` (frame-stream §2): a reader of the revision that defined `frame` without them ignores them; a sink of this revision refuses a frame whose `number` or `capture_ms` is malformed (`frame_link_malformed`), or whose `number` does not follow its group's (`frame_number_mismatch`). - This revision also defines the manifest's `refines` (§3) and a rendition entry's `refines` and `envelope_manifest` (§7.1) as OPTIONAL members under the MINOR rule above; envelopes that use them keep their `wai` value. The exception does not cover them: an envelope whose `refines` is malformed still parses, and [staged-delivery](extensions/staged-delivery.md) §4 reports it (`refines-malformed`); one whose `envelope_manifest` does not match its entry still parses, and §7.1 reports it (`component-manifest-mismatch`). `derived_from`, on a manifest and on a rendition entry (§7.1, *Derived renditions*), is defined the same way: an envelope whose `derived_from` is malformed still parses. - New capabilities (§5) MAY be added in any MINOR revision. Existing capabilities MUST NOT be redefined — once a capability string is registered for a codec, its payload format is fixed forever; for a registration completed as the next item says, from the revision that completes it. - **Completing a registration.** A WAI-native string whose §5 row named the decoder that reads its payload and fixed no byte layout (naming, at most, a tool that wrote it) has a registration with no payload format to hold. A MINOR revision MAY complete such a registration by pinning a byte layout, which is not a redefinition. Envelopes that carried another form under the string, a tool's output among them, become non-conforming; they still parse, and the completing revision lists them in §5. From that revision on, the string's payload format is fixed as the item above states. §5, *Payloads of the WAI-native integer codecs*, completes the registrations of `wai.video.int_motion`, `wai.video.int_hyper`, `wai.neural.int_hyper`, `wai.audio.int_codec` and `wai.splat.int_codec` this way, and §5, *Payload of `wai.generate.spectral`*, completes that string's. - **Editions.** A registration that names an edition (or version) of its standard carries that edition. A registration that names none carries the edition of its named standard current on the date it was registered, and no later edition or amendment. A later edition or amendment that changes the bitstream a decoder must accept is registered, if at all, under a capability string of its own; it never widens an existing string. The machine-readable registry records both (`edition`, `registered`; [`registry/capabilities.json`](registry/capabilities.json)). Where which edition was current on the registration date has not been established, the registration says so (§5), and what it admits beyond the tools of the standard's first edition is unspecified until a revision records the edition. Citing a later edition of the same specification as the reference for a format, where the bitstream a registration admits does not change, is not a redefinition. - A MINOR revision MAY add a value of an informational manifest field (the `media` classes of §3); a reader accepts a value it does not know. - A registration also fixes the capability's **role** (§5, §7.1): standalone media, or companion-only — applied with a base rendition, never on its own. Changing a capability's role, or narrowing the renditions a companion-only capability applies to, redefines it. Widening them does not: no conforming envelope stops conforming, and a reader of an earlier revision that reports the new binding as not conforming does not apply that companion and can still present its base. - This revision adds a third role, **refinement-only**: a payload applied, in a declared order, to the output of the stage below it, bound to that output's producer by content hash ([staged-delivery](extensions/staged-delivery.md)), and never decoded on its own. It differs from companion-only, which is unordered, names its base by capability and travels only inside a `WAI2`: a refinement is ordered, names its base by content and travels as its own object. Changing a capability into or out of either role redefines it; admitting another base (§5, *Base admission*) widens it. The manifest member `refines` (§3) is an OPTIONAL member defined under the rule above for MINOR revisions: an envelope that does not carry it keeps its bytes and its meaning. A reader of an earlier revision does not advertise a refinement-only capability, so it finds such an envelope's capability unsupported and the envelope inert. - A registration of a capability that decodes against a parameter set also fixes that set's shape (§5, §3.1). Changing one file to several narrows it and requires a new MAJOR; several to one widens it, which a MINOR revision MAY do. - Removing or repurposing an existing capability — changing its payload format or its role — requires a new MAJOR. - A MINOR revision MAY add a conformance rule that enforces a registration, or the definition of a manifest field, as it was made, changing no payload format and no role. Such a rule makes non-conforming only envelopes that used a capability against its registration or a field against its definition, and the revision lists every kind of envelope it makes non-conforming; they still parse. The companion rules of §5 and §7.1 are such rules, and §7.1 lists the envelopes they affect (*Envelopes the companion rules make non-conforming*). §3.1's pin rules are such rules, and §3.1 lists the envelopes they affect. - Registering a capability gives a string a payload format and a role that no earlier revision gave it, and the rules of §5 and §7.1 then apply to it. An envelope that used the string before then used a capability no revision defined, and no rule checked that use against a registration it did not yet have: §7.1 constrains an HDR descriptor's base only when the base's capability is registered, and holds a companion of an unregistered capability only to naming a base that is present (rules 2 and 3). Leaving a use unchecked does not make it conform to a registration made later, so the registering revision MAY make such an envelope non-conforming where it uses the string against the new registration. This narrows nothing a registration fixed and is not a redefinition. The kinds of envelope are listed here, once, for every registration, so a registering revision need not list them again: registering a standalone capability makes non-conforming a `WAI2` that carried it as a companion (rule 1) and, when it is outside the `video` media class, one that bound an HDR descriptor to it (rule 2); registering a companion-only capability makes non-conforming an envelope that carried it as a `WAI1` `capability` or `fallback` or as a selectable rendition, that bound it to a base or a number of bases its registration does not admit, or that bound another companion to it (no companion applies to a companion-only capability); registering a refinement-only capability makes non-conforming an envelope that carried it as a `WAI1` `capability` without `refines`, as a `fallback`, or as a selectable rendition or a companion, and one that bound a companion to it. Such envelopes still parse. - **Planned breaks.** A capability that comes to decode through the integer operator set ([integer-operators](extensions/integer-operators.md) §13) refuses some inputs it decoded before, or decoded differently by build. Each is a new refusal of input no committed corpus contains, and no committed output changes; integer-operators §15.3 states them, and the changelog records each when it lands. Landed in this revision: - `wai.neural.int_synth`: a payload whose reserved byte is not 0, or whose `C` is 0, or whose latents exceed `2^26` values; a set with no layers, with a layer whose `out_ch`, `k` or `stride` is 0, with a field of `2^32` or more, or with a shift of 128 or more; a set or payload that a cap refuses (a tensor, or a transposed convolution's uncropped output, past `2^26` elements); and a set whose certificate does not meet `acc64`. A shift from 64 to 127, which a build used to mask or panic on, now has its exact meaning. - `wai.splat.int_codec`: a set refused at load by its lowering, before any stream is decoded (`model_mismatch`): a layer with a bias of magnitude `2^63 − 1` or more, or a `check` range its producer cannot meet, each of which refused every decode (`field_range`) when the network ran; a network with no layer of tag 0, 1 or 2; and a header `shift` or `gf` of 128 or more that no layer uses. - `wai.audio.int_codec`: the same, for its synthesis, whose `check` ranges include its PCM step's: a set whose last layer cannot give a sample inside that range, which refused every decode at that step, is refused at load. - `wai.neural.int_hyper` and the keyframe of `wai.video.int_hyper`: the same, for either of its networks, `h_s` and `g_s`: such a set is refused after the payload's shapes are checked and before either stream is decoded. - `wai.neural.int_mlicpp`: the same, for any of its three networks, `h_s`, `entropy` and `g_s`: such a bundle is refused after the payload's header and the networks' geometry are checked and before either stream is decoded. Four checks its decoder made when a network ran now come before the streams, with the same code (`model_mismatch`): a layer that does not fit the channels before it, a network that does not read the payload's channel count, a header `shift` or `gf` of 128 or more that a layer uses, and a leaky ReLU's shift of 64 or more; where a stream or a value was refused first, the bundle now is. A bundle with a convolution whose padded side exceeds `2^26` is refused. - `wai.world.model`'s integer renderer (informative): what the direct renderer, which checked nothing, rendered from or panicked on is refused before the first frame: a set whose `afrac` is outside `1..=30` or differs between its two networks, with no action plane, or that breaks a `WHM1` network's rules above (`model_mismatch`); a row that does not carry one value per action plane; `T` that does not give the latent's shape back, or `g_s` that does not plan on it (`model_mismatch`); a latent that is not `C·lat·lat` values (`geometry_mismatch`), of side 0, or past `2^26` values; a move whose plane value leaves `i64`. A value outside a `check` range is refused (`field_range`) where the renderer computed past its exact range. - `wai.image.jpegai`, on both reference decode paths (its scale path and entropy decodes, §13.6.1): a bundle that fails a load check of §13.6.1, among them a bound above 255 or a shift outside `0..=127`, which the loader wrapped, or whose scale graphs do not meet `acc32`, a sum past `i32` or a shift past 63 (`model_mismatch`); and a latent or hyper-latent substream that ends before the decode it carries, which panicked (`stream_exhausted`). A sink holding the integer weight bundle reports the exact decode's refusal rather than decoding through the float path. Its exact decoder's hyper decoders, context stages and synthesis (§13.6.2): a weight file that breaks §13.6.2's member rules, which the loaders panicked on, or whose blocks do not have the shapes the topology names, or networks whose certificate does not meet `acc64` (`model_mismatch`); and a dequantised residual, a latent or an activation of those networks that leaves `i32` as a Q16 value, where the decoder computed on (`field_range`). - `wai.video.int_motion`, the P-frames of `wai.video.int_hyper`, and the four residual `int_refine` capabilities: none. They decode through the stage operators alone (integer-operators §13.5), with the output and the refusal of the decoders they replaced on every input. --- ## Appendix A — Reference implementation `wai-rs/` (Rust). Builds as `lib`, `cdylib`, `staticlib` so the C ABI in `wai-rs/src/ffi.rs` drops in as `libwai.dylib` / `.so` / `.dll` and can be called from any language. The crate wraps: - **image**: `image` crate (PNG, JPEG, AVIF via `ravif`), `jpegxl-rs` (libjxl 0.11.x). - **audio**: `opus` (libopus 1.x), `claxon` + `flac-bound` (libFLAC). - **video**: `rav1e` (AV1 encode) + `dav1d` (AV1 decode). - **text**: `zstd` (libzstd), `xz2` (liblzma). Run `cargo test --lib`. With the `codecs` feature, `wai-rs/build.rs` finds libFLAC through pkg-config (on macOS without pkg-config, in the Homebrew prefix); where it does not, set `RUSTFLAGS="-L "`. Decode speed is an implementation property, not a conformance property: the integer decoders run faster kernels (SIMD, threads) built to give the same integer for every output element as the retained scalar reference kernels. That equivalence is argued by construction and tested, not machine-proved (the harnesses of §7 do not reach these kernels) — see [`research/decode-throughput.md`](research/decode-throughput.md) for the argument, its tests, its limits and measured throughput. ## Appendix B — Why a *capability menu* For a format a standard already specifies, WAI names the standard and the sink decodes it with the library it already has: the zeroth condition's purpose is **availability**, so a file opens wherever that library is present. Where WAI needs a property no registered standard specifies — a reconstruction that is byte-identical on every machine, a world or a film that replays to the same state — it defines a WAI-native capability class with its own payload format and its own conformance criterion (§5, §7). The envelope, the dispatch rules, the registry's classes and the shared-prior model are what WAI itself specifies. ## Appendix C — License Apache-2.0. The standard and the reference implementation are open; royalty-free implementation is a precondition for adoption, so every default capability (§5) is royalty-free. Companion implementations outside this tree keep their own licences. The licence does not cover the marks: see [`TRADEMARKS.md`](TRADEMARKS.md).