open-standards/wai/extensions/energy-measurement.md
Transaction Science 2aa4e54d3f energy-measurement §6.3: cite packaging §11, as the section checker reads it
check-wai-section-refs.py resolves a cross-document section only to a heading, and
packaging's 11.6 is a numbered paragraph under §11; §6.3's new sentence on step
vocabularies cited "§11.6". It cites "§11, its steps and fabrics", as the sentence
after it already does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 21:14:59 -04:00

72 KiB
Raw Permalink Blame History

WAI Extension: Energy Measurement

Status: Draft. Specifies how a joule figure is acquired, so that the joules_micro field the receipt profiles carry means the same thing in two independent implementations. It defines an acquisition class and its signed encoding (§2, §2.7–§2.8), an acquisition protocol with a liveness rule for the power reader (§3, §3.1), a quality rule (§4), and a reporting contract (§6) whose values are published in a signed report that names the receipt it describes and leaves that receipt's bytes unchanged. A receipt that carries none of these additions keeps exactly the bytes it had. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

1. Why an acquisition protocol

jwp-receipts.md defines joules_micro as "microjoules consumed producing this object". That fixes the unit and the scope of attribution. It does not fix how a number gets into the field, and without that the field is a number-shaped hole: one implementation can write a counter reading, another an arithmetic model, a third a constant, and every one of them is conformant. The figures are then incomparable, and — worse — indistinguishable, because nothing in the receipt says which kind it is.

This extension closes that. It requires two things of any receipt it governs that carries energy: that the figure declare how it was acquired, and that the measurement declare whether it was good enough to publish.

The contribution is not the number. It is the number plus its acquisition class, and the discipline of withholding both when the measurement fails.

Scope. This extension governs every receipt profile WAI defines that carries an energy figure, and the producers and verifiers of those receipts. They include the receipts §2 lists, which carry joules_micro or, in the energy binding, microjoules; the MoQ WAI_RECEIPT property (moq-streaming-format §5); and the JWP group and object receipts (jwp-receipts §2.4), which carry joules_total and joules_micro. The list is not closed: a profile WAI defines is governed as soon as it carries a figure.

It does not govern a receipt profile that WAI ingests and whose members that profile fixes. An OER/2 receipt (oer-receipts) is one. It carries a non-zero energy.joules_total with no member for the class, and cannot gain one: a member not listed for its path makes the receipt non-canonical (§3 there). What an OER receipt carries instead is an evidential grade, provenance.how, and oer-receipts §2 states which grade each class supports. No rule of this extension binds an OER receipt, or its producers and verifiers as such: not the class of §2, and not the publication gate of §4 or the reporting contract of §6 either. OER/2's own rules govern it, and an OER receipt with a non-zero figure and no class breaks no rule here.

One rule reaches past the governed receipts. §2's rule for carrying a WAI figure into a vocabulary with only three class names binds whoever carries it, although the receipt the figure lands in is not governed.

Two receipts WAI defines carry a figure that the group signature does not cover in its legacy form: the JWP group receipt and the JWP object receipt (jwp-receipts §2.4.1 and §2.4.2). The group receipt signs joules_total, the sum of its objects' figures. The object receipt carries its own joules_micro, which the group signature covers only through the object's Merkle leaf (jwp-receipts §2.2). Each meets §2 as follows:

  • An object's figure carries its class as an optional label (§2.8), bound into its Merkle leaf with the figure and the object's origin. Absent, the leaf and every signed byte are the legacy ones and the figure is unlabelled. Present, the leaf covers the figure, its class, the class's evidence and the origin, and the group signature, which covers the Merkle root, covers them too.
  • A group total may carry a class of its own, signed under the labelled group payload (jwp-receipts §2.3) together with its coverage and the parent link. The class is the one the objects' classes compose to (jwp-receipts §2.4.1), so a holder of the group receipt alone holds a signed class for the total, and a holder of every object checks it (jwp-receipts §3, The group total). A group in the legacy payload carries none; a verifier holding every object reads its total from the objects' labels as §2.8 reads a total, and otherwise reads it as unlabelled.
  • A WAI_RECEIPT property (moq-streaming-format §5) has no signature of its own. Its class is inside a signature only where it equals a signed statement of the same object's figure and class: the label in the object's leaf, or an energy claim about the object. A sink reads it as a class only after checking that it does (moq-streaming-format §5).

An energy claim (jwp-receipts §2.4.5) is a receipt of its own, signed by whoever acquired the figure. It restates an object's joules_micro beside its class and the class's evidence in §2.7's JSON fields, and meets §2. A verifier holding the claim and the object receipt rejects the pair if the two figures differ, or, where the object's leaf is labelled, if the two classes or their evidence differ. It is the way for a party other than the publisher to sign a class for an object's figure.

The interactive-worlds session receipt is a profile of the group receipt that carries the class as an optional signed label (interactive-worlds §8, and §2.8 here). It is signed under its own domain, wai:world-receipt\x01, not the base group receipt's, and nothing above changes it.

Whose key signed a figure's class can be confirmed under jwp-receipts §7: an origin the verifier has anchored lists the key with the authority energy/ followed by the class. That is the origin's statement of which of its keys states figures of that class, and a key given one class cannot state another. For the hardware classes the confirmation holds only under an anchor the relying party pinned, never one fetched on first use (jwp-receipts §7.5). It is not evidence about the instrument (§2.2), and no confirmation ranks a figure above its class (§2). jwp-receipts §7.5 recommends that a hardware-class figure be signed by a key held by the component that signs the reading, apart from the key that signs delivery, and has a verifier report whether the key also holds delivery.

2. The acquisition class (REQUIRED)

A receipt this extension governs (§1) that carries a non-zero energy figure MUST carry an acquisition class alongside it. The one exception is the unlabelled legacy form that §2.8 keeps for the receipt families that sealed a figure before the class existed, the JWP object receipt and the JWP group receipt's legacy payload among them. A WAI_RECEIPT property's class counts only where §1 says it does.

class meaning requires
CalibratedInstrument Read from an instrument external to the measured device — a shunt, a power analyser, a metering socket — that holds a current calibration covering the range and conditions it was used in. a present, non-zero measurement; a declared uncertainty (§2.3); a calibration reference (§2.5)
OnChipCounter Read from an energy counter the measured silicon keeps about itself — RAPL, NVML, SMC, IOReport (§2.9) — or from any other instrument whose uncertainty is not traceable to a current calibration (§2.2). a present, non-zero measurement; a declared uncertainty (§2.3); the counter's filtering state (§2.4)
ModelBased Computed from a model calibrated on the host it describes (e.g. wall time × an active power measured on that host). A real number, honestly labelled as derived. A constant nobody calibrated there — a nominal TDP, a typical draw — is Estimator, however it is multiplied. —
Estimator A coarse constant or load estimator. —
HwShunt (legacy) Read from a hardware energy interface, sub-class unspecified, no uncertainty declared. Accepted in receipts sealed before the hardware class was refined; never emitted (§2.6). a present, non-zero measurement

CalibratedInstrument and OnChipCounter are refinements of HwShunt, the hardware rung of the three-name vocabulary (HwShunt / ModelBased / Estimator) the receipt families elsewhere in the ecosystem use. A producer that emits a WAI figure into a vocabulary with only those three names MUST map both refinements to HwShunt; that loses the distinction and asserts nothing false. The vocabulary is extended, not replaced. The evidential grade of an OER receipt (oer-receipts §2) is a separate axis, and that section states which grade each class supports.

