compliance: grade on water too, and retire the two magic floats #71

Merged
dcharlot merged 1 commit from compliance/composite-grade into main 2026-09-03 15:11:26 -04:00

2026-08-30

David Charlot
compliance: grade on water too, and retire the two magic floats
All checks were successful
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 58s
standards workspaces build + test / aac-rs (pull_request) Successful in 1m11s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m6s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m47s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m14s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m10s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m2s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m33s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 7m38s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 2m32s
standards workspaces build + test / map-rs (pull_request) Successful in 2m59s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m15s
standards workspaces build + test / openpay (pull_request) Successful in 4m25s
standards workspaces build + test / arl-rs (pull_request) Successful in 17m57s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 8m33s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 16m51s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 8m15s
standards workspaces build + test / sense-rs (pull_request) Successful in 7m16s
`EedReport::is_compliant()` was `self.pue < 1.5 && self.renewable_pct >= 50.0`:
two hardcoded floats with no provenance, no version, and no way to say which
instrument they encode — the exact shape `BandingScale` was added to replace,
sitting in the same crate, on the path a regulator would read.

It also silently ignored water. `EedReport` has collected `water_usage_liters`
all along, and the schemes that grade facilities grade on power **and** water,
so the check discarded an axis it already had in hand. The test that
demonstrates this is the reason for the deprecation rather than an argument for
it: a facility with PUE 1.10 and 2.0 L/kWh **passes `is_compliant()` while its
actual grade is F**.

Three pieces:

- `wue_milli_l_per_kwh()` derives Water Usage Effectiveness as an integer, and
  returns `None` rather than 0 when IT energy is zero. WUE is undefined there,
  and a 0 would read as *perfect* water efficiency for a facility that reported
  nothing — the flattering direction, which is the one to refuse.
- `CompositeRating` combines several metric ratings into one published grade
  under a **declared** rule. "Worst of" and "mean of" are both defensible and
  give different letters for the same facility, so the rule travels with the
  grade for the same reason a `Rating` carries its scale. It keeps its
  components, so a reader sees *which axis set the grade* — a facility rated D
  on water with an A on power is a materially different thing from one rated D
  on both, and a bare letter cannot tell them apart. `binding_component()` names
  the axis an operator has to improve to move the letter, and `covers()` reports
  whether a required axis was graded at all, because a grade that silently omits
  one is not the scheme's grade.
- `grade()` ties them together, taking the scales rather than embedding any.
  Which thresholds apply is the instrument's business, not this crate's — the
  same reason `BandingScale` still ships no canonical scale.

`is_compliant` is deprecated rather than deleted: it is public API, and the
deprecation note carries the reasoning to the call site, which a silent removal
could not. Pre-existing tests that exercise it keep working under a
module-level allow.

Duplicate metrics are refused: the same axis graded twice votes twice, which
under a worst-of rule is harmless and under any other rule is a silent weighting
nobody declared.

Found by the 2026-08-29 sweep, which flagged both that WUE was not rateable
end-to-end and that this function had survived the change meant to retire it.

Verified: 50 jouleclaw-compliance tests pass (7 new), no clippy warnings in the
crate — the four reported are pre-existing, in jouleclaw-core and
jouleclaw-energy.
2026-08-30 17:15:09 -04:00