jouleclaw: every compute fabric builds on hardware that has the device, and metal's kernels run #329

Merged
dcharlot merged 27 commits from feat/metal-ratchet into main 2026-10-20 16:25:58 -04:00
Owner

The metal feature of jouleclaw-omni did not compile. It had 3063 errors, because no job had ever built it: 40 architecture files carried #[cfg(feature = "metal")] blocks that had never once been through a compiler. An unbuilt feature does not stay still, it drifts.

It now compiles with 0 errors, and twelve of its kernels are executed and checked against CPU references on a real GPU.

How the 3063 came down

errors what they were
start 3063 never built
imports 286 2780 imports the files never made
model refs 111 Result<T> resolving to core::result::Result<T, E> for want of the crate's one-parameter alias
RwLock 65 see below
kernels 45 three shader sources that were never written
PHASE27_OPS 0 21 kernels and 13 helpers referenced by name and never implemented

Three real bugs, invisible until the code compiled

  • mamba2's quantized decode read its dimensions transposed. Both decode dispatches set K into buffer(3) and N into buffer(4), but matmul_q4k_f16 — and every other kernel in shader.rs — declares N at buffer(3).
  • The model RwLock made four legal signatures impossible. Fifteen pipelines held weights as Arc<parking_lot::RwLock<Model>>. No .write() is ever taken on a model field anywhere in the crate, and Model's mutating-looking methods take &self and only madvise already-mapped pages, so the lock guarded nothing — while fn w(&self) -> Result<&LazyTensor> cannot borrow out of a temporary guard (E0515 in canary, fibo, mochi, sd3). The other 28 pipelines already used Arc<Model>, and florence2.rs documents the same conclusion in a comment. Removing it dropped 214 .read() calls.
  • hal/mod.rs gated use crate::core::Error on cuda/rocm, but discover_metal() uses it too.

Also: mochi called a self.mul that does not exist; moonshine applied ? to batched_sv, which returns a Tensor and whose other 13 callers omit it; mamba2 was written against a QuantType enum and dequantize_*_public functions that do not exist, where the crate has GgmlType and a dequantize_to_f16 dispatcher that handles every block format rather than the two mamba2 enumerated.

Three checks, because each catches what the last cannot

  1. check-fabric-errors.py — per-fabric error count, pinned, may fall but never rise. Its non-zero-exit gate had to be narrowed to a zero tally: it was firing on every healthy run of a fabric still in debt, because cargo exits 101 for those very errors. It still catches what it was written for — a cudarc build script that panics with 0 compiler messages.
  2. check-metal-shaders.py — compile_pipeline builds every shader at runtime, so an MSL error is invisible to cargo and surfaces only on dispatch. xcrun metal is the same frontend the runtime uses. It earned itself immediately: flash_attention_f16 declared uint2 threadgroup_position_in_grid beside uint thread_position_in_threadgroup, and MSL requires every position attribute to have the same component count. No type checker or reviewer would have caught that.
  3. tests/metal_kernels.rs — compiling a kernel says nothing about what it computes. Twelve are dispatched and checked: nine against CPU references, two against their own inverse, and flash_attention against a full softmax over all keys. Sizes are awkward on purpose (257 elements for a 1-D dispatch, kv_seq 37 against a 32-wide tile, q_seq 40 across two query blocks) because the bugs live in the remainder, not the body. The suite fails rather than skips when no device is present.

Verified by corruption rather than by a green run: tightening flash_attention's tolerance to 1e-9 and adding 1.0 to kv_head_expand's reference fails exactly those two and nothing else. The flash-attention diagnostic is worth recording — got -0.25927734 against -0.25930187, so the tiled online-softmax kernel agrees with full attention to 2.5e-5, which is f16 rounding.

The other fabrics

Every fabric now gets a job on hardware that has the device. x86_64 Linux went from not compiling at all — one unstable-macro AMX probe in capabilities.rs had made the crate unbuildable there in every configuration — to compiling. cuda 0 on an RTX 4050 with CUDA 12.8; vulkan 0 against a real Vulkan 1.4 loader; rocm now discovers the Radeon 8060S through runtime-loaded HIP with verified struct offsets and a plausibility gate that refuses rather than reporting garbage.

rocm has no error-count job on purpose: rocm = [] declared a feature with no dependencies and no code, so it compiled perfectly while providing nothing, and a green check would have reported health it did not have.

State

  • --features metal: 0 errors, 0 clippy errors across the ~19k lines this makes reachable
  • 44/44 shader sources compile; 12/12 kernel tests pass on a GPU
  • default build unchanged: 44 tests pass
  • cuda cannot be checked on macOS by design (cudarc needs the toolkit) and runs on the linux host

Known gaps, stated rather than papered over

  • mimo's sliding window is enforced only on decode. Prefill calls prefill_attention, which takes no window argument and applies a full causal mask, so SWA layers see the whole prefix. The comments claimed the kernel handled it; they now say what actually happens. Windowed prefill masking is not implemented.
  • vae_channel_reduce, vae_final_conv_sigmoid and the Mochi middle block carry no weights at their dispatch sites, so they average channel groups. That matches the call sites, not the reference model.
  • Nine of the 21 kernels have no numeric test yet: the six VAE stages, im2col_patch_embed, dequantize_rvq and dilated_conv1d (which nothing dispatches).

🤖 Generated with Claude Code