A counter reading is not an estimate. RAPL, NVML and IOReport are sensor values, and OnChipCounter says so (§2.9 states where this departs from other documents in the repository). What separates the two hardware classes from each other is what backs the figure's uncertainty (§2.2), and what separates both from the rungs below is provenance and scope, not accuracy — see §5.

The classes are ordered by what backs the figure's uncertainty statement, strongest first: CalibratedInstrument, OnChipCounter, HwShunt (legacy), ModelBased, Estimator. Wherever this extension says "the weaker class applies", it means this order.

Normative:

  • An unmetered figure is not a figure of zero joules. Where a field encodes unmetered as 0 — joules_micro in every receipt profile WAI defines, and the legacy fields that predate this section — that 0 is the unmetered marker: a reader MUST present it as unmetered and MUST NOT present, total, average or compare it as 0 J. A total over parts that include unmetered parts covers only the measured parts (Partial, energy-binding §4) and MUST say so. A field or form defined after this revision marks unmetered explicitly — class tag 0 beside a zero figure, as the labelled JWP leaf and group do (jwp-receipts §2.2, §2.3) — and never by a bare 0 alone. A meter that cannot measure produces no reading at all, never a reading of zero, and a model whose output is zero is not a measurement of zero either.
  • An implementation MUST NOT emit a non-zero energy figure without a class in a receipt this extension governs (§1), except in the unlabelled form of §2.8. An unlabelled number cannot be compared to any other number.
  • An implementation MUST NOT emit a class with a zero or absent figure. That claims a measurement which did not occur.
  • The class MUST be inside the signature, so an intermediary cannot promote a ModelBased figure to a hardware class, or an OnChipCounter figure to a CalibratedInstrument one, in transit. The class's evidence — the declared uncertainty, the filtering state, the calibration reference — MUST be inside the signature with it (§2.7).
  • A verifier MUST treat a receipt violating either coupling as invalid, not merely as unlabelled — with the one exception of a legacy unlabelled figure in a receipt family that carries the class as an optional label (§2.8) — and MUST treat a CalibratedInstrument or OnChipCounter class that lacks its declared uncertainty (§2.3), or a CalibratedInstrument class that lacks its calibration reference (§2.5), the same way.

The reference implementation enforces these rules in verify() rather than documenting them, and returns no rate at all — never 0 — when unmetered, because a zero reads as "this work was free", which is a stronger and false claim than "nobody measured". The class and its evidence have one definition (energy_class in wai-rs, mirrored byte for byte by quantum_energy in wai-quantum), and every receipt within this extension's scope (§1) that the reference implementation seals carries its figure in one of two ways:

  • Always present, in the receipts defined with a class from the start: the energy binding and its C2PA companion assertion (energy-binding), the wai.video.int_motion receipt, the wai.video.* OTT receipts, and the energy claim (jwp-receipts §2.4.5).
  • As an optional label (§2.8), in the receipt families that sealed a figure before the class existed and whose issued receipts must keep verifying: the world-session, film and reel, haptic, score, 4D-splat, audio-scene, ternary-reconstruction and provenance-step receipts in wai-rs, and every quantum receipt of wai-quantum (circuit, calibration, job, mitigation, decode, compile, rearrange, phasor, and the bill of materials per entry).

wai-rs reads and verifies JWP group and object receipts in both forms of each, computes an object's leaf in both forms of jwp-receipts §2.2, reads a group total from its objects, and reads a WAI_RECEIPT property against a signed statement of its object (jwp_delivery). Neither crate writes a WAI_RECEIPT property, and wai-quantum seals no JWP group receipt; wai-rs builds them for its conformance corpus and for the objects its reference deriving edge publishes (deriving-edge §6), whose object receipts it labels, the unmetered marker included.

2.1 Relationship to network-layer energy identities

The classes above are WAI's own vocabulary. An adopted IETF GREEN working-group draft (draft-ietf-green-power-and-energy-yang, revision -04 when this section was written) defines a graded data-source-accuracy identity hierarchy for device and sub-component energy, which is the network layer's answer to the same question this section asks: how was this number obtained? Its graded measured identities are bounds on the total error of one device reading, of the form |actual − sensor| ≤ sensor × X % or an absolute limit. The declared uncertainty of §2.3 is a different kind of statement about a different quantity, and the rules below keep the two apart.

  • An implementation that also reports under a network-layer energy model SHOULD derive its acquisition class from that model's identity rather than assigning one independently, and MUST state which identity it derived from. Two vocabularies for one property, assigned separately, will disagree.

  • A derivation MUST NOT improve the class. Where a network-layer identity maps ambiguously, the weaker WAI class applies. A measured identity, graded or not, says a sensor was read. It does not say that the sensor's error is traceable to a calibration, so it yields OnChipCounter unless the implementation holds the calibration reference of §2.5.

  • An implementation MUST state how far its acquisition class lets the figure be leaned on. A class without that is a label, and grading provenance exists to put a number on it. For the two hardware classes the number is the declared uncertainty of §2.3. ModelBased and Estimator do not yet carry one in any receipt profile; that remains open.

  • A graded band MUST NOT be declared as a figure's uncertainty. The band bounds one reading of the device. A WAI figure is the difference of two bracket means, attributed per object (§3). A pure gain error carries through that difference unchanged and a constant offset cancels, but readings that are each within a band can otherwise differ from the true marginal by far more than the band, relative to the difference. A band MAY inform the counter's systematic component when the declared uncertainty is evaluated (§2.3); the declaration remains the implementation's own evaluation of the figure.

  • A declared uncertainty MUST NOT be used to select or assert a graded measured identity. No coverage factor makes the step sound, for three reasons:

    1. A graded band is a limit. A declared uncertainty is a standard uncertainty. Expanded at k = 2 it corresponds, for a normal distribution, to a coverage probability of about 95 %, which is not a limit.
    2. An OnChipCounter declaration does not cover the counter's own systematic error (§2.3), so it is not a statement of total error at all.
    3. The declaration is about a per-object marginal figure, and the identity is about a device or sub-component reading. Treating one as the other is the conflation the next paragraph forbids.

    A graded identity for the device's reading has to rest on a limit established for that reading, such as a vendor's stated accuracy for the counter or the maximum permissible error an instrument has been verified against over its range and conditions of use, under that model's own definitions. Nothing in a WAI receipt supplies that limit.

WAI does not adopt the network-layer model, and this section does not restate it. The scopes differ — that model is device- and sub-component-scoped, WAI's figures are per-object — and conflating them would breach §4's attribution rules. What is required is that the two do not contradict each other about the same measurement.

2.2 Two kinds of hardware evidence

An on-chip counter and a calibrated external instrument are both hardware readings, and both are real measurements. They are different evidence, and a single class put them at one trust level.

  • An on-chip counter is the measured silicon reporting on itself. Its reading is a sensor value. What it cannot offer is an uncertainty traceable to a reference: the figure's uncertainty is whatever its vendor states or the implementation can evaluate. Some counters also add deliberate noise to their output as a side-channel defence (§2.4), so the same counter is noisier over a short window than a long one.
  • A calibrated instrument's error has been established against a reference and written into a certificate a third party can read. A deployed regime that signs measured energy per transaction shows the same split between signature and trust: in EV charging, signed meter values in the Open Charge Metering Format (OCMF) are accepted under German calibration law because they come from a conformity-assessed, legally verified measuring system — the meter together with the component that signs its values. The signature binds each value to that system so a customer can check it later. It does not make the value accurate; the metrological assessment does. (Legal verification against maximum permissible errors is not the same statement as a calibration certificate's uncertainty; §2.1 keeps the two apart, and §2.5 asks for the latter.)

