mesh-meter: hw-meter-apple meters a Mac with the SMC where IOReport is not live (stacked on #622, #630) #631

Merged
dcharlot merged 3 commits from mesh-meter/smc into main 2026-11-05 06:13:34 -05:00
Owner

Stacked on #622 and #630. The base is jouleclaw-energy/smc-system (#622). The branch also merges mesh-meter/min-window (#630), so until #630 lands the diff includes its commit. Only the last commit, e7403fde3, is new here. Once both merge, retarget this PR to main.

What changes

mesh-meter's hw-meter-apple feature now also enables jouleclaw-energy/smc. On macOS 27, IOReport's CPU rail is frozen for an unprivileged reader (seen on an M5 Max and an M3 Ultra). On such a Mac, HwMeter::detect now picks the SMC's whole-machine power integral (ModelBased, EnergyDomain::System) instead of the load estimator. A live IOReport counter still comes first.

Why this is sound:

  • Short spans stay estimates. #630's minimum-window rule handles the SMC's 2 s floor. A span at least 2 s long is sealed ModelBased. A shorter one, which covers most served requests, is billed this crate's estimate of its own length, as before.
  • Long spans can't read low. System covers the whole request (#622), so a long span's figure stands for it. It reads high, because it includes whatever else the machine powered, but never low.

mesh-core, mesh-openai and mesh-engine-gguf pick this up through their own hw-meter-apple and metal features. ProcessMeter's host fallback also becomes the SMC on such a Mac, under the same window rule. The docs (crate, HwMeter, mesh-openai's serve example) describe the new backend. A new hardware test covers the Mac path.

Verified on an M3 Ultra (IOReport CPU rails frozen)

Check Result
Bridge selection picks apple-smc, with a 2 s floor
20 ms span Estimator, 0.38 J
2.2 s span ModelBased, 152.6 J (the whole machine, which other jobs share)
mesh-openai serve example, server,hw-meter-apple a microsecond serve is sealed Estimator, 172 µJ
mesh-openai serve example, server,metal the process meter still seals HwShunt

Tests:

  • macOS: mesh-meter and mesh-core with hw-meter-apple; mesh-openai with server,hw-meter-apple and with server,metal. Clippy is clean. mesh-engine-gguf --features metal passes cargo check.
  • Linux: mesh-meter with hw-meter-apple passes, and clippy is clean.

🤖 Generated with Claude Code

**Stacked on #622 and #630.** The base is `jouleclaw-energy/smc-system` (#622). The branch also merges `mesh-meter/min-window` (#630), so until #630 lands the diff includes its commit. Only the last commit, `e7403fde3`, is new here. Once both merge, retarget this PR to `main`. ## What changes `mesh-meter`'s `hw-meter-apple` feature now also enables `jouleclaw-energy/smc`. On macOS 27, IOReport's CPU rail is frozen for an unprivileged reader (seen on an M5 Max and an M3 Ultra). On such a Mac, `HwMeter::detect` now picks the SMC's whole-machine power integral (`ModelBased`, `EnergyDomain::System`) instead of the load estimator. A live IOReport counter still comes first. Why this is sound: - **Short spans stay estimates.** #630's minimum-window rule handles the SMC's 2 s floor. A span at least 2 s long is sealed `ModelBased`. A shorter one, which covers most served requests, is billed this crate's estimate of its own length, as before. - **Long spans can't read low.** `System` covers the whole request (#622), so a long span's figure stands for it. It reads high, because it includes whatever else the machine powered, but never low. `mesh-core`, `mesh-openai` and `mesh-engine-gguf` pick this up through their own `hw-meter-apple` and `metal` features. `ProcessMeter`'s host fallback also becomes the SMC on such a Mac, under the same window rule. The docs (crate, `HwMeter`, `mesh-openai`'s serve example) describe the new backend. A new hardware test covers the Mac path. ## Verified on an M3 Ultra (IOReport CPU rails frozen) | Check | Result | |---|---| | Bridge selection | picks `apple-smc`, with a 2 s floor | | 20 ms span | `Estimator`, 0.38 J | | 2.2 s span | `ModelBased`, 152.6 J (the whole machine, which other jobs share) | | `mesh-openai` serve example, `server,hw-meter-apple` | a microsecond serve is sealed `Estimator`, 172 µJ | | `mesh-openai` serve example, `server,metal` | the process meter still seals `HwShunt` | Tests: - **macOS:** `mesh-meter` and `mesh-core` with `hw-meter-apple`; `mesh-openai` with `server,hw-meter-apple` and with `server,metal`. Clippy is clean. `mesh-engine-gguf --features metal` passes `cargo check`. - **Linux:** `mesh-meter` with `hw-meter-apple` passes, and clippy is clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mesh/1 can bind what taught the weights, not only which weights answered
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 53s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m7s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m41s
1c8cac9e7d
§3.6 already makes a decision receipt verifiable **by re-execution**: with
`weights_digest` and `precision`, a verifier runs the forward pass again and
gets the same probabilities. That settles whether this answer came from these
weights. It says nothing about where the weights came from — and a decision
model is ordinarily fitted to a corpus of earlier decisions, which is what
decides which answer the probabilities favour before any request arrives.

§3.7 adds that binding as two OPTIONAL fields, paired the way `weights_digest`
and `precision` are because neither carries the claim alone:

  training_digest     BLAKE3 over the canonical encoding of the corpus records
                      in the order the fit consumed them, each as its content
                      id. The order is in the address because it is part of
                      what the fit consumed.
  training_authority  what a verifier can DO with that corpus: `signed` (every
                      record signed by the principal that produced it, so a
                      third party can check it without trusting whoever
                      trained on it), `logged` (append-only, attested head, so
                      removal and reordering are detectable, but records are
                      not attributable), or `opaque` (bytes and a digest).

As with `weights_digest`, the absence is the signal: a verifier distinguishes
an unattributable model from an attributable one instead of assuming, which is
the only reason these are optional rather than required.

The section also forbids something. A fitted decision model is usually
introduced because it is cheaper than the generation it displaces, and a
receipt MUST NOT state that saving: those joules were never metered, because
that generation was never run. `uj_per_decision` is a measured figure, and a
difference against an unrun alternative is not — a receipt carrying one would
assert an estimate in a field a reader is entitled to read as measurement. An
operator who wants the comparison runs both and keeps both receipts, so the
difference lives between two sealed figures rather than inside one of them.

Conformance vectors do not move. The published reference serve in
`conformance/v1/` is a generation, and both fields are decision-only and
OPTIONAL, so `reference/signed_core.hex` and `reference/envelope.hex` are
unchanged and need no regeneration.

Nothing in this repository yet produces a `training_digest`. The spec now says
how such a model is bound; the fit that emits one is in INGEST.md's Adding
list, which is honest about the order these landed in.

INGEST.md also gains the `mesh/` section it never had. Noted while there and
NOT fixed here, because it is a separate job: that file is dated 2026-05-23,
carries 4 sections for 22 standards, pins "Rust 1.95.0" where the root
`rust-toolchain.toml` says 1.98.0, and routes 12 links to github.com issues,
which is not where this project's issues live any more.

Guards run locally, all clean: comparative prose (4104 files), vanity metrics
(523 Markdown files), spec refs (1966 citations across 17 standards, all
resolve), orphan sources.