The `metal` feature of `jouleclaw-omni` did not compile. It had **3063 errors**, because no job had ever built it: 40 architecture files carried `#[cfg(feature = "metal")]` blocks that had never once been through a compiler. An unbuilt feature does not stay still, it drifts. It now compiles with **0 errors**, and twelve of its kernels are executed and checked against CPU references on a real GPU. ## How the 3063 came down | | errors | what they were | |---|---|---| | start | 3063 | never built | | imports | 286 | 2780 imports the files never made | | model refs | 111 | `Result<T>` resolving to `core::result::Result<T, E>` for want of the crate's one-parameter alias | | RwLock | 65 | see below | | kernels | 45 | three shader sources that were never written | | PHASE27_OPS | **0** | 21 kernels and 13 helpers referenced by name and never implemented | ## Three real bugs, invisible until the code compiled - **`mamba2`'s quantized decode read its dimensions transposed.** Both decode dispatches set `K` into `buffer(3)` and `N` into `buffer(4)`, but `matmul_q4k_f16` — and every other kernel in `shader.rs` — declares `N` at `buffer(3)`. - **The model `RwLock` made four legal signatures impossible.** Fifteen pipelines held weights as `Arc<parking_lot::RwLock<Model>>`. No `.write()` is ever taken on a model field anywhere in the crate, and `Model`'s mutating-looking methods take `&self` and only `madvise` already-mapped pages, so the lock guarded nothing — while `fn w(&self) -> Result<&LazyTensor>` cannot borrow out of a temporary guard (E0515 in canary, fibo, mochi, sd3). The other 28 pipelines already used `Arc<Model>`, and `florence2.rs` documents the same conclusion in a comment. Removing it dropped 214 `.read()` calls. - **`hal/mod.rs` gated `use crate::core::Error` on cuda/rocm**, but `discover_metal()` uses it too. Also: `mochi` called a `self.mul` that does not exist; `moonshine` applied `?` to `batched_sv`, which returns a `Tensor` and whose other 13 callers omit it; `mamba2` was written against a `QuantType` enum and `dequantize_*_public` functions that do not exist, where the crate has `GgmlType` and a `dequantize_to_f16` dispatcher that handles every block format rather than the two mamba2 enumerated. ## Three checks, because each catches what the last cannot 1. **`check-fabric-errors.py`** — per-fabric error count, pinned, may fall but never rise. Its non-zero-exit gate had to be narrowed to a *zero* tally: it was firing on every healthy run of a fabric still in debt, because cargo exits 101 for those very errors. It still catches what it was written for — a `cudarc` build script that panics with 0 compiler messages. 2. **`check-metal-shaders.py`** — `compile_pipeline` builds every shader at **runtime**, so an MSL error is invisible to cargo and surfaces only on dispatch. `xcrun metal` is the same frontend the runtime uses. It earned itself immediately: `flash_attention_f16` declared `uint2 threadgroup_position_in_grid` beside `uint thread_position_in_threadgroup`, and MSL requires every position attribute to have the same component count. No type checker or reviewer would have caught that. 3. **`tests/metal_kernels.rs`** — compiling a kernel says nothing about what it computes. Twelve are dispatched and checked: nine against CPU references, two against their own inverse, and `flash_attention` against a full softmax over all keys. Sizes are awkward on purpose (257 elements for a 1-D dispatch, `kv_seq` 37 against a 32-wide tile, `q_seq` 40 across two query blocks) because the bugs live in the remainder, not the body. **The suite fails rather than skips when no device is present.** Verified by corruption rather than by a green run: tightening `flash_attention`'s tolerance to 1e-9 and adding 1.0 to `kv_head_expand`'s reference fails exactly those two and nothing else. The flash-attention diagnostic is worth recording — `got -0.25927734` against `-0.25930187`, so the tiled online-softmax kernel agrees with full attention to 2.5e-5, which is f16 rounding. ## The other fabrics Every fabric now gets a job on hardware that has the device. **x86_64 Linux went from not compiling at all** — one unstable-macro AMX probe in `capabilities.rs` had made the crate unbuildable there in every configuration — to compiling. `cuda` 0 on an RTX 4050 with CUDA 12.8; `vulkan` 0 against a real Vulkan 1.4 loader; **`rocm` now discovers the Radeon 8060S** through runtime-loaded HIP with verified struct offsets and a plausibility gate that refuses rather than reporting garbage. `rocm` has no error-count job on purpose: `rocm = []` declared a feature with no dependencies and no code, so it compiled perfectly while providing nothing, and a green check would have reported health it did not have. ## State - `--features metal`: 0 errors, 0 clippy errors across the ~19k lines this makes reachable - 44/44 shader sources compile; 12/12 kernel tests pass on a GPU - default build unchanged: 44 tests pass - `cuda` cannot be checked on macOS by design (cudarc needs the toolkit) and runs on the linux host ## Known gaps, stated rather than papered over - `mimo`'s sliding window is enforced only on decode. Prefill calls `prefill_attention`, which takes no window argument and applies a full causal mask, so SWA layers see the whole prefix. The comments claimed the kernel handled it; they now say what actually happens. Windowed prefill masking is not implemented. - `vae_channel_reduce`, `vae_final_conv_sigmoid` and the `Mochi` middle block carry no weights at their dispatch sites, so they average channel groups. That matches the call sites, not the reference model. - Nine of the 21 kernels have no numeric test yet: the six VAE stages, `im2col_patch_embed`, `dequantize_rvq` and `dilated_conv1d` (which nothing dispatches). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jouleclaw: the metal feature's error count may fall, never rise
Some checks failed
jouleclaw metal ratchet / the metal feature's error count may fall, never rise (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
40c4732d0f
`jouleclaw-omni`'s `metal` feature does not compile: 3063 errors on main. No
job ever built it, which is how it got there -- 40 architecture files carry
`#[cfg(feature = "metal")]` blocks that have never once been compiled.

The cause is narrow for its size. 19 distinct messages account for all 3063,
and 2491 of them are 13 missing names: `Tensor` (1288 uses, 19 files), `DType`
(441), `Shape` (367), `Arc` (335). t5.rs imports the metal `hal` types and
never imports any of those, then uses them throughout its metal blocks. The
remaining ~570 are real drift -- 316 of them `DType` having taken a second
generic argument its callers do not pass.

This does not fix that, deliberately. There is no test, no tests directory and
no CI job that touches a Metal GPU in this crate, so code made to compile here
would be unverified by construction -- a feature that looks working is worse
than one that plainly does not. Fixing it means deciding first whether Metal
acceleration is wanted, then building the feature in CI so it cannot drift
again, then the imports, then the drift, then tests that exercise a GPU.

What it does instead is stop the rot: the count is pinned, and may fall but
never rise. Whoever fixes a batch lowers BASELINE and keeps the gain; whoever
edits these files cannot quietly deepen the hole. It is the same ratchet
`check-orphan-sources.py` uses, which is how that baseline could go 25 -> 1
rather than drifting to 26.

Not a red job on purpose: a check that is always red teaches everyone to ignore
red, which is the pathology that let this feature rot in the first place. It is
green today.

Nightly and path-filtered rather than per-PR -- the fleet's queue is the scarce
resource, and a number that moves only when someone edits these files does not
need checking on every push.

The script refuses a run that emitted no JSON rather than reporting zero
errors: cargo exits 0 when a target is skipped, and a check that produced
nothing is indistinguishable from one that passed.

Verified on the macOS build host: reports 3063 and exits 0 at BASELINE 3063;
exits 1 with an error at 3062, so it detects a rise rather than always passing;
and at 3064 it passes while advising the baseline be lowered.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: the metal feature's missing imports, 3063 errors down to 286
All checks were successful
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 58s
jouleclaw metal ratchet / the metal feature's error count may fall, never rise (pull_request) Successful in 22s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 35s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 6m51s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m28s
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 1m8s
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 2m51s
db592799b7
The metal blocks in these files use `Tensor`, `Shape`, `DType`, `Result`, `Arc`
and a few others that the files never import. Nothing noticed because no job
built the feature, so the blocks had never once been compiled.

92% of the 3063 errors were that, and nothing more:

  2491  `cannot find type X` -- 13 names, `Tensor` alone 1288 times in 19 files
   316  `enum takes 2 generic arguments but 1 was supplied`, every one of them
         `Result<T>` resolving to `core::result::Result<T, E>` because the
         crate's one-parameter alias was not imported either

24 files now import what they use, each `#[cfg(feature = "metal")]` to match
the code that needs them, so the default build gains nothing: 0 errors and the
same 29 warnings as before, with 44 tests still passing. The import paths come
from a working sibling, `unet.rs`, not from guesswork -- `crate::tensor`
re-exports `DType` and `Shape` from `core`, so one line covers three names.

