Rust 1.99.1 on current main: the pin, the MSRV floor it must not move, and three jobs that were passing on host state #594

Closed
dcharlot wants to merge 5 commits from chore/rust-1.99.1-now into main

2026-11-03

Transaction Science
CI: two macOS legs depended on runner state the pin change cleared or never had
Some checks failed
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 16s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 52s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m36s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 7m59s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Failing after 58m37s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 39m42s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 40m49s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 40m13s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 28m14s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 28m17s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 10s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m56s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 3m1s
wai-ops-npu integer operators on neural processors / builds · no device is not a pass (linux-arm64) (pull_request) Successful in 23s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 1m50s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 3m8s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 30s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m47s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 1m30s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 9m38s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 36s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 1h2m1s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 2m6s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 30s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 3m56s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 2m46s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 3m37s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 4m17s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 1h34m52s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 2h44m2s
Both failed on this branch for reasons that are about how the `macos` label is
provisioned, not about the code. That label is served by four hosts, which are
not identically set up:

  tx-dev-mac         Mac Studio M3 Ultra      full Xcode
  tx-mbp-m5max-48    MacBook Pro M5 Max 48    full Xcode
  tx-mbp-m4max-128   MacBook Pro M4 Max 128   full Xcode
  tx-imac-pro-macos  iMac Pro (x86_64)        Command Line Tools only

Which host takes a job is not predictable, so a leg that needs more than the
base install passes or fails by where it lands.

wai-examples, the apple-app step
  `rustup target add` had never named the apple slices' targets; the job ran on
  targets some earlier toolchain happened to have left on the runner. A target's
  std belongs to one toolchain, so moving the pin to 1.99.1 left the job with
  none of them and the macos slice failed at x86_64-apple-darwin with E0463,
  "can't find crate for `core`". The five targets are now added by name, the
  same set and the same line as wai-sink-swift.yml, which has always done this.
  The tvos slices' nightly is a separate toolchain and keeps its own targets, so
  it is not re-added.

jouleclaw-fabrics, the Metal shader step
  Xcode ships the Metal compiler as a downloadable component, and an Xcode or
  macOS upgrade uninstalls it. Three of the four hosts reported
  `Status: uninstalled` (Xcode 27B47), and on those every `xcrun metal` fails
  with "missing Metal Toolchain" -- which check-metal-shaders.py reports as all
  44 shaders failing to compile, so a provisioning gap reads as a code failure.
  The job now installs the component if it is absent. It is idempotent and
  persists on the host, so the download happens once per host per Xcode version,
  and it makes the job correct wherever it lands instead of only on the host
  that was provisioned by hand. Where there is no full Xcode -- the iMac Pro --
  it now fails with that as the stated reason rather than as 44 broken shaders.

  Verified on two real hosts rather than reasoned about: the absent branch takes
  the download path on a host reporting `uninstalled`, and the present branch
  short-circuits on the Studio, printing `Apple metal version 32023.922`. The
  component was installed on the Studio by hand first and
  `scripts/check-metal-shaders.py` then reported 44 compiled, 0 failed,
  0 skipped, which is what confirmed the shaders themselves are fine.

Neither leg's workflow had said what it needed; both read it off a host. That is
the class of fault a toolchain change exposes, because it clears per-toolchain
state while leaving the host otherwise untouched.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-11-03 00:45:20 -05:00
Transaction Science
standards-build: the proof gate read echo | grep -q under pipefail, a 1-in-20 flake
The `joulespec-proofs` leg failed on this branch with Kani's own output saying
the opposite of the gate's verdict:

     ** 0 of 336 failed (1 unreachable)
     ** 4 of 4 cover properties satisfied
    VERIFICATION:- SUCCESSFUL
    widening_a_set_can_only_lower_its_cap did not verify

The step runs under `set -euo pipefail` and asked
`echo "$out" | grep -q '^VERIFICATION:- SUCCESSFUL'`. `grep -q` exits at its
first match; `echo` is then still writing, takes SIGPIPE and exits 141; and
`pipefail` makes the pipeline return 141, so a match that was found reads as not
found. The failure message is printed by the `||` branch of a grep that in fact
matched.

Measured on the build host against this harness's real output rather than
assumed: the output is 191,128 bytes, its one `VERIFICATION:- SUCCESSFUL` line
is line 1839 and four lines follow it, so `grep -q` always exits with the writer
mid-stream. Twenty trials of each form on that exact string: the piped form
failed 1, the here-string 0. So this is a standing ~5% flake in the gate, not
something the toolchain change introduced — `cargo kani` compiles with its own
pinned compiler and does not read `rust-toolchain.toml`, so the pin cannot alter
the property count. #570 passed this leg for the same reason a coin comes up
heads.