A signature settles who said a number. It says nothing about how far the number can be from the energy actually spent. Confirming whose key it is (jwp-receipts §7) settles which origin stands behind the key, and for which class, and nothing about the reading. The declared uncertainty (§2.3) is the statement about that, and the class says how much of it the declaration covers. For CalibratedInstrument it covers the instrument's error as established by its calibration, together with the measurement's own scatter. For OnChipCounter it covers only what the implementation could evaluate, which does not include the counter's own systematic error.

What separates the two classes is whether the uncertainty is traceable, not where the sensor sits. An external meter with no current calibration MUST be reported as OnChipCounter, the weaker class; a sense resistor read by the device's own firmware and reported through the device's own counter is OnChipCounter whatever its construction. The class therefore does not record where the sensor sits — at the die or at the wall, with or without supply losses — and a verifier reasoning about scope (§5) cannot learn it from the class.

Neither class is an accuracy grade. A small declared uncertainty on an on-chip counter says the reading was precise. How accurate it was rests on the counter, and the class is what tells a reader that.

2.3 The declared uncertainty (REQUIRED for the hardware classes)

A CalibratedInstrument or OnChipCounter class MUST carry a declared uncertainty of two parts:

field meaning
relative_ppm The standard relative uncertainty of the figure (coverage factor k = 1, in the sense of the GUM, JCGM 100:2008), in integer parts per million of the figure. An expanded uncertainty U stated at coverage factor k — the usual form on a calibration certificate — is declared as U / k.
window_us The integration window the figure was accumulated over, in integer microseconds. For the protocol of §3, the busy bracket's window.
  • Both parts MUST be non-zero. A relative uncertainty of zero claims a perfect measurement; a window of zero is not an integration. A verifier MUST treat either as an undeclared uncertainty.

  • The window is not optional. Counter noise depends on it — filtered counters are several times noisier over 100 ms than over 1 s (§2.4) — so a relative error without its window cannot be compared with anything.

  • An implementation converting a fractional uncertainty to relative_ppm MUST round up, so the declaration never states less uncertainty than was evaluated.

  • The declaration describes the figure as sealed, and joules_micro is a whole number of microjoules. Whatever the measurement, the integer carries its own resolution, and the declaration MUST include it:

    • A figure rounded from an estimate to the nearest microjoule is within ±0.5 µJ of it. Taken as rectangular over that limit (GUM F.2.2.1), this adds a standard uncertainty u_res = 0.5/√3 µJ (≈ 0.289 µJ).
    • A figure read as the difference of two whole-microjoule register readings is within one step of the energy at each end. Two such offsets differ by a triangular error over (−1, +1) µJ (GUM 4.3.9), which adds u_res = 1/√6 µJ (≈ 0.408 µJ). A register whose hardware unit is coarser than a microjoule hides that unit from the reader, and the declaration MUST cover it separately.

    The term is fixed in microjoules, so relative to the figure it grows as the figure shrinks: a rounded figure of 1 µJ is uncertain by at least 29 % from its rounding alone, one of 10 µJ by 2.9 %, and one of 1,000 µJ by 0.029 %.

  • Because of that, every declaration satisfies joules_micro × relative_ppm ≥ 288 676: the absolute standard uncertainty joules_micro × relative_ppm / 10⁶ µJ is at least 0.5/√3 µJ, and 288 676 is the least integer at or above 10⁶ × 0.5/√3. A verifier MUST treat a hardware class whose declaration is below this floor as invalid. The check needs nothing but the receipt, and it is in integers, so every verifier reaches the same verdict. It is a necessary condition, not a sufficient one: a declaration above the floor can still understate what was not evaluated.

What the declaration covers depends on the class:

  • CalibratedInstrument: the instrument's calibrated uncertainty at the range and conditions of use, combined with the measurement's own uncertainty as evaluated below.
  • OnChipCounter: the components the implementation can evaluate — at minimum the measurement's own uncertainty as evaluated below, and any noise the counter's vendor states it adds at the declared window. It cannot include an unquantified systematic offset of the counter. An OnChipCounter declaration is therefore not a statement of the figure's total error and MUST NOT be presented as one. A reader MUST read it as the evaluated part of the figure's uncertainty, to which the counter's systematic error adds an amount nobody has stated. The class name is what tells a reader that.

For the bracketed marginal protocol of §3, the per-unit estimate is E = (mean_busy − mean_idle) × window ÷ W, where W is the work the window paid for, estimated from the completion count C as below. The measurement's own relative uncertainty combines two components, and the declaration adds the rounding of E to the sealed figure F:

u_power = sqrt(s_idle² / n_idle + s_busy² / n_busy) / (mean_busy − mean_idle)
u_count = u(W) / W
u_meas  = sqrt(u_power² + u_count²)                relative to E
F       = round(E)                                 the figure sealed, in µJ
u_rel   = sqrt((E · u_meas)² + (0.5/√3 µJ)²) / F   declared, relative to F

u_meas is relative to the estimate and u_rel to the figure a reader sees. The measurement's part is carried across in microjoules, so a figure that rounds down declares it relative to the smaller number. At E = 0.563 µJ with u_meas = 1.54 %, F is 1 and u_rel is 28.9 %, not 1.54 %.

  • u_power is the statistical (Type A) standard uncertainty of the marginal draw, with s the sample standard deviation of each bracket. It cannot be evaluated from fewer than two samples in either bracket, or without a positive marginal draw.

  • u_count is the completion-count term. C is the number of reconstructions counted as completing inside the window, and N is the number that can be in progress at once — the worker count. The count is exact as a count; it is not exact as a measure of the work the window's energy paid for, because reconstructions part-done at an edge are invisible to it. What that error can be depends on how the window opened:

    window opened work W lies in estimate W u(W) u_count
    from rest — every worker held at a start barrier and released as the window opens [C, C + N) C + N/2 N / (2√3) N / (√3 · (2C + N))
    on running workers — the workers' progress at the opening edge spread over a whole reconstruction (C − N, C + N) C N / √3 N / (√3 · C)

    From rest, no reconstruction begins before the window, so only the closing edge contributes: each worker is part-way through one reconstruction the count cannot see, and the count reads low, never high. On running workers both edges contribute, in opposite directions. In both cases, with only the limit known, the error is taken as rectangular over it (GUM §4.3.7). From rest, that is exact when the workers' progress at the closing edge moves together and falls anywhere in a reconstruction with equal likelihood — identical payloads released together do move together — and conservative when their progress is spread. On running workers it is conservative in both cases.

    A window that opens the moment the workers are started, without a barrier, is in neither row. When a reconstruction takes much longer than starting the workers, they are all near the start of one at the opening edge, so the count reads low by up to N — by about N/2 on average — and a figure divided by C reads high by about N / (2C): 8 % at ten workers and sixty completions. The symmetric running-window model does not describe it. The reference meters were built this way until this revision; their windows now open from rest.

    The term shrinks only as C grows, so it is large when an expensive payload completes only a handful of times (§3). An implementation MUST state which opening it used; a measurement report states it in its bracket's opening (§6). An implementation that removes more of this term by construction MUST state how, and MUST still declare whatever part it has not removed.

  • The window is timed on a monotonic clock around the busy bracket. An implementation whose clock resolution is not negligible against the window MUST include it.

