Skip to main content

WAI Extension: Energy Measurement

Mirrored from the canonical text at commit 117bad22 ().

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 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.

classmeaningrequires
CalibratedInstrumentRead 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)
OnChipCounterRead 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)
ModelBasedComputed from a calibrated per-operation model (e.g. wall time × a power constant). A real number, honestly labelled as derived.—
EstimatorA 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:

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:

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 seals a JWP group receipt for delivery — wai-rs builds them only for its conformance corpus — or writes a WAI_RECEIPT property.

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.

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.

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:

fieldmeaning
relative_ppmThe 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_usThe integration window the figure was accumulated over, in integer microseconds. For the protocol of §3, the busy bracket’s window.

What the declaration covers depends on the class:

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 %.

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:

statemeaning
OnThe reader determined that filtering was active.
OffThe reader positively determined that no filtering was active.
UnknownThe reader could not determine the state.

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.

2.7 Signed encoding

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

tagclassfollowed by
0no 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—
1HwShunt (legacy)—
2ModelBased—
3Estimator—
4OnChipCounterrelative_ppm u32 BE · window_us u64 BE · filtering u8 (0 Unknown, 1 Off, 2 On)
5CalibratedInstrumentrelative_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:

fieldsnake_case carriersC2PA companion assertion (camelCase)
class labelenergy_provenanceacquisition
declared uncertaintyenergy_uncertainty {relative_ppm, window_us}uncertainty {relativePpm, windowUs}
filtering stateenergy_counter_filteringcounterFiltering
calibration referenceenergy_calibration_refcalibrationRef

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:

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

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:

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:

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):

documentclasses 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.rsModelBased — a vendor model derived from frequency, voltage and utilisation
jouleclaw/jouleclaw-rs/crates/jouleclaw-energy/MEASURED_ENERGY.md, conformance/README.mdModelBased
jouleclaw/jouleclaw-rs/crates/jouleclaw-jcr1/conformance/README.md, vectors.jsonModelBased
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:

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:

conditionidlebusymarginalreported
quiet20.45 W54.89 W34.45 W10,565 µJ/decode
(the quiet row predates this rule, so its ratio was not recorded)
build running~23.9 W24.26 W0.36 W497 µ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):

ratioverdict
≥ 10clean — publishable
≥ 3usable for relative comparison — not publishable
≥ 1noisy — do not publish
< 1unusable — 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.

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

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 profilereceiptsubject_type and identityfigure; its classindexsigned by
moq-jwp:objectJWP 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 hashjoules_micro; the label in its leaf (jwp-receipts §2.2)its leaf indexthe group receipt’s signer_pubkey
moq-jwp:claim-linkenergy claim (jwp-receipts §2.4.5)receipt: its link_hashjoules_micro; its classnullits signer_pubkey
wai:energy-binding-idenergy binding (energy-binding §2)receipt: BLAKE3("wai:energy-binding-id\x01" ‖ JCS(body)) (energy-binding §4)microjoules; acquisitionnullno 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-idthe wai.video.int_motion receipt and the wai.video.* OTT receiptsreceipt: its receipt hashjoules_micro; its classnullits 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-idthe world-session, film and reel, haptic, score, 4D-splat, audio-scene and ternary-reconstruction receiptsreceipt: its receipt hash, over the payload in the form it was signed (§2.8)joules_micro; its optional labelnullits signer_pubkey
wai:asset-receipt-idprovenance receiptreceipt: its receipt hashstep i’s joules_micro; that step’s optional labelstep, from 0its 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:phasor-receipt-idthe quantum receiptsreceipt: its receipt hash in the form it was sealed, labelled or notjoules_micro; its optional labelnullits signer_pubkey
wai:quantum-qbom-idquantum bill of materialsreceipt: its receipt hashentry i’s joules_micro; that entry’s optional labelentry, from 0its 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:

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).

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.