Both `grep -q` reads in the two proof steps now take a here-string, which has no
writer to kill. The two that capture into a variable already end in `|| true`
and are unaffected.

This is the fourth place this pattern has been found in the repo (see the
here-string fixes in `check-lockfiles.sh`, `check-tests-in-ci-selftest.sh` and
`standards-touched-selftest.sh`), and the first in a workflow rather than a
script.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-11-03 00:45:20 -05:00
Transaction Science
clippy 1.99: two findings the comparison missed, and one it could not have seen
The two commits before this were written against a main 903 commits older than
this one, so their comparison of clippy 1.98.0 against 1.99.1 was re-run over
every cargo root that has gained Rust code since. It found these.

Method, because the first attempt was wrong

`rustup run <toolchain> cargo clippy` does NOT select that toolchain's clippy.
`cargo` resolves the `clippy` subcommand by searching PATH for `cargo-clippy`,
and on this machine Homebrew's (1.99.1) comes first, so both toolchains reported
`clippy 0.1.99` and the comparison was of one clippy against itself. The runs
behind this commit call each toolchain's own binary by path
(`~/.rustup/toolchains/<tc>/bin/cargo-clippy`, with `RUSTC` set to match and
`RUSTUP_TOOLCHAIN` unset), which gives `clippy 0.1.98` and `clippy 0.1.99`.
Confirming the delta that way: of the 24 constants `std::f64::consts` has
carried, 1.98.0 flags 18 and 1.99.1 flags 20 — the two added are exactly
EULER_GAMMA and GOLDEN_RATIO, as the previous commit says.

What changed

- wai-quantum, engine/synth/kak.rs: `1.618_033_988_749_895` becomes
  `std::f64::consts::GOLDEN_RATIO`. This is a `clippy::approx_constant`, which
  is deny-by-default, so it is an error and not a warning. The line arrived on
  2026-10-27, two days after the comparison was made, as one of six "mixing
  weights with nothing in common" that `kak` tries in turn. The literal and the
  constant are the same f64 — both `0x3ff9e3779b97f4a8` — so no value the
  decomposition computes changes. The constant is stable well below this tree's
  1.97 MSRV (it compiles on 1.96.0). The other five weights are not flagged:
  1/sqrt(3) and Feigenbaum's delta are not constants clippy knows.
  No workflow runs clippy inside wai/wai-quantum, so this was latent in CI and
  would have met anyone who ran clippy there by hand.

- Six `assert!(x.is_empty())` the previous commit missed, five of which were
  already in the tree when it was written: aac-core (translations, prediction
  twice, symbols), access-core (scan_order) and openpay's op-connect (account).
  `clippy::assert_is_empty` is new in 1.99, is allow-by-default, and reaches
  these crates through their own `#![warn(clippy::pedantic)]`, which
  `#![deny(warnings)]` then makes an error in the two aac crates.
  Each gains a message naming the value instead of the array comparison the
  previous commit used, because none of these six is a Vec or a slice: four are
  a HashMap, a BTreeSet or `OrderDiff`, which cannot be compared to `[] as [T; 0]`
  at all, and `Vec<PredictionCandidate>` derives Debug but not PartialEq, which
  `assert_eq!` against an empty array needs. A message is what the lint asks for
  anyway — it exists so a failure prints the value rather than only "false" — and
  it is the reason the lint does not fire at the other 147 `assert!(…is_empty())`
  sites that have arrived since: with a message supplied, it stays quiet.

Not changed, with the reason

- The 1.97 MSRV. `rust-version` is the floor a consumer of these reference
  implementations must meet, not the compiler this tree builds with; raising it
  narrows who can build an open standard and buys nothing, since no code here
  needs 1.98 or 1.99. `wai-quantum-webgpu.yml` installs 1.97.0 beside 1.99.1 to
  hold that floor, and that leg is untouched.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-11-03 00:45:20 -05:00
Transaction Science
toolchain: Rust 1.98.0 -> 1.99.1 (change-controlled pin)
Approved by the owner on 2026-10-22. Procedure: change `channel`, run
`rustup show`, then run the pipeline.

What changed
- rust-toolchain.toml and eoc/eoc-rs/rust-toolchain.toml: channel "1.98.0"
  becomes "1.99.1". These are the only two pins in the tree, and the root one
  governs every other cargo root.
