### Packaging: each step on the fabric that does it with the least energy

- **Steps and fabrics** ([packaging](extensions/packaging.md) §11.6). The computations of
  a pack and a verify are named steps (`source-read`, `segment`, `base-search`,
  `base-code`, `refine-code`, `sse`, `object-hash`, `digest`, `floor-read`,
  `floor-decode`, `index`, `io`, and `source-decode` before a pack), and each may run on a
  CPU, a GPU, a media engine or a neural processor (`npu`). Every step is defined in integers (and
  AV1 decoding by its decoding process), so where it runs changes no byte of a package
  and no verdict: §11.2 holds across fabrics. A packager runs a step on a backend only
  after it has given the reference's output on qualifying inputs; a verifier computes a
  check on another fabric only where the package states the value it compares with, and
  decides any mismatch again on the reference. No hardware encoder computes a WAI step; a
  floor encoded on one is a §7.5 floor. A floor states no decoded-output digest, so a
  hardware decode never decides a floor verdict.
- **The fabric record** ([jwp-receipts](extensions/jwp-receipts.md) §2.4.8,
  [energy-measurement](extensions/energy-measurement.md) §6.3). A measurement claim may
  carry `fabrics`: each step with every fabric that ran it and its backend, and the
  figure divided into one share per fabric, attributed `task` (the operating system's
  account of the work's own energy) or `rail` (the fabric's whole rail, the work its sole
  user, read by sampling every user's busy time through the span). A rail shared with
  other work is never divided by busy time, and a fabric that ran a step has a share of
  more than 0. `fabrics` is the one claim member that is absent rather than null, so every
  existing claim and package keeps its bytes; a verifier before this revision refuses a
  claim that carries it (`unknown_member`). New reasons: `measurement_fabric_unknown`, `measurement_fabric_order`,
  `measurement_fabric_unmetered`, `measurement_fabric_unused`, `measurement_fabric_sum`.
- **wai-pack** places each call of a step on the fabric whose measured cost for its size
  is least (`--fabric cpu|gpu|auto:<costs.json>`, `wai-pack fabric list|calibrate`), the
  CPU on a tie, where unmeasured, and for every call another fabric does not take. With
  feature `gpu`, the motion search, SSE and the object hashes run on a GPU through
  **wai-pack-gpu**, integer WGSL kernels through wgpu, shown exact on Metal (Vulkan and
  DX12 are built and not run, and nothing is claimed for them). With feature
  `fabric-meter` on macOS, `--meter fabric` meters a pack per fabric without privileges
  (the task's own and billed CPU energy, and the GPU's whole rail where the pack was its
  sole user) and seals an `OnChipCounter` figure with a declared uncertainty and the
  claim's fabric record. `wai-pack floor-decode` decodes a
  package's floors with libdav1d or the media engine and prints each piece's digest, for
  comparing decoders. The Python verifiers stay on the CPU and share no code with wai-rs;
  `claim_verify.py` and `pack_verify.py` read the fabric record.
- **Conformance.** Claim vectors of the fabric record appended after the existing ones, which a test
  pins by digest. wai-pack-gpu's kernels are held to references transcribed from the text
  and every edited kernel is caught; wai-pack's fabric differential packs every golden on
  a GPU byte for byte and gives every package and staged mutation the CPU's verdict.

