open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcr1/conformance/README.md
Transaction Science 33f0b89124 jouleclaw-energy: a live IOReport reading is a hardware reading, and only a live one
The owner's decision, applied: a vendor energy counter (RAPL, NVML, IOReport)
is a real reading, and what separates one such reading from another is
provenance, not accuracy. This crate gave RAPL and NVML `HwShunt` and gave the
IOReport counter `ModelBased`, on the reasoning that Apple's Energy Model is a
vendor model. That reasoning grades accuracy. What the counter could not
establish was provenance: on macOS 27.0.1 its CPU rails are frozen for an
unprivileged reader, and that is now caught by the liveness probe. A counter
that has passed it is as much a reading as RAPL is.

The grade. `AppleIoReportCounter` declares `HwShunt`, and stamps it on every
reading through one constant, `READING_GRADE`, shared by `provenance()` and
`read()`. It earns the grade by being live: the counter exists to read only
where `admits()` let it through (CPU rail `Live`), and a declined counter
produces no reading to carry any grade, so a frozen host still meters through
the load-average estimator at `Estimator`.

The rule, written once and shared (jouleclaw SPEC §1.3, §9.4; JCR-1 §2.3;
the crate docs; vendor-energy PROTOCOL/README): a vendor counter's reading 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 IOReport: the CPU rail itself, in
at least 5 intervals, 4 of every 5, over at least 300 ms while the probing
thread burns CPU). A counter present but not live 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.

No partial reading from the GPU rail. Where the CPU rail is frozen but `GPU
Energy` still advances (the M5 Max), the counter stays declined. The GPU rail
is machine-wide: every GPU client on the host moves it, display compositing
included, with nothing of the metered work running. It does not cover part of
the work; it covers other work, so no coverage field makes it honest. The
rationale is in the module docs and SPEC §1.3.

Docs and data that said otherwise:
- SPEC §1.3 table and floors, §9.4; JCR-1 §2.3 and the crate README (toy
  vectors become measurements only off counters that were live).
- JCR-1 vector 6's description said "measured on Apple IOReport". Its joules
  are toy values like every vector's. Only the `description` changed; it sits
  outside the signed core, which `verify.py` builds from `receipt` alone. Both
  verifiers pass 10/10 after the edit: `verify.py` (cbor2 6.1.4, cryptography
  50.0.2, exit 0) and the independent `verify.go` (exit 0). `git diff` of the
  file is that one line; a field-by-field JSON diff finds only (6,
  description). The conformance README's slot 6 line follows.
- vendor-energy conformance: README row 27 names `AppleIoReportCounter` and the
  `HwShunt` grade, with the liveness condition a filled fixture must meet;
  `apple-silicon-ioreport.json` is an unsigned, empty stub (`signed_by` null,
  every workload not run, no hash of it anywhere), so its `impl` and
  `provenance` are corrected in place.
- MEASURED_ENERGY.md: a dated note that the 74.1 J / 25.5 W row was committed
  2026-06-12, predates macOS 27, and recorded neither chip nor OS. The "reads
  CPU/GPU/ANE/DRAM with no sudo" claim is replaced by what macOS 27.0.1 does:
  the counter opens without sudo, but the CPU rails are frozen (all 645 rails
  on the M3 Ultra), so those hosts are estimated.
- local-index / rerank tier SHOULDs, the CLI's `meter` help, meter.rs,
  apple.rs, energy_probe, Cargo feature comments, harness-econ docs.
- l3-jouleclaw README: it claimed `HwShunt` on RAPL/NVML hosts, but the
  binding builds jouleclaw-energy with `ioreport` only, so off Apple Silicon
  the receipt is the token estimate. It now says what happens on each host.
- mesh-schema's `HwShunt` definition includes vendor counters subject to
  liveness; mesh-meter, the mesh README and mesh-engine-gguf no longer say
  real silicon alone yields `HwShunt`.
- The Live-branch assertions in mesh-meter, l3-jouleclaw and jouledesk-github
  expected `ModelBased` for IOReport; they expect `HwShunt`. jouledesk-github's
  fixtures that paired `apple-ioreport` with `ModelBased` now pair it with
  `HwShunt`, and keep a `ModelBased` case under a neutral meter name.

Tests. `a_live_counters_readings_are_graded_as_hardware_readings` builds a
counter on `Live` directly. That opens the real all-channel subscription, which
opens here even though the gate declines this host. It reads it twice and
asserts each reading is `HwShunt` over `SocTotal`. On this M5 Max (macOS 27.0.1):
"an admitted IOReport counter: opens=true, 2 readings, each graded HwShunt",
so the read path is covered on a frozen host. With `--features "ioreport
rapl"`, `a_live_ioreport_reading_has_the_grade_of_a_rapl_reading` compares the
grade with `RaplCounter`'s own. The used/declined tests assert `HwShunt` in
their live branch. This host still takes the declined branch: "ioreport
declined (CpuRailFrozen): 154 ms of CPU work metered by `apple-silicon` as
6200000 µJ, provenance estimator".