A figure whose u_rel cannot be evaluated — too few samples, no positive marginal draw, no completions, or an estimate that rounds to zero (§4) — MUST NOT be sealed under a hardware class. W is the divisor of the published per-unit figure; the raw count C is reported beside it (§3).

The declared uncertainty does not absorb the attribution bias of §4. That bias is one-directional — a busy machine always reads low — and no symmetric uncertainty describes it. (The completion-count bias of a window opened without a barrier, above, runs the other way: it reads high.) The §4 ratio remains required alongside the declaration, and a figure that fails §4 is not rescued by a large declared uncertainty.

2.4 Counter filtering state (OnChipCounter)

Some on-chip counters filter their output as a side-channel defence. The technical guidance published with advisory INTEL-SA-00389 (Running Average Power Limit Energy Reporting, CVE-2020-8694, CVE-2020-8695) describes RAPL energy filtering: noise added to the energy reported, typically under 2 % standard deviation in readings at 1 s intervals, growing to 5–15 % at 100 ms, with larger variance possible at thermal design power. Filtered energy is reported when SGX is enabled or system software has enabled filtering (on some implementations the processor sets it during boot to protect SGX), and TDX uses the filtered energy information. Software that can read model-specific registers sees it as IA32_MISC_PACKAGE_CTLS[0] (ENERGY_FILTERING_ENABLE), supported where IA32_ARCH_CAPABILITIES[11] is set; once set, that bit cannot be cleared by software.

So an OnChipCounter class carries the filtering state as one of:

state meaning
On The reader determined that filtering was active.
Off The reader positively determined that no filtering was active.
Unknown The reader could not determine the state.
  • An implementation MUST report Off only on positive evidence. A reader that cannot see the control state — an unprivileged process, an interface that does not expose it — MUST report Unknown, never infer Off from absence.
  • A verifier MUST read Unknown as possibly filtered.
  • Where the state is On or Unknown, the declared uncertainty (§2.3) SHOULD include the noise the vendor states for the declared window.
  • A CalibratedInstrument class carries no filtering state: an external instrument has no counter filter.

2.5 Calibration reference (CalibratedInstrument)

A CalibratedInstrument class MUST carry calibration_ref: a non-empty identifier that resolves to the calibration certificate covering the instrument as used — a URI, or the issuing laboratory's certificate number.

The reference makes the calibration claim checkable, not true. A verifier holding it can obtain the certificate and confirm that it covers the instrument, that it was current when the figure was measured, and that the declared uncertainty is consistent with it. The receipt's signature proves who made the claim. It says nothing about the instrument.

2.6 Legacy HwShunt

Receipts sealed before this revision carry HwShunt. Its meaning is fixed as hardware, sub-class unspecified, no declared uncertainty.

  • A verifier MUST accept HwShunt in a receipt that is otherwise valid. The signed encoding of §2.7 leaves every legacy receipt's signed bytes unchanged, so such a receipt verifies exactly as it did.
  • A verifier MUST rank HwShunt below both refined hardware classes. It asserts a hardware reading and nothing about the reading's uncertainty.
  • An implementation MUST NOT emit HwShunt in a new receipt. A producer that cannot say which kind of hardware evidence it has, or cannot declare an uncertainty for it, has not established what the refined classes require. A verifier cannot see when a receipt defined with a class from the start was sealed, so it accepts HwShunt there as above. The reference implementation meets the rule in its own producers, none of which emits HwShunt, and holds its callers to it in part: its meters cannot produce HwShunt, a new energy binding, an optional label (§2.8), the label of a JWP object's leaf or group, and an energy, measurement or operating-point claim (jwp-receipts §2.4.5, §2.4.8–§2.4.9) refuse it, and the wai-rs variant is deprecated, so code that names it draws a compiler warning. The constructors of the wai.video.int_motion receipt and the wai.video.* OTT receipts accept HwShunt, so that an issued receipt can be recreated byte for byte, and nothing in them refuses it. The warning reaches only code that names the variant. A class parsed from its label (EnergyProvenance::from_label, from_parts) can be HwShunt, as a verifier needs, and a caller that passes such a class to those constructors draws no warning.
  • HwShunt carries no evidence fields. A receipt pairing HwShunt with a declared uncertainty, a filtering state or a calibration reference is ambiguous and MUST be rejected.

2.7 Signed encoding

Receipts that sign a binary payload encode the class as one tag byte, followed by the class's evidence:

tag class followed by
0 no class: the unmetered marker beside a zero figure; in a receipt family of §2.8, the slot of an unlabelled legacy figure beside a non-zero one —
1 HwShunt (legacy) —
2 ModelBased —
3 Estimator —
4 OnChipCounter relative_ppm u32 BE · window_us u64 BE · filtering u8 (0 Unknown, 1 Off, 2 On)
5 CalibratedInstrument relative_ppm u32 BE · window_us u64 BE · reference length u32 BE · calibration_ref UTF-8

Tags 0–3 are followed by nothing, exactly as before the hardware class was refined; that is what keeps legacy receipts verifying without re-signing.

Receipts carried as JSON carry the same evidence as named fields beside the class label, and omit them for the classes that carry none, so a legacy body is byte-identical to one written before this revision. The names are fixed:

field snake_case carriers C2PA companion assertion (camelCase)
class label energy_provenance acquisition
declared uncertainty energy_uncertainty {relative_ppm, window_us} uncertainty {relativePpm, windowUs}
filtering state energy_counter_filtering counterFiltering
calibration reference energy_calibration_ref calibrationRef

The snake_case carriers are the rendered wai.video.int_motion receipt, every receipt carrying an optional label (§2.8), and the body of an energy claim (jwp-receipts §2.4.5); in a labelled bill of materials the fields sit inside each labelled entry. A claim has no optional members and no legacy form, so an energy claim writes the fields a class does not carry as null rather than omitting them, and writes an OnChipCounter's filtering state even when it is Unknown. Every snake_case field is energy_-prefixed so that it cannot collide with a field a receipt already renders — a quantum job receipt's calibration_ref names the calibration receipt the job ran under, not a certificate. A reader MUST refuse evidence fields that appear without a class label, and MUST NOT drop a malformed label and read the receipt as unlabelled.

2.8 Optional labels on receipts that predate the class