Co-Authored-By: Claude Opus 5 <[email protected]>
The entry for version 2 of the route record named the product whose proposal it
adopted, against CONTRIBUTING's public-text rule. The name is redacted in place
with a dated marker, as this changelog's history redacts names, and the sentence
keeps its disclosure: the proposal came from a product of WAI's maintainers
[name removed 2026-11-03].

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The name check read only the private list, which never held the maintainers' own
product names, so a changelog line naming one passed it. Those names are public
already, and the private list also serves checks of text about the products, which
names them where it should; so they are listed in the script, MAINTAINER_PRODUCTS,
in any case, joined or with one hyphen or underscore, the shorter one standing alone.
They are applied beside the private list, with the same opt-out, and an unset private
list still fails closed. The self-test gains a case for each spelling, a generic
phrase that is not a hit, an honoured opt-out, and the unset list.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A hardware decoder against software decoders of the same format (arXiv 2402.09001,
Table IV), fewer frames chosen by the encoder (arXiv 2603.18305, Table V) and a lower
resolution or coarser quantiser chosen by the encoder (arXiv 2511.00707, Table 4), each
with what was measured and against what. They are informative: no record states them,
no rule reads them, and none is a figure of a WAI decoder. The section says how they bear
on the text: the two encoder choices cost frames or quality, SPEC §4's energy order
already ranks the platform's power-efficient decode first, and a hardware row of this
revision reads no media engine, so it and the first point are not like for like.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The private list is a secret, given only to the run on a push to main, so a pull
request that named one of the maintainers' products was caught only after it landed.
Those names need no secret: --maintainer-products-only applies MAINTAINER_PRODUCTS
alone and reads no private list, and the repository checks run it on every change.
The default still requires the private list and fails closed without it.

The script's header and CONTRIBUTING now say which products the script lists: those
the maintainers' public site names. A product not yet announced is named on no site,
so the private list holds it until the day it is announced, when it moves to the
script. The self-test gains cases for the new mode: a product is a hit, a clean file
is clean, the private list is not read, and a missing file fails closed. Two
paragraphs are rewrapped to their file's width.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Point 3 said its energy was read by the processor's own counter through a software
tool. The paper's tool reads the processor's counter and the graphics processor's,
and the paper states neither whether the idle energy is subtracted nor whether Table
4's savings are the measured or the predicted energy of the configurations chosen;
the point now says so. Point 2's classifier chooses per rate-factor setting, of which
Table V covers four, not per quantisation setting.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
WAI's WebAssembly legs ran two stock wasmtime versions: 49.0.2 in the
quantum and face install steps, and 38.0.3 in wai-ops.yml and wai-vector.yml
(wai-ops runs the wasm32-wasip2 decode determinism-tiers §5 cites). A stock
wasmtime leaves NaN canonicalisation off and lets each relaxed SIMD
instruction take the host's own behaviour, so the bits of a NaN a module reads
back, and the result of a relaxed instruction, were the engine's choice.

Every install step now pins wasmtime 50.0.1 by version and SHA-256 (the
x86_64 Linux release archive, 685466455dd4...98a5, the digest the release
lists), and every run passes

    -W nan-canonicalization=y -W relaxed-simd-deterministic=y

wasmtime's two determinism settings: every NaN a float instruction makes is
the canonical one, and each relaxed SIMD instruction has one behaviour on
every host. The flag names are 50.0.1's own, read from that release's
`wasmtime run -W help` on the build host. The two 38.0.3 steps gain the
architecture check and the digest the others already had.

Both settings took effect on the build host (arm64, the 50.0.1 release for
that platform). f32.add of a NaN with payload 0x200001 and 1.0 gives
0x7fe00001 without the flags and the canonical 0x7fc00000 with them. The
fixed relaxed behaviour is the engine's, not always the one WebAssembly's
deterministic profile prescribes: f32x4.relaxed_madd(1+2^-12, 1+2^-12,
-(1+2^-11)) gives the fused 2^-24 with and without the flag, where the
profile's choice (parameter 0) is the unfused fadd(fmul), which gives 0.
The workflows' comment says so.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
determinism-tiers §5 says a WebAssembly decoder at decode-equivalence MUST
NOT use relaxed SIMD, and that the browser crate was validated without it by
hand, "which CI does not check". CI now checks it. wasm-tools 1.250.0, pinned
by version and SHA-256, validates the node bundle and the platform_decode
bundle the job builds, and the package of record the site serves
(reach/record/wai_web_bg.wasm), with --features=-relaxed-simd,-threads. A
relaxed SIMD instruction, a shared memory or an atomic in any of them fails
the job.

Before the packages, the step shows that it can fail. A planted module with
i8x16.relaxed_swizzle and one with a shared memory each validate with the
default features, and each is refused with them off for its own feature's
reason (the error text is matched).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Main's run 17676 at 2bef11f71 failed on both arm64 legs with "No space left
on device": linux-aarch64 in the checkout's `git fetch`, and macOS in the
toolchain's temporary files. Both runners live on one host, whose disk was
full. No fixture was decoded, yet the cross-architecture matrix read as red.

Each leg now begins, before the checkout, with a step named
"infrastructure: this runner's disk has room for the leg". It measures the
free space under the workspace, the runner's temporary directory, TMPDIR and
HOME. Below a floor of 4 GiB it fails with an error that begins
"infrastructure:" and says that no fixture was decoded. The leg itself writes
under 1 GiB (measured on the build host: about 270 MiB of working tree and a
67 MiB release target), and a cold toolchain install about 1 GiB more.

A disk can also fill while the leg runs, from the jobs that share it. A
second step runs only when a step after the check failed. It measures again,
and names the failure infrastructure when the disk is below the floor, or
says that the failure is not the disk.

Both steps are bash and skip on Windows, as the matrix comment says.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The install steps' comment said every WAI workflow that runs wasmtime pins one
version and passes both determinism settings, but nothing enforced it: a step
that ran a stock or differently pinned wasmtime would have merged green.
scripts/check-wasmtime-pin.py now fails, in the repository checks, any workflow
that

1. downloads a wasmtime release other than 50.0.1, or checks it against any
   SHA-256 but that archive's;
2. installs wasmtime another way (cargo install, the install script, an action);
3. runs wasmtime (run, serve, compile, or a module given to it) or names it as
   a CARGO_TARGET_*_RUNNER without -W nan-canonicalization=y and
   -W relaxed-simd-deterministic=y.

It also fails when it finds no download or no run, so a check that looked in
the wrong place cannot pass. On this tree it finds the downloads and runs it
should. Its self-test (scripts/check-wasmtime-pin-selftest.sh) passes a scratch
workflow shaped like these and fails each way of breaking it that the
self-test lists, matching the reason in the output.

The comment's relaxed_madd claim was measured on arm64 only. It now rests on
both architectures, measured on an arm64 macOS host and an x86_64 Linux host
with a small probe (wasmtime 50.0.1's release for the host, checked against
the digest the release lists):

    host Darwin arm64; wasmtime 50.0.1 (c307ec81d 2026-10-29)
    f32.add(bits 0x7fa00001, 1.0)                     [no flags]: 0x7fe00001
    f32x4.relaxed_madd(1+2^-12, 1+2^-12, -(1+2^-11)) [no flags]: 0x33800000
    f32.add(bits 0x7fa00001, 1.0)                     [both flags]: 0x7fc00000
    f32x4.relaxed_madd(1+2^-12, 1+2^-12, -(1+2^-11)) [both flags]: 0x33800000
    an unknown -W option is refused: error: failed to parse -W / --wasm option:
      unknown option: no-such-option

    host Linux x86_64; wasmtime 50.0.1 (c307ec81d 2026-10-29)
    (the same five lines, bit for bit)