Run on this M5 Max: jouleclaw-energy 24+1+1 (default), 76 lib + 1 + 1
(`ioreport`), 79 lib (`ioreport rapl`); jouleclaw-jcr1 50; harness-econ 14;
local-index 41; rerank 37; cli 10; mesh-meter (`hw-meter-apple`) 10;
mesh-engine-gguf 1; l3-jouleclaw 2 + 4 (2 ignored, need a model);
jouledesk-github 12. All pass.

Falsified, each mutant restored with `git checkout` and the tree confirmed clean:
- `READING_GRADE` set back to `ModelBased`: the new test fails at the
  declared grade (left: ModelBased, right: HwShunt), 75 passed / 1 failed.
- Only `read()`'s stamp set back to `ModelBased` (the declared grade left at
  `HwShunt`): the new test fails on the reading itself, "a live counter's
  reading is not graded as a hardware reading" (ModelBased, SocTotal) vs
  (HwShunt, SocTotal), 75 / 1. The read path is what the test pins.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 20:17:13 -04:00

77 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JCR-1 Conformance Vector Suite
A reference test suite for the **JouleClaw Receipt Spec (JCR-1)**. Ten signed
receipt vectors plus a standalone verifier. A second implementation in any
language is **vector-conformant** when it reproduces these results — which is the
gate that turns JCR-1 from "a format JouleClaw uses" into "a standard."
## Files
- `jcr1-vectors.json` — the 10 vectors. Each carries the receipt (JSON
projection), the deterministic-CBOR signed core (hex), and the COSE_Sign1
envelope (hex).
- `jcr1-test-keys.json` — the fixed Ed25519 keypair and gateway HMAC keys. **Test
material only**, published for reproducibility.
- `jcr1-verify.py` — standalone reference verifier. Depends only on `cbor2` and
`cryptography` (no JouleClaw code).
## Run
```
pip install cbor2 cryptography
python3 jcr1-verify.py jcr1-vectors.json jcr1-test-keys.json
```
Expected: `10/10 vectors verified`.
## What each vector exercises (JCR-1 7.3 slots)
1. **L0** cache hit — picojoule class, no tools.
2. **L1** deterministic primitive (arithmetic) — no model.
3. **L1** IaC/tool-only — a `terraform`-style describe closes the query, **zero
tokens**, with a gateway HMAC. (The spec's worked example.)
4. **L2** retrieval-grounded — claim provenance + a span citation.
5. **L3** local model — joule class, HwShunt GPU.
6. **L3** retrieval + model on a **ModelBased** span, mJ-floored (toy figures,
like every vector here: not an IOReport or any other reading).
7. **L4** remote frontier RPC — **Estimator** (remote energy unmeasurable).
8. **Mixed span** HwShunt + Estimator → worst-counter rule forces **Estimator**.
9. **Gateway HMAC** — two metered tool calls, both signed by `gw-edge-9`.
10. **Promoted skill** — same `input_hash` as vector 5, now closing at **L1 for
9 µJ** instead of 2.5 J. The turnover/“enzyme” claim, made checkable.
Vectors 5 and 10 share an `input_hash` on purpose: side by side they show one
query class collapsing from L3 (2,500,000 µJ) to L1 (9 µJ) after promotion — a
~270,000× drop on that class, the per-deployment decay loop in a single diff.
## What the verifier checks
1. **Re-encode determinism** — the signed core must re-serialize to identical
bytes (RFC 8949 §4.2.1 canonical CBOR).
2. **Envelope signature** — COSE_Sign1 (RFC 9052), EdDSA/Ed25519, `kid` = steward.
3. **Gateway HMACs** — each `tool_receipt` HMAC-SHA-256 recomputed from the
NUL-delimited canonical payload.
4. **Honesty consistency** — `energy_provenance` equals the worst counter in the
span; `joules_uj ≥ Σ tools_touched`; ModelBased/Estimator values respect the
1 mJ resolution floor.
## It has teeth (negative tests, all DETECTED)
- Understating `joules_uj` in the body → re-encode mismatch.
- Claiming `HwShunt` on an Estimator span → envelope payload mismatch (can't
forge without the steward key).
- Forging a tool-receipt joule count → re-encode mismatch / HMAC fail.
- One-bit tamper of the envelope → Ed25519 verification fail.
## Canonicalization note (clarifies JCR-1 §3.2)
The signed core uses **RFC 8949 §4.2.1 core deterministic encoding**: map keys
sorted length-first then bytewise on the encoded key (as `cbor2 canonical=True`
emits). A second implementation MUST match this ordering exactly, or step 1 fails.
This is the precise reading of §3.2 and should be folded into the spec as an
erratum.
## Conformance levels
- **Producer-conformant** — emits receipts whose signed core re-encodes
identically and whose provenance/resolution obey §2.3.
- **Verifier-conformant** — implements checks 1–4 above.
- **Vector-conformant standard** — an *independent* implementation verifies all
10 vectors here. That is the milestone that makes JCR-1 a standard rather than
a house format.
> Reminder from the strategy: a receipt proves **cost + provenance, not output
> correctness**. Pair JCR-1 with the calibrated escalation gate so the *answer*
> is trustworthy, not only the bill.