A receipt family that sealed joules_micro before this extension existed has issued receipts that must keep verifying. Such a family carries the class as an optional label:

  • Absent. The signing payload, the receipt's identity hash and its JSON are exactly the legacy ones. The figure is unlabelled: a verifier MUST accept the receipt if it is otherwise valid, and MUST NOT read the figure as any class. An unlabelled figure is not comparable with any labelled one; it is not upgraded to one, and in particular not to HwShunt.
  • Present. The signing domain's final version byte, 0x01 in every such family (e.g. wai:world-receipt\x01), becomes 0x02, and the class's signed encoding (§2.7) follows the joules_micro field it labels, before the fields that followed the figure in the legacy payload. The version byte keeps every labelled payload distinct from every unlabelled one, so a label can be neither added to nor stripped from a signed receipt; the encoding is self-delimiting, so the fields after it keep their legacy framing. A receipt whose identity hash covers its signing payload covers the label with it.
  • A label MUST NOT be HwShunt — none of these receipts ever carried it — and MUST NOT sit beside a zero figure. A verifier MUST treat either, or a refined class without its evidence, as invalid.
  • New receipts. A producer SHOULD label every non-zero figure it seals in such a family. The unlabelled form exists for receipts issued before the label did, and an unlabelled figure tells a reader nothing about how it was obtained. This is a recommendation, not a conformance requirement. No verifier can check it: a figure sealed unlabelled today has exactly the bytes of one sealed before the label existed, and a verifier accepts both (above). That does not set it apart from §2.6's rule on HwShunt, which no verifier can check in a receipt defined with a class from the start either. What sets it apart is that the reference implementation neither meets it in all its own producers nor holds its callers to it. Two of its producers seal new non-zero figures without a label (end of this section). In these families no constructor takes the class. build() and seal() in wai-rs, and seal() and the helpers that call it in wai-quantum, seal the figure unlabelled, and a label is added afterwards, by re-signing (below). A provenance step is labelled before its receipt is built instead: ProvStep::new makes the step unlabelled, and ProvStep::with_energy_class labels it. None of these refuses a non-zero figure without a label, and none of the unlabelled paths is deprecated. A library can hold its callers to this rule by the means §2.6 describes for HwShunt. It would need a constructor that takes the class and refuses a non-zero figure without one, and it would keep the unlabelled path only for recreating issued receipts, deprecated, so that code sealing a new unlabelled figure draws a compiler warning. The reference implementation has not done this.

Where a receipt carries several figures, each is labelled where it sits:

  • A provenance receipt labels each step. A labelled step's leaf hash uses the 0x02 step domain with the class after the step's figure; an unlabelled step keeps its legacy leaf. A receipt with any labelled step signs under the 0x02 receipt domain and writes, after every step's figure, that step's optional class — 0 for an unlabelled step.
  • A quantum bill of materials labels each entry the same way: under the 0x02 domain, every entry's figure is followed by its optional class, 0 when unlabelled. An entry's class restates its stage receipt's class, and a verifier binding the bill to its stage receipts checks that they agree.
  • A JWP group receipt labels each object in that object's Merkle leaf (jwp-receipts §2.2). A labelled object's leaf uses the 0x02 leaf domain, with the figure, its class and the object's origin after the content hash; an unlabelled object keeps its legacy leaf. Its group may sign the total's own class under the 0x02 group-signing domain (§1).

A provenance or quantum bill total carries no class of its own, and neither does a JWP group total in the legacy payload. A sum over figures of different classes is only as strong as its weakest part, and an unmetered part is not a zero. A reader that holds every part reads such a total as follows:

  • if every part's figure is the unmetered marker, the total is unmetered;
  • otherwise, if any non-zero figure is unlabelled, the total is unlabelled;
  • otherwise the total reads at the weakest class among the non-zero figures, in §2's order, as a class name only. A total read this way carries no declared uncertainty and MUST NOT be presented as carrying one. It covers the whole of the work when no part is unmetered, and only the measured parts otherwise (energy-binding §4's Whole and Partial).

A reader that does not hold every part reads such a total as unlabelled. A JWP group total in the labelled payload carries its own class instead, composed by jwp-receipts §2.4.1's rule, which adds a declared uncertainty for a hardware class: the parts' figure-weighted declarations, rounded up, over the longest window — linear in the parts, so it assumes their errors fully correlated.

In the reference implementation, each wai-rs family has an energy_provenance field and with_energy_class(), which re-signs with the receipt's own key; provenance steps have ProvStep::with_energy_class(). wai-quantum, a published crate, adds the label without changing any existing type: quantum_energy::Labelled<R> wraps a sealed receipt and re-signs it over the labelled payload, and quantum_energy::LabelledQbom labels a bill per entry. A labelled quantum receipt fails the inner receipt's own verify() — its signature covers the labelled payload — so a reader that does not know about labels refuses it rather than silently dropping the class. A verifier that accepts both forms parses with quantum_energy::MaybeLabelled, which takes the form from the JSON and refuses a malformed label rather than reading the receipt as unlabelled. The reference wai-quantum verify CLI and the HTTP handler's POST /verify accept both forms this way. A job receipt names its calibration by the identity of the form the calibration is in, and MaybeLabelled::verify_against_calibration checks the link for either form of each. Tests pin one unlabelled receipt of every family to the bytes it had before the label existed.

What the reference implementation seals in these families:

  • The reference meters that seal into them (wai_meter, wai_world_meter, wai_quantum_meter, wai_prov) label every non-zero figure they seal, write a measurement report (§6) for it by default, and seal a figure they could not measure with the unmetered marker, unlabelled.
  • Two producers seal a new non-zero figure without a label, and so fall short of the SHOULD above. world_model::frame_receipt is handed its caller's figures without their class; a caller that knows the class builds the steps itself with ProvStep::with_energy_class. The in-browser demos of wai-web seal illustrative figures, fixed in code or passed in by the page.
  • A generator that recreates a committed conformance corpus byte for byte seals that corpus's figures unlabelled; wai_quantum_ops_vectors gen seals non-zero ones. Every committed corpus predates the label, so these generators recreate issued receipts, which is what the unlabelled form is for.
  • The constructors and sealing helpers above are not counted. Each returns its receipt, or its provenance step, to a caller that can still label it.

2.9 IOReport, and where this departs from other documents

IOReport — the SoC energy interface the reference meters read through a non-privileged reader — is classed OnChipCounter. Its readings are the measured silicon's own report of its energy, and this extension classes a figure by that provenance. The interface's channels sit in a group named "Energy Model", and it is a private interface whose derivation is not publicly documented. That makes the counter's systematic error unstated, which an OnChipCounter declaration already excludes (§2.3). It does not make the figure a model this implementation computed (ModelBased) or a constant (Estimator).

Other documents in this repository class IOReport differently. This extension does not change them; where a figure passes between the two, the weaker class applies (§2):