0x33800000 is 2^-24, the fused result; the unfused fadd(fmul) gives 0. So the
NaN setting takes effect on both, and relaxed_madd is fused on both with and
without the relaxed setting. That matches 50.0.1's source (the
wasmtime-internal-cranelift crate, read from the registry): the translator
lowers F32x4/F64x2RelaxedMadd through fma_f32x4/fma_f64x2
(src/translate/code_translator.rs L2530-2539), which emit a native fma on a
host that has one, a fused library call under relaxed-simd-deterministic on a
host that has none, and the unfused fmul and fadd only on a host with no FMA
and the setting off (src/func_environ.rs L5907-5925). The setting is what
makes the result fused on every host. And since an unknown -W option stops
wasmtime, a run that exits 0 with the two flags has parsed them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
§5 said the browser crate's SIMD validation was done by hand, "which CI does
not check". Since "wai-web-wasm: the packages validate with relaxed SIMD and
threads off", wai-web-wasm.yml validates both bundles and
reach/record/wai_web_bg.wasm with relaxed SIMD and threads disabled. §5 now
says so, and says what CI still does not check: that they hold no other SIMD
instruction. The changelog gains the CI entry for this branch.

The commands that reproduce CI's wasmtime legs ran a stock wasmtime: the WAI
Quantum READMEs (English and Chinese), the bit_identity test's header, the WAI
README's edge example, and the conformance READMEs (quantum, qasm3, formats,
answers, intents). Each now passes -W nan-canonicalization=y
-W relaxed-simd-deterministic=y, as CI does. The determinism-cost run scripts
under wai/research keep their commands: they record runs already made.

The quantum docs check could not see that drift. For a `norun=ci:` block it
stripped every leading VAR=value before matching the command against the
workflow, and its pattern, \S*, did not read a quoted value. It now reads a
quoted or bare value, and when the workflow sets VAR (as an env: key or in a
script) the documented value must be one the workflow gives it, so
CARGO_TARGET_WASM32_WASIP2_RUNNER=wasmtime is refused against a workflow that
sets it to the flagged runner.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The disk pre-check read df under the leg's four directories (the workspace,
the runner's temporary directory, TMPDIR and HOME). Three gaps remained.

1. On linux-aarch64 df reads the runner VM's disk, not the host's. Run in a
   job container started as the runner starts one (its image and its two
   cache mounts), the step's loop put all four directories on the VM's data
   disk (84 GiB free), while the host volume that holds the disk image had
   50 GiB. The image is a 200 GiB file that was already allocated on the host
   but for 0.7 GiB, so a full host volume could take back at most that much.
   The step now also writes and syncs 32 MiB once on each filesystem it
   measures (dd conv=fsync, which the macOS host's dd and the job image's
   both take), and names a write refused for space, an I/O error, a read-only
   filesystem or a quota infrastructure. That also catches a disk out of
   inodes, which df's block count does not show. Another failed write is a
   warning, not a verdict.
2. The second determinism matrix, wai-conformance.yml's byte-exact job, runs
   on the same three labels with no disk check. It now has both steps, with
   the same floor.
3. The floor had no reading behind it. The step's loop, run on 2026-11-04 in
   each label's job environment: linux-x86_64 201 GiB (one host) and 304 GiB
   (the other); linux-aarch64 84 GiB; macos 78 GiB under the workspace and
   the runner's temporary directory, 85 GiB under TMPDIR and HOME. The floor
   stays at 4 GiB: it fails a leg only on a host within a few GiB of full,
   and the macOS runner's internal disk, where HOME and TMPDIR sit, has gone
   from 7 GiB free to 118 MiB within hours, with its jobs failing under HOME.
   The env comment says so.

The class of the failure is still not in the status context: the forge
reports `wai cross-architecture byte-equality / <label>` as failed for a full
disk as for a divergence. The comment now says so, and why the check is not a
job of its own per label: the `linux` label has two hosts, so such a job
could measure another host's disk than the leg's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
§1 now records five published routes to a reproducible stage, each from the
paper section read. The explicit-parameter route keeps its entropy stage and
lets the reconstruction drift: its body says so, and its periodic I-frames
re-anchor the picture to one float decode (§3.2, Appendix B.8). Two integer
routes join the quantised decoder: a float model run in a 16-bit integer mode,
whose accumulators were observed not to overflow (§4.5), and an integer-trained
codec (abstract only). One more line reaches no tier: float synchronised on a
tested hardware class, whose streams decode only within the GPU groups its
tests found (Table IV, §III-B). §7.1 cites the two records of float decode
across devices beside WAI's record, and is not a comparison.

syfai-input §5 and the September sweep's row of arXiv 2608.00483, G7 and F5
are corrected against the bodies read on 2026-11-03.

research/catalogue-prior.md records a linear basis learned on openly
licensed films of one studio, measured against AV1: its readings, procedure,
decision rule and the time the rule was fixed. The rule refutes a linear or
spectral catalogue basis and exact recurrence across titles for a studio's
catalogue; a learned prior is not measured. tools/wai_catalogue_prior_verify.py
recomputes every BD-rate and verdict from the readings and checks every figure
the page quotes, in the conformance workflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A reconstruction kept within a bound of the exact one between points at which
it is made exact again is measured on named devices and a named corpus, and a
sink cannot check it from what it received. So §3 says, normatively, that no
tier, class or claim states such a bound, and three rules follow: a decode of a
NeuralIntegerExact capability in reduced precision or float is not a decode of
it; a capability whose payload holds several frame types takes the class of its
weakest; and a clip digest, a stage hash or a binding over a sequence covers
only frames each decoded at decode-equivalence. SPEC §7 points to it.

A reconstruct-session decoder entry's `variant` now names the path that ran:
`exact`, `float`, or null for a capability with one path. Rule 13 refuses a
NeuralIntegerExact capability named with another path
(session_variant_not_exact); rule 14 refuses a float path under a pin of
decode-equivalence (session_tier_exceeds_variant); and against the stage
claims, a stage hash over a base an entry decoded at a weaker step, or over a
base or layer decoded by a path that is not exact, is refused
(session_stage_hash_not_exact).

claim-conformance gains a vector for each refusal and accepted ones for both
of wai.image.jpegai's paths, appended after the earlier vectors, which a test
pins by digest. claim_verify.py reads the same rules, and differential.py
generates sessions around them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai.image.jpegai decodes through its exact decoder or through a float decode,
and both returned the same result, so neither a receipt nor a binding check
could tell which had run. decode_envelope, decode_envelope_strict,
decode_multi, decode_multi_strict and decode_payload now return a Dispatched:
the output, the capability the payload decoded through (its own or the
fallback) and the path, DecodePath::Sole, Exact or Float. DecodePath::variant
gives the term a session claim's decoder entry states.

check_reconstruction_binding reads the path: over a decode-equivalence
capability or the exact decoder it reports whether the hash holds, and over
the float decode it reports the binding as not checked, never as failed, as
reconstruction-binding §2 requires. The notes in determinism-tiers §5 and
reconstruction-binding §2 that the dispatch did not report the path are gone.

tests/jpegai_decode_path.rs runs the float path and requires the result, the
session claim and the binding check to say so, and the exact decoder likewise.
Its JPEG-AI cases need inputs outside the repository and skip without them;
the case with one path runs in the neural gates.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Rule 14 refused only `float` under a pin of decode-equivalence, while rule 13
and the stage-hash check read any variant but null or exact as not exact. Rules
6 and 13 already refuse such a pin for every class the registry gives, so rule
14 reaches only capabilities with no class, and there `fp16` passed. The three
now share one predicate, DecoderEntry::exact_path: null, `exact`, or, for a
NeuralIntegerExact capability, the lowering its registration names. The last is
how opus-dred §7.2's present entry names wai.audio.opus.dred.int's integer
path, `dred-int/1`, which rule 13 would otherwise have refused; opus-dred says
a session claim of that decode may name it so.

