an uncalibrated power model is an estimate, not ModelBased #220
Merged
dcharlot
merged 8 commits from 2026-10-11 22:20:18 -04:00
fix/uncalibrated-model-is-estimate into main 2026-10-11
ci(wai-web-wasm): the native unit-test count is 32 with the OTT grade test
All checks were successful
standards workspaces build + test / proof-rs (pull_request) Successful in 1m24s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m20s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m8s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 4m23s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m15s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 16s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 8m29s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 9s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 25s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 49s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m24s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 4s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 3m11s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 17m33s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 4m46s
standards workspaces build + test / aac-rs (pull_request) Successful in 3m38s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m14s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 39s
standards workspaces build + test / map-rs (pull_request) Successful in 49s
standards workspaces build + test / mesh-rs (pull_request) Successful in 56s
standards workspaces build + test / openpay (pull_request) Successful in 3m12s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 14m54s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m15s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m41s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 3m55s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 6m12s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m2s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 24m19s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 51s
The wai-web native step pins its test count so a test that stops being compiled fails instead of passing silently. This branch adds video_ott::tests::a_page_supplied_figure_is_sealed_as_an_estimate, so the count is 32; the gate still read 31 and failed the job with every test green. Name the new test's group in the comment beside the others. Co-Authored-By: Claude Opus 5.5 <[email protected]>
sandbox-exec-microvm: the liveness tick advances the fake counters itself
Some checks failed
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 7m16s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m49s
WAI conformance / cargo-class corpora · macos (pull_request) Failing after 10m28s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 41s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m58s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m7s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no comparison (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no company or product (pull_request) Successful in 3s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m16s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m6s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m34s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m10s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m12s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m16s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m14s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m24s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 4m8s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m24s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 14s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 8m39s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 24s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m41s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 4m57s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 5s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Failing after 2m35s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m26s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 18m9s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 3m54s
The RAPL and MSR meter tests drove their fake counters from a writer thread on a 2 ms timer while the liveness probe slept between samples. On a loaded host (load ~85 here) the writer was starved for whole sample intervals, and the probe then judged a live fake counter frozen: the two tests failed in 1-3 of every 5 runs on this branch and occasionally on main. Each tick now writes the next rising step and then sleeps, so every interval the probe samples holds exactly one advance whatever the scheduler does. 16 of 16 runs passed, 6 of them with 40 extra busy threads. Co-Authored-By: Claude Opus 5.5 <[email protected]>
jouleclaw-fabric: seed the CPU and AMX matmul figures Estimated, not Benchmarked
local/cpu-neon (130 mJ/GFLOP) and local/amx (7 mJ/GFLOP) were seeded Benchmarked, though each is a recorded throughput priced at an ASSUMED ~5 W core draw: the energy was never read. l3-jouleclaw's projection_grade rightly treats Benchmarked as a calibrated input, so with JOULECLAW_FABRIC=1 and no calibration row this host recorded, a projection priced from these seeds was sealed ModelBased: an uncalibrated constant claiming a model's grade (JCP SPEC §5.1 rung 6). The seeds are now Estimated, as the GPU seeds already were, so a seeded projection is an Estimator figure and a host calibration row still replaces the seed at the grade its writer declared. EnergyProvenance's docs say an assumed power makes a figure Estimated. New tests: jouleclaw-fabric every_seeded_figure_is_an_estimate, and l3-jouleclaw tests/fabric_grade_seeded.rs (fabric on, no calibration file: the cpu-neon entry is Estimated and the receipt Estimator). The existing calibrated/estimated fabric-grade tests are unchanged and pass. No vector carries a fabric seed's grade. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-web: seal the OTT demo's page-supplied joules as Estimator, not ModelBased
OttSession::new seals whatever non-zero joules_micro the page hands it as ModelBased. Nothing in the session measured, modelled or calibrated that figure, so labelling it a model claims better provenance than how it was obtained (the family's ladder, JCP SPEC §5.1: a model earns ModelBased by its calibration). It is now sealed Estimator; zero stays the unmetered marker with no class. New test a_page_supplied_figure_is_sealed_as_an_estimate. No vector changes: the OTT session is a demo surface, nothing under a conformance or vectors directory is produced by it, and reach/record keeps the package of record as it was. Co-Authored-By: Claude Opus 5.5 <[email protected]>
sandbox-exec-microvm, sandbox-exec-wasm, sandbox-meter: grade nominal-cost figures Estimator
Three reference estimators priced work by a coefficient no host calibrated and graded the figure ModelBased: - sandbox-exec-microvm: with no live CPU counter, vCPU-seconds × the reference 12,000 µJ/vCPU-second (a nominal work-unit cost), and the accelerator's "coarse proxy" (that cost × 10); - sandbox-exec-wasm: fuel × the reference 20,000 µJ per million fuel; - sandbox-meter StorageActivity (from_samples, from_volume): ops and bytes × nominal NVMe-class pJ coefficients documented as "calibrated". By the family's ladder (JCP SPEC §5.1) a model earns ModelBased by a calibration on the host; a nominal coefficient is the whole of such a model, so the figure is an estimate. - MicroVmConfig.calibrated and WasmConfig.fuel_cost_calibrated (both false by default) keep a ModelBased path for a cost the operator calibrated on the host, as spec/receipts.md's "calibrated table" describes; the accelerator proxy is Estimator either way. Neither config is constructed outside its crate. - Tests that pinned the over-claim now pin Estimator: cpu_only_run_meters_modelbased (renamed ..._an_estimate), a_cpu_counter_that_held_across_a_run_is_not_a_measured_zero, power.rs's two RAPL fallback tests, runs_a_unit_and_meters_cpu_energy, storage_globs_enforced_through_execution, contention_is_loaded_minus_ baseline. New tests: a fallback is a model only at a host-calibrated cost (CPU) and never for the proxy (accelerator); the same for the fuel cost; both storage constructors are estimates. - boot_microvm example's 15 W/vCPU fallback is Estimator too. - SPEC §6.3, spec/receipts.md, SECURITY.md, README and sandbox-meter's Provenance docs say a nominal or assumed coefficient is Estimator. No vector changes: sandbox-conformance passes every class, file-backed vectors included, and conformance/v1 is untouched (its builders use fixed constructors, none of these estimators). Co-Authored-By: Claude Opus 5.5 <[email protected]>
aac-core: grade the store's elapsed-time receipts Estimator, not ModelBased
timed_receipt prices every store mutation (register_user, create_board, add_cell, record_utterance, predict, set_vocabulary_level) at elapsed wall time × an assumed draw no device calibrated, and tagged it ModelBased while its own doc called it "an estimate". By the family's metering ladder (JCP SPEC §5.1) a model earns ModelBased by its calibration; an assumed draw scaled by time is rung 6, Estimator. The figure is unchanged. Its doc said "~2 mW", but 2.0 × elapsed µs is 2 µJ per µs, i.e. 2 W: the doc now says what the code computes. access-core's Provenance / Receipt docs now say ModelBased is a draw the device measured and an assumed draw is an estimate. New test store_receipts_are_estimates. No vector changes (aac gen-vectors output is byte-identical; the vectors carry no provenance). Co-Authored-By: Claude Opus 5.5 <[email protected]>
proof-solvers: grade wall time × the default 15 W Estimator, not ModelBased
ns_to_uj prices an attempt at wall time × a fixed ~15 W that no host calibrated, and Propositional, Z3Smt, LeanVerifier and every Z3Server attempt that is not sealed as a tree reading graded that figure ModelBased. By the JCP ladder (SPEC §5.1) and the proof SPEC's own definition a model earns ModelBased by its calibration; an assumed power scaled by time is an estimate, so the figure claimed better provenance than how it was obtained. - proof-schema: Energy::estimator(uj), and Provenance docs that say a default or assumed parameter makes a figure Estimator. - proof-solvers: DEFAULT_ACTIVE_MILLIWATTS (15 W, same arithmetic) and wall_time_estimate; all four sites now Energy::estimator. The public Modelled / modelled_uj names are kept; their docs say estimate. - Tests that pinned the over-claim now pin Estimator: grade_attempt's unit tests, z3_tree.rs (server(), refuted goal, settle bound, cascade total [Estimator, HwShunt] -> Estimator, undeclared z3), and proof-cli tests/measure.rs (receipt "provenance Estimator", "stay Estimator"). New test: every wall-time rung (T0 proved/refused, one-shot z3, an absent Lean) is Estimator with no measurement. - proof-cli, proof-cascade, proof SPEC §5 / README, and joule-code-remediate (FormalOutcome docs, joule_fix's printed label) say Estimator. proof/conformance/v1 is unchanged: gen-vectors output is byte-identical (it seals the stand-in ladder's estimate_tier figures, never ns_to_uj). Co-Authored-By: Claude Opus 5.5 <[email protected]>
jcp-energy: grade time × the default power Estimator, not ModelBased
SPEC §5.1 grades rung 5 as wall time × a HOST-CALIBRATED active power
(ModelBased) and rung 6 as an estimate. jcp-energy's ladder fell to
Meter::TimePower at DEFAULT_ACTIVE_MILLIWATTS (15 W, an assumed figure no
host measured) and every counter rung's span degraded to the same 15 W
figure, all graded ModelBased: better provenance than how the figure was
obtained. The power is the whole of that model, so a default power is a
constant scaled by time, an estimate.
- Meter::UncalibratedTimePower { milliwatts } and Rung::UncalibratedTimePower
(Estimator), built by Meter::uncalibrated_time_power; detect() falls to
it, so Detection.selected, rung() and provenance() all say estimate.
- Meter::TimePower / Meter::time_power stay ModelBased, documented as a
power calibrated on this host.
- counter_span / ioreport_span / process_span degrade to the new
uncalibrated_span (Estimator) instead of Energy::modeled.
- Tests that pinned the over-claim now pin Estimator: the RAPL/NVML/
per-process/IOReport fallback-span tests, the declined-IOReport meter
test, and the detect_with selection tests. New tests: a host-calibrated
power stays ModelBased while the default is Estimator, detect() falls to
the estimate, and the fallback span helper.
- jcp-conformance C9 now checks both grades.
- SPEC §5 / §5.1 rungs 5-6, jcp-schema's Provenance docs and the README
say a default or assumed power is rung 6. No vector changes (jcp
gen-vectors output is byte-identical; no jcp vector carries ModelBased).
Co-Authored-By: Claude Opus 5.5 <[email protected]>