jcp §5: a GPU counter's plausibility verdict was a bool, and conflated two findings #185

Merged
dcharlot merged 1 commit from fix/gpu-plausibility-magnitude into main 2026-10-08 10:26:50 -04:00
Owner

plausible_gpu_counter compares a counter's implied rate against two bounds —
1.5× the board's maximum power limit, and 2× the board's mean draw plus 5 W —
and returned bool.

What the bool threw away

Everything that made the comparison useful was discarded at the return: which
bound broke, by how much, and the rate it broke it at. A counter a tenth
over a bound and one twenty times over were the same answer.

That also made the judgement irreproducible. The margins are constants in this
crate; re-grading a past refusal against a revised margin needs the rate, and the
rate did not survive the check.

It conflated two findings

One branch fired when the board's own draw reading exceeded the board's own
limit — an RTX 4050 Laptop GPU reports about 590 W for a second after it wakes.
That says the yardstick is broken, not that the counter is overstating. Yet
CounterStatus::Implausible's doc asserted:

It is not counting the board's energy, so a figure from it would debit energy
the device never spent.

…for a case whose evidence does not support it. A broken yardstick is an
indeterminate.

The verdict now carries its figures

enum GpuPlausibility {
    Plausible            { rate_mw },
    CounterOverRate      { rate_mw, bound_mw, bound: GpuBound },   // PowerLimit | MeanDraw
    BoardTelemetryUnusable { draw_mw, limit_mw },
}

CounterStatus gains Unjudgeable for the last. Both still decline the rung
— unjudgeable is not admissible and declining is the safe direction — so
selection behaviour is unchanged. What changes is the diagnosis, which is the
difference between replacing a counter and waiting for a board to settle.

The hardware job corrected my first shape of this

I had the broken-reading check void the whole judgement. The real RTX 4050 on
jetson-hub refused it: one 590 W post-wake spike among otherwise sane 14.8 W
samples turned a counter running persistently at four to thirty times the board's
draw into "cannot judge" — a worse diagnosis than the overrun it actually is,
and a disagreement with the test's own independent oracle.

A reading past the board's own limit is now discarded individually, and only
that reading
. One broken sample is not a broken bracket. Unjudgeable is
reserved for a bracket with no usable reading left at all.

That also fixes something the old code hid: the mean summed every reading, so
a 590 W spike inflated it and made the mean-draw bound more permissive. It was
invisible before only because any such reading short-circuited the check first. A
test pins it, asserting the spike-inflated mean would have admitted a counter the
sane reading alone refuses.

And when both bounds break, the power limit is reported: a board cannot draw
past its own limit by construction, while the mean-draw bound is soft (telemetry
lags a load step). Being a static spec value rather than a reading, the limit is
never discarded either — so a broken draw sample cannot excuse a counter that
overran it outright.

Spec

§5 gains Plausibility (REQUIRED where a bound is readable) beside the
existing Liveness requirement — the spec said nothing about this, and liveness
alone would admit the RTX 4050's counter, which advances in every sample
interval while running at four to thirty times the board's draw. Perfectly live,
and no count of that board's energy.

The new text requires the rate be checked against an independently-read bound
where one exists, SHOULD-records the rate and the bound rather than only the
refusal, and requires an unusable bound reading be reported as unjudgeable
rather than as a counter that overran. Where no bound is readable the requirement
does not apply and liveness stands alone.

A test of mine that was wrong

I first asserted the mean-draw bound binds on the jetson-hub figures. It does
not: 119.5 W is over the 97.5 W power cap, so that bound binds. The code was
right and the test was wrong. Both cases are now pinned separately, plus a case
where the mean-draw bound binds alone (44 W inside a 97.5 W cap, past 2 × 10.4 W

  • 5 W).

Verification

jcp-rs workspace 403 passed, clippy clean on jcp-energy.

reverted caught by
board reading checked after the rate 2 tests
the indeterminate collapsed back into Implausible a_live_gpu_counter_past_its_board_is_implausible
the bound label always PowerLimit the_verdict_says_which_bound_broke_and_by_how_much
Unjudgeable admitted as selectable 2 tests