The stage-hash refusal is per object: an entry naming the base at a weaker step
counts whichever units it presented, so the outcome does not depend on whether
the verifier holds the outputs. determinism-tiers §3 rule 3 now says so. The
vector session_stage_hash_not_exact moves its fallback decode inside the set,
at unit 2, so it is refused under either reading, and the earlier form stays as
session_stage_hash_not_exact_outside_the_set, the per-object case.

determinism-tiers §3 calls the closed vocabulary a pin's, says rule 3 governs
decoded media while generation-equivalence carries its own digest, and says
rule 2 is held over the registry class. The README says rule 6 enforces it, with
an inter-frame capability's vector, and rule 14 is its per-path complement.

Five vectors are appended after the earlier ones, which a test pins by
digest: a registered lowering accepted, another capability's lowering
refused, `fp16` under decode-equivalence refused, an inter-frame capability
over its class refused, and the per-object case.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
check_reconstruction_binding compared only the hash, so a binding of another
decoderId, format or size than the exact decoder computes was reported as
Differs. reconstruction-binding §2 forbids reporting a binding as failed when
the verifier decoded some other way than its descriptor says. Such a binding
is now BindingCheck::OtherReconstruction, with the path that ran; for the
exact decoder that is any decoderId but 2.

wai_neural_decode_ex dropped the path and the capability, so a native sink
could not state its decoder entry's variant. wai_decoded_t gains `path`
(WAI_DECODE_PATH_SOLE, _EXACT or _FLOAT) and `fallback`, 1 when a WAI1
envelope decoded through its fallback. include/wai.h is regenerated.

The neural gates counted the two JPEG-AI cases' skips as passes, so CI ran
only the one-path case. That step now selects its two committed-input cases by
name, one of them a binding over int_mlicpp checked under its descriptor. A new
job in the 24.04 image fetches the pinned jpegai/v1 bundle and runs the exact
decoder's case with WAI_REQUIRE_SOTA_VECTORS=1, requiring it by name and
refusing a skip. The float decode needs the reference-software assets, which
no job holds, so its case runs locally only; the test header and
determinism-tiers §5 say so. The C ABI step runs the path and fallback test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Reason gains three variants and has no #[non_exhaustive], so the API check
counts them as a break, and the entry named none. It now acknowledges them,
the five neural dispatch functions' new return type (the neural feature is
outside the checked API, so the check does not report it), and wai_decoded_t's
two new fields. The entry also states the exact path, the per-object stage-hash
check, where each decode-path case runs, and that §1 records the five routes
while §7.1 cites the two float-decode records.

syfai-input's G11 and the September sweep's G9 said the result does not record
which path ran. Each gains a dated status note pointing to determinism-tiers §5
and neural::Dispatched::path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
In the sessions CI's run of the differential generates (seed 1) neither
session_tier_exceeds_variant nor session_stage_hash_not_exact was the verdict
once. An entry naming a stage set's base almost never had the unit the session
names the set at, so session_first_unit_mismatch came first, and a path that
is not exact under a pin of decode-equivalence rarely met a capability with no
class. Entries naming the base now take that unit, as an honest sink states
it, four times in five, and the path defect moves its entry to another
capability more often, an unclassified one half the time.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The previous change did not reach either rule: a planted regression of rule 14
to `float` alone still left the differential with nothing to report, since the
random sessions are refused by an earlier rule first. session_decode_paths now
sweeps one picture through one entry over five capabilities (classified at each
tier, or not at all), seven terms for the path, three pins and both kinds of
decoder, where nothing else decides, so rules 6, 13 and 14 each give the
verdict. session_stage_bounds, whose sessions pass every earlier rule, states a
stage hash a third of the time, and then half the time unpins the base's entry
or names another path on an entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
An encoder SHOULD pin the parameter set a payload was coded against wherever a
capability that decodes it is registered as decoding against one, whatever the
intent (SPEC §3.1, Pin by default).
An envelope that pins nothing there still conforms in 1.x; a verifier reports it
(prior_unpinned), informatively: Wai::check_unpinned, WaiMulti::check_unpinned and
codecs::pin_by_default. wai verify now reads the envelopes under each path, refusing
one whose pin breaks SPEC §3.1 and noting prior_unpinned; wai inspect and wai wrap note
it too. pin-conformance/unpinned.json holds the vectors, reached by wai_pin_vectors and
by pin_verify.py, which reads the classes from the published registry export.

A reconstruct-session decoder entry's pin (jwp-receipts §2.4.12) now names the set an
unpinned decode read, by the digest a pin over those bytes names, with the tier none.
The reference sink's base decode gives it (staged::BaseDecode::set, from
IntParams::read_pin), and stage_measure's sessions carry it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The browser recorder (wai-web's SessionHandle.decoderFor) still wrote pin and tier null
for every decode that verified no pin, so for one unpinned decode the page and the native
tool sealed different claims, against SPEC §3.1 rule 4 and jwp-receipts §2.4.12. Every
committed fixture pinned its base, which hid it. decoderFor now takes the set the decode
read, a trailing argument, apart from whether it verified a pin; StageBase gives both
(paramSet, pinned) from staged::decode_base_pinned. A decode that verified no pin is named
by the set it read, with the tier none, as stage_measure's recorder names it; a pinned
decode given a set other than its pin's is refused. measure_verify.py names the set as the
text does: the SHA-256 of a one-file capability's file, otherwise of the wai.prior.set
listing of the files read.

staged-measure-conformance/fixtures/unpinned is a title over the staged corpus's unpinned
wai.neural.int_hyper base (image_int_hyper_unpinned), decoded against the same files the
still's pin names, so its decoder entry names that digest; goldens.json regenerated
with wai_stage_measure. The parity test and verify_measure_wasm.mjs pass the verified-pin
flag apart from the triple's pin, so both recorders and both verifiers are compared on it,
and verify_staged_wasm.mjs holds StageBase.pinned and paramSet to every staged case.

jwp-receipts §2.4.12 says that an entry from a sink of the earlier text may carry null for
an unpinned decode that read a set, which a verifier cannot tell from one that read none.
SPEC §3.1 rule 2 says that an unpinned envelope conforms unless §7 requires the pin
(replicate_unpinned). DecoderEntry::pin says what it now names.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
conformance-results §4.1: a relying party that admits an implementation on a
conform-result/1 record requires the record accepted, its run passed (not_conformant), its
suite one whose corpus the party holds (suite_unknown), and its corpus digest that corpus's
(corpus_mismatch). wai verify --conformant [--root <wai-dir>] applies the rules against a
checkout; without it a record of a run that did not pass verifies as before. A sink kind:
wai conform sink --suite native-sink gives a sink each session of
live-conformance/native-sink/ with its answers withheld, and each configuration the corpus
states a session refuses; wai_native_sink_vectors answers [--c-abi] is the reference sink,
through its module or through the C interface the platform integrations link.

wai-breaking.yml's runner job runs the native sink both ways and the score decoder, each
record admitted against the checkout's corpus, and a planted sink that presents an object
whose digest does not match: its run must exit 1 with tampered-fragment failed, and
admission must refuse its record at rule 2. tests/cli_conform_sinks.rs holds the same, and
corpus_mismatch and suite_unknown; it has its [[test]] entry with its required features,
so check-tests-in-ci.py passes. The binaries are built with the test step's features, so
cargo reuses what that step built. The browser sink has no sink suite, and §7 says that
§4.1 has only this reference implementation, with no admission vectors.

