open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcr1/examples
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science c07d4c5b47
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m25s
standards workspaces build + test / aac-rs (pull_request) Successful in 42s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 44s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 40s
standards workspaces build + test / map-rs (pull_request) Successful in 36s
standards workspaces build + test / mesh-rs (pull_request) Successful in 28s
standards workspaces build + test / openpay (pull_request) Successful in 1m38s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m27s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 57s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m49s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m11s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m6s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m32s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m18s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m47s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m49s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 2m45s
standards workspaces build + test / sense-rs (pull_request) Successful in 2m44s
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Successful in 2m21s
jouleclaw-energy: RAPL is the sum of every package zone, each of which must be live and each wrapped at its own range
`RaplCounter` read one file, `/sys/class/powercap/intel-rapl:0/energy_uj`, and
its liveness probe watched that one file, cached per path. On a multi-socket
server that is package 0's energy alone, graded `HwShunt` for the domain
`CpuPkg` while every other socket's energy is missing. And nothing makes zone 0
a package: `intel-rapl:<n>` is only an identifier, and each zone says what it
is in its `name` file, so a host whose zone 0 is the platform zone (`psys`) or
a `dram` zone had that domain read and probed as the package. proof-cascade
does this right since 9334ec0c; eoc-meter now does too (26165a77); this is the
same rule here.

- The package set is listed from the powercap directory: every top-level
  `intel-rapl:<n>` zone whose `name` reads `package-<digits>`. Left out wherever
  they sit, zone 0 included: `psys` (the platform zone, whose energy includes
  the packages', so summing it beside them counts them twice), `dram`, the
  `core`/`uncore`/`dram` sub-zones (`intel-rapl:0:0`), the control type, and
  the MMIO interface (`intel-rapl-mmio:0`, also named `package-0`, which
  republishes a package). The listing reads the directory, not fixed indices.
- Liveness: one channel per package, and the shared rule asks every channel to
  be live, so RAPL is live only when EVERY package keeps advancing while the
  probe burns CPU. A host with no package zone (only `psys`) is `Unavailable`
  with nothing opened or burned.
- The cache is per package set, keyed by the package zones' directories, not
  per file path. `RaplCounter::new()` lists the set and reuses a verdict for
  the same set; the counter sums exactly the packages that were probed.
- `read()` returns a running total: the first read's package counters summed,
  then each package's delta added, each taken modulo its own
  `max_energy_range_uj`. Summing the raw counters would make one package's
  wrap a fall of the sum, and with sockets at different ranges no single range
  is right. Before this, a wrap of the one zone was a fall, which `jcr1_mint`
  and the like take as no reading; now a wrap is read across. The files are
  read under the counter's lock, so two threads' reads are folded in the order
  they were taken, and an older read is never taken for a wrap. A package that
  cannot be read fails the read (`Platform`): no figure that leaves a package
  out. A package whose counter falls while its range is unknown (absent, or 0)
  makes that read `CounterWrap`, and every later one too, because the total
  would be short by energy no one can know.
- The read path is no longer compiled only for Linux: off Linux the counter is
  still never available (`rapl_liveness` is `Unavailable` there, with no
  probe), but the code it would run is the code the tests run on a Mac.

API: `RAPL_ENERGY_PATH` and `RaplCounter::with_path(&'static str)` are gone, as
a single `energy_uj` path cannot say which domain it is or stand for every
package; `RaplCounter::with_root(dir)` takes a powercap directory instead (a
container or chroot that mounts sysfs elsewhere), and `POWERCAP_ROOT` names
the default. `rapl_liveness()` takes no argument: it is this host's package
set. Nothing in the monorepo called the removed items. Docs that said a RAPL
figure is one file are corrected (`liveness.rs`, `detect_meter`, and the
`jcr1_mint` example's header).

Tests, on fake powercap directories under the temp dir (removed when done), so
they run on macOS:
- a two-socket server (the control type, package-0 and package-1 with core and
  dram sub-zones, psys, a top-level dram, intel-rapl-mmio:0) lists packages 0
  and 1 only, and with every zone moving the delta is the two packages' energy
  (250,000 + 400,000 uJ) and nothing else;
- zone 0 named psys beside package zone 1: zone 1 alone is listed, sampled and
  summed;
- per-zone wrap: package 0 wraps at 262,143,328,850 while package 1 advances,
  then package 1 wraps at 65,532,610,987: deltas of 1,700 and 2,500 uJ; taken
  at the other zone's range, package 1's wrap would be off by the difference
  of the two ranges;
- a package with no range, absent or 0, is summed while it rises; its fall is
  `CounterWrap`, and so is the next read;
- an unreadable package fails the read and the opener;
- an only-psys host, an empty directory and a missing one: no package, the
  real probe returns `Unavailable` in under 100 ms (no burn), and
  `RaplCounter::with_root` is unavailable and reads `NoCounter`;
- scripted: two packages advancing are Live, one held is Frozen;
- the cache: once per package set, and a set with one more package is another
  set; the key of a listed tree is its package directories;
- the production probe (real reads, real CPU burn, real clock) on a two-socket
  tree: held packages are Frozen after the whole budget; both packages advanced
  by a writer thread are Live inside it; package 0 and psys advanced while
  package 1 holds is Frozen.

Falsified, each mutant applied to this commit, run, and restored with
`git checkout` (blob hash equal to HEAD's):
- back to `intel-rapl:0` only, whatever its name: 8 of the 14 RAPL tests fail;
- every top-level zone summed (no name check): 5 fail;
- every package wrapped at package 0's range: 1 fails, the per-zone wrap test;
- the probe watching the first package alone: 1 fails, the production probe
  with package 1 held;
- the cache keyed by the first package's path alone: 1 fails.

What ran where, on this M5 Max (macOS 27.0.1): jouleclaw-energy `--features
rapl` 48 lib + 2 integration tests pass, `--features ioreport,rapl,nvml` 111 +
2, default features 34 + 2; mesh-meter 2 by default, 10 with
`--features hw-meter-rapl`, 12 with `--features hw-meter-apple`;
jouledesk-github 12; the `jcr1_mint` example compiles. For
x86_64-unknown-linux-gnu, `cargo check --all-targets --features rapl` and
`cargo clippy --all-targets` with `rapl` and with `rapl,nvml` pass with no
warning in a file this touches (clippy's existing ones are in jouleclaw-core,
the ledger tests and the IOReport FFI), and mesh-meter's clippy with
`hw-meter-rapl` is clean. The sysfs reads under the real powercap directory
and the Linux-only cached probe are type-checked, not run: there is no Linux
host with readable RAPL here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 22:20:49 -04:00
..
gen_v1_1_vectors.rs jouleclaw-jcr1: implement JCR-1 v1.1 — intent in the signed core (+3 vectors) 2026-06-01 21:16:41 -04:00
jcr1_mint.rs jouleclaw-energy: RAPL is the sum of every package zone, each of which must be live and each wrapped at its own range 2026-09-30 22:20:49 -04:00