🤖 Generated with Claude Code

`plausible_gpu_counter` compares a counter's implied rate against two bounds — 1.5× the board's maximum power limit, and 2× the board's mean draw plus 5 W — and returned `bool`. ## What the bool threw away Everything that made the comparison useful was discarded at the return: **which** bound broke, **by how much**, and the **rate** it broke it at. A counter a tenth over a bound and one twenty times over were the same answer. That also made the judgement irreproducible. The margins are constants in this crate; re-grading a past refusal against a revised margin needs the rate, and the rate did not survive the check. ## It conflated two findings One branch fired when the **board's own draw reading** exceeded the board's own limit — an RTX 4050 Laptop GPU reports about 590 W for a second after it wakes. That says the *yardstick* is broken, not that the counter is overstating. Yet `CounterStatus::Implausible`'s doc asserted: > It is not counting the board's energy, so a figure from it would debit energy > the device never spent. …for a case whose evidence does not support it. A broken yardstick is an **indeterminate**. ## The verdict now carries its figures ```rust enum GpuPlausibility { Plausible { rate_mw }, CounterOverRate { rate_mw, bound_mw, bound: GpuBound }, // PowerLimit | MeanDraw BoardTelemetryUnusable { draw_mw, limit_mw }, } ``` `CounterStatus` gains `Unjudgeable` for the last. **Both still decline the rung** — unjudgeable is not admissible and declining is the safe direction — so selection behaviour is unchanged. What changes is the diagnosis, which is the difference between *replacing a counter* and *waiting for a board to settle*. ### The hardware job corrected my first shape of this I had the broken-reading check **void the whole judgement**. The real RTX 4050 on jetson-hub refused it: one 590 W post-wake spike among otherwise sane 14.8 W samples turned a counter running persistently at four to thirty times the board's draw into *"cannot judge"* — a worse diagnosis than the overrun it actually is, and a disagreement with the test's own independent oracle. A reading past the board's own limit is now discarded **individually, and only that reading**. One broken sample is not a broken bracket. `Unjudgeable` is reserved for a bracket with no usable reading left at all. That also fixes something the old code hid: the mean summed **every** reading, so a 590 W spike inflated it and made the mean-draw bound *more permissive*. It was invisible before only because any such reading short-circuited the check first. A test pins it, asserting the spike-inflated mean would have admitted a counter the sane reading alone refuses. And when both bounds break, the **power limit** is reported: a board cannot draw past its own limit by construction, while the mean-draw bound is soft (telemetry lags a load step). Being a static spec value rather than a reading, the limit is never discarded either — so a broken draw sample cannot excuse a counter that overran it outright. ## Spec §5 gains **Plausibility (REQUIRED where a bound is readable)** beside the existing Liveness requirement — the spec said nothing about this, and liveness alone would admit the RTX 4050's counter, which advances in *every* sample interval while running at four to thirty times the board's draw. Perfectly live, and no count of that board's energy. The new text requires the rate be checked against an independently-read bound where one exists, SHOULD-records the rate and the bound rather than only the refusal, and requires an unusable bound reading be reported as unjudgeable rather than as a counter that overran. Where no bound is readable the requirement does not apply and liveness stands alone. ## A test of mine that was wrong I first asserted the mean-draw bound binds on the jetson-hub figures. It does not: 119.5 W is over the 97.5 W power cap, so that bound binds. The code was right and the test was wrong. Both cases are now pinned separately, plus a case where the mean-draw bound binds alone (44 W inside a 97.5 W cap, past 2 × 10.4 W + 5 W). ## Verification `jcp-rs` workspace **403 passed**, clippy clean on `jcp-energy`. | reverted | caught by | |---|---| | board reading checked *after* the rate | 2 tests | | the indeterminate collapsed back into `Implausible` | `a_live_gpu_counter_past_its_board_is_implausible` | | the bound label always `PowerLimit` | `the_verdict_says_which_bound_broke_and_by_how_much` | | `Unjudgeable` admitted as selectable | 2 tests | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jcp §5: a GPU counter's plausibility verdict was a bool, and conflated two findings
Some checks failed
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Failing after 7s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no comparison (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no company or product (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 backends (pull_request) Has been cancelled
4e9a6d6adf
`plausible_gpu_counter` compares a counter's implied rate against two bounds —
1.5x the board's maximum power limit, and 2x the board's mean draw plus 5 W —
and returned `bool`. Everything that made the comparison useful was discarded at
the return: which bound broke, by how much, and the rate it broke it at. A
counter a tenth over a bound and one twenty times over were the same answer.
That also made the judgement irreproducible: the margins are constants in this
crate, and re-grading a past refusal against a revised margin needs the rate,
which did not survive.

It conflated two findings, too. One branch fired when the **board's own draw
reading** exceeded the board's own limit — an RTX 4050 Laptop GPU reports about
590 W for a second after it wakes. That tells you the yardstick is broken, not
that the counter is overstating, and `CounterStatus::Implausible`'s doc then
asserted "it is not counting the board's energy" for a case whose evidence does
not support it. A broken yardstick is an indeterminate.

`GpuPlausibility` now carries the verdict with its figures:
`Plausible { rate_mw }`, `CounterOverRate { rate_mw, bound_mw, bound }` with
`GpuBound ∈ { PowerLimit, MeanDraw }`, and `BoardTelemetryUnusable { draw_mw,
limit_mw }`. `CounterStatus` gains `Unjudgeable` for the last. Both still
decline the rung — unjudgeable is not admissible and declining is the safe
direction — so selection behaviour is unchanged; what changes is the diagnosis,
which is the difference between replacing a counter and waiting for a board to
settle.

Two ordering choices, both written down where they are made. The board's reading
is checked **first**: a counter measured against a yardstick known to be wrong
would be reported with a magnitude that means nothing, so a broken reading yields
no magnitude at all. And when both bounds break, the power limit is reported,
because a board cannot draw past its own limit by construction while the
mean-draw bound is soft (telemetry lags a load step) — naming the harder bound
is the more informative diagnosis.

SPEC §5 gains **Plausibility (REQUIRED where a bound is readable)** beside the
existing Liveness requirement. Liveness is necessary and not sufficient, and the
spec said nothing about this: the RTX 4050's counter advances in every sample
interval while running at four to thirty times the board's draw — perfectly
live, and no count of that board's energy. The new text requires the rate be
checked against an independently-read bound where one exists, SHOULD-records the
rate and the bound rather than only the refusal, and requires that an unusable
bound reading be reported as unjudgeable rather than as a counter that overran.
Where no bound is readable the requirement does not apply and liveness stands
alone.

One of my own tests was wrong first time and the code was right: I asserted the
mean-draw bound bound first on the jetson-hub figures, but 119.5 W is over the
97.5 W power cap, so that bound binds. Both cases are now pinned separately,
with a case where the mean-draw bound binds alone.

jcp-rs workspace: 403 passed, clippy clean on jcp-energy.

Co-Authored-By: Claude Opus 5 <[email protected]>
dcharlot force-pushed fix/gpu-plausibility-magnitude from 4e9a6d6adf
Some checks failed
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Failing after 7s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no comparison (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no company or product (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 backends (pull_request) Has been cancelled
to aa551552a2
All checks were successful
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 38s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m6s
standards workspaces build + test / aac-rs (pull_request) Successful in 55s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 44s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 29s
standards workspaces build + test / map-rs (pull_request) Successful in 28s
standards workspaces build + test / mesh-rs (pull_request) Successful in 25s
standards workspaces build + test / openpay (pull_request) Successful in 1m25s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m51s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 5m2s
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 4s
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 1m9s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m58s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m28s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m8s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m10s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m12s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m15s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m10s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m42s
2026-10-07 15:04:59 -04:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!185
No description provided.