### Staged delivery in the browser, a base writer, a trace and a bench

- **A base is bounded before it is decoded, and its chain from the start**
  ([staged-delivery](extensions/staged-delivery.md) §4.5, §4.2, §14). A base whose units'
  output, with 32 bytes for each stage its kept record holds, passes the chain budget is
  not added: its envelope is reported `chain-over-limit`, no chain is kept, its kept
  record is untouched, and its layers stay held. Where a base's capability declares a
  cost before decoding (the integer payloads SPEC §5 pins), a sink applies its cost
  limit to that declared cost first, and SPEC §4 treats a base past it as one it does
  not decode, moving on to the fallback; a capability that declares no cost
  (`wai.neural.int_synth`, `wai.neural.int_mlicpp`) decodes under its format's caps. The corpus gains `base_over_budget`;
  `staged_verify.py` implements the rule independently.
- **The sink in the browser.** `wai-web` binds `wai::staged::StageSink` for JS
  (`src/stage.rs`). `StageBase.decode` decodes a base envelope by SPEC §4 through the
  integer path, with its pin verified against the parameter set the page holds in
  memory and under the page's cost limit, which is a required argument (`null` for the
  format's caps only; it bounds a base whose capability declares a cost);
  `StageBase.fromStage0` takes a base the page decoded elsewhere, which is **claimed**:
  its capability must be the manifest's or its fallback and one SPEC §4 would take (an
  inert envelope is refused), its tier is never above what the capability gives an
  unpinned base, and every report, unit and stage hash of its chain says `claimed`. A base's facts cannot
  be raised from JS (no `viaFallback` setter; `attested` only rises), and `addBase`
  takes the base. `StageSink` adds bases, offers layers, expires holds, removes, attests
  and forgets bases, and reads back every unit's stage, producer, frozen flag, tier,
  shape, output, stage hash (with its `claimed` mark) and squared error against a
  reference. `stageLayerInfo` reads a layer's `refines`, `WIR1` header, declared cost and
  byte split (framing, manifest, payload), and a base's declared decode cost, before
  either is offered. Reports and units come back in the corpus's own form. Media reach
  the page as `WAI1` bytes only.
- **The browser equals the native sink.** `wai-web/demo/verify_staged_wasm.mjs`
  replays every case of `staged-conformance/` through the wasm32 build: each integer
  base is decoded in wasm32 and must give its `stage0.bin`, its tier and its fallback
  flag, and every report, final unit, stage hash and clip hash must equal what the
  native sink wrote. `wai-web-wasm.yml` runs it and watches the corpus; the crate's
  native tests replay the corpus through the binding's pure-Rust half as well.
- **One base path.** `staged::decode_base` runs SPEC §4 for a base through
  `Wai::dispatch_verified`: its capability, then its fallback, each only where it is
  dispatchable, so a refinement-only or companion-only capability makes the envelope
  inert (`missing_capability`) and never reaches its fallback. It takes the sink's cost
  limit (checked before any symbol is decoded or output allocated, `cost_over_limit`)
  and its key log (SPEC §3.1 check 5 over a pin and over an unpinned set; none skips
  it). `decode_base_via` asks for one of the two capabilities and refuses any other
  (`not-offered`). The refusals come in a stated order: `not-wai1`, then `encrypted`
  (SPEC §6.4 before §4), then `not-offered`, then §4's; a parameter set is read only
  for a capability that reads one. Its own tokens are staged-delivery's kebab-case sink
  vocabulary; SPEC and payload codes pass through in snake_case. A pin counts toward
  the base's tier only where it resolved. A
  one-file set pinned without a form offers every held file to the pin, the member the
  capability reads first. The CLI and the browser share this path.
- **A keyframe-0 base writer.** `int_payload::encode_wiv1_zero_motion` codes RGB8
  frames as a `WIV1` keyframe-0 payload (zero motion, one block per frame, a closed
  group of pictures): the reference encoder the corpus generator used, now in the
  library. The corpus regenerates byte for byte through it. It refuses a clip past the
  format's caps before allocating (`too_large`). `wai stage base` writes a
  `wai.video.int_motion` base with it from raw frames, with its dimensions multiplied
  checked, and decodes it back before writing.
- **A trace to check against.** `wai stage apply` is now a sink replay: envelopes are
  taken in order, routed by content (one with `refines`, or a refinement-only
  capability, is a layer; any other is a base, decoded by SPEC §4), and a base given
  after its layers releases the layers held for it. `--json` prints each step's reports
  in the corpus's form (bytes that are not a `WAI1` this sink reads, and a base it
  cannot decode, are the step's error by their code, and the replay goes on; a base
  read with `--stage0` is claimed, and its step, units, chain's reports and final entry
  say so), and every stage a unit reached in the step, in the
  order the sink applied the layers (`StageSink::set_trace`), so a batch that takes a
  unit up several stages lists each; every stage hash a delivery in that order reaches
  is in it. A test replays the corpus through it and requires the cases' reports and
  final units.
- **`wai_stage_bench`.** Measures one staged set natively: per stage, the envelopes'
  bytes (framing, manifest and payload, and cumulative), PSNR or SNR per unit and over
  the clip from the exact integer squared error against the source at the units' final
  shape (a unit of another shape has no figure at that stage), the time each stage took
  (median and quartiles over at least 20 runs), the direct comparator (one layer per
  base at the stage's step, straight from stage 0, or why it does not apply) and every
  unit's stage hash. Energy is reported as unmetered.