The catalogue's receipt.verify (the new options, and the envelopes the pin-by-default commit
added) and conformance.run (the sink kind, the {case} placeholder) are exported again, and
Studio's actions regenerated from the export: actions.mjs --check had failed since that
commit. c_abi::take reads and frees no null buffer.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
every_corpus_case_seals_an_honest_session replays each staged case as a sink
and records its session, but its decoder entries named no pin and no tier
for any base. Since determinism-tiers §3 rule 3, a stage hash over a
NeuralIntegerExact base is refused unless every entry naming the base is at
decode-equivalence, so the honest sessions of the pinned int_hyper,
int_codec and splat cases were refused with session_stage_hash_not_exact.

A base's entry now names what the sink's decode states (jwp-receipts
§2.4.12): the pin it verified, with the tier that pin declares; for an
unpinned decode that read a set, the digest a pin over the bytes read
names, with the tier none (SPEC §3.1, Pin by default, as
IntParams::read_pin names it); nothing for a decode that read no set.
Layer entries name nothing, as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai breaking reports staged-measure-conformance/goldens.json as a wire break:
the unpinned fixture's evaluation was added, and the corpus-wide dedup
record, taken over every fixture's objects, counts its objects too, so its
totals moved. The entry named no break for it. It now acknowledges it, and
says that no other fixture's evaluation changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Two passages followed a published route's limitation with a sentence about
WAI's integer networks: in §1, an integerised video codec's accumulators,
whose overflow was observed not to happen rather than bounded; in §7.1, a
requantisation that was not bit-exact across neural processors. Each
passage now describes the route alone. integer-operators §8 and §5.1
specify WAI's bounds and rounding.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
claim-conformance: an unpinned decode's entry names the set it read, and one vector keeps the earlier text's null
Some checks failed
wai-quantum views in agent hosts / views · a scripted host (pull_request) Successful in 7m30s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 9m42s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 15m43s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Failing after 5m42s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 14m44s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 9m39s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 12m11s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 10m18s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 31m16s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 25m3s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 30m52s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 1m59s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m12s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 1m2s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 31m3s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m35s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 17s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 14s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 50s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 4m44s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 23s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 9m36s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 26s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 1m17s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 2m12s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 2m30s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m15s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m30s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 2m21s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
081b71e9b4
Two decode-path vectors stated an unpinned NeuralIntegerExact decode with
pin and tier null, the form of the earlier text. Under SPEC §3.1, Pin by
default, rule 4 and jwp-receipts §2.4.12, a sink names the set it read, by
the digest a pin over it names, with the tier none, and null means a decode
that read no set or an entry from a sink of the earlier text.
session_variant_not_exact_unpinned and session_stage_hash_over_an_unpinned_base
now write the entry so, and each is still refused for its own reason: rule
13, and a stage hash over a base whose tier is not decode-equivalence. A
vector appended after them, session_stage_hash_over_an_unpinned_base_earlier_text,
keeps the null form, which a verifier cannot tell from a decode that read
no set, and is refused all the same. The vectors before the decode-path
rules are unchanged, as the test that pins them by digest requires.

differential.py reaches the tier none too: in its decode-path sweep, in the
mutation that puts a path under a pin, and where its stage-bounds sweep
unpins the base's entry, which now writes either form.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-web-wasm: the native unit test count includes the decoder entry's set test
All checks were successful
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 10m48s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m49s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 13m1s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m54s
wai-vector vector graphics / independent checker (Python) (pull_request) Successful in 12m11s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 33m18s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 38m48s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 5m24s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 6m18s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 5m51s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m8s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m32s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 39m58s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 6m0s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 2m3s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m34s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 40m14s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 52s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 37s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 12m10s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h8m39s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 1m11s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 54s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 37s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 2m2s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 3m2s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 3m0s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m50s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 2m47s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 10m6s
2a48fffdb7
Pin by default added measure::tests::a_decoder_entry_names_the_set_its_decode_read,
so the native unit tests step's count check must expect it; the step otherwise
fails after every test has passed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Under load the relay can take a group whole only after the age window has
passed its number, because its streams finish out of order. Such a group is
late: it is never stored, and it is counted in groups_late. The by-age test
expected six evictions whatever the order, and failed 3 against 6 when three
groups came late. It now checks that every group is evicted or late, and that
each group stored is counted as it goes. A second run makes the out-of-order
case happen on purpose (group 0 and group 2's receipts, then, once the window
has passed group 2, group 1 and group 2's objects) and checks three stored,
three late.

The store also counted an eviction after releasing the index lock, so a
reader that found the group gone could read the count one short (5 against 6
with a delay injected there). The count now moves under the same lock as the
removal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
watch-together: the page makes its audio context before its join; a slot is set apart only when the machine ran nothing of the page
All checks were successful
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 21m22s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 7m27s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 10m15s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 11m59s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 6m48s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m44s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 9m5s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 33m23s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 7m11s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 18m7s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m19s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m20s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 1m2s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m45s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 32m36s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 32s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 16s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m5s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 27s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 58s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 39m55s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 1m24s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 40m34s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 20s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 2m40s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m39s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 4m1s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 11m3s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 4m17s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h10m6s
4e8e4fb098
The watch-together example failed twice on the macOS runner for #616, on a loaded host (load
average about 50, then about 30). Each time the first page in the browser, Ada's, signed its
first presentation statement after its join, at 3.83 s and then 3.44 s on the room clock, and
then none in the slots from 4 s and 5 s (and 6 s the second time), while it was still entering
(begin()): it followed the log from 7.49 s, then 8.49 s, 3.7 s and 5.0 s after its first
statement, where Ben's page took 1.2 s and 1.0 s. Ada's page was silent at least 2.17 s, then
at least 3.56 s, with nothing refused, and was never taken for gone. What held it on the runner
was not measured.

What was measured:
- On the CI host, with CI jobs running (load average 30 to 39), in a browser launched as the
  example's test launches it (headless, the same flags, at nice 10), on a blank page with
  nothing else in it: the first audio context in a fresh browser held its page's thread 172 to
  192 ms (3 runs), for the constructor call alone; a second page's took 3.8 to 4.0 ms; neither
  page's thread had a gap over 60 ms in the 1.5 s after. That is a tenth or less of Ada's
  silences. Moving the context before the join takes about 0.2 s, as measured there, out of the
  stretch in which the page must state; what held Ada's page for the rest is unexplained. The
  rest of begin() (its audio worklet, its relay session, its WebAssembly, its first draws, the
  camera and microphone) was not measured there, nor an audio context made beside that work.
- On a laptop, in 25 runs of the example: the first page's audio context 94 to 128 ms, the
  second's 0.8 to 1.4 ms.
- On a laptop, on main, two injected faults each leave empty the slots just after the first
  page's first statement, as in CI: the audio-context call held 2.5 s (a busy wait in it; the
  slots from 1 s and 2 s, 1 run), and the first page's renderer process stopped 2.5 s from its
  join (SIGSTOP; the slot from 2 s, 2 of 2 runs). Neither was measured on the CI host.

This change is not shown to make the example pass on the CI host. If what held Ada's page there
was the page's own work on its thread, or the host running the page's other threads and not
that one, the check below still fails (its heartbeat ticking), and what it prints does not tell
those two apart.