Errors under `--features metal`: 3063 -> 286, and the ratchet's baseline moves
with it. What is left is real, and now visible rather than buried:

   175  E0308 mismatched types -- genuine drift in the API underneath
    53  E0425 cannot find value, of which 27 are shader kernels that were never
         written: 8 files call `sources::PHASE27_OPS`, 3 call `sources::MATVEC`
         and `sources::MATMUL_Q8_0`, and shader.rs defines neither. No import
         can fix an absent kernel.
    27  E0716 temporary dropped while borrowed
    11  E0599 no such method
    14  E0658 unstable, E0061 arg counts, E0515 lifetimes, E0603 privacy

None of that is mechanical, and none of it is verifiable here: this crate still
has no test and no CI job that touches a Metal GPU. Compiling is not working,
and the next step is a job that builds this feature on hardware that has the
device, so a fix can be checked rather than hoped at.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw: build every compute fabric, on hardware that has the device
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 16s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Failing after 16s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 42s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 4m5s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m0s
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 1m24s
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 3m33s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 45s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m31s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m47s
b243c37bf3
`metal` reached 3063 errors because no job built it. The fix for that is not a
one-off: it is a job per fabric, so none of them can drift unobserved again.

  metal   -> macos runner, Apple GPU. Baseline 286.
  cuda    -> linux-hw, which has an RTX 4050, driver 595.84 and CUDA 12 at
             /usr/local/cuda. Baseline 0.
  vulkan  -> linux-hw, which has a Vulkan 1.4.318 loader. Baseline 0.

cuda and vulkan report zero errors today, but every build of them so far has
been on macOS, where neither device exists: that is type-checking, not
evidence. `cudarc` wants the CUDA toolkit and `ash` wants the system loader,
so these jobs are the first real build of either, and they may well fail. That
is the point of running them.

A baseline above zero is a debt, not a pass. Zero means the fabric compiles,
which is still not that it works -- none of these runs a kernel yet, and that
is the next rung.

`rocm` deliberately has no job. `rocm = []` in Cargo.toml declares a feature
with no dependencies and no code, so it compiles perfectly while providing
nothing. A green check would report health it does not have, and an error count
structurally cannot see an empty feature. If AMD compute is in scope, that stub
is the gap, and the gfx1151 box is not a registered runner.

The linux job fetches the source by hand rather than with actions/checkout:
that host has no Node. It fetches the commit, not the ref, and refuses if what
arrived is not what was asked for.

Verified on the build host: metal reports 286 at baseline 286 and exits 0; cuda
and vulkan report 0; with metal's baseline set one lower the guard exits 1, so
it detects a rise rather than always passing; and an unknown feature name is
rejected instead of silently succeeding.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: compile on x86_64 at all, and make the fabric guard honest
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
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) Has been cancelled
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
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) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
bfb97c9e02
Two things the new per-fabric jobs found on their first run, both invisible
until something built this crate on a machine that was not a Mac.

1. It did not compile on x86_64 Linux in ANY configuration -- not with
   `--features vulkan`, not with cuda, not with default features.
   `hal/capabilities.rs` detects Intel AMX with
   `is_x86_feature_detected!("amx-tile")`, which needs the unstable
   `x86_amx_intrinsics` feature (rust-lang#126622). No stable toolchain can
   build that line, and it sits in a `#[cfg(target_arch = "x86_64")]` block, so
   an aarch64 Mac never saw it and every build so far had been on a Mac.

   CPUID answers the same question on stable: AMX-TILE is
   CPUID.(EAX=07H, ECX=0):EDX[24], read only once leaf 0 says leaf 7 exists.

2. The guard I added in this branch reported `cuda` green on that host while
   cuda did not build. `cudarc`'s build script panics unless a cuda-version
   feature is chosen, and a panicking build script is not a
   `compiler-message`: the error tally was 0, under the baseline, and the job
   passed. A clean tally is not a build.

   It now fails when cargo exits non-zero even though the tally is within
   baseline, and prints cargo's stderr, so a build script, a missing system
   library or an unchosen dependency feature cannot hide behind a count. It
   also prints the first five error messages: a number alone is not actionable
   from a CI log, as finding the AMX error required going to the host by hand.

That is the sixth variant this week of a check that exits 0 having done
nothing, and the first one I wrote myself. Counting what failed is not the same
as confirming the work happened.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: the CPUID helpers live in std::arch::x86_64
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 11s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Failing after 27s
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
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) Has been cancelled
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) Has been cancelled
81ce9fd760
`std::arch::__cpuid` does not exist; the x86 intrinsics are in the
`std::arch::x86_64` submodule. The block is already
`#[cfg(target_arch = "x86_64")]`, so naming it is safe.

Caught by the job this branch adds, on the host that has the architecture --
which is the second time in one day it has found something a Mac could not see.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: choose a CUDA version so cudarc can build at all
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 12s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Failing after 32s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m0s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m6s
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 1m26s
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) Failing after 2m22s
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
64b6bf1023
`cuda = ["dep:cudarc"]` never built anywhere: cudarc's build script panics
unless one of its cuda-version features is selected, and none was. The guard in
this branch reported it green because a panicking build script emits no
compiler error -- fixed in the previous commit, which is how this surfaced.

`cuda-version-from-build-system` asks nvcc rather than pinning a version here.
This fleet's NVIDIA host has 12.8; pinning `cuda-12080` would build here and
break on the next host. The job adds /usr/local/cuda/bin to PATH because nvcc
is not on it by default, which is also what any consumer building with
`--features cuda` will need.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: port cuda discovery to cudarc 0.16
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 8s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Failing after 26s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 50s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 58s
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 1m11s
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 3m18s
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 16s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 19s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 9m37s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 3m20s
01004fd7eb
cudarc 0.16 replaced `CudaDevice` with `CudaContext` and moved the per-device
queries behind one `attribute()` call. `compute_capability`, `num_sms`,
`shared_memory_per_block` and `memory_info` no longer exist. This code was
written against the old shape and had never been compiled, because nothing
built the `cuda` feature -- the first real build of it, yesterday, got five
errors in before stopping, and the rest only appeared once those were cleared.

  CudaDevice::new(i)          -> CudaContext::new(i as usize)
  device.compute_capability() -> attribute(COMPUTE_CAPABILITY_MAJOR / _MINOR)
  device.num_sms()            -> attribute(MULTIPROCESSOR_COUNT)
  device.shared_memory_...()  -> attribute(MAX_SHARED_MEMORY_PER_BLOCK)
  device.memory_info()        -> result::mem_get_info()

That last one matters beyond the rename: `cuMemGetInfo` reports (free, total),
and the old call site bound (total, free). Taking the order from cudarc's own
doc comment rather than assuming it avoided reporting free memory as the
card's capacity -- which would have compiled, run, and been wrong.