document classes IOReport as
jouleclaw/SPEC.md (provenance table; realistic floors) ModelBased — "vendor-provided estimate", "model-based, not measured"
jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/src/lib.rs (the ModelBased variant's examples) and src/apple_ioreport.rs ModelBased — a vendor model derived from frequency, voltage and utilisation
jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/MEASURED_ENERGY.md, conformance/README.md ModelBased
jouleclaw/jouleclaw-rs/crates/jouleclaw-jcr1/conformance/README.md, vectors.json ModelBased
jouleclaw/jouleclaw-rs/crates/jouleclaw-compliance/src/passport.rs (MeasurementMethod::IoReport) Estimator, pending an in-process reader
jcp/jcp-rs/crates/jcp-energy/src/lib.rs (Meter::IoReport) ModelBased — a real on-die reading, carried at model grade
joule-code/examples/l3-jouleclaw/src/bin/run.rs (and its README, which describes the host as Estimator until IOReport is wired) ModelBased

The documents that class IOReport as hardware agree with this section at the three-name level: sandbox/README.md, proof/README.md, joule-code/spec/receipt.md (HwShunt), and the eoc-meter crate ("measured-grade"). jcp/jcp-rs/crates/jcp-efficiency/MAPPING.md states the same position in prose: vendor counters are real sensor readings, whose derivation and error bounds are undisclosed.

3. The reference protocol: bracketed marginal measurement

On-die energy counters report the draw of a whole package or SoC, not of one process. A decode cannot be isolated on such an interface, so the reference protocol measures the marginal draw the work adds to an otherwise-idle machine:

  1. Idle bracket. Sample power for a fixed count with no work running. Record the mean and the standard deviation.
  2. Saturating burst. Run the reconstruction continuously on N threads, counting completions. Many threads are used deliberately: a single-threaded burst on a modern SoC often fails to lift total draw clear of idle drift. The threads SHOULD be held at a start barrier and released as the window opens, so the window opens from rest (§2.3).
  3. Busy bracket. Sample power again for a fixed count while the burst runs, recording the wall-clock window it spans and the standard deviation.
  4. Attribute. energy = max(0, mean_busy − mean_idle) × window, then divide by the work the window paid for — C + N/2 from rest, C on running workers (§2.3).

Per-unit energy is total marginal energy ÷ the work it paid for, so the thread count enters the figure only through the part-done reconstructions at the window's edges, which the count cannot see. It enters the figure's uncertainty the same way (§2.3, u_count). Completions MUST be counted per reconstruction, not per fixed-size batch: a cheap payload runs millions of times and an expensive one a handful, and a coarse batch collapses the count. For the same reason an expensive payload SHOULD be burst over a window long enough that its completions far outnumber the threads. With a handful of completions the count term alone is large: ten threads and sixty completions give about 9.6 %.

An implementation MUST report the idle mean and standard deviation, the busy mean and standard deviation (sample standard deviations, as §2.3 uses), the sample counts, the window, the completion count, the thread count and how the window opened alongside any figure it publishes. Those numbers are what make a figure auditable, and they are what its declared uncertainty (§2.3) is computed from; the figure alone is not auditable. Where the figure is sealed in a receipt, they are published as §6 says.

3.1 A live power reader

A power reader can return values for a rail that is not being refreshed. A frozen rail reads as zero in every sample, or as the last value the reader holds; a rail refreshed in batches reads the same value except where one batch lands, and one refresh can be published in two steps in adjacent samples. Bracketed, either gives an idle bracket whose samples are all equal and a busy bracket with a lump or a step in it: a flat idle, a positive marginal, and a ratio (§4) that reads as clean — from no measurement of the work at all.

So a figure is sealed under a hardware class only from brackets in which the reader's rail was live. A rail is live in a bracket only if:

  • it advanced in two consecutive intervals;
  • it advanced in at least five intervals, and in at least four of every five of the bracket's intervals; and
  • the bracket spans at least 300 ms.

An interval is one sample of a power reader, in which the rail advanced if the sample is strictly above zero and differs from the sample before it (the first sample of a bracket has none before it, and advanced if it is above zero); or one pair of successive reads of an energy counter, in which it advanced if the second read exceeds the first, across the counter's wrap. A reader that holds its last value repeats it, and a repeated value is not an advance, whatever the value. Both brackets must be live. One advance is not a live rail, and neither is one refresh published in two steps. An implementation reading a counter at the ends of a span alone has one interval, which is never enough: it reads the counter during the span as well.

A figure from a bracket that is not live MUST NOT be sealed under a hardware class. The producer seals it with the unmetered marker, or under a weaker class it can justify. A measurement report carries each bracket's liveness facts — its live intervals and its longest run of them (§6.2) — so a verifier checks the first two conditions from the report; the span is the producer's to check.

A bracket whose samples are all equal is not evidence of a quiet machine, and never of a live rail: its samples advanced once at most. Its standard deviation is zero, and under a hardware class a reader refuses a bracket whose sd_uw is 0 whatever liveness facts it carries.

4. Attribution quality (REQUIRED)

The marginal method is only meaningful when the burst lifts power clearly above the machine's own idle fluctuation. When it does not, the method does not degrade gracefully — it returns a confidently-formatted number that is far too low, because an inflated idle baseline is subtracted from a busy mean that never rose.

This is not a theoretical concern. Measuring one fixed clip with one binary, minutes apart on the same machine:

condition idle busy marginal reported
quiet 20.45 W 54.89 W 34.45 W 10,565 µJ/decode
(the quiet row predates this rule, so its ratio was not recorded)
build running ~23.9 W 24.26 W 0.36 W 497 µJ/decode

A 21× error, in the flattering direction, with nothing in the output to distinguish the two.

So an implementation MUST compute the ratio of the marginal draw to the idle standard deviation and report it. A measurement report reports it by carrying the values it follows from, and every reader derives the same verdict from them (§6.2):

ratio verdict
≥ 10 clean — publishable
≥ 3 usable for relative comparison — not publishable
≥ 1 noisy — do not publish
< 1 unusable — the machine was not idle

The publication bar is 10, not 3, and that is an empirical result rather than a round number. A later reading of the same clip at a ratio of 3.8 — inside what an earlier draft of this rule called "usable" — reported 2,469 µJ against the 10,565 µJ above: a 4.3× disagreement from a reading the rule had passed. A ratio in the 3–10 band is sound for comparing two workloads measured back-to-back on one machine, because the bias applies to both. It is not sound for an absolute figure.

The bias has a direction. A busy machine inflates the idle baseline, which is then subtracted from a busy mean that never rose as far, so a poor bracket always reads low. An implementation reporting energy therefore errs toward flattering itself, which is precisely why the check must be automatic rather than left to the operator's judgement.

  • An implementation MUST NOT seal a figure under a hardware class (CalibratedInstrument, OnChipCounter) when the reader's rail was not live (§3.1), when the ratio is below 1, or when the per-unit figure rounds to zero. None is a measurement of low energy; each is a failure to measure, and the receipt MUST be emitted unmetered instead.
  • An implementation MUST NOT publish an absolute figure taken below a ratio of 10, and SHOULD warn whenever it produces one.
  • A reader MUST NOT present a figure as publishable unless the verdict its measurement report gives is clean (§6.2). A reader holding no report for a figure cannot tell whether the figure met this bar, and MUST NOT say that it did.

Emitting an unmetered receipt is the correct outcome of a failed measurement, not an error state. A tool that says "I did not measure this" is more useful than one that says "this decode cost 267 µJ" when the true figure is forty times higher.

5. What the figure is, and is not

  • It is machine-specific. The same codestream on different silicon legitimately measures differently. Energy is a property of an execution, not of an artifact.
  • It is a marginal figure over an idle baseline, so it excludes the fixed cost of having a machine powered on, and attributes shared platform overhead to the work only insofar as the work raised it.
  • It is scoped to what the interface reports — a package or an SoC, not a process. Provenance and scope are the honest limitations, not sensor accuracy.
  • It depends on the build. A debug build of the reference decoder measured 4.9× a release build of the same code. An implementation MUST state the build profile alongside any published figure; a measurement report states it in build (§6).
  • It is not verifiable by re-execution. A third party re-running the decode reproduces the result and the work, never the joules.

That last point is the reason the receipt profiles are shaped as they are. Where a class's reconstruction is byte-exact and proven across architectures, a verifier holding the artifact re-derives the output and the work unit. It cannot re-measure the energy, and it cannot re-measure anything that describes how the energy was obtained: the acquisition class and its evidence (§2.2–§2.5), the bracket values of §3 and their liveness facts (§3.1), the ratio they give (§4), the build profile, and the coverage and method a receipt states beside the figure. Those are the measurer's statements, as the figure is, and a signature makes them attributable, not true.

Some of them can still be checked without re-measuring anything: a declaration against the resolution floor (§2.3), which needs nothing but the receipt; a calibration reference against the certificate it names (§2.5); and a measurement report's values against the figure and the declared uncertainty they must give, and against the liveness rule (§6.2). Values that pass those checks are consistent, not correct: a measurer who invents every value consistently passes every one of them. Pairing a meter with a reproducible outcome narrows what rests on the measurer to the measurement and its description. So an implementation SHOULD report energy against a work unit that a verifier can recompute from the artifact, and MUST NOT report it against a work unit only the producer can compute.

6. Reporting contract

A published figure MUST be accompanied by: the acquisition class (§2), with its declared uncertainty and window (§2.3) and its filtering state (§2.4) or calibration reference (§2.5); the build profile (§5); the recomputable work unit the rate is expressed against; and, for a figure obtained under the protocol of §3, the idle mean and standard deviation, the busy mean and standard deviation, the sample counts, each bracket's liveness facts (§3.1), the window, the completion count, the thread count and how the window opened. The attribution-quality ratio (§4) follows from those values (§6.2).

Where a figure is sealed in a receipt with a class, its producer MUST publish these, except the work unit, which the receipt carries, as a measurement claim about the figure (jwp-receipts §2.4.8). The claim names the figure by its figure profile (§6.1), restates it with its class, and leaves the receipt that seals it unchanged. Only the key that signed the figure may sign the claim, so a figure that no Ed25519 key signs — an energy binding's (§6.1) — has no measurement claim; carrying a binding's report in its C2PA manifest is outside this revision. A report printed beside a receipt but not signed does not meet this section. No verifier can tell a figure whose report was withheld from one that never had one, so this rule binds producers, and what a verifier checks is a report it holds (§6.2).

Producers that fall short of this section, recorded rather than exempted: the generators that recreate a committed corpus with its unlabelled legacy figures (§2.8); world_model::frame_receipt, which is handed its caller's figures without their class or their bracket; and the in-browser demos of wai-web, which seal illustrative figures. A figure sealed with no class cannot meet this section, because a measurement claim restates a class.

A figure published without these is not wrong so much as unusable: nothing about it can be checked, reproduced, or compared.

6.1 Figure profiles

A report about a figure (jwp-receipts §2.4.8–§2.4.9) names it by a figure profile, an index, and the identity of the receipt that carries the figure. A profile is named by the domain its receipt's identity is computed under, without the domain's final version byte. It fixes the claim's subject_type, how the identity is computed, which figure an index selects, where the figure's class is, and which key signed it.

figure profile receipt subject_type and identity figure; its class index signed by
moq-jwp:object JWP object receipt (jwp-receipts §2.4.2), accepted under its group (§3) object: its §2.1 content hash; the claim's group is the group receipt's link hash joules_micro; the label in its leaf (jwp-receipts §2.2) its leaf index the group receipt's signer_pubkey
moq-jwp:claim-link energy claim (jwp-receipts §2.4.5), or reconstruct-session claim whose energy is not null (§2.4.12) receipt: its link_hash joules_micro; its class (for a session, energy.joules_micro and the class energy writes) null its signer_pubkey
wai:energy-binding-id energy binding (energy-binding §2) receipt: BLAKE3("wai:energy-binding-id\x01" ‖ JCS(body)) (energy-binding §4) microjoules; acquisition null no Ed25519 key
wai:video-receipt-id, wai:video-manifest-receipt-id, wai:video-ssai-receipt-id, wai:video-keys-receipt-id, wai:video-package-receipt-id, wai:video-channel-receipt-id the wai.video.int_motion receipt and the wai.video.* OTT receipts receipt: its receipt hash joules_micro; its class null its signer_pubkey
wai:world-receipt-id, wai:film-receipt-id, wai:haptic-receipt-id, wai:score-receipt-id, wai:splat4d-receipt-id, wai:audio-receipt-id, wai:ternary-receipt-id the world-session, film and reel, haptic, score, 4D-splat, audio-scene and ternary-reconstruction receipts receipt: its receipt hash, over the payload in the form it was signed (§2.8) joules_micro; its optional label null its signer_pubkey
wai:asset-receipt-id provenance receipt receipt: its receipt hash step i's joules_micro; that step's optional label step, from 0 its signer_pubkey
wai:quantum-receipt-id, wai:quantum-calibration-id, wai:quantum-job-id, wai:quantum-mitigate-id, wai:quantum-decode-id, wai:quantum-compile-id, wai:quantum-rearrange-id, wai:quantum-fabric-id, wai:phasor-receipt-id the quantum receipts receipt: its receipt hash in the form it was sealed, labelled or not joules_micro; its optional label null its signer_pubkey
wai:quantum-qbom-id quantum bill of materials receipt: its receipt hash entry i's joules_micro; that entry's optional label entry, from 0 its signer_pubkey

A receipt hash here is BLAKE3(identity domain ‖ signing payload ‖ signature), as each family defines it. One content hash can be delivered in more than one group, so a moq-jwp:object report also names the group, and the same object in another group is another figure. A claim naming a profile not in this table is refused (jwp-receipts §3.1, figure_unknown_profile). A receipt family that seals a figure after this revision adds its row.

6.2 The measurement report

A measurement report (jwp-receipts §2.4.8) carries a figure's §3 values as integers:

  • each bracket's sample count n; its mean, in microwatts, rounded to the nearest with a half rounding up; its sample standard deviation (divisor n − 1, as §2.3 uses), in microwatts, rounded up, so a sealed dispersion never states less than was evaluated; and its liveness facts (§3.1): the samples in which the reader's rail advanced, and the longest run of consecutive ones;
  • the window T, the busy bracket's, in microseconds rounded to the nearest: the window_us of the figure's declared uncertainty (§2.3);
  • the completion count C, the thread count N, and how the window opened.

A producer MUST compute the figure it seals, and the least uncertainty it declares, from those integers as below and not from the samples they summarise, so that every verifier reproduces both exactly.

Let M be the busy mean less the idle mean, and let the work the window paid for (§2.3) be Wn / Wd: Wn = 2C + N and Wd = 2 for a window opened from rest, Wn = C and Wd = 1 on running workers. The per-unit estimate is E = M·T·Wd / (10⁶·Wn) µJ, and the figure is E rounded to the nearest microjoule, a half rounding up:

F = ⌊(2·M·T·Wd + 10⁶·Wn) / (2·10⁶·Wn)⌋

With n_i, s_i the idle bracket's count and standard deviation and n_b, s_b the busy bracket's, §2.3's u_rel over those integers, multiplied out, is the least integer p for which:

p² · K ≥ P,   where
K = 12 · n_i · n_b · Wn⁴ · F²
P = 12 · Wn² · T² · Wd² · (s_i² · n_b + s_b² · n_i)
  +  4 · n_i · n_b · M² · T² · Wd² · N²
  + 10¹² · n_i · n_b · Wn⁴

The three terms of P are u_power, u_count and the 0.5/√3 µJ of rounding, each carried across in microjoules (u_count is N / (√3 · Wn) from rest and on running workers alike). The least p always meets the resolution floor of §2.3, F · p ≥ 288 676. Both computations are exact integer arithmetic. With every value at most 2⁵³ − 1 (jwp-receipts §2.4.3), no product exceeds 2⁵¹² and no floating-point operation is involved, so every verifier reaches the same F and p.

A figure sealed under OnChipCounter or CalibratedInstrument MUST come from brackets whose rail was live (§3.1), and MUST declare a relative_ppm of at least p over window_us = T. It declares more wherever its declaration covers more than the bracket does: an instrument's calibration (§2.3), the noise a filtered counter's vendor states (§2.4), or a clock resolution that is not negligible (§2.3). A figure whose p exceeds 2³² − 1 cannot be declared (§2.7) and MUST NOT be sealed under a hardware class.

The attribution-quality ratio (§4) is M / s_i. Every reader derives the same verdict from the report's values: clean when M ≥ 10 · s_i, usable for relative comparison when M ≥ 3 · s_i, noisy when M ≥ s_i, and unusable otherwise. The verdict is about the bracket's arithmetic; under a hardware class a report is accepted only where the liveness facts also show the rail live and neither bracket's sd_uw is zero, so a flat idle bracket from a frozen rail, or from a reader holding a stale value, is refused, not read as clean.

What a verifier checks with a report is arithmetic: that the figure is the one its values give, that the declared uncertainty is at least what they support, and, under a hardware class, that the rail was live and the ratio is at least 1 (jwp-receipts §2.4.8). It does not check the values, which cannot be re-measured (§5).

6.3 A figure divided by fabric

Work can run on more than one kind of processor, a fabric: cpu, gpu, media (a hardware video engine) or npu (a neural processor). A measurement report MAY carry a fabric record (jwp-receipts §2.4.8, fabrics): the steps of the work, each with every fabric that ran it and the backend that did, and the figure divided into one share per fabric that ran a step. The figure is the sum of its shares, and its class (§2) is the class of the whole: a share is no measurement of its own. A figure divided by fabric is sealed under the class of its weakest share's reading, with that class's evidence over the span; the reference meter's shares are both OnChipCounter readings (§2.9), filtering Unknown, with a declared relative standard uncertainty of 5 % (the counters' read granularity, not a measured spread) and the span as its window, so its figure is an OnChipCounter figure. A fabric that ran a step has a share of more than 0: 0 J is no reading of work.

