open-standards/joule-ui/joule-ui-rs/crates/joule-ui-interaction/tests
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science 7539c62e19
Some checks failed
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
standards workspaces build + test / jouleclaw-rs (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / arl-rs (pull_request) Has been cancelled
standards workspaces build + test / eoc-rs (pull_request) Has been cancelled
standards workspaces build + test / jcp-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-ui-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / joulehook-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / proof-rs (pull_request) Has been cancelled
standards workspaces build + test / sandbox-rs (pull_request) Has been cancelled
standards workspaces build + test / sense-rs (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Has been cancelled
joule-ui: a span with no CPU reading is sealed as an estimate of the interaction, never as HwShunt
joule-ui's energy record carries one figure per interaction and has no
coverage field. Both `SpanMeter` adapters (joule-ui-serve's, and the
examples' `support/span_meter.rs`) graded a span by its records alone, so a
span from an NVML-only probe set (a Linux host whose only live counter is the
GPU's: a `Gpu` record, `HwShunt`, and no CPU record at all) was sealed
`HwShunt` for the whole interaction: the GPU's energy, passed off as a reading
of a handler that ran on the CPU. `Span::stop`'s held-CPU rule does not reach
it, because there is no CPU counter to have held.

The rule now: a span with no hardware reading of the CPU
(`Measurement::reads_cpu`) is sealed as the meter's `Estimator` figure for
that span's wall time (`PowerMeter::estimate`, wall x the meter's TDP, never 0
for work that ran). A span that reads the CPU passes through unchanged, with
any GPU record beside it (RAPL and NVML: the sum, `HwShunt`). A span that was
already the estimator's record is replaced by the same figure. The rule is
one function, `interaction_figure`, applied where each adapter closes a span.
The examples' adapter is now generic over the same `Spans` seam
joule-ui-serve's has (defaulting to `PowerMeter`), so it can be driven over
scripted spans, and a new integration test includes it by `#[path]`.

SPEC §5 gains the sentence the shared vendor-counter MUST implies for this
format: with no coverage field, a figure from a counter that does not read the
domain the work ran on (a GPU counter alone, for a handler on the CPU) MUST
NOT be graded `HwShunt` for the interaction. joule-ui-serve's Cargo comment no
longer lists NVML alone as a source of a `HwShunt` receipt.

Tests: `a_gpu_only_span_is_sealed_as_an_estimate_never_as_a_reading`, in
joule-ui-serve (through the real `Host`) and in joule-ui-interaction's new
`tests/span_meter.rs` (through the real `run_interaction` and the examples'
adapter): a scripted 8 ms GPU-only span (9,000 uJ `HwShunt`) is sealed as
160,000 uJ `Estimator` with no measured figure; a CPU+GPU span is sealed
`HwShunt` at their sum (10,500 uJ); a CPU-only span as itself; the chain
verifies. joule-ui-serve, -interaction, -conformance, -mcp, -core, -a2ui and
-render pass (72 tests); clippy adds nothing (one existing joule-ui-core
lint); `real_meter` and `jcp_metered` run as before on this M5 Max (every
interaction `Estimator`, the 15 J grant spent and the sixth denied).
`gen_vectors` regenerated into a scratch directory is byte-identical to
`conformance/v1/` (`diff -r` clean, MANIFEST included): the conformance
pack's `StepMeter` is not a `SpanMeter`, and nothing in the signed core
changed. Cargo.lock gains only the new sandbox-schema dev-dependency edge.

Falsified, each restored from git and re-run green: either adapter sealing the
span as it stands (`interaction_figure` returning it unchanged) fails its
`a_gpu_only_span_is_sealed_as_an_estimate_never_as_a_reading`.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 20:47:34 -04:00
..
span_meter.rs joule-ui: a span with no CPU reading is sealed as an estimate of the interaction, never as HwShunt 2026-09-30 20:47:34 -04:00