`Error` was never imported in this module either; it is now, gated to the
features whose discovery functions use it.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: discover AMD GPUs through HIP, with real capabilities
Some checks failed
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
7f3daec8d1
`discover_rocm` was `// TODO` returning nothing, behind `rocm = []` -- a
feature with no dependency and no code, which compiled perfectly while
providing nothing. The hardware is here (framework-128gb-0000: Radeon 8060S,
gfx1151) so the backend can be real.

HIP is opened at runtime with libloading rather than linked, which is the shape
jouleclaw-loader-gguf already uses for CUDA and libnuma: nothing is needed at
build time, so `--features rocm` compiles on a Mac or an NVIDIA host and finds
no AMD devices there. Linking it would make the feature unbuildable wherever
ROCm is absent, which is exactly how `cuda` came to demand a toolkit on every
builder.

Capabilities are read, not guessed. `hipGetDevicePropertiesR0600` gives
warpSize, multiProcessorCount, sharedMemPerBlock, maxThreadsPerBlock and
compute capability; the R0600 suffix is what pins that ABI, and the offsets
come from the compiler on a ROCm 6.4 host -- `cc -D__HIP_PLATFORM_AMD__` plus
`offsetof` -- not from counting padding by hand. The buffer is 4096 bytes
against a 1472-byte struct so a later HIP that grew it still writes inside.

Every value is range-checked before use: a wavefront is 32 or 64 and nothing
else, CUs are 1..=1024, compute capability 1..=99. If a future layout moves a
field this refuses with what it read, because the alternative is reporting
garbage as hardware capability -- and `Capabilities` cannot say "unknown", so a
zero there would read as "no compute units", "cannot do f16", and a
`recommended_block_size()` of 0. Better to fail loudly than to be believed.

f16/bf16/f8/int8 and the matrix tile are derived from the architecture, the way
the CUDA path derives its own from compute capability. Bandwidth is an estimate
per architecture, with gfx1151 called out: an APU shares LPDDR with the host
and is nowhere near a discrete card.

`examples/devices.rs` prints what discovery finds, so any host's fabric can be
inspected directly.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: gfx1151 reports cc 11.5, and say what multiProcessorCount counts
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 20s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 21s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
ad79998573
Running discovery on the AMD box found two things reading the code could not.

The bandwidth estimate was 2.25x too high for the part it was written for. An
arm matching (11, 51) never fired, because HIP reports gfx1151 as compute
capability 11.5 -- the trailing 1 is the stepping, not the minor. It fell
through to the discrete-RDNA3 figure, 576 GB/s, for an APU that shares LPDDR5X
with the host at about 256. gfx115x is all Strix-class, so (11, 5) now carries
the APU number and (11, _) keeps the discrete one.

And `compute_units` deserves a note rather than a correction. HIP's
`multiProcessorCount` is 20 on this part while rocminfo counts 32 Compute
Units, because on RDNA a Work Group Processor is two CUs. Both numbers are true
of different units. HIP's own figure is passed through unscaled, as the CUDA
path does with the same field, and the comment says which it is -- scaling it
by an assumption about the generation would be a guess dressed as a
measurement.

The FFI itself is confirmed: these values match HIP's own C API exactly
(cc 11.5, multiProcessorCount 20, warpSize 32, gfx1151) on a program compiled
against the real header, so the offsets read what they claim to.

Also removes an `unsafe` block that is no longer needed around the CPUID reads;
rustc says it is unnecessary, and it was only there because I assumed those
intrinsics were still unsafe.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: the metal model references, 286 errors down to 111
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 32s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 31s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 12s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Failing after 1m3s
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 1m58s
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 4m14s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
2c72f2b6d7
Of the 286, 175 were one mistake repeated: `Model` was wrapped in
`Arc<RwLock<Model>>` and these files, never having been compiled, kept passing
`&self.model` where `&Model` was wanted. 169 call sites in 10 files now deref
the read guard, which is the idiom those same files already use elsewhere
(`self.model.read().get_weight(..)`).

Five stragglers were the same shape on a local rather than a field. The sixth
was a real boundary: parler_tts held `Arc<RwLock<Model>>` and called
`T5Encoder::new`, which takes `Arc<Model>`, as do its three other callers.

Two facts decided that one rather than guesswork. The conventions split 22
files on `Arc<Model>` against 16 on `Arc<RwLock<Model>>`, so the lock-free form
is the majority, not the exception -- changing T5Encoder would have dragged
three working callers toward the minority. And **no file ever takes a write
lock through it**: not one `model.write()` in any of the 16. The lock guards
read-only access. So parler_tts drops it and matches its callee.

That leaves the same simplification available across the other 15: an
`Arc<RwLock<Model>>` nobody writes through, and ~147 `&*self.model.read()`
derefs that exist only to satisfy it. Collapsing them to `Arc<Model>` would
delete both. Not done here -- the current state is correct, only
over-synchronised, and finishing the error count comes first.

errors 286 -> 111, with E0308 gone entirely. Default build unchanged at 0
errors and the same 29 warnings, 44 tests still passing.

What remains is mostly not drift but absence: 53 E0425 for things that do not
exist (27 of them the shader kernels `PHASE27_OPS`, `MATVEC`, `MATMUL_Q8_0`,
and ~20 `gpu_ops` helpers named `<op>_on`), 27 E0716 lifetime errors, 11 E0599
missing methods.

Co-Authored-By: Claude Opus 5 <[email protected]>
Fifteen architecture pipelines held their weights as
`Arc<parking_lot::RwLock<Model>>`. No `.write()` is ever taken on a
model field anywhere in the crate, and `Model`'s mutating-looking
methods (`prefetch_prefix`, `evict_prefix`) take `&self` and only issue
madvise on already-mapped pages, so the lock guarded nothing. The other
28 pipelines already use `Arc<Model>`; florence2.rs documents the same
conclusion in a comment.

The lock was not merely redundant, it made four legal signatures
impossible: `fn w(&self, name: &str) -> Result<&LazyTensor>` borrows out
of the temporary `RwLockReadGuard` (E0515 in canary, fibo, mochi, sd3).
Converting removes 214 `.read()` calls and fixes those four.

Also fixed, each verified against the crate's own working precedent:

- CommonKernels had no `mul` field though `mul_f16` sits in the same
  ELEMENTWISE source as the wired `add_f16`. Added the pipeline.
- `kv_cache.update` takes 5 args (llm.rs:1098, deepseek.rs:279); jamba
  and mimo passed a 6th window hint. `PagedKVCache` is a flat per-layer
  buffer with no eviction, so it could never have honoured it.
- `MoeRouter::route` takes 2 args (llm.rs:996, deepseek.rs:357); jamba
  and mimo passed a third `None`.
- bare `f16` (unstable) -> `half::f16`, matching the other 71 uses in
  diffusion.rs.
- duplicate `T5Config` import in flan_t5.rs.
- `hal:🤘:buffer` made pub(crate) for two in-crate users.

