diff --git a/arl/ARL-S.md b/arl/ARL-S.md index 8c0c48c74..b634a8142 100644 --- a/arl/ARL-S.md +++ b/arl/ARL-S.md @@ -41,6 +41,8 @@ Three categories. All three are required above Tier 0. Higher-level energy measurement frameworks built on these primitives include Zeus (open-source per-request energy measurement on production stacks including vLLM), TokenPowerBench (phase-aligned attribution to prefill and decode stages), MELODI (CPU and GPU instantaneous power aligned to inference phase), and PIE-P. The ML.ENERGY benchmark uses Zeus on H100 and B200 hardware. These compose with RAPL and NVML rather than replace them. +A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, or equivalent) may be recorded as physical telemetry only while the counter is demonstrably live for the domain the figure claims: the Supervisor 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). A counter that is present but not live — frozen, or republished in lumps — must not produce a physical-telemetry figure; the energy it would have covered is reported unmetered, and the attestation should record why. A figure must not claim coverage of a domain its counter does not read. + Telemetry is signed by the Supervisor with a hardware-backed key (TPM, HSM, or secure enclave). The reference signing primitive set is Ed25519 over JCS-canonicalized JSON (RFC 8032 + RFC 8785 + SHA-256). These are the same primitives used by the Microsoft Agent Governance Toolkit (April 2026, MIT-licensed) and Mastercard Verifiable Intent (March 2026), so attestations are compatible with the broader receipt ecosystem at the crypto layer. The SUT has no access to the telemetry stream. The Harness has no path to modify it. Sigstore is an acceptable artifact signing infrastructure on top of these primitives. Retention: Tier 2 sessions for at least 6 months. Tier 3 sessions for at least 24 months. diff --git a/joule-code/CHANGELOG.md b/joule-code/CHANGELOG.md index 7ea6b8030..9277219ad 100644 --- a/joule-code/CHANGELOG.md +++ b/joule-code/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to the Joule Code standard are recorded here. The format fol - `joule-code-collab` (Research) lands the **federated-collaboration interface** (`Collab` trait: submit / committed / membership), a **single-node reference cluster** (`LocalCluster`), and the **BFT consensus core** (`LockstepCluster`): a multi-node *lockstep deterministic simulation with BFT supermajority commit* — an op commits only when ≥`2f+1` of `n=3f+1` honest nodes independently validate it, and committed ops are `op_id`-ordered so every honest node derives a byte-identical log. Tested: commits with honest agreement, tolerates `f` Byzantine nodes (safety), loses liveness only beyond `f`, rejects non-members despite quorum, deterministic round ordering. It also adds `protected` — **FROST threshold authorization** of protected operations: a `t`-of-`n` FROST (Ed25519) aggregate signature over an op's `op_id`, verifiable against the cluster's single group key (no member holds the whole key; fewer than `t` cannot authorize). Tested: a 2-of-3 threshold authorizes and binds exactly one op_id; below threshold cannot. And **MLS group keying** (RFC 9420, via `openmls`, `tests/mls_keying.rs`): the cluster members form an MLS group and derive a shared group key with no central server — verified that members agree on the exported secret, that adding a member advances the epoch, and that a member an epoch behind derives a different (forward-secret) key. (SPEC §7, `spec/collab.md`.) - `examples/transport-moqt/` — the **CommunicationOS (MoQT) transport binding**, the last of the four federation layers. A consumer binding that carries a collaboration's committed (consensus-ordered) coding operations over [`inv-moq`](../../joulesperbit/crates/inv-moq) — CommunicationOS's MoQT (Media over QUIC Transport) protocol with its JWP receipt extension. The end-to-end test wires the whole stack in-process: `LockstepCluster` commits ops → each is published as a MoQT object → every object carries a real Ed25519/BLAKE3 **signed receipt** → a subscriber receives all ops, verifies the receipts against the publisher key, and recovers the original `SignedOp` intact; a second test shows a receipt-requiring subscriber rejecting an untrusted publisher's group (ownerless authenticity). Driven through `inv-moq`'s `MockFabric` (real signatures + BLAKE3 merkle receipts, no QUIC; the `quic` feature is the real-wire path behind the same trait surface). Standalone workspace, so the reference library stays free of a joulesperbit dependency. **The four federation layers — consensus, threshold authorization, group keying, transport — are now all implemented and tested.** (SPEC §7, `spec/collab.md`.) +### Changed + +- **§6 / `spec/receipt.md` §2 — a vendor counter is a hardware reading only while it is demonstrably live.** A reading from a vendor energy counter (RAPL, NVML, Apple SMC/IOReport) MAY be tagged `HwShunt`, and supply `measured_uj`, only while the counter has been observed advancing under load for the domain the figure claims (for IOReport: the CPU energy rail itself, in at least 5 sample intervals, at least 4 of every 5, over at least 300 ms of CPU burn). A counter that is present but not live — frozen, or republished in lumps — MUST NOT produce either; the reading falls back to the estimator. A figure MUST NOT claim coverage of a domain its counter does not read. No wire or conformance-vector change. + ## [0.2.0] — draft ### Changed diff --git a/joule-code/ROADMAP.md b/joule-code/ROADMAP.md index 4c2e645ed..6d9f8e0c7 100644 --- a/joule-code/ROADMAP.md +++ b/joule-code/ROADMAP.md @@ -11,7 +11,7 @@ Where the standard goes after v0.1.0. The reference library in [`joule-code-rs/` ## Near-term (v0.2) -- **Measured energy.** Bind the receipt's `measured_uj` / `HwShunt` path to real hardware interfaces (RAPL on Linux, SMC/IOReport on Apple Silicon) via JouleClaw's energy + calibration crates. Promote §6 measured path from Engineering toward Solid where the platform delivers it. +- **Measured energy.** Bind the receipt's `measured_uj` / `HwShunt` path to real hardware interfaces (RAPL on Linux, SMC/IOReport on Apple Silicon) via JouleClaw's energy + calibration crates. A vendor counter feeds that path only while it is demonstrably live for the domain it claims ([`spec/receipt.md`](spec/receipt.md) §2); where it is present but not live — as IOReport's CPU rails are to an unprivileged reader on macOS 27 — the receipt stays on the estimator. Promote §6 measured path from Engineering toward Solid where the platform delivers it. - **Cascade lower tiers.** Land real L0 (content-addressed op cache) and L2 (embedding + hybrid retrieval) stages so frontier calls (L4) are genuinely the last resort, not the first. - **Per-task routing.** Choose the closing tier and the L4 leg per request from intent + budget, recorded in the receipt. diff --git a/joule-code/SPEC.md b/joule-code/SPEC.md index 3521a8cae..d8c164c8c 100644 --- a/joule-code/SPEC.md +++ b/joule-code/SPEC.md @@ -102,10 +102,12 @@ A `Receipt` accounts for one coding operation and **MUST** carry: - `op_id` — the operation it accounts for (§3). - `tier` — the tier that closed the request (§1.1). -- `energy` — a record `{ measured_uj: Option, estimated_uj: u64, provenance: Provenance }`. `measured_uj` is present only when obtained from a hardware energy interface. `estimated_uj` is always present. -- `provenance` — one of `HwShunt` (measured at a hardware shunt/RAPL/SMC), `ModelBased` (computed from a calibrated per-operation model), `Estimator` (a coarse constant estimator). A reading tagged `HwShunt` **MUST** correspond to a present `measured_uj`; a reading tagged `Estimator` **MUST NOT** carry one. +- `energy` — a record `{ measured_uj: Option, estimated_uj: u64, provenance: Provenance }`. `measured_uj` is present only when obtained from a hardware energy interface that is live for the domain the figure claims. `estimated_uj` is always present. +- `provenance` — one of `HwShunt` (read from a hardware energy interface: an external shunt, or a vendor energy counter — RAPL, NVML, Apple SMC/IOReport — while it is live), `ModelBased` (computed from a calibrated per-operation model), `Estimator` (a coarse constant estimator). A reading tagged `HwShunt` **MUST** correspond to a present `measured_uj`; a reading tagged `Estimator` **MUST NOT** carry one. - `sequence`, `nonce` — monotonic sequence and per-receipt nonce. +A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, ...) **MAY** be tagged `HwShunt` only while the counter is demonstrably live for the domain the figure claims — observed advancing under load, by the test in [`spec/receipt.md`](spec/receipt.md) §2. A counter that is present but not live — frozen, or republished in lumps — **MUST NOT** supply an `HwShunt` tag or a `measured_uj`; the reading falls back to the estimator, and a figure **MUST NOT** claim coverage of a domain its counter does not read. + ### 6.1 Signed form (JCR-1) The receipt's signed, on-the-wire form is a **JCR-1 envelope** — the signed-receipt format shared across the Transaction Science family. As of **v0.2** Joule Code adopts JCR-1 rather than a bespoke preimage, so a Joule Code receipt verifies under the family's existing JCR-1 tooling (and its cross-language Python/Go verifiers). @@ -145,7 +147,7 @@ Per the family discipline, each part is classified and the classification is res |---|---|---| | §2 cargo, §3 identity, §4 canonical form | **Solid** | content addressing + deterministic CBOR are well-trodden | | §6 receipt (`estimated`, `Estimator`) | **Solid** | the meter exists in the reference consumer today | -| §6 receipt (`measured`, `HwShunt`/`ModelBased`) | **Engineering** | requires a hardware energy interface; honest absence when unavailable | +| §6 receipt (`measured`, `HwShunt`/`ModelBased`) | **Engineering** | requires a hardware energy interface that is live for the domain it claims; honest absence when unavailable or not live | | §1.1/§5 cascade binding | **Engineering** | the agent schema (JouleClaw) exists; binding L0–L4 to coding requests is real integration work | | §5.1 grant-gated consultation | **Solid** | the JCP runtime and chained receipts exist today; the binding is composition, exercised by C5 | | §7 federated collaboration | **Research** | interface-level only in v0.1; not required for conformance | diff --git a/joule-code/joule-code-rs/crates/joule-code-receipt/src/lib.rs b/joule-code/joule-code-rs/crates/joule-code-receipt/src/lib.rs index d78f45600..fb2b39f69 100644 --- a/joule-code/joule-code-rs/crates/joule-code-receipt/src/lib.rs +++ b/joule-code/joule-code-rs/crates/joule-code-receipt/src/lib.rs @@ -22,8 +22,11 @@ pub const J_OUT_UJ: u64 = 2_000_000; /// How honest an energy reading is (SPEC §6). #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Provenance { - /// Read from a hardware energy interface (RAPL/SMC/shunt). Requires a - /// present `measured_uj`. + /// Read from a hardware energy interface: an external shunt, or a vendor + /// energy counter (RAPL, NVML, SMC/IOReport) only while that counter is + /// demonstrably live for the domain the figure claims (`spec/receipt.md` + /// §2) — a present counter that is not live falls back to the estimator. + /// Requires a present `measured_uj`. HwShunt, /// Computed from a calibrated per-operation model. `measured_uj` may be absent. ModelBased, diff --git a/joule-code/spec/receipt.md b/joule-code/spec/receipt.md index 37c36237b..05b62ff22 100644 --- a/joule-code/spec/receipt.md +++ b/joule-code/spec/receipt.md @@ -17,7 +17,7 @@ Receipt { } Energy { - measured_uj: Option, // present ONLY when from a hardware interface + measured_uj: Option, // present ONLY when from a live hardware interface (§2) estimated_uj: u64, // always present provenance: Provenance, } @@ -29,12 +29,16 @@ Provenance = HwShunt | ModelBased | Estimator 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 (RAPL, Apple SMC/IOReport, an external shunt). A reading tagged `HwShunt` **MUST** have `measured_uj = Some`. +- `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). 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. @@ -66,4 +70,4 @@ and tags the reading `Estimator`. The coefficients are **non-normative** and tun ## 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. A consumer's UI **SHOULD** surface the provenance so a reader can tell a measured joule from an estimated one. +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. diff --git a/map/CHANGELOG.md b/map/CHANGELOG.md index 63f75b1d1..11a8a2127 100644 --- a/map/CHANGELOG.md +++ b/map/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to the Map standard and its reference implementation. Format follows Keep a Changelog; the standard versions independently of the reference crates (which share the `map-rs` workspace version). +## [Unreleased] + +### Changed + +- **SPEC §6 / `spec/receipt.md` §2 — a vendor counter is a hardware reading + only while it is demonstrably live.** A RAPL, NVML or Apple IOReport reading + MAY be graded `HwShunt` only while the counter has been observed advancing + under load for the domain the figure claims (for IOReport: the CPU energy rail + itself, in at least 5 sample intervals, at least 4 of every 5, over at least + 300 ms of CPU burn); a present counter that is not live — frozen, or + republished in lumps — falls back to the estimator. No wire or + conformance-vector change. + ## [0.1.0] — 2026-06-04 Initial draft standard — the protocol spine. diff --git a/map/SPEC.md b/map/SPEC.md index f833bb473..50ef1e7c4 100644 --- a/map/SPEC.md +++ b/map/SPEC.md @@ -99,7 +99,7 @@ The receipt is the family's JCR-1 envelope (`map-receipt`). A receipt **MUST** c - an `Energy` record: `measured_uj: Option`, `estimated_uj: u64`, `provenance: Provenance`; - the publisher/resolver identity and an Ed25519 signature (COSE_Sign1/EdDSA over canonical det-CBOR). -The provenance coupling is normative: `HwShunt` **REQUIRES** a present `measured_uj`; `Estimator` **MUST** leave it absent; `ModelBased` **MAY** include it. A session's total cost is the sum of its tile receipts. A resolver **MUST NOT** report a `measured` figure it did not measure. +The provenance coupling is normative: `HwShunt` **REQUIRES** a present `measured_uj`; `Estimator` **MUST** leave it absent; `ModelBased` **MAY** include it. A session's total cost is the sum of its tile receipts. A resolver **MUST NOT** report a `measured` figure it did not measure. A vendor energy counter (RAPL, NVML, Apple IOReport, ...) grades a figure `HwShunt` only while it is demonstrably live for the domain the figure claims; a counter that is present but not live — frozen, or republished in lumps — **MUST NOT** produce one ([`spec/receipt.md`](spec/receipt.md) §2). A reference (non-normative) estimator orders the tiers by joule class: a cache hit is picojoules; a base/terrain tile is microjoules; a field tile is sub-millijoules; a feature/entity tile is millijoules; a splat tile is joules. The standard is that the figure is reported and honestly tagged — not the constant. diff --git a/map/map-rs/crates/map-receipt/src/lib.rs b/map/map-rs/crates/map-receipt/src/lib.rs index 4f1cf5cc7..9527b4b79 100644 --- a/map/map-rs/crates/map-receipt/src/lib.rs +++ b/map/map-rs/crates/map-receipt/src/lib.rs @@ -27,8 +27,11 @@ pub const UJ_BY_TIER: [(Tier, u64); 5] = [ /// How honest an energy reading is (SPEC §6). #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Provenance { - /// Read from a hardware energy interface (RAPL/SMC/shunt). Requires a - /// present `measured_uj`. + /// Read from a hardware energy interface: a shunt, or a vendor energy + /// counter (RAPL, NVML, Apple SMC/IOReport) while that counter is + /// demonstrably live for the domain the figure claims (see + /// `spec/receipt.md` §2). A counter that is present but not live is not a + /// hardware reading. Requires a present `measured_uj`. HwShunt, /// Computed from a calibrated per-operation model. `measured_uj` may be absent. ModelBased, diff --git a/map/spec/receipt.md b/map/spec/receipt.md index 2a81c104d..f9bbd2bd5 100644 --- a/map/spec/receipt.md +++ b/map/spec/receipt.md @@ -25,7 +25,7 @@ Receipt = { | Provenance | `measured_uj` | Meaning | |--------------|---------------|---------| -| `HwShunt` | **required** | Read from a hardware energy interface (RAPL/SMC/shunt). | +| `HwShunt` | **required** | Read from a hardware energy interface (shunt, or a RAPL/NVML/SMC/IOReport counter while it is live — below). | | `ModelBased` | optional | Computed from a calibrated per-operation model. | | `Estimator` | **forbidden** | A coarse constant; honestly flagged as not measured. | @@ -34,6 +34,20 @@ Receipt = { (conformance **C-neg**). The spec never claims an accuracy the platform cannot deliver. +A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, ...) **MAY** +be graded as a hardware reading (`HwShunt`, with `measured_uj`) 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). 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. `Receipt::seal` cannot check liveness; that duty is the meter's, +upstream of the receipt. + ## 3. Reference estimator (non-normative) Microjoules per resolved tile, ordered by tier — `map_receipt::UJ_BY_TIER`: diff --git a/mesh/SPEC.md b/mesh/SPEC.md index dfd59783f..2fabaa08f 100644 --- a/mesh/SPEC.md +++ b/mesh/SPEC.md @@ -106,6 +106,25 @@ A receipt that violates the coupling MUST NOT be sealable. This is the rule that keeps "measured" honest: a deployment with no hardware meter reports `Estimator` and says so, rather than dressing an estimate up as a measurement. +`HwShunt` covers a shunt and a vendor energy counter (RAPL, NVML, Apple +IOReport), but a counter counts only while it is live: + +> 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). 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. + +`mesh/1` has no coverage field. So a figure from a counter that does not cover +the whole request, such as a GPU counter on a host whose CPU has none, MUST NOT +be graded `HwShunt`. + --- ## §4 Routing — cheapest-sufficient diff --git a/sense/SPEC.md b/sense/SPEC.md index 729fe4fba..8c1795d30 100644 --- a/sense/SPEC.md +++ b/sense/SPEC.md @@ -163,14 +163,31 @@ honest zero estimate, never a measurement). ## 7. Energy and provenance (REQUIRED) Every metered figure — a surfacing's price, a synthesis's cost — is an integer -microjoule pair: `measured_uj` (present only from a hardware interface) and +microjoule pair: `measured_uj` (present only from a live hardware interface) and `estimated_uj` (always present), tagged with a **Provenance** (`HwShunt`, `ModelBased`, `Estimator`). This is the family's shared energy model: a figure is reported with the honesty of how it was obtained and **never promoted**. The honesty invariant is that `HwShunt` requires a measurement and `Estimator` -forbids one. Measurement itself is a **recognized edge**: the sibling **Sandbox** -standard's `PowerMeter` (real RAPL/IOReport) is the reference meter; Sense defines -what an interaction records, the host wires the meter it trusts. +forbids one. + +A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, ...) **MAY** +be graded as a hardware reading (`HwShunt`, with `measured_uj`) 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). 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. + +Measurement itself is a **recognized edge**: the sibling **Sandbox** standard's +`PowerMeter` is the reference meter — it reads RAPL, NVML or IOReport, grades a +reading `HwShunt` only while its counter is live, and falls back to its estimator +when it is not. Sense defines what an interaction records; the host wires the +meter it trusts. ## 8. The sealed, hash-chained surfacing log (REQUIRED) @@ -217,7 +234,8 @@ standard, not a dependency it owns: - **JCP** (capability ⊗ joule-budget) — gates *who* may subscribe to *which* source class, for *how many* joules. Sense is the afferent dual. - **Sandbox** — runs the capture in metered, attested isolation; its `PowerMeter` - is the reference meter (§7) and its attestation is what earns a datum the + is the reference meter (§7: a vendor counter only while live, else its + estimator) and its attestation is what earns a datum the `Attested` trust level (§2). - **JouleClaw** — the reference cascade and frontier-model substrate behind the synthesis fallback (§6). diff --git a/sense/sense-rs/crates/sense-schema/src/lib.rs b/sense/sense-rs/crates/sense-schema/src/lib.rs index 6eb7b8cb3..245923a54 100644 --- a/sense/sense-rs/crates/sense-schema/src/lib.rs +++ b/sense/sense-rs/crates/sense-schema/src/lib.rs @@ -211,7 +211,10 @@ impl TrustLevel { /// promoted**: an estimate is never dressed as a measurement. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Provenance { - /// A hardware energy reading (RAPL, IOReport, NVML). + /// A hardware energy reading: a vendor counter (RAPL, IOReport, NVML) only + /// while that counter is demonstrably live for the domain the figure + /// claims (SPEC §7). A present counter that is not live — frozen, or + /// republished in lumps — falls back to the estimator, never `HwShunt`. HwShunt, /// A calibrated model-based apportionment. ModelBased, @@ -230,7 +233,7 @@ impl Provenance { } /// A two-part energy figure in integer microjoules: `measured_uj` is present only -/// from a hardware interface; `estimated_uj` is always present. The honesty +/// from a live hardware interface; `estimated_uj` is always present. The honesty /// invariant ([`Energy::check`]) is that `HwShunt` requires `measured_uj` and /// `Estimator` forbids it. #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -241,7 +244,8 @@ pub struct Energy { } impl Energy { - /// A real hardware measurement. + /// A real hardware measurement, from a counter that is live for the domain + /// it claims (SPEC §7). pub fn measured(uj: u64) -> Self { Self { measured_uj: Some(uj), estimated_uj: uj, provenance: Provenance::HwShunt } } diff --git a/smart-byte/conformance/v1/regeneration.md b/smart-byte/conformance/v1/regeneration.md index 8e0839d75..51ff871f5 100644 --- a/smart-byte/conformance/v1/regeneration.md +++ b/smart-byte/conformance/v1/regeneration.md @@ -111,6 +111,24 @@ this document planned do not exist. ## Editorial change log +### 2026-09-30 — treatise §8.6: a counter counts only while it is live; no wire-format change + +§8.6 now says when a node may read `measured_microjoules` from a hardware +energy counter: only while that counter is demonstrably live for the work, +meaning it has been seen advancing under load for the domain the +measurement claims. A counter that is present but frozen, or that is +republished in lumps, gives the same honest zero as an absent counter. + +**The wire format, the vectors and every `expected_*` value are unchanged.** +The change narrows when a node may report a non-zero measurement. It does +not change the field, its encoding, or any SAID, signature, lockstep or +gossip computation. The envelope and SAID vectors carry +`measured_microjoules` as a fixed input (1200, 0 and 1), and their expected +values depend on that number, not on how a node came to report it, so none +of them changes. This entry is here because the conformance gate requires a +spec change to come with a pack change, and directs an editorial change to +record its reason in this file. + ### 2026-09-30 — key-event logs and envelopes, on the v1 wire format The pack gains `kel_vectors.json` (25 vectors) and `envelope_vectors.json` diff --git a/smart-byte/spec/treatise_v1_parts_I_II_III_combined.md b/smart-byte/spec/treatise_v1_parts_I_II_III_combined.md index d6529895d..9e650a897 100644 --- a/smart-byte/spec/treatise_v1_parts_I_II_III_combined.md +++ b/smart-byte/spec/treatise_v1_parts_I_II_III_combined.md @@ -586,7 +586,7 @@ The substrate provides no semantic validation of cargo. A USD-byte whose cargo c Every smart byte carries a record of the cumulative energy cost of operations performed on it. The record has two parts: -- **`measured_microjoules`**: the sum of energy measurements taken by nodes performing operations on the byte. Where RAPL or equivalent hardware energy counters are available, the measurement is read from the hardware. Where they are not, the measurement is zero (an honest report of "not measurable on this node"). +- **`measured_microjoules`**: the sum of energy measurements taken by nodes performing operations on the byte. Where RAPL or equivalent hardware energy counters are available and demonstrably live for the work — observed advancing under load for the domain the measurement claims — the measurement is read from the hardware. Where they are not — absent, or present but frozen or republished in lumps — the measurement is zero (an honest report of "not measurable on this node"). - **`estimated_microjoules`**: the sum of workload-correlated estimates predicting the operation's energy cost based on a calibrated model. The estimation function is a substrate-level constant, deterministic, and verifiable: any honest node executing the same operation produces the same estimate. The two-part design is the substrate's solution to a real problem. Per-operation energy measurement is approximate at the per-process level (§4.3) — RAPL measures the package, and other processes contribute to the package draw. The measurement is meaningful and useful, but it is not a precise per-byte attribution. The estimation function provides a parallel signal: an independent prediction of what the operation should have cost, based on workload characteristics that the substrate knows. The two together let the substrate detect divergence: a node whose measured values consistently undershoot the estimated values is either running faster hardware than the model expects (legitimate, and the model can be recalibrated) or is lying about its measurements (a dissent-log entry, see §14).