The IOReport watch, `CPU_RAILS`, was "any one": Live as soon as ONE CPU rail
met the sustained-advance rule. The power reading sums every CPU rail
(`counts_once`), and on a multi-die part that is two rails, `DIE_0_CPU
Energy` and `DIE_1_CPU Energy` on an M3 Ultra. So one die live beside a
frozen one would have admitted the meter and bracketed one die's energy as
the whole CPU's, as `HwShunt`. RAPL was already held to every package
counter it sums (9334ec0c); IOReport now is too.
The rule: Live only when every CPU rail present in the samples advanced in
at least five intervals, in at least 80% of those observed, over at least
300 ms; Frozen otherwise; Absent with no CPU rail. A rail is present if it is
in any sample, the first included (the watch already registered every
sample's rails; a test now pins it), and is judged over every interval
observed. With every source on the same rule there is nothing for
`Watched.every` to choose, so the field is gone: a `Watched` is which
channels to watch, and the watch needs every one of them.
Two test-side checks encoded the old rule and now encode this one: the
oracle behind the real-IOReport tests says "moved" only when every CPU rail
it reads changed at five reads or more and at 80% of them, and
`assert_verdict_matches_record`, the tests' own reading of a probe record,
calls a run Live only when every CPU rail seen, the first sample's included,
rose in at least 5 intervals at 80% over 300 ms. The oracle reads exactly the
probe's rails on both hosts: one on this M5 Max, the two dies on the M3
Ultra.
Docs: the meter module doc, `IoReportStatus`, `CpuRail`, `Watched`,
`CPU_RAILS`, `RailWatch` and `PACKAGES`; SPEC §5's liveness clause (for
IOReport, every CPU rail the figure sums, one per die, must advance on its
own); the proof README.
Tests, all scripted (macOS here). The rule:
`watch_two_dies_that_both_keep_advancing_is_live` (live at the tenth
interval, or at the fifteenth when one die misses its first three, either
die), `watch_one_die_that_keeps_advancing_beside_a_frozen_one_is_frozen` (the
other die held, stepped once, stepped five times, or advanced three
intervals in five, either die; and twin `CPU Energy` channels),
`watch_one_die_alone_that_keeps_advancing_is_live`, and
`watch_a_die_in_only_some_samples_is_a_rail_the_watch_needs`. The whole probe
loop: `the_probe_needs_every_die_to_keep_advancing`. The real `host_status()`
on scripted reads: `host_status_calls_two_dies_that_keep_advancing_live` and
`host_status_calls_one_live_die_beside_a_frozen_one_frozen`. The single-rail
tests are unchanged. Two existing tests encoded "any one":
`two_advances_of_the_same_rail_are_not_live_and_sustained_ones_are` held
DIE_0 constant and expected Live from DIE_1 alone, so DIE_0 now advances at
every interval and the verdict is still DIE_1's; and
`rapl_every_package_counter_must_keep_advancing` drops its contrast with the
any-one-rail watch, which no longer exists.
proof-cascade: 86 lib tests and the three integration files pass on this M5
Max. The same lib test binary passes 86/86 on the M3 Ultra (macOS 27.0.1),
where the real probe gave `CpuRailFrozen` over 25 and 26 intervals and the
oracle saw 0 changes on both dies in 19 reads. `cargo test --workspace`
passes (126 tests) and the proof-conformance binary passes all 10 checks.
Clippy adds nothing for aarch64-apple-darwin (two warnings in the IOReport
FFI predate this) and is clean for x86_64-unknown-linux-gnu.
Falsified, each restored from git and the suite re-run green: the rule back
to any one rail fails the one-live-die-beside-a-frozen-one tests (rule, loop
and `host_status`), the two-live-dies test, the some-samples test, the
updated two-advances test and the RAPL every-package test; registering a
rail only once an interval has closed fails
`watch_a_die_in_only_some_samples_is_a_rail_the_watch_needs`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
6.4 KiB
proof — A Carrier for Verified Work
The verification cargo class of the substrate. A proof obligation is content-addressed; a solver is anything that can attempt one at a declared tier; a discharged obligation seals as a signed JCR-1 receipt that records which tier closed it and the joules it cost. The standard fixes the one axis the theorem-proving field leaves implicit — joules per verified proof — and makes it portable: any prover can emit a Proof receipt, and any auditor can verify it with the same tooling as a Map, Sandbox, or Joule Code receipt.
The cheapest sufficient solver wins. Every obligation goes to the cheapest rung
that can discharge it — deterministic automation (T0), then SMT (T1), then a
small distilled prover (T2), then a frontier model (T3, last resort) — and
escalates only on failure. Correctness is never traded for energy: a solver
returns proved only when a verifier would accept the artifact, so the standard
changes which tier pays for a proof, not whether it is checked. The joules
spent on a cheaper solver that ran and failed first are disclosed as the cost
of escalation, never hidden. Energy carries an honest provenance tag
(HwShunt / ModelBased / Estimator), and a receipt for an Ungrounded
statement says, in the signed artifact, that the statement was never validated
against intent — a proof is not a specification.
- Site: jouleproof.transaction.science (the JouleProof pillar is the steward + services layer over this standard).
- Licence: Apache-2.0 for reference code (see
LICENSE); CC-BY-4.0 for specification text (seeLICENSE-SPEC). - Status: v0.1.0 draft. Specification core published (
SPEC.md); reference workspaceproof-rs/.
What's here
proof/
├── SPEC.md — the normative standard (§1–§9)
├── conformance/v1/ — published vectors (receipt wire + signed core + envelope)
└── proof-rs/ — the Apache-2.0 reference implementation
The reference implementation (proof-rs/)
proof-schema— the content-addressed goal (blake3(statement‖0x00‖context)), the cheapest-first tier ladder, the honest energy model (HwShunt/ModelBased/Estimatorwith the coupling enforced),SpecGrounding, the verdict, and theSolvertrait every backend implements. Canonical det-CBOR content addressing.proof-solvers— two real rungs, their energy modeled from measured wall time (ModelBased, a ~15 W power model — not a hardware reading): a propositional decider (T0) that parses a boolean goal and decides validity by truth-table in process, andz3(T1) — shell or kept resident across goals — that decides an SMT-LIB goal (assert the negation;unsat⇒ valid). Each refuses rather than fakes, so the router escalates. The model rungs (T2/T3) are honest stand-ins behind the same trait.proof-cascade— the escalation router (every joule accounted,wasted_ujdisclosed), the content-addressed proof cache (the energy flywheel, durable as line-delimited JSON), batch energy accounting against a frontier-only baseline with the per-tier Amdahl breakdown, and a real hardware energy meter (meter— theHwShuntbackend): it brackets a real proof, run on every core, against an idle baseline using the platform's energy interface (IOReport's Energy Model, read directly through its C API on Apple Silicon and used only while every CPU energy rail is live, one per die on a multi-die part; RAPL's package counters on Linux, used only while every one is live) and returns measured microjoules, so the headlinejoules per verified proofcan be a real reading, not only a model. A vendor counter's reading is gradedHwShuntonly while the counter is live for the domain it claims (SPEC.md§5), and the meter checks that before it brackets anything, by one rule on both platforms (the counter keeps advancing in at least 5 sample intervals, at least 4 of every 5, over at least 300 ms while the probe burns CPU): on Apple Silicon for every IOReport CPU energy rail the figure sums (CPU Energy, or each die'sDIE_<n>_CPU Energy), on Linux for every RAPL package counter the figure sums (psysis neither summed nor probed). Returns nothing where no interface is reachable or its counter is not live — the caller keeps the honestly-taggedModelBasedfigure rather than inventing one.proof-receipt— theproof/1JCR-1 receipt: canonical det-CBOR + COSE_Sign1/EdDSA, vendored byte-compatible with the family's cross-language verifiers; refuses to seal an unproved goal.proof-conformance— C1–C5 + a negative pack, all checks real, published vectors inconformance/v1/.proof-cli— theproofreference demo: a proof workload reporting joules-per-proof against a frontier-only baseline — like for like, charged only for the goals the cascade proved, with the all-goals figure and its goal count beside it — the Amdahl breakdown, the cache flywheel, and a sealed + verified receipt.proof --measureadds a real hardware reading of a non-trivial T0 proof (HwShunt) where the meter produces one; that needs a counter the meter has seen to be live (on Apple Silicon every IOReport CPU energy rail, on Linux every RAPL package counter). On the Macs measured so far (macOS 27.0.1, an M5 Max and an M3 Ultra) IOReport's CPU energy rail is frozen for an unprivileged reader, so--measuredeclines there, says why, and leaves every figureModelBased; on Linux, RAPL'senergy_ujis root-only on current kernels.
cargo test --workspace green; cargo clippy --workspace --all-targets is
warning-free for Linux, and on macOS reports two lints in proof-cascade's
IOReport FFI. The two bottom rungs decide for real, with energy modeled from
wall time; the model rungs are honestly marked as stand-ins until inference
backends are wired.
Honesty the standard records
- A proof is not a specification.
spec_groundingrides in the signed receipt;Ungroundedis the default and a prover may never self-certify it. - The multiple shrinks with difficulty. The accounting reports energy per closing tier, so the few hardest goals dominating the joules (Amdahl) is visible, not averaged away.
- Energy is reported at all — per proof, with an honest provenance tag — which the field otherwise leaves to be inferred from device-days.