### Energy reports, labelled object leaves, and what the signatures cover

- **Reports about a figure.** Two claim classes, [`extensions/jwp-receipts.md`](extensions/jwp-receipts.md)
  §2.4.8–§2.4.9, report on one energy figure without changing the receipt that seals
  it. A claim names that receipt by a **figure profile** — the receipt's identity domain
  less its version byte, so the registry is the code's own
  ([`extensions/energy-measurement.md`](extensions/energy-measurement.md) §6.1) — and its
  identity, and restates the figure with its class. `measurement` carries the bracket's
  values as integers with each bracket's liveness facts, the build (profile, toolchain,
  target) and the power reader; only the key that signed the figure may sign it, so a
  figure no Ed25519 key signs (an energy binding's) has no `measurement` claim. A
  hardware figure's report must name its power reader (`measurement_no_power_reader`),
  with or without a bracket, and a `null` bracket says the figure was not obtained under
  the bracketed protocol. Because only §3.1 step 6 shows the signer is the figure's, a
  `measurement` claim is accepted only against the receipt that carries its figure:
  checked without it, it is `figure_not_held`, and `ClaimReceipt::attribution` gives a
  verdict only for a claim accepted against that figure.
  `operating-point` records the requested, committed and delivered operating points,
  from a vocabulary named by URI, and a prediction. energy-measurement §6 makes the
  `measurement` claim the carrier of a class-bearing figure's report and lists the
  producers that fall short.
- **Exact report arithmetic.** energy-measurement §6.2 gives the figure and the least
  declaration a report's integers support as exact integer formulas, at whatever width
  their products need. Producers seal from the same integers; computed from unrounded
  samples, a declaration could come out one ppm below what the published integers
  support. `wai-rs` `energy_report` implements it with no floating-point arithmetic, and
  `claim-conformance/claim_verify.py` recomputes the pinned brackets with Python's
  integers.
- **Derived, never stated.** The §4 ratio and verdict, whether a commitment was met,
  and a prediction's residual are derived by every reader from what a claim carries. A
  report carrying its ratio is refused (`unknown_member`).
- **A live power reader.** energy-measurement §3.1: a rail is live in a bracket only if
  it advanced in two consecutive intervals, in at least five and in at least four of
  every five, over at least 300 ms, in both brackets; a figure from a bracket that is not
  live is never sealed under a hardware class. A power sample advances only when it is
  above zero and differs from the sample before it, so a reader that holds its last
  value never advances; a reader of a report refuses, under a hardware class, a bracket
  whose `sd_uw` is 0 whatever liveness facts it carries. A frozen rail, a stale value
  held, one batch refresh, and one refresh published in two steps all used to give a
  flat idle bracket and an infinite ratio that sealed as `OnChipCounter`; `energy_burst`
  and `energy_meter` now refuse them, with fault-injection tests, and a counter meter reads its counter during a span
  rather than only at its ends. On a host whose reader reports a rail that does not
  advance, the reference meters seal unmetered and say why.
- **The unmetered marker.** energy-measurement §2: an unmetered figure is not a figure
  of zero joules. A `0` that marks unmetered is never presented, totalled or compared as
  0 J; a total over parts that include one covers only the measured parts; new forms
  mark unmetered with class tag `0`. quantum-sim, provenance, interactive-worlds,
  moq-streaming-format and SPEC read `0` this way. `ModelMeter` returns no reading rather
  than a labelled zero or a saturated product, and `wai-quantum-serve`'s `POST /verify`
  renders an unmetered receipt as `"joules_micro": null, "metered": false`.
- **The labelled JWP leaf.** An object's class rides in its Merkle leaf,
  `BLAKE3("moq-jwp:merkle-leaf\x02" ‖ content_hash ‖ u64_be(joules_micro) ‖ class ‖
  u32_be(len(origin)) ‖ origin)`, so the group signature covers the object's figure, its
  class with its evidence, and its origin (jwp-receipts §2.2, §2.4.2). A label, or the
  origin, can be neither added, stripped nor altered in transit.
- **The labelled group payload.** `moq-jwp:group-sign\x02` signs the legacy fields and
  then the total's class, its coverage and the parent link (§2.3, §2.4.1); the legacy
  payload never signed the parent. The class is composed from the objects' classes by an
  integer rule — the weakest class, and for a hardware class `⌈Σ F·p / Σ F⌉` ppm over the
  longest window — and a verifier holding every object checks it (§3, *The group
  total*), alongside the sum.
- **Position.** An object must sit at the position its inclusion proof walks (§3 step
  5, `proof_position_mismatch`), which closes the duplicated last leaf of an odd level
  and an object presented at another object's index — the latter could hide a weaker
  class from the group total. Group signatures are held to the strict Ed25519 rule
  claims use. §3.3 lists the delivery reasons; a group's link hash is defined over its
  signing payload and signature.
- **`WAI_RECEIPT`** ([`extensions/moq-streaming-format.md`](extensions/moq-streaming-format.md)
  §5): `0` is the unmetered marker, `group_receipt` is the group's link hash, and the
  property's class reads as signed only where it equals the object's leaf label or an
  accepted `energy` claim; otherwise it is discarded (`property_disagrees`) or read as
  unlabelled. A class read as signed names the key that signed it — the group's for a
  leaf, the claim's for a claim — so a class a relay signs into the property under its
  own key is never read as the publisher's.
- **What stays unverifiable.** energy-measurement §5 and energy-binding §3 now say it is
  the measurement — the joules and every field describing how they were obtained — not
  one number, and that a report's values can be checked for consistency, which is not
  truth. energy-binding §7.4 no longer says green metadata is registered; it is not yet.
- **Implementation.** `wai-rs` (feature `receipt_claims`): `jwp_delivery` reads and
  verifies both forms of each JWP receipt, the group total and the property;
  `energy_figure` holds the profile registry and views every figure-bearing receipt
  family, the quantum receipts through `MaybeLabelled`; the reference meters write a
  measurement report beside the receipt by default (`--no-report` to opt out;
  `--previous-report` with no file is a usage error), and `wai_prov` presents its total as
  `Partial` over the measured steps, or `UNMETERED`, never as 0 µJ. joule-code's
  `joule-moq` (0.2.0) builds and verifies both labelled forms, checks position, holds
  publisher keys and group signatures to the strict rule (a non-canonical key encoding is
  refused as a key), refuses an unsigned coverage on a legacy group, and runs every
  leaf, group and object vector of the new `jwp-conformance/` corpus.
- **Conformance and CI.** `claim-conformance/` gains vectors for every new reason, the
  arithmetic at its boundaries, liveness faults (a held value among them) and the
  labelled leaf; the earlier vectors are unchanged and pinned. `jwp-conformance/` holds the JWP corpus
  (`wai_jwp_vectors`) and `jwp_verify.py`, an independent verifier. CI now runs
  `claim_verify.py`, `differential.py` (fixed seed) and `jwp_verify.py` on the linux
  runner, and the JWP corpus on every platform of the conformance matrix. The
  conformance build includes `receipt_claims`, so `wai_meter` and `wai_world_meter`
  are built on every platform of the conformance matrix; `wai-energy-receipts.yml`
  builds those two, `wai_video_meter` and `wai_quantum_meter` on linux, linux-arm64
  and macos; no workflow builds `wai_prov`, which needs `codecs`. joule-code's CI runs
  `joule-moq` with its QUIC transport.
- **Build.** Every reference meter bin (`wai_meter`, `wai_world_meter`,
  `wai_video_meter`, `wai_quantum_meter`, `wai_prov`) now also requires the
  `receipt_claims` feature, because it writes a measurement report. Cargo skips a bin
  whose required features are off without an error, so a build that names only the
  older features (`--features video_receipt`, say) no longer produces that meter; add
  `receipt_claims`.

**Wire.** Every receipt issued in a legacy form keeps its bytes and verifies as before:
v1 groups, `\x01` leaves, every claim and corpus vector already pinned, `wai-quantum`'s
receipts (no `wai-quantum` code changes). The new forms are refused by software that
predates them: a verifier or relay refuses a labelled group at §3 step 2 and a labelled
object at §3 step 5, and a claim verifier refuses `measurement` and `operating-point` as
`unknown_class`. A group's `sign_version` other than 2 is `group_label_invalid`.
**External JWP implementations must adopt the `\x02` leaf and the labelled group payload
before verifying objects or groups that use them, and hold publisher keys to the
canonical-encoding rule**; the in-tree `joule-moq` does, and its public API changes are
listed in joule-code's CHANGELOG. `wai-quantum-serve` (0.4.0) changes the `POST /verify`
response: an unmetered receipt renders as `"joules_micro": null, "metered": false`
where it rendered its marker as the integer `0`, and every other receipt adds
`"metered": true`; a client that reads `joules_micro` as an integer must accept
`null`. New meter receipts can declare one ppm more than before, because they
seal from the published integers, and a meter now refuses a rail that is not live where
it used to seal a figure.