1. The page makes the composition's audio context before it enters the co-watch log (app.js
   enter(), the new Compositor.openAudio()), since from that join it states in every slot
   (co-watch §7.3), so that hold is not in the stretch in which it must state. The rest of the
   entry (begin()) still runs after the join. begin() takes the compositor the entry made; in
   any other room it makes one, as before. The snapshot carries when the context was made, on
   the room clock, and how long making it held the thread (cowatch.audio_open).

2. A compositor made for an entry that failed is closed when the next entry makes its own
   (Compositor.close(): its mix timer, its worklet node, its drawing, its frames and its audio
   context). Before, it stayed, its audio context open and its mix timer running.

3. The statement loop records its stalls (cowatch.js run(), snapshot().stalls): each gap over
   half a slot between two of its passes, `{ from, to }` on the page's estimate of the room
   clock, with how long its wait and its signing took in it, on that clock (`timer_us`,
   `signing_us`); the rest of a stall is the loop's own work. It states every half slot while
   it runs, so it leaves a slot empty only inside such a stall. Its wait is a method (`wait`),
   and roomTime(ms) gives the room clock at an instant of the page's clock. The snapshot
   carries the loop's wait (`pass_ms`) and the page's clock beside the room clock (`wall_ms`).
   The co-watch rule and §7.3 are unchanged.

4. The example's slot check (co-watch §7.3: a statement in every slot while present) sets an
   empty slot apart only if the machine ran nothing of the page in the slot's second half: a
   stall of the loop spans that half; a heartbeat worker that the test starts in each page,
   ticking every 20 ms, did not tick in it either (to within a pass at each end); and the stall
   is the loop's wait and its signing but for at most one pass of its own work. Otherwise the
   check fails and says why: no stall of the loop (a statement lost); the heartbeat ticking (the
   page's thread did not run its loop while the worker ran: the page's own work holding the
   thread, or the host running the worker and not the page's thread, which the check does not
   tell apart); or more than a pass of the loop's own work (its own code, an await outside its
   measures, or the thread taken off the processor inside it). On a host that runs the page's
   threads unevenly, the check can fail in these ways with no defect in the page. Pass or fail,
   it prints each page's audio-context time, its loop's stalls and its heartbeat's silences over
   100 ms. They show whether the page's thread or the whole page was held, not what held it.

Unit tests (cowatch.test.mjs) run the loop on a room clock the test moves: no stall and every
slot held while it runs; a thread held while the loop waited, recorded once with all of the
stall its wait, and the only empty slots those it spans; a gap just over half a slot recorded
and one of half a slot not; a stall in a pass's own work recorded with a wait of one pass, the
rest neither wait nor signing.

Verified on a laptop with this change on main (152aab5c7), in a browser launched as the
example's test launches it and niced:
- From an archive build.sh made, with the WebAssembly build-web.sh made from crates this change
  does not touch, run-examples.sh browser passes video-room, watch-together, messaging,
  remote-desktop and package-and-deliver in each of 2 runs, and watch-together alone 2 more.
- With this room client served beside an earlier archive's binaries (the same Rust but for the
  relay's DVR change in the commit before), watch-together passes 3 of 3, and the faults below
  ran on that set. In each passing run the first page's audio context was made before its join
  and Ada's loop had no stall. Ben's deliberate hold, a synchronous request, shows as a stall of
  3.8 to 4.2 s with his heartbeat never silent.
- The room client's unit tests pass under node --test (77).
- Falsified, each fault put into a scratch copy of the room client, 2 runs each unless said:
  the audio context made in begin() again and that call held 2.5 s (a busy wait), the check
  fails: no statement in the slots from 1 s and 2 s (Ada) and 4 s and 5 s (Ben), each in a
  stall of the loop with its heartbeat ticking, the context printed as made after the join in
  2.5 to 2.6 s. A 2.5 s busy wait just after the join, or 4 s after it, fails it the same way:
  the slots it spans, with the heartbeat ticking. Every statement of the third whole slot after
  each join dropped fails it (no stall of its loop). One 1.5 s await in the loop's own work
  fails it (heartbeat ticking, 1.5 s neither its wait nor its signing); the same await inside
  the loop's wait fails it on the heartbeat alone. The page's renderer process stopped 2.5 s
  (SIGSTOP) at Ada's join, or 2.5 s after it, or Ben's 1 s after his (1 run): it passes, the
  slots inside the stop set apart; the heartbeat was silent and the loop stalled over the stop,
  to within 25 ms. The stop at Ada's join and a 2.5 s busy wait 4 s after it (1 run): the
  stop's slot is set apart and the busy wait's fail.
- In the unit tests, the wait measured on another clock than the stall, no stall recorded, a
  stall recorded only past a whole slot, and the wait left out of the record each fail one or
  two of the stall tests.
- A video room: one page publishes; the other presses Watch, its first relay connection is
  refused (a fault the probe injects), and it presses Watch again. Then that page holds one
  audio context open (the first closed) and one mix timer, and mixes 50 blocks of 20 ms a
  second. On main it holds two open and two timers; with close() doing nothing, two open. The
  same in a watch room: one open with this change, two on main.