While removing mimo's window hint I found its comments claim the window
is enforced in the attention kernel "via the window_hint parameter".
It is not: decode clamps the visible cache via `effective_cache_len`,
but prefill calls `prefill_attention`, which takes no window argument
and applies a full causal mask, so SWA layers see the whole prefix.
Corrected both comments to say so rather than delete the intent
silently. Windowed prefill masking remains unimplemented.

Co-Authored-By: Claude Opus 5 <[email protected]>
Three shader sources the architecture files compile pipelines from had
never been written, and two API groups had drifted. All verified against
the crate's own working precedent rather than guessed:

sources::MATVEC and sources::MATMUL_Q8_0 (6 errors)
  Modelled on the existing MATMUL_Q4K: one thread per output row, same
  buffer slots. The Q8_0 block layout -- 32 values in 34 bytes, f16
  scale then 32 int8 -- is taken from `dequantize_q8_0` in
  hal/metal/lazy_load.rs, which is the reference implementation.

sources::PROCEDURAL (7 errors in fusion.rs)
  SDF ray marching, fractal noise (perlin/simplex/worley/value with
  fbm), palette mapping, and a Karplus-Strong waveguide. Every buffer
  slot and enum code is fixed by the dispatch sites in fusion.rs, and
  the SDF node encoding by `encode_sdf_scene` in the same file. The SDF
  tree evaluates in two linear passes -- points root-to-leaf, distances
  leaf-to-root -- because the encoder always emits children before
  parents, so no recursion is needed. Output is interleaved RGB, which
  is what FusionOutput::Image documents.
  MetalOps gained the five pipelines plus a `compute()` accessor.

mamba2 quantization (4 errors)
  It was written against a `QuantType` enum and `dequantize_*_public`
  functions that do not exist. The crate uses `GgmlType` and a private
  `dequantize_to_f16` dispatcher, so the import now points at the real
  enum, `LazyTensor::ggml_type()` replaces `quant_type()`, and the
  prefill path calls the shared dispatcher -- which covers every block
  format the loader supports, not just the two mamba2 enumerated.
  `QuantType::None => unreachable!()` became a real error arm, because
  Q4_0/Q5_0/Q5K/Q6K are reachable and have no quantized matvec kernel.

Two latent bugs found while doing this, both invisible until now
because these files had never compiled:

- mamba2's two decode dispatches set K into buffer(3) and N into
  buffer(4), but matmul_q4k_f16 -- and every other kernel in shader.rs
  -- declares N at buffer(3) and K at buffer(4). The quantized decode
  path would have read free dimensions transposed. Swapped to match.
- hal/mod.rs gated `use crate::core::Error` on cuda/rocm, but
  discover_metal() uses it too.

Also: mochi called a `self.mul` that does not exist (now
`elementwise_binary` with the new CommonKernels::mul, as chatterbox
does), and moonshine applied `?` to `batched_sv`, which returns a
Tensor -- the other 13 callers omit it.

The guard's non-zero-exit check also had to be fixed: it fired whenever
a fabric with a baseline above zero built, because cargo exits 101 for
those very errors. It now gates on a zero tally, which is the case it
was written for -- a build script failing silently.

Standing caveat unchanged: this is compilation, not correctness. No
test and no CI job yet runs a Metal kernel, so none of these shaders
has been executed.

Co-Authored-By: Claude Opus 5 <[email protected]>
`MetalCompute::compile_pipeline` builds these sources at runtime, so a
syntax or type error in a kernel is invisible to `cargo check` and to
the per-fabric error guard. It would surface only when something
dispatched that pipeline -- and since no test runs a Metal kernel, that
means never. The 515 lines of MSL added in the previous commit had no
check of any kind behind them.

`xcrun metal` is the same frontend the Metal runtime uses, so compiling
each source offline closes exactly that gap. All 43 shader sources in
shader.rs compile, the three new ones included.

This still only establishes that the shaders compile, not that they
compute the right thing; numeric checks need a test that dispatches them
on a device. The macOS runner has a GPU, so that is reachable once the
metal feature itself builds.

Co-Authored-By: Claude Opus 5 <[email protected]>
`sources::PHASE27_OPS` was referenced by eight architecture files and had
never been written, so 23 pipelines named kernels that did not exist. The
remaining 22 errors were `gpu_ops::*_on` helpers in the same state.

Nothing here was invented: every kernel's buffer slots, grid shape and
scalar order is fixed by an existing dispatch site, and every helper's
signature by its call site. The Mochi VAE stages dispatch directly, so
their layouts came from mochi.rs; the rest came from the `*_on` calls in
sam2, mochi, bark, sesame_csm, moonshine and chatterbox.

21 kernels in PHASE27_OPS:
  patch/window    im2col_patch_embed, window_partition, window_unpartition,
                  max_pool2d, patchify_3d, unpatchify_3d
  attention       split_qkv, kv_head_expand, rope_batched, flash_attention
  activations     elu, euler_step, modulation_split
  codecs          dequantize_rvq, dilated_conv1d
  video VAE       vae_conv1x1, vae_spatial_upsample_2x, vae_channel_reduce,
                  vae_temporal_upsample, vae_final_conv_sigmoid,
                  vae_extract_frame

flash_attention stages K/V tiles in the threadgroup memory the caller
already allocates and folds them in with an online softmax, so no S x S
score matrix is materialised. It is non-causal, which is correct for the
two diffusion transformers that dispatch it. The partition/patchify pairs
are exact inverses of each other.

13 helpers in gpu_ops.rs, each allocating its own shared output buffer as
the existing helpers in that module do.

The offline shader check added in the previous commit earned itself
immediately: flash_attention_f16 declared `uint2
threadgroup_position_in_grid` beside `uint
thread_position_in_threadgroup`, and MSL requires every position
attribute in a kernel to have the same component count. That is a
runtime pipeline-build failure, invisible to cargo, and no reviewer or
type checker would have caught it.

State: `--features metal` compiles with 0 errors and 0 clippy errors
across the ~19k lines this makes reachable; all 44 shader sources
compile; the 46 default tests still pass.

Still not correctness. `cargo test --features metal` runs the same 46
tests as the default build and both integration tests are ignored, so
not one of these kernels has ever been executed. The macOS runner has a
GPU, so that is now reachable and is the next thing worth doing.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: run the Metal kernels and check what they compute
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 17s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 17s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 15s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
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) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
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) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
2948b1e892
Until now `cargo test --features metal` ran exactly the same 46 tests as
the default build, and both integration test targets were ignored, so not
one shader in this crate had ever been dispatched. Everything the last
few commits claimed about these kernels was a claim about compilation.

tests/metal_kernels.rs dispatches twelve of them on a real device and
checks each against an independent reference:

  against a CPU reference   elu, euler_step, rope_batched, matvec,
                            matmul_q8_0 (vs dequantise-then-multiply),
                            max_pool2d, split_qkv, kv_head_expand,
                            modulation_split
  against its own inverse   window_partition/window_unpartition,
                            patchify_3d/unpatchify_3d
  against naive attention   flash_attention, vs a full softmax over all
                            keys computed on the CPU