Each share states how its energy was attributed to the work:

  • task: the operating system's account of the work's own energy on that fabric, as it accounts a task's use of the processors, which other work on the host does not enter. On the reference hosts it is the kernel's per-task CPU energy read with proc_pid_rusage at RUSAGE_INFO_V6, ri_energy_nj + ri_billed_energy − ri_serviced_energy: the task's own energy, and the energy system services spent for it and the kernel billed to it, less what it spent servicing others. The kernel folds a thread's energy in only when the thread leaves its core, and a process's read of itself does not fold the thread that reads, so each end's read is taken only once the reading thread's own energy count is seen to move across a sleep; a read that does not fold is no reading.
  • rail: the fabric's whole rail over the span, its idle and static draw over the span included, in which the work was the fabric's sole user: at least 99% of the busy time every user of the fabric accrued over it. The users are read at least every 200 ms through the span, each user's busy time differenced between consecutive reads by an identity it keeps for its life, the first read before the rail's start and the last after its end, so that the busy window encloses the rail's. A user of the work's own that vanishes, a difference that is negative, or a read that fails, gives no share; another user that vanishes is counted busy for the whole interval it vanished in, and nothing is clamped. The rail is read through the span, and must be live over it (§3.1). A user created and destroyed between two reads is not seen; that is the attribution's residual. The window of a rail share runs from the rail's republish before the span to its republish after it, so it can exceed the span by up to one republish period on each side; the figure's declared window is the span's.

