### The receipt ledger prices media jobs per operation, and bills the work done

- **Tariff version 3** ([extensions/receipt-ledger.md](extensions/receipt-ledger.md) §4.6): each job price
  also names an `operation` of the catalogue (`media.encode`, `media.decode`), and a job is priced by its serving
  capability **and** its operation, the one its route record names. Within one capability an encode (a motion search,
  then a codestream written) and a decode (a reconstruction) spend different energy for the same output units, so one
  price per capability overpriced one or underpriced the other, and a decode could not be billed at its own price. A
  job whose capability and operation the tariff does not price bills nothing. A version-2 reader cannot read a price
  that names an operation (`op_len` and `operation` follow `capability`), so this is a version of its own: a tariff and
  its invoices of version 3 (`WLT1`, `WLI1` with version byte 3, the invoice laid out as version 2's).
- **A chain bills a job's work, not its output's identity** (§5.2, §5.3, §6.9, §12): under a tariff of version 3
  the records billed once for a job are its route record and its hops' OER/2 receipts, new on every run; its output's
  decode receipt (kind 15) is cited, and carried in its lines' citation digests, but is not billed once. The codecs
  are deterministic, so the same request run again delivers the same output receipt from a new hop with new energy:
  that re-run is billed, in the invoice that holds it or a later one, and its output receipt is cited again. A replayed
  hop receipt or route record is refused as before (`record_rebilled` across the chain, `record_duplicate` within an
  invoice), so two lines of one invoice cite one output receipt only under different hop receipts; two route records
  of one job are two runs of it, no longer `record_overlap`. A tariff of version 2 reads, verifies and bills exactly as
  before, an output once; a package keeps its own rule in every version (a delivered product, once per receipt).
- **The corpus** adds nine vectors: encode and decode of `int_motion` at their own prices, a re-run billed in the
  next invoice of its chain, one output under two hops of one invoice billed for each, an operation the tariff does not
  price, a replayed hop receipt refused, one hop under two lines refused, prices out of order by operation, a version-2
  invoice under a version-3 tariff, and the re-run refused under version 2. Its version-3 jobs are routed by the route
  corpus's router under that corpus's seeds; `routes/vectors.json` is unchanged. `receipt_ledger_verify.py` reads
  version 3 and its rules, requires the new mutated copies to fail, and drops two more of its checks (`operation`,
  `output-once`); the ledger service (`wai/wai-ledger`) applies the chain rule of its tariff's version.
- **Fixed:** a job price whose capability (or, in version 3, operation) is not UTF-8 text is refused
  `tariff_invalid`, as §4.3 reads it: its form is a rule, not the layout. The reference read it `malformed`, unlike the
  text and `receipt_ledger_verify.py`; no vector held such a price.
- **Breaking:** `api:rust:wai::receipt_ledger::JobPrice::operation`: a job price states its operation, empty in
  version 2. A struct literal adds `operation: String::new()`.
- **Breaking:** `api:rust:wai::receipt_ledger::JobFacts::operation`: a job source's operation, its route record's.
- **Breaking:** `api:rust:wai::receipt_ledger::check_across`: takes the tariff's version first, which decides what a
  chain bills once and whether two records of one job overlap.
- **Breaking:** `record:corpus:wai/live-conformance/ledger/vectors.json`: the control `invoice_version` gives an
  invoice of version 4, since version 3 is now defined, and is refused `unknown_version` as before; every other vector
  keeps its outcome, and the version-3 vectors are added.