- 64 workflows under .github/workflows (the forge's CI): every `Install Rust
  1.98.0`, `rustup toolchain install / default / component add / target add
  --toolchain 1.98.0` and `--default-toolchain 1.98.0` now names 1.99.1
  (409 lines). Two of those lines are in build steps rather than install
  steps (wai-conformance.yml's two `wasm32 (unix)` steps each
  `rustup target add --toolchain`), and they move with the rest: a target
  added to a toolchain that is not installed is an error.
- Left as they are, because they record what was measured on 1.98.0:
  standards-build.yml's "Verified on a native arm64 Linux container (rustc
  1.98.0)", wai-conformance.yml's note on Rust 1.98's LLD 22, and the
  "rustc 1.98.0 (example)" strings in receipts, vectors and docs. The
  one-codegen-unit workaround that note explains also stays. 1.99.1 ships
  LLD 23.1.1, which the note says links those inputs, but removing the
  workaround should wait for a run at the CI path on x86_64.

Why
- 1.98.0 has a P-critical miscompile, rust-lang/rust#161441 (I-miscompile,
  regression-from-stable-to-stable). rustc emits a vacant (null) method slot
  in a trait-object vtable, so a safe dynamic call jumps to address zero
  (undefined behaviour). RELEASES.md records the fix in 1.98.1 ("rustc: fix
  miscompilation in generating vtables").
- 1.99.1 is the current stable (channel manifest dated 2026-10-15; rustc
  58cf8f9c3 2026-10-13). It also fixes 1.99.0's own regressions: wcslen on
  UEFI and embedded targets, x86_64 FFI `bool` returns, and the rust-lld rpath
  on macOS.

Evidence
All of it ran on the build host ([email protected], aarch64-apple-darwin)
through ~/kani-logs/remote/rb. Nothing was built on the dev Mac.

- `rustup show`: the active toolchain is 1.99.1-aarch64-apple-darwin,
  "overridden by .../rust-toolchain.toml" (and by eoc/eoc-rs's own file
  there). rustc 1.99.1 (58cf8f9c3 2026-10-13), LLVM 23.1.1, clippy 0.1.99,
  rustfmt 1.10.0. The baseline is rustc 1.98.0 (88d9e12ae 2026-08-18).
- Scope: every cargo root the pin governs, which is 46 of the 49 tracked
  lockfiles. The other three: two are vendored crates that resolve inside
  their parents, and wai/wai-rs/fuzz builds on its own pinned nightly.
- Trees. The final tree is main at 96117c570 plus these two commits. Main
  moved four times while this ran, and each root's evidence comes from the
  newest tree it was run on:
  - 13 roots on the final tree: every root main changed after 1a465f23d,
    and every root that consumes such a crate by path.
  - 12 roots on 1a465f23d plus these two commits.
  - 7 roots on b16816671 plus these two commits.
  - 14 roots on aa61ab3b9 plus the pin change.
  For each root in the last three groups, checked with git diff and the
  lockfiles' path packages: none of its files, and no crate it reaches by
  path, differs on the final tree.
- Each root got:
  (a) `cargo fmt --all -- --check` on the pin and on 1.98.0. The output is
      byte-identical in all 46. CI gates no root on rustfmt, and none is
      rustfmt-clean on main.
  (b) `cargo clippy --locked --keep-going --workspace --all-targets` on both
      toolchains, with the diagnostics compared line by line. After the
      previous commit, no root has a diagnostic that only 1.99.1 reports.
      openpay's one differing line is the same lint at the same site,
      reworded.
  (c) `cargo test --workspace --locked`.
  (d) the root's other CI steps that can run on this host: feature-gated
      tests, conformance suites, release-profile tests, the aac page-set
      checks, and every clippy -D warnings gate. The gates are
      standards-build's macOS meter and omni lints (jouleclaw-energy x2,
      jouleclaw-omni metal, jouleclaw-loader-gguf, jcp, proof, eoc, sandbox),
      wai-pack, wai-quantum-cli (default, no-default and metal),
      wai-quantum-service, wai-quantum-qpu and wai-quantum-desktop.
- Totals: `cargo test --workspace` ran in 43 roots: 12,532 passed, 1 failed,
  101 ignored. The other 3 roots are wasm32-only, and their
  `cargo build --release --target wasm32-unknown-unknown` passed. Every
  other CI step passed (62 of 62).
- On the final tree: scripts/check-lockfiles.sh (cargo 1.99.1) found all 47
  lockfiles current, and scripts/check-advisories.py passes.
- tokio is 1.54.1 in every lockfile cargo reads. That is patched for both
  RUSTSEC-2026-0386 (>= 1.53.3) and RUSTSEC-2026-0384 (>= 1.54.1). The 1.53.1
  in vendor/wtransport/Cargo.lock is the upstream file kept with the vendored
  source; cargo resolves wtransport inside its parents, and both gates skip
  that file.
- What is not green, each one reproduced on 1.98.0:
  - wai-ops-gpu: under the debug profile, `corpus` trips the debug_assert at
    exec.rs:187 on both toolchains. CI runs it in release only, and that
    passes (6/6).
  - wai-ops: clippy::derived_hash_with_manual_eq (deny-by-default) on both
    toolchains. No CI job runs clippy there.
  - wai-vector/wasm: `--all-targets` cannot build the lib-test target (its
    own `panic_impl`) on either toolchain. `clippy --lib` for wasm32 reports
    0 diagnostics on both.
  - eoc-cascade's hit_calibration_process_energy test reads real energy
    counters, and it fails some of the time on the loaded shared host. In
    interleaved runs each toolchain passed 18 of 20. The full eoc-rs suite
    passed on the final tree (741 passed).
- Environment, not code:
  - wai-quantum-desktop embeds the Studio's build, so wai/quantum-studio was
    built first (`npm ci`, `node build.mjs`), as CI does.
- Not covered here: the x86_64 and arm64 Linux and Windows legs; the GPU,
  NPU, FPGA, emulator and hardware-meter legs; wasm32 tests under Node,
  wasmtime and wasip2; and the fuzz job.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 00:45:20 -05:00
Transaction Science
clippy 1.99: fix what Rust 1.99.1's clippy newly reports, before the pin moves
These are the only lints clippy 1.99.1 reports that clippy 1.98.0 does not.
Every cargo root in the tree was compared on both toolchains (the evidence is
in the next commit). 1.98.0's clippy also builds every target of the fixed
code, and reports nothing it did not report before, so this commit stands
under either pin.

What changed, and why

- clippy::assert_is_empty is new in 1.99. 36 sites, all in test code
  (#[cfg(test)] modules; no lib or bin build reports any):
  aac-core and access-core, 23 sites; openpay's op-crypto-extra, op-emv,
  op-iso20022, op-reconciliation, op-routing, op-screening, op-settlement
  and op-tax, 13 sites. `assert!(x.is_empty())` becomes
  `assert_eq!(x, [] as [T; 0])`, `assert_ne!` for the negation, or `""` for
  strings, so a failure prints the value instead of only "false". aac-core and
  access-core are `#![deny(warnings)]` and `#![deny(clippy::all)]`, so without
  this their clippy run fails on 1.99.1.
  Judgment call: at 18 of the 36 sites, clippy's own "MachineApplicable"
  suggestion does not compile. It names local types by crate-relative path
  (`finder::Found`, which is not in scope in a test module), or offers a bare
  `[]` whose element type cannot be inferred. So each site names its element
  type as its own module sees it (`[] as [Found; 0]`, `[] as [f64; 0]`). The
  four lines rustfmt would wrap are wrapped the way rustfmt wraps them.

- clippy::approx_constant (deny-by-default) now knows EULER_GAMMA and
  GOLDEN_RATIO. Both are in std::f{32,64}::consts and stable since 1.94; the
  jouleclaw workspace MSRV is 1.97.
  - jouleclaw-omni, inference/architecture/mochi.rs: `1.618_034` becomes
    `std::f32::consts::GOLDEN_RATIO`. They are the same f32
    (1.61803400516510009765625), so the latents do not change. This file is
    in standards-build.yml's macOS gate (`cargo clippy -p jouleclaw-omni
    --features metal -- -D warnings`), which fails on 1.99.1 without the fix.
  - jouleclaw-outlier, c_factor: `0.5772156649` becomes
    `std::f64::consts::EULER_GAMMA`. Judgment call: the literal was
    truncated, so c(n) moves by 3.1e-12. The normalisation in the
    isolation-forest paper uses the Euler-Mascheroni constant itself, so this
    is the intended value. No other crate and no committed vector reads these
    scores, and the crate's tests pass unchanged.

- smart-byte-rs/Cargo.lock: async-trait 0.1.89 becomes 0.1.92, which adds
  syn 3.0.9 as its dependency. 0.1.89 put `#[must_use]` on every trait method
  it generates. clippy 1.99 now counts the returned `Pin<Box<dyn Future>>` as
  must_use already, so clippy::double_must_use fired at 9 #[async_trait] trait
  methods. The attribute there is the macro's, not ours, so the right fix is
  the macro: 0.1.92 no longer emits it, and every other lockfile in this tree
  already uses 0.1.92. A narrow `cargo update -p async-trait --precise 0.1.92`
  also moved data-encoding-macro-internal (which accepts syn >=1, <3) from syn
  2 to syn 1. That was put back to syn 2.0.117, as on main, so the lock
  changes only what the bump needs. `cargo update --workspace --locked` and
  scripts/check-lockfiles.sh accept it.

Left as they are

- openpay op-dispute-evidence evidence.rs:92 (clippy::double_must_use) is
  reported on 1.98.0 too. Only the message's wording changed in 1.99.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 00:45:20 -05:00