All twelve pass. Sizes are chosen to be awkward on purpose -- 257
elements for a 1-D dispatch, kv_seq 37 against a 32-wide tile, q_seq 40
across two query blocks -- because the bugs in this kind of code live in
the remainder, not the body.

The suite does not skip when no Metal device is present; it fails. A test
that passes by doing nothing is the failure mode this whole exercise has
been about.

Verified by corruption, not just by a green run: tightening
flash_attention's tolerance to 1e-9 and adding 1.0 to kv_head_expand's
reference makes exactly those two fail and nothing else. The flash
attention diagnostic is worth recording -- got -0.25927734 against
-0.25930187, so the tiled online-softmax kernel agrees with full
attention to 2.5e-5, which is f16 rounding.

The metal job now runs this, so the kernels cannot silently rot the way
the 3063 compile errors did.

Co-Authored-By: Claude Opus 5 <[email protected]>
dcharlot changed title from jouleclaw: the metal feature's error count may fall, never rise to jouleclaw: every compute fabric builds on hardware that has the device, and metal's kernels run 2026-10-20 04:40:04 -04:00
jouleclaw-rs: refresh the lockfile for libloading
All checks were successful
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 21s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 19s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 44s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m49s
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 1m12s
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 3m22s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m2s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 48s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m23s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m39s
5b49020c58
`check-lockfiles.sh` runs every lockfile with `--locked`, and this one
had been stale since `libloading` was added as the optional dependency
behind the `rocm` feature. The dev-dependencies added for the Metal
kernel tests needed no new entries -- `half` and `metal` were already in
the graph -- so the whole delta is one line.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw fabrics: count the metal kernel tests before trusting the run
Some checks failed
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
3103f52917
tests/metal_kernels.rs is behind `#![cfg(feature = "metal")]`. If that
cfg ever stops holding, the file compiles to nothing, the target runs 0
tests, and cargo exits 0 -- a green check for a suite that never ran.

That is not hypothetical: `cargo test --test metal_kernels` without
`--features metal` declares 0 tests and exits 0 today. The feature flag
is the only thing standing between this suite and a silent pass.

The step now lists the tests first and fails below 12.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-omni: every kernel this branch wrote now has a numeric test
Some checks failed
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
e920f1ac64
The previous commit left nine kernels with no numeric check — the six
Mochi video-VAE stages, im2col_patch_embed, dequantize_rvq and
dilated_conv1d — and the five sources::PROCEDURAL kernels were untested
too. All fourteen are covered now, so all 28 kernels this branch
introduced are checked against an independent reference.

The VAE stages are dispatched directly from mochi.rs rather than through
a `*_on` helper, so each test reproduces that call site's grid shape as
well as its buffer layout. Those grids are threadgroup counts, which
oversubscribe by 16x or 256x; the tests therefore also confirm the
kernels' bounds guards hold, which is what makes that convention safe.

Where a CPU reference would just restate the kernel, the tests check
properties that a wrong kernel would not satisfy:

- perlin_noise: deterministic per seed, different across seeds, inside
  its amplitude, never an all-zero field, and additive blend onto an
  existing field actually adds — for all four noise bases.
- sdf_raymarch: a unit sphere is hit at frame centre and fully lit
  facing the light, the corners stay exactly background, and shading
  falls off towards the limb (a flat disc would pass the first two).
- ks_excite: inside the velocity envelope, never silent, deterministic,
  and the pluck's peak follows the pluck position.
- ks_synthesize: matched against the same serial recurrence on the CPU,
  plus the requirement that a sub-unity loop gain actually decays.

Geometry is chosen to exercise the awkward paths: im2col uses padding
with a stride that does not divide the input, and asserts the padding
path was reached; vae_channel_reduce uses 8 channels into 3, so the last
group is short; vae_temporal_upsample uses 3 frames into 7; dequantize_rvq
includes an out-of-range code that must be skipped rather than read past
the table.