- Not shown: that the example passes on the CI host.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-quantum-contract.yml: the baselines are the versions just published
All checks were successful
wai-quantum contract / does this change touch it (pull_request) Successful in 21s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 25s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
wai-quantum contract / the policy is linked, and the deprecations page reads (pull_request) Successful in 8s
wai-quantum contract / API compatibility · linux (pull_request) Successful in 3m56s
wai-quantum contract / schemas and the committed tool lists · linux (pull_request) Successful in 6m39s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m53s
8f1f1c3c6e
wai-quantum 0.8.1, wai-quantum-cli 0.2.4 and wai-quantum-qpu 0.4.1 are on
crates.io, so the API is checked against them from here on.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge pull request 'wai-quantum-contract.yml: the baselines are 0.8.1, 0.2.4 and 0.4.1, the versions just published' (#621) from wai/quantum-contract-baselines-0.8.1 into main
Some checks failed
wai-quantum contract / does this change touch it (push) Successful in 7s
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Successful in 5s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
wai-quantum contract / schemas and the committed tool lists · linux (push) Has been cancelled
wai-quantum contract / API compatibility · linux (push) Has been cancelled
7f5b19b079
Merge pull request 'Wave A: public-name check, WebAssembly determinism in CI, decode-path reporting, and pin by default' (#616) from wai/wave-a into main
All checks were successful
wai-quantum for Python / python · linux (push) Successful in 2m42s
wai-quantum extension points / the registry and the example · linux (push) Successful in 2m20s
wai-quantum other formats / readers, writers and the set · linux (push) Successful in 3m40s
wai-quantum contract / API compatibility · linux (push) Successful in 4m15s
wai-quantum other formats / the set under wasm32-wasip2 (wasmtime) (push) Successful in 3m38s
wai-vector vector graphics / macos-arm64 (push) Successful in 2m3s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 9m6s
wai-quantum error correction and mitigation / codes, decoders, texts and mitigation · linux, release (push) Successful in 2m37s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (push) Successful in 1m28s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 4m56s
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (push) Successful in 1m51s
wai-quantum contract / schemas and the committed tool lists · linux (push) Successful in 6m17s
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (push) Successful in 2m19s
wai-quantum studio and desktop / studio · browser (push) Successful in 3m39s
wai-quantum service / service · linux (push) Successful in 5m1s
wai-vector vector graphics / wasm32-wasip2 (wasmtime) (push) Successful in 59s
wai-vector vector graphics / wasm32 under Node (push) Successful in 52s
wai-vector vector graphics / fuzz, peak allocation, comparison count (push) Successful in 20s
wai-vector vector graphics / linux-x86_64 (push) Successful in 2m17s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m0s
wai-quantum views in agent hosts / views · the page and its engine (push) Successful in 3m6s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 4m52s
wai-quantum views in agent hosts / views · a scripted host (push) Successful in 3m22s
wai-vector vector graphics / independent checker (Python) (push) Successful in 3m10s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Successful in 16m37s
wai-vector vector graphics / wasm32 in three browser engines (push) Successful in 5m45s
WAI Studio / Studio in Chromium and Firefox · macos (push) Successful in 10m21s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Successful in 17m42s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Successful in 16m3s
WAI Studio / Studio in WebKit · linux (push) Successful in 23m28s
f1258784d4
wai-quantum-cli docs: llms.txt names the site's parts as the site does, and lists WAI Quantum's home
All checks were successful
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 12s
wai-quantum docs, course and locales / does this change touch it (pull_request) Successful in 14s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 8s
wai-quantum contract / the policy is linked, and the deprecations page reads (pull_request) Successful in 8s
wai-quantum views in agent hosts / does this change touch it (pull_request) Successful in 13s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Successful in 35s
wai-quantum editors / editors · macos (pull_request) Successful in 1m31s
wai-quantum service / service energy · linux packages (pull_request) Successful in 1m38s
wai-quantum for Python / python · macos (pull_request) Successful in 1m59s
wai-quantum command line / command line · macos (pull_request) Successful in 2m5s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m29s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (pull_request) Successful in 19s
wai-quantum editors / editors · linux (pull_request) Successful in 2m51s
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Successful in 2m13s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 3m14s
wai-quantum for Python / python · linux (pull_request) Successful in 3m31s
wai-quantum service / service · macos (pull_request) Successful in 3m52s
wai-quantum contract / API compatibility · linux (pull_request) Successful in 4m56s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 3m3s
wai-quantum service / service · linux (pull_request) Successful in 5m40s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m17s
wai-quantum contract / schemas and the committed tool lists · linux (pull_request) Successful in 6m39s
wai-quantum views in agent hosts / views · the page and its engine (pull_request) Successful in 3m51s
wai-quantum views in agent hosts / views · a scripted host (pull_request) Successful in 3m39s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m7s
wai-quantum command line / command line · linux (pull_request) Successful in 8m54s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 9m41s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 8m33s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m35s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 16m15s
1bc4164367
The site gave each part of WAI Quantum one name (wai-transaction-science-web cf63cd3), but
the generated agent docs still called them by their old names: "the console", "the quantum
IDE", and "the circuits course" for a course whose title is "Quantum circuits, checked". They
also did not list /quantum/, now the front door.

guide.rs's Pages section now lists WAI Quantum's home first, then Quantum Studio, the job
console and the circuit builder. It says "the job service" where it meant the service, and
names the course by its title, as does the Start here line for `wai-quantum learn`.
docs/llms.txt and docs/llms-full.txt are generated again from it, and the guide's tests (the
committed docs are what the binary generates) pass.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge pull request 'wai-quantum-cli docs: llms.txt names the site's parts as the site does, and lists WAI Quantum's home' (#623) from wai/quantum-llms-names into main
All checks were successful
wai-quantum command line / does this change touch it (push) Successful in 11s
wai-quantum docs, course and locales / does this change touch it (push) Successful in 5s
wai-quantum for Python / does this change touch it (push) Successful in 5s
wai-quantum contract / does this change touch it (push) Successful in 15s
wai-quantum editors / does this change touch it (push) Successful in 11s
wai-quantum service / does this change touch it (push) Successful in 6s
wai-quantum studio and desktop / does this change touch it (push) Successful in 13s
wai-quantum views in agent hosts / does this change touch it (push) Successful in 11s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Successful in 11s
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Successful in 4s
wai-quantum command line / command line · linux (push) Successful in 3m3s
wai-quantum editors / editors · linux (push) Successful in 2m17s
wai-quantum for Python / python · linux (push) Successful in 2m52s
wai-quantum contract / API compatibility · linux (push) Successful in 4m31s
wai-quantum studio and desktop / studio · browser (push) Successful in 4m6s
wai-quantum command line / command line · macos (push) Successful in 2m1s
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Successful in 5m46s
wai-quantum service / service · linux (push) Successful in 4m47s
wai-quantum views in agent hosts / views · the page and its engine (push) Successful in 2m54s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 4m27s
wai-quantum views in agent hosts / views · a scripted host (push) Successful in 3m18s
wai-quantum editors / editors · macos (push) Successful in 1m28s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 5m18s
wai-quantum for Python / python · macos (push) Successful in 2m38s
wai-quantum service / service energy · linux packages (push) Successful in 1m13s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 9m50s
wai-quantum service / service · macos (push) Successful in 3m47s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 4m29s
wai-quantum contract / schemas and the committed tool lists · linux (push) Successful in 12m14s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Successful in 42m0s
0b0bd799c5
Merge pull request 'mesh/1: bind what taught the weights, not only which weights answered' (#612) from mesh/decision-training-provenance into main
All checks were successful
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 2m45s
b89ff395da
Three things in this file were false rather than merely stale, which is worse
in the one document whose job is to say what the ecosystem is.

**The pin.** It said "Rust 1.95.0". The root `rust-toolchain.toml` says 1.99.1
after the bump that just landed, so the file was two bumps behind.

**The MSRV policy.** It said "Per-workspace MSRV is declared in each
`Cargo.toml` (`rust-version = \"1.95\"`). CI enforces both." No first-party
crate declares `rust-version` at all. The only two mentions in the tree are
`wai/wai-verify/Cargo.toml`, carrying a note that it deliberately has none
because that verifier ships its own pinned nightly, and a vendored
`wtransport` manifest declaring 1.88, which is third-party code stating its
own floor. The section now records the policy that is actually in force: one
pin at the root, no MSRV floor, because a per-crate floor is a second and
quieter version statement that drifts from the pin.

**The tracker.** Twelve links pointed at `github.com` issues. The three
"Tracked in issues labelled X" links now point at the forge, whose issue list
answers 200 anonymously. The nine per-item numbers were **dropped rather than
translated**: Forgejo numbers issues and pull requests from one counter, so a
pre-migration `#7` is not necessarily today's `#7`, and neither credential
available here can read issues to confirm a mapping — both 403. A wrong link
is worse than none, and asserting a mapping I cannot check is how this file
got into this state.

It also claimed to record "the scope of each protocol", having done so for 3
of 22. Rather than write 19 scope paragraphs by paraphrasing READMEs — a
second copy that would drift exactly as these facts did — the file now
**indexes** the 22 standards and links each to its own README and SPEC, which
are the source of truth. The four sections that carry real Included / Adding
content keep it and are marked in the index. Every one of the 44 relative
links was checked to resolve, and every README and SPEC path asserted to exist
before being written.

Guards clean: comparative prose (4104 files), vanity metrics (523 Markdown
files), spec refs (1966 citations across 17 standards), orphan sources.

Stacked on mesh/decision-training-provenance (#612), which adds the `mesh/`
section this index marks as detailed.

Co-Authored-By: Claude Opus 5 <[email protected]>
The links had nothing on the other side, and wai-verify pins no toolchain
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 22s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m34s
2e0c56fe6b
Two corrections to the reconciliation, both from checking rather than
reasoning.

**The Adding lists were not tracked anywhere.** I had repointed the three
"Tracked in issues labelled X" links at the forge's issue list and dropped the
nine per-item numbers for want of a verifiable mapping. The real reason is
simpler and worth stating: the forge repository has its issue tracker enabled
and **empty** — `open_issues_count` is 0 — because the migration carried code
and pull requests, not issues. There was never a `#7` to point at. So the three
lines now say what is true, which is that these lists are themselves the
record, and the closing note carries the evidence and the consequence: filing
them as forge issues would be the better state, and `/issues` is 403 for both
credentials available here, so it is not something this change can do.

**`wai-verify` pins no toolchain.** The note I wrote repeated the crate's own
comment, that it "ships its own pinned nightly". It does not: there is no
`rust-toolchain.toml` in that crate. The nightly belongs to the model checker,
which brings its own toolchain for the proof harnesses; the crate only declines
to state an MSRV that would outrank it. The distinction matters for the policy
one line above it — **nothing in this repository pins a second version**, and
the corrected text says so.

Confirmed while here: both pins on `main` are 1.99.1 after #606, and 1.99.1 is
what `channel-rust-stable.toml` currently publishes, so the repository is on
latest stable with one pin and no floor.

Guards clean. 43 relative links, 0 broken. The one remaining `github.com` is
inside the prose explaining the removal.

Co-Authored-By: Claude Opus 5 <[email protected]>
Merge pull request 'INGEST.md: correct the pin and the MSRV policy, and fix the links (replaces #617)' (#628) from mesh/ingest-reconcile-2 into main
All checks were successful
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 1m22s
a223c597da
mesh-meter: a span shorter than its counter's minimum window is an estimate
All checks were successful
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 6s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 14s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 49s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 54s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m13s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 1m49s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 2m56s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m30s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Successful in 3m24s
energy meters on real hardware / sink decode table · per-task energy and the GPU rail on macOS (pull_request) Successful in 2m16s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 2m46s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 1m42s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 7m42s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 3m52s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 6m56s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 11m48s
energy meters on real hardware / RAPL and NVML on jetson-hub (pull_request) Successful in 35s
energy meters on real hardware / sink decode table · RAPL on jetson-hub (NVML surveyed) (pull_request) Successful in 2m23s
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Successful in 24m54s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 17m32s
4a7ca45718
A counter declares the smallest window over which its readings are not noise
(min_window_ns: about 10 ms for RAPL and IOReport, 100 ms for NVML; 2 s for a
Mac's SMC power integral). Across a shorter span its delta is whatever its
updates and quantization gave, often zero or a whole update period, yet mesh
graded it at the counter's grade: a few-millisecond request could be sealed
HwShunt at 0 µJ, or ModelBased at a power reading's extrapolation.

- SPEC 3.3: a span shorter than the minimum window of the counter that would
  grade it MUST NOT be graded HwShunt or ModelBased from that counter; it is
  an estimate of the request, and SHOULD be billed by an estimator that
  resolves the span's own length, so a short request is never billed zero.
- HwMeter opens its own window (Meter::open_span), which Session uses: it
  times the span, and one shorter than the backend's floor
  (HwMeter::min_window) is billed this crate's EstimatorMeter over the span's
  own length, graded Estimator with no measured_uj, as a span across a failed
  read is. Past the floor the counter's figure stands, graded as before.
  min_window is zero where the bridge already bills by its estimator.
- ProcessMeter: where ProcessSpanMeter falls back to the host meter, a span
  shorter than the host meter's floor is billed the same way. Spans its own
  CPU and GPU counters metered are not the host meter's and are unaffected.
- jouleclaw-energy: ProcessSpanMeter::fallback_min_window, the active fallback
  meter's min_window_ns, so a caller can apply the rule. Additive.

Each span is timed from after its opening read to before its closing one, a
little shorter than the counter's own window, so a span at the floor is judged
short rather than long.

Tests: under a 50 ms floor a 20 ms span is Estimator at the estimator's figure
for 20 ms, and a 60 ms span keeps the counter's figure and grade (HwShunt and
ModelBased); the bridge's minimum window is its counter's until a failed read,
then zero; a host-meter fallback span under the host floor is an estimate,
past it the host figure stands, and a span this process's own counters
metered keeps its grade. Linux x86_64: mesh-meter (default, hw-meter-rapl),
mesh-core (hw-meter-rapl) and mesh-conformance pass; clippy clean. macOS
(M3 Ultra): mesh-meter and mesh-core with hw-meter-apple pass, including a
real in-process serve sealed HwShunt; clippy clean for mesh-meter and
jouleclaw-energy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
mesh-meter: hw-meter-apple meters a Mac with the SMC's whole-machine power where IOReport is not live
All checks were successful
wai-vector vector graphics / independent checker (Python) (pull_request) Successful in 3m2s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 3m0s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 34m32s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m9s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 22m13s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 16m25s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 11m1s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 13m37s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 33m15s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 26m0s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m51s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m53s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 16m21s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m53s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 28s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 40m8s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 17s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 1m47s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 1m21s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 35s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m2s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 2m1s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 2m21s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 25s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 17m5s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 7m45s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 1m33s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 2m23s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h8m16s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 3m39s
e7403fde3b
hw-meter-apple now enables jouleclaw-energy's `smc` beside `ioreport`. On a Mac
whose IOReport CPU rail is frozen for an unprivileged reader (macOS 27 on an
M5 Max and an M3 Ultra), HwMeter::detect's backend becomes the SMC's
whole-machine power integral (ModelBased, EnergyDomain::System) instead of the
load estimator. A live IOReport counter still comes first.

The minimum-window rule (#630) is what makes this sound: the SMC's figure needs
2 s, so a span at least that long is sealed ModelBased, and a shorter one (most
served requests) is this crate's estimate of its own length, as before. System
covers the whole request (#622), so a long span's figure stands for it: high,
since it holds whatever else the machine powered, never low.

mesh-core, mesh-openai and mesh-engine-gguf take it through their own
hw-meter-apple and metal features. ProcessMeter's host fallback becomes the SMC
on such a Mac, under the same window rule.

On the M3 Ultra: the bridge picks apple-smc with a 2 s floor; a 20 ms span is
Estimator (0.38 J) and a 2.2 s span ModelBased (152.6 J for the whole, shared
machine); mesh-openai's serve example over hw-meter-apple seals a microsecond
serve as Estimator (172 µJ), and over metal its process meter still seals
HwShunt. Tests pass on macOS (mesh-meter, mesh-core with hw-meter-apple;
mesh-openai with server,hw-meter-apple and server,metal) and Linux (mesh-meter
with hw-meter-apple); clippy clean; mesh-engine-gguf --features metal checks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot changed target branch from jouleclaw-energy/smc-system to main 2026-11-05 04:31:48 -05:00
Merge main into mesh-meter/smc (#622 and #630 have landed)
All checks were successful
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been skipped
wai-quantum studio and desktop / desktop app · linux (pull_request) Has been skipped
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Has been skipped
wai-quantum studio and desktop / desktop app · windows (pull_request) Has been skipped
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been skipped
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been skipped
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 6s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Has been skipped
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Has been skipped
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been skipped
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been skipped
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Has been skipped
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Has been skipped
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 15s
wai-quantum for JavaScript / javascript · linux (pull_request) Has been skipped
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 7s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Has been skipped
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been skipped
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been skipped
WAI Studio / does this change touch it (pull_request) Successful in 8s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Has been skipped
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Has been skipped
WAI Studio / Studio in WebKit · linux (pull_request) Has been skipped
wai-web wasm32 / does this change touch it (pull_request) Successful in 15s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been skipped
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 32s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m34s
energy meters on real hardware / sink decode table · per-task energy and the GPU rail on macOS (pull_request) Successful in 2m56s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 1m3s
8e3e5be695
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!631
No description provided.