compliance: grade on water too, and retire the two magic floats #71
Merged
dcharlot
merged 1 commit from 2026-09-03 15:11:26 -04:00
compliance/composite-grade into main 2026-08-30
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.