CI's count assertion goes to 26.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw fabrics: pin metal's clippy count — nothing was linting it
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 22s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 25s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 5s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 45s
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 1m9s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Has been cancelled
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) Has been cancelled
7b5ec0d802
standards-build.yml has a clippy step with `-D warnings` for exactly this
hazard, and its comment records the lesson: "Lints in it went unseen until
a macOS sweep found them (#244). Each crate is linted here, on its own
platform and with the features its tests use, and a warning fails the
step." It lints jouleclaw-energy --features ioreport. It never linted
jouleclaw-omni --features metal, because that did not compile.

It compiles now, so the ~19k lines the feature makes reachable are built
by the fabrics job and linted by nothing — the same shape as the 3063
compile errors, one bar further along. A feature nobody lints drifts
exactly like a feature nobody builds.

The count is 10983, all of it pedantic-family; `clippy::all` is clean and
there are 0 clippy errors, so no correctness lint fires across the whole
feature. That is too many to add to the `-D warnings` list today, so it
is pinned here instead: visible, non-increasing, and reported by lint so
the shape of the pile is in the log rather than a bare number.

Two measurement notes, because the first number I took was wrong:

- `--all-targets` lints the lib and the lib's test target, so every
  library warning arrives twice and the raw tally came to 22028 —
  exactly double, lint for lint. A count that doubles when a cargo flag
  changes is not a measurement. Warnings are now deduplicated by
  (code, file, line, column).
- The guard treats a non-zero exit as suspicious only when the tally is
  zero. clippy exits 0 with warnings present, so a failure alongside no
  diagnostics is the case that means something broke outside the lint.

A clippy *error* fails the step outright whatever the baseline says:
those are deny-by-default, mostly correctness, and never acceptable.

Co-Authored-By: Claude Opus 5 <[email protected]>
The source regex only matched `r#"..."#`. `clippy::needless_raw_string_hashes`
rewrites 42 of the 44 shader consts to `r"..."`, at which point this check
found 2 sources, compiled them, and reported success. The shaders were
fine; the check had quietly stopped looking at them.

That is the failure this check exists to prevent, in the check itself. Two
changes:

- the pattern accepts any hash count, with a named backreference so the
  closing delimiter has to match the opening one;
- MIN_SOURCES refuses a run that finds fewer than 44 sources. The count may
  rise, never fall. A check that inspects a handful of files and exits 0 is
  worse than no check, because it reads as a pass.

Co-Authored-By: Claude Opus 5 <[email protected]>
`cargo clippy --fix` with the feature enabled, so the ~19k lines it makes
reachable are covered. 10983 -> 4209 warnings across 66 files, all of it
mechanical and none of it behavioural:

  format!("{}", x)            -> format!("{x}")
  p.contents() as *mut T      -> p.contents().cast::<T>()
  &x as *const _ as *const u32 -> (&raw const x).cast::<u32>()
  (n + d - 1) / d             -> n.div_ceil(d)
  impl<'a> Foo<'a>            -> impl Foo<'_>
  nested if-let               -> let-chains

Verified after the rewrite, not assumed: 0 compile errors, all 44 shader
sources still compile, the 26 Metal kernel tests still pass on a GPU, and
the 44 default-feature tests still pass. The kernel tests are the load
bearing check here -- a bad pointer-cast rewrite in a dispatch path would
show up as wrong numbers, not as a compile error.

It also broke scripts/check-metal-shaders.py, which the previous commit
fixes: rewriting `r#"..."#` to `r"..."` took that check from 44 sources to
2 while it still reported success.

Co-Authored-By: Claude Opus 5 <[email protected]>
4209 -> 313 warnings. Fourteen lints allowed crate-wide, each with the
reason it is wrong for this code rather than a note that the count was
inconvenient:

- the four cast_* lints (3009 sites). Metal, CUDA and Vulkan take
  dimensions as u32 and coordinates as f32; Rust indexes with usize. Every
  dispatch boundary converts, in bounded ranges -- a tensor dimension that
  does not fit in u32 cannot be dispatched at all.
- too_many_arguments (219). A kernel's signature is its parameter list: a
  3-D patchify needs channels, frames, height, width and three patch
  extents beside the context, pipeline and command buffer. Grouping them
  would add 20+ single-use structs.
- similar_names, many_single_char_names (232). Tensor and attention code
  names things the way the mathematics does, and those names are short and
  similar on purpose.
- needless_range_loop (98). Numeric kernels walk several arrays at one
  index, often at an offset from the loop variable, which iterator form
  cannot express without obscuring which index is read.
- too_many_lines, unused_self, unnecessary_wraps, items_after_statements,
  needless_pass_by_value, match_same_arms, struct_excessive_bools,
  return_self_not_must_use.

What is deliberately NOT here: float_cmp, cast_ptr_alignment and
erasing_op. Those three are correctness-adjacent -- a float equality, a
pointer cast to a stricter alignment, and an expression multiplied by zero
-- and get read one at a time rather than allowed in bulk.

Co-Authored-By: Claude Opus 5 <[email protected]>
`clippy::invalid_regex` found this, which is the reason the lint sweep was
worth doing.

The GPT-2 pre-tokenizer pattern ended `...|\s+(?!\S)|\s+`. That is a
negative look-ahead, and the regex crate supports no look-around at all,
so `Regex::new` returned Err on every call. The call site was

    if let Ok(re) = regex::Regex::new(r"...") { tokenizer.pattern = Some(re); }

so the error was discarded and `pattern` stayed `None` for every
non-CLIP model. `encode` then falls back to:

    work.split_whitespace().collect()

which discards whitespace entirely. GPT-2-style BPE encodes a leading
space as part of the token -- " world" and "world" are different tokens,
which is what the byte-level 'Ġ' prefix represents -- so dropping the
spaces produces a different token sequence for essentially every input.
Wrong tokens in, wrong text out, and nothing anywhere reported a problem.

The fix is not new code: `pre_tokenize_gpt2` in jouleclaw-loader-gguf
already implements this split with the same pattern minus the look-ahead
term, under `.expect(...)`, and has tests for it. omni's copy was the
outlier. The two literals are now identical.

Both patterns are now installed with `expect` rather than `if let Ok`,
because a pre-tokenizer that fails to compile must not quietly degrade to
no pre-tokenizer at all. clippy::invalid_regex validates these literals at
compile time, so the expect cannot fire.

One divergence from published GPT-2 remains and is documented at the
pattern: dropping `\s+(?!\S)` changes whitespace runs of two or more,
where GPT-2 leaves the final space for the following ` ?\p{L}+` and this
consumes the whole run. That matches the loader crate's behaviour, so the
two are at least consistent.

Verified: 297 + 11 + 7 + 14 + 14 loader-gguf tests, 44 omni tests and the
26 Metal kernel tests all pass.

Co-Authored-By: Claude Opus 5 <[email protected]>
From the 313 left after the allow-list, these are the ones where clippy
was reporting a defect rather than a preference:

- seven unused imports, three of them `matmul_bf16_neon` imported and
  never called in falcon_h1, cohere2_moe and mellum.
- `erasing_op` x3: `0 * s` and `0 * dim` written for symmetry with the
  sibling `1 *` and `2 *` terms in packed-QKV index arithmetic. Harmless,
  but dead arithmetic, and keeping the lint live is worth more than the
  symmetry.
- `attn_layer_idx` in ggml_graph.rs was declared and incremented in two
  places and never read. Its sibling `ssm_layer_idx` is read fifteen
  times to index per-layer SSM state, so the asymmetry looked like a
  missing KV-cache index. It is not: `attn_idx` a few lines below
  recomputes the same attention-layer ordinal with an O(n) rescan per
  layer. Dropped the dead counter.
- `HashMap<(u32, u32), ()>` -> `HashSet<(u32, u32)>` in the mesh edge set.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw: metal clippy reaches zero, and -D warnings now gates it
Some checks failed
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 18s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 18s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 5s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 43s
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 2m25s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 2m4s
standards workspaces build + test / joulecontract-rs (joulecontract/joulecontract-rs, joulecontract-rs, linux-arm64, true) (pull_request) Successful in 55s
standards workspaces build + test / map-rs (map-conformance, map/map-rs, map-rs, linux-arm64) (pull_request) Successful in 58s
standards workspaces build + test / aac-rs (aac-conformance, aac/aac-rs, aac-rs, linux-arm64) (pull_request) Successful in 3m17s
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 56s
standards workspaces build + test / openpay (openpay, openpay, linux-arm64) (pull_request) Successful in 3m19s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 42s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 59s
standards workspaces build + test / macOS energy backends (pull_request) Failing after 3m58s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m37s
standards workspaces build + test / arl-rs (arl/arl-rs, arl-rs, linux) (pull_request) Successful in 1m9s
standards workspaces build + test / eoc-rs (eoc/eoc-rs, -p eoc-meter --features cuda, eoc-rs, linux) (pull_request) Successful in 2m7s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m42s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m13s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m13s
standards workspaces build + test / proof-rs (proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 1m36s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, sandbox-rs, linux) (pull_request) Successful in 2m23s
standards workspaces build + test / sense-rs (sense/sense-rs, sense-rs, linux) (pull_request) Successful in 1m14s
standards workspaces build + test / smart-byte-rs (smart-byte/smart-byte-rs, smart-byte-rs, linux) (pull_request) Successful in 4m10s
bdeccb7403
10983 -> 0, and `jouleclaw-omni --features metal` joins the `-D warnings`
clippy step in standards-build.yml, so it cannot regress. The pinned
ratchet added earlier is deleted: a denial is strictly stronger than a
count that may not rise.

The honest accounting, because "zero" is doing some work in that sentence:

  6774  fixed by `cargo clippy --fix` (earlier commit)
  3896  allowed as crate policy, grouped with reasons (earlier commit)
   282  allowed here, grouped with reasons
    ~31 fixed here

Of the ~31 fixed here, three were defects rather than style:

- the GPT-2 BPE pre-tokenizer regex, which never compiled (its own commit)
- `unet.rs` computed a kernel-size heuristic and shadowed it on the very
  next line, so the first was dead; and a `to_q/to_k/to_v` branch returned
  the same `cin` as the arm below it
- a `///` block documenting nothing

The rest were mechanical: checked_div for guarded divisions, clone_from,
an `#[ignore]` given its reason, 6.28 -> TAU, 0.6931472 -> LN_2.

Two allows are soundness notes, not style, and say so at the attribute:

- `cast_ptr_alignment` (8): these cast mmap'd GGUF bytes to f32/u16
  slices. GGUF aligns tensor data, so they are aligned in practice, but
  that is a file-format invariant the type system is not carrying.
  bytemuck::try_cast_slice would check it.
- `mut_from_ref` (1): `as_mut_slice(&self)` hands out a `&mut` from a
  `&`. It is unsafe and the caller carries aliasing, but the signature
  invites misuse.

One allow is a correctness argument against the lint: `manual_clamp`.
`x.min(hi).max(lo)` is not `x.clamp(lo, hi)` for floats, because
`f32::min` returns the non-NaN operand -- the chain scrubs NaN while
clamp propagates it. Taking clippy's advice would let a NaN timestep
through a diffusion schedule.

Verified after every edit, not at the end: 0 errors, 44/44 shaders,
26/26 Metal kernel tests on a GPU, 44 omni tests, 343 loader-gguf tests,
and `clippy -- -D warnings` exits 0.

Co-Authored-By: Claude Opus 5 <[email protected]>
jouleclaw-loader-gguf: restore three items clippy only saw as unused in one configuration
All checks were successful
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 17s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 18s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m7s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
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 2m59s
standards workspaces build + test / aac-rs (aac-conformance, aac/aac-rs, aac-rs, linux-arm64) (pull_request) Successful in 3m57s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 2m44s
standards workspaces build + test / joulecontract-rs (joulecontract/joulecontract-rs, joulecontract-rs, linux-arm64, true) (pull_request) Successful in 3m45s
standards workspaces build + test / map-rs (map-conformance, map/map-rs, map-rs, linux-arm64) (pull_request) Successful in 3m34s
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 2m40s
standards workspaces build + test / openpay (openpay, openpay, linux-arm64) (pull_request) Successful in 3m44s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 48s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m15s
standards workspaces build + test / arl-rs (arl/arl-rs, arl-rs, linux) (pull_request) Successful in 1m15s
standards workspaces build + test / eoc-rs (eoc/eoc-rs, -p eoc-meter --features cuda, eoc-rs, linux) (pull_request) Successful in 2m8s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m22s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m40s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m13s
standards workspaces build + test / proof-rs (proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 1m30s
standards workspaces build + test / sense-rs (sense/sense-rs, sense-rs, linux) (pull_request) Successful in 1m17s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, sandbox-rs, linux) (pull_request) Successful in 2m32s
standards workspaces build + test / smart-byte-rs (smart-byte/smart-byte-rs, smart-byte-rs, linux) (pull_request) Successful in 4m8s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m30s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m38s
530f44cad4
CI caught this: "macOS energy backends" failed because
jouleclaw-loader-gguf would not compile with `--features "rayon
fabric-meter"`:

    error[E0426]: use of undeclared label `'attn`
      --> crates/jouleclaw-loader-gguf/src/mellum.rs:558:31

I had removed that label because clippy reported it unused. It is unused
-- under `-p jouleclaw-omni --features metal`, which is the only
configuration I linted. The `break 'attn` that needs it sits inside
`#[cfg(feature = "fabric")]`, which that run never compiled.

Auditing the rest of those "unused" removals found two more of the same
shape, both of which would have broken a build nothing here runs:

- cuda_overlay.rs still had 5 uses of `c_void` after I dropped the
  import; all of them inside
  `#[cfg(all(any(target_os = "linux", target_os = "windows"), feature = "cuda"))]`.
- numa.rs still had 3, inside `#[cfg(all(target_os = "linux", feature = "numa"))]`.

Each import is restored carrying the same cfg as its users, so it is
present where it is needed and absent where it is not, and each says so.
The label is restored with `#[allow(unused_labels)]` and the reason.

The fourth removal was genuine: `matmul_q5_k_neon` had a
`use std::arch::aarch64::*` it did not use, because the intrinsics live
in `q5_k_sub_block_neon_sums`, which has its own.

The lesson is about the method, not these three lines. `clippy --fix`
and a clean `-D warnings` run tell you about one feature set. In a
workspace where a crate is built under several, "unused" is a statement
about the configuration you linted, and deleting on that basis breaks
the configurations you did not. The gate added in the previous commit
only lints `--features metal`, so it could not have caught any of this.

Verified under the configurations that differ, not just the one I
changed: process_calibration and marginal_energy with
`rayon fabric-meter`, loader-gguf's 315 default tests, both `-D warnings`
lints in that CI step, and the metal guards unchanged.

Co-Authored-By: Claude Opus 5 <[email protected]>
Merge origin/main into feat/metal-ratchet
All checks were successful
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been skipped
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 7s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been skipped
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m6s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m53s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 1m30s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 1m51s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 3m23s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 4m52s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 5m17s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 3m29s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 3m30s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 5m37s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 5s
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-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 3m44s
standards workspaces build + test / arl-rs (arl/arl-rs, arl-rs, linux) (pull_request) Successful in 1m17s
standards workspaces build + test / eoc-rs (eoc/eoc-rs, -p eoc-meter --features cuda, eoc-rs, linux) (pull_request) Successful in 2m5s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m42s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m16s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m15s
standards workspaces build + test / pool-rs (pool/pool-rs, pool-rs, linux) (pull_request) Successful in 1m11s
standards workspaces build + test / proof-rs (proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 1m34s
standards workspaces build + test / sense-rs (sense/sense-rs, sense-rs, linux) (pull_request) Successful in 1m15s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, sandbox-rs, linux) (pull_request) Successful in 2m32s
standards workspaces build + test / smart-byte-rs (smart-byte/smart-byte-rs, smart-byte-rs, linux) (pull_request) Successful in 3m58s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 54s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 9m38s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 3m56s
adb60aebd5
main moved 246 commits ahead and one hunk conflicted:
.github/workflows/standards-build.yml, where both sides added a lint to
the macOS `-D warnings` step. The two additions are complementary and
both are kept.

main's addition lints jouleclaw-energy's DEFAULT build, and its comment
makes the same point this branch ran into from the other direction:
"every hardware meter in `detect_meter` is behind a `cfg`, so the
default build is a different program, and a lint pass that never
compiles it cannot speak for it."

That is exactly what bit this branch: a label whose `break` sits behind
`cfg(feature = "fabric")` was deleted because a `--features metal` lint
reported it unused, and the fabric-meter build in this very job stopped
compiling. The resolution records that the new metal lint carries the
same caveat, so the next person does not read it as covering the crate.

Merged rather than rebased: other feature branches in this repo merge
main in the same way (1ae28b840, 29e7f07ab), and it needs no force-push.
The merge was taken against a pinned SHA, not the moving ref.

Co-Authored-By: Claude Opus 5 <[email protected]>
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!329
No description provided.