Some checks failed
energy meters on real hardware / RAPL and NVML on jetson-hub (push) Has been cancelled
energy meters on real hardware / sink decode table · RAPL on jetson-hub (NVML surveyed) (push) Has been cancelled
energy meters on real hardware / sink decode table · per-task energy and the GPU rail on macOS (push) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (push) Has been cancelled
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 2m15s
wai-app and Create / wai-app · does this change touch it (push) Successful in 1m45s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 5m43s
joule-code conformance gate / joule-moq-ingest, every target (push) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (push) Has been cancelled
The meters count an IOReport interval only within three of the probe's ticks, and the texts that state the rule said nothing of it, so an implementation following any of them would call a lump-refreshed rail live once load stretched its intervals. Each now says what an interval is (from one sample in hand to the next), that only one no longer than three of the probe's ticks (75 ms at its 25 ms tick) counts, that a longer one counts as nothing (not among the intervals, not as an advance, not towards the 300 ms), and that the 300 ms is the summed length of the intervals that count. The normative clauses in arl/ARL-S.md, jcp/SPEC.md, joule-code/spec/receipt.md, joule-ui/SPEC.md, jouleclaw/SPEC.md, JCR-1-spec.md, map/spec/receipt.md, mesh/SPEC.md (a block quote), proof/SPEC.md and sense/SPEC.md; proof-schema's quotation of proof/SPEC.md's; jouleclaw-energy's conformance README; and the proof and sandbox READMEs, which say the cap is IOReport's alone. Map's and Joule Code's unreleased changelog entries, which record the rule as it was added, are amended, since neither release has gone out. No wire or conformance-vector change. Co-Authored-By: Claude Opus 5.5 <[email protected]>
73 lines
5.5 KiB
Markdown
73 lines
5.5 KiB
Markdown
# Joule Code — The Receipt
|
|
|
|
Normative sub-specification of [`../SPEC.md`](../SPEC.md) §6. CC-BY-4.0.
|
|
|
|
Every coding operation carries a **receipt**: a signed, two-part energy record carried in a Joule Wire Protocol (JWP) frame. The receipt is the falsifiable cost basis of the operation — not its market price, but its honest energy cost.
|
|
|
|
## 1. Structure
|
|
|
|
```
|
|
Receipt {
|
|
op_id: ContentId,
|
|
tier: Tier,
|
|
energy: Energy,
|
|
sequence: u64,
|
|
nonce: [u8; 8],
|
|
sig: [u8; 64], // Ed25519 over the energy preimage (§3)
|
|
}
|
|
|
|
Energy {
|
|
measured_uj: Option<u64>, // present ONLY when from a live hardware interface (§2)
|
|
estimated_uj: u64, // always present
|
|
provenance: Provenance,
|
|
}
|
|
|
|
Provenance = HwShunt | ModelBased | Estimator
|
|
```
|
|
|
|
## 2. The provenance contract (REQUIRED)
|
|
|
|
The `Provenance` tag states how honest the figure is, and the spec never claims more than the platform delivers:
|
|
|
|
- `HwShunt` — read from a hardware energy interface: an external shunt, or a vendor energy counter (RAPL, NVML, Apple SMC/IOReport) while that counter is live for the domain the figure claims (below). A reading tagged `HwShunt` **MUST** have `measured_uj = Some`.
|
|
- `ModelBased` — computed from a calibrated per-operation energy model. `measured_uj` **MAY** be absent.
|
|
- `Estimator` — a coarse constant estimator (e.g. per-token coefficients applied to L4 token counts). `measured_uj` **MUST** be absent.
|
|
|
|
A runtime **MUST NOT** populate `measured_uj` from anything but a hardware interface, and **MUST NOT** tag a reading `HwShunt` without a present `measured_uj`. Absence is the honest answer when the platform cannot measure.
|
|
|
|
**Vendor counters.** A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, ...) **MAY** be graded as a hardware reading only while the counter is demonstrably live for the domain the figure claims: the implementation **MUST** have observed the counter covering that domain advance under load (for Apple IOReport: the CPU energy rail itself advancing in at least 5 sample intervals, in at least 4 of every 5, over at least 300 ms while the probing thread burns CPU; an interval runs from when one sample is in hand to when the next is, and only one no longer than three of the probe's ticks, 75 ms at its 25 ms tick, counts: a longer one counts as nothing, neither among the intervals, nor as an advance, nor towards the 300 ms, which is the summed length of the intervals that count). A counter that is present but not live — frozen, or republished in lumps — **MUST NOT** produce a hardware-graded figure; the implementation falls back to its estimator or reports the work unmetered, and **SHOULD** record why. A figure **MUST NOT** claim coverage of a domain its counter does not read; where the format has a coverage field, such a figure is Partial.
|
|
|
|
In this receipt the hardware grade is a present `measured_uj` and the `HwShunt` tag: a counter that is present but not live supplies neither.
|
|
|
|
## 3. Signed form — JCR-1 (v0.2)
|
|
|
|
As of v0.2 the receipt's signed form is a **JCR-1 envelope** (SPEC §6.1), the signed-receipt format shared across the Transaction Science family — not a bespoke preimage. A Joule Code receipt therefore verifies under the family's existing JCR-1 tooling and its cross-language (Python/Go) reference verifiers.
|
|
|
|
```
|
|
core = canonical-det-CBOR( # RFC 8949 §4.2.1, length-first keys
|
|
{ jc_receipt: "joule-code/1", op_id, tier, estimated_uj,
|
|
measured_uj?, energy_provenance, sequence, nonce, steward } )
|
|
envelope = COSE_Sign1( # RFC 9052, EdDSA -8
|
|
protected = { 1: -8, 4: bstr(steward) },
|
|
payload = core,
|
|
signature = Ed25519_sign(endpoint_secret, Sig_structure) )
|
|
```
|
|
|
|
`Sig_structure` is `["Signature1", protected, external_aad(empty), core]` (RFC 9052 §4.4). Verification parses the tagged COSE_Sign1 (CBOR tag 18), rejects any `alg` but `-8`, rejects a `kid` other than the expected steward, checks the Ed25519 signature, and confirms the payload equals the receipt's canonical core. Sealing the receipt this way makes the cost basis non-repudiable by the endpoint that produced it and interoperable with every other family pillar.
|
|
|
|
> v0.1 used a bespoke `estimated_uj ‖ sequence ‖ nonce [‖ measured_uj]` preimage; v0.2 replaces it with JCR-1. This is the v0.1→v0.2 wire change.
|
|
|
|
## 4. The estimator of last resort (non-normative coefficients)
|
|
|
|
When only token counts are available — the common L4 case, where a remote ACP agent reports `input_tokens` / `output_tokens` but no energy — the estimator computes:
|
|
|
|
```
|
|
estimated_uj = input_tokens * J_IN_uj
|
|
+ output_tokens * J_OUT_uj
|
|
```
|
|
|
|
and tags the reading `Estimator`. The coefficients are **non-normative** and tunable; the reference consumer ships datacenter-scale defaults where output dominates prefill. Reference values (illustrative, not part of conformance): `J_IN_uj = 200_000`, `J_OUT_uj = 2_000_000` (i.e. 0.2 J / 2.0 J per token). The point of the standard is not the constant — it is that the figure is reported, signed, and honestly tagged as an estimate.
|
|
|
|
## 5. From estimated to measured
|
|
|
|
Promoting a tier's receipts from `Estimator` to `HwShunt`/`ModelBased` is the work item that turns the meter "real" (ROADMAP v0.2). The receipt schema does not change; only the `provenance` tag and the presence of `measured_uj` improve as the platform gains a hardware interface that is live for the work (§2). A consumer's UI **SHOULD** surface the provenance so a reader can tell a measured joule from an estimated one.
|