A span that gives a figure divided by fabric lasts at least 1 s and five reading intervals. No attribution divides a rail that other work shared by its users' busy time, and a rail share is never a part of a rail: it is the whole rail, or there is none. Busy time does not apportion energy: a GPU kernel that keeps the GPU busy at a low clock and one that keeps it busy at a high clock accrue the same time and draw very differently, and a division by GPU time has been measured to charge a decode three to fifteen times the GPU energy it drew alone (jouleclaw-energy, process_gpu). Where a fabric that ran a step was shared and its rail cannot be attributed, the span has no fabric record: the producer meters it otherwise (§3's bracket, over the whole figure), or seals it unmetered. So does a span that ran a step on a fabric with no live counter: on the reference hosts (macOS 27 on arm64) the media engine and the neural processor have none an unprivileged process can read.

A figure profile defines the vocabulary of its record's steps. A measurement report about a figure whose profile defines no step vocabulary MUST NOT carry a fabric record; in this revision only wai:video-package-receipt-id defines one (packaging §11, its steps and fabrics).

The record says where the work ran and what each fabric drew; it changes nothing a figure's verifier checks of the figure itself (§6.2). Which fabric ran a step changes no output of a step whose output its specification fixes (packaging §11, its steps and fabrics), so a record is a statement about energy, not about what was produced.

7. Worked example

wai.video.int_motion, real-footage vector, 8 frames of 96×96 RGB, release build, IOReport via a non-privileged reader:

work                : 221,184 subpixel-ops (8 x 96 x 96 x 3, recomputable)
cpu power  idle     : 24.95 W  (sd 0.23 W, 10 samples)
cpu power  busy     : 25.84 W  (14 samples)
marginal (busy-idle): 0.89 W
decodes             : 1,525 over 4.23 s
marginal / idle sd  : 3.8x  (usable for relative comparison — NOT publishable)
-> per decode        : 2,468.8 uJ
-> per kilo-subpixel : 11.16 uJ
acquisition class   : HwShunt

The run above predates the refinement of §2.2–§2.6, and its receipt says HwShunt. The reference meter now emits OnChipCounter for the same interface, with filtering state Unknown (a non-privileged IOReport reader has no documented way to read a filtering state, if the interface has one) and the §2.3 uncertainty: the statistics of both brackets combined with the completion-count term and the 0.5/√3 µJ that rounding the figure to whole microjoules adds. It also opens its window from rest and divides by C + N/2; the run above opened on freshly started workers and divided by C, so its per-decode figure also carries the high-reading count bias of §2.3. None of this can be reconstructed for that run: neither the busy bracket's standard deviation nor the thread count was recorded, and substituting either would be the invention this section refuses. The reference meter now also publishes these values, with the build profile, in a measurement report (§6). The run above printed them to its console, and its report cannot be written after the fact.

This example is deliberately a failing one. It is a complete, honestly reported bracket that this extension nonetheless forbids publishing as an absolute figure, because 3.8 is below the bar of §4 — and the earlier reading of the same clip on a quieter machine differed by 4.3×. It is shown rather than a clean bracket because a clean bracket is not currently reproducible on the authoring machine, and substituting an invented one would be the exact failure this document exists to prevent. An implementation quoting a figure for this vector MUST first obtain a bracket at ≥ 10.

The receipt seals the codestream hash, the per-frame decoded-pixel hashes, the work figure, the energy and its class under one signature. A verifier re-derives the codestream hash, the frame hashes and the work figure from the codestream alone. The energy, its class and the class's evidence rest on the signer (§5); a report about the figure lets a verifier check that they are consistent with the bracket, and no more (§6.2).

8. Reproducing a figure

An implementation claiming conformance SHOULD publish, with any figure: the vector decoded, the build profile and toolchain, the reader used for the power interface, the bracket parameters of §3, and the declared uncertainty with the evidence of §2.3–§2.5. A figure whose bracket is not published cannot be reproduced, and an unreproducible energy number is an assertion, not a measurement — which is the failure this extension exists to prevent. A measurement report (§6) publishes, signed, the build profile, the toolchain and target, the power reader and the bracket with its liveness facts, in cleartext: the measuring machine's power levels and build environment are visible to whoever holds the report.