Skip to content

fix(ci): unblock main — pin wasmtime example to toolchain MSRV + trigger CI on examples/** - #285

Merged
avrabe merged 2 commits into
mainfrom
fix/wasmtime-example-msrv
Oct 1, 2026
Merged

avrabe merged 2 commits into
mainfrom
fix/wasmtime-example-msrv

Conversation

@avrabe

@avrabe avrabe commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

main's cargo job has been red on both OSes since at least 2026-09-22, blocking the entire release process (AGENTS.md requires CI to pass completely before a release). Two defects, one causal chain.

Defect 1 — the MSRV break (why main is red)

Dependabot's wasmtime bumps (#265, #281) moved examples/wasmtime-loader to wasmtime 49.0.1, MSRV rustc 1.96.0, while rust-toolchain.toml pins 1.94.0. Build Examples fails with requires rustc 1.96.0.

MSRV by line (crates.io): 49.x → 1.96.0, 48.x → 1.95.0, 47.x → 1.94.0. So 47.0 is the newest line that builds here.

  • Pin wasmtime = "47.0".
  • Declare rust-version = "1.94" so cargo's MSRV-aware resolver selects compatible transitive versions (observed: downgrades cranelift-* 0.136.1 → 0.134.4) and a future incompatible bump fails as a resolver error naming the requirement instead of an opaque mid-build rustc error.

Why not bump the toolchain: the example is in the workspace exclude list, so this touches no shipping crate. Bumping rust-toolchain.toml to 1.96 would re-qualify every formal-verification gate (Kani, Verus, Rocq, witness MC/DC) and both Bazel targets immediately before a release, to fix an example. That belongs in its own PR with its own full-CI qualification.

Defect 2 — why it reached main at all (the durable fix)

The cargo job's Build Examples / Test Wasmtime Example steps build examples/wasmtime-loader, but rust.yml's path filters covered only src/**, Cargo.{toml,lock}, BUILD.bazel, MODULE.bazel and the workflow file — not examples/**.

So the job that builds the examples was never triggered by changes to the examples. Dependabot's bumps touched only examples/wasmtime-loader/Cargo.toml → this workflow never ran → they merged with zero validation → the breakage surfaced on the next unrelated src/** push, making main look broken by innocent commits.

Added examples/** and rust-toolchain.toml to both the push and pull_request filters. An example-only regression now fails on its own PR instead of poisoning main. (This PR is itself the proof: before the filter fix it ran one check — "Documentation claims hold" — and could not validate its own fix.)

⚠️ Also note: examples/wasmtime-loader/.gitignore ignores Cargo.lock and the lockfile is untracked, so CI resolves fresh every run — the fix has to live in Cargo.toml; a cargo update --precise pin would not hold.

Verified locally on the pinned 1.94.0 toolchain

  • cargo build --release — succeeds (was: MSRV failure)
  • cargo run --release -- --help — succeeds (the next CI step)
  • forcing wasmtime = "49.0" again reproduces a clear resolver MSRV error, so the guard isn't vacuous

Follow-up (not release-blocking): dependabot will re-propose wasmtime 49; that wants the toolchain bump PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH

avrabe and others added 2 commits October 1, 2026 15:25
main's `cargo` job has been red on both OSes since at least 2026-09-22,
blocking the entire release process (AGENTS.md requires CI to pass completely
before a release). Root cause: dependabot's wasmtime bumps (#265, #281) moved
examples/wasmtime-loader to wasmtime 49.0.1, whose MSRV is rustc 1.96.0, while
rust-toolchain.toml pins channel 1.94.0. The "Build Examples" step therefore
failed with "requires rustc 1.96.0".

MSRV by wasmtime line (crates.io): 49.x -> 1.96.0, 48.x -> 1.95.0,
47.x -> 1.94.0. So 47.0 is the newest line that builds on the pinned
toolchain. Pin to "47.0" and declare `rust-version = "1.94"` on the crate so
cargo's MSRV-aware resolver selects compatible transitive versions (observed:
it downgrades cranelift-* 0.136.1 -> 0.134.4) and an incompatible bump fails
fast as a resolver error naming the requirement, instead of an opaque rustc
error mid-build.

Scoped deliberately to the example: examples/wasmtime-loader is in the
workspace `exclude` list, so this touches no shipping crate. Bumping
rust-toolchain.toml to 1.96 instead would re-qualify every formal-verification
gate (Kani, Verus, Rocq, the witness MC/DC harness) and both Bazel targets
immediately before a release, to fix an example — that belongs in its own PR
with its own full-CI qualification, after v0.12.0.

Note: examples/wasmtime-loader/.gitignore ignores Cargo.lock and the lockfile
is untracked, so CI resolves fresh on every run; the fix has to live in
Cargo.toml, not a `cargo update --precise` pin.

Verified locally on the pinned 1.94.0 toolchain:
- `cargo build --release` succeeds (was: MSRV failure)
- `cargo run --release -- --help` succeeds (the next CI step)
- forcing wasmtime = "49.0" again reproduces a clear resolver MSRV error

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
…ts own PR

The `cargo` job's "Build Examples" and "Test Wasmtime Example" steps build
examples/wasmtime-loader, but rust.yml's path filters covered only src/**,
Cargo.{toml,lock}, BUILD.bazel, MODULE.bazel and the workflow file — NOT
examples/**. So the job that builds the examples was never triggered by
changes to the examples.

That is how main went red: dependabot's wasmtime bumps (#265, #281) touched
only examples/wasmtime-loader/Cargo.toml, so this workflow did not run and
they merged with zero validation. The MSRV breakage then surfaced on the next
unrelated src/** push, making main look broken by innocent commits and
blocking the release.

Adds examples/** (and rust-toolchain.toml, since every job's compiler comes
from it and a channel change can break any of them) to both the push and
pull_request filters. Net effect: an example-only regression now fails on its
own PR instead of poisoning main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
@avrabe avrabe changed the title fix(ci): pin wasmtime example to the repo toolchain's MSRV (unblocks main) fix(ci): unblock main — pin wasmtime example to toolchain MSRV + trigger CI on examples/** Oct 1, 2026
@codecov

codecov Bot commented Oct 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe
avrabe merged commit 6b691d1 into main Oct 1, 2026
12 checks passed
@avrabe
avrabe deleted the fix/wasmtime-example-msrv branch October 1, 2026 14:26
avrabe added a commit that referenced this pull request Oct 21, 2026
Four additions and three corrections to the v0.12.0 entry.

Added:
  * #305, placed FIRST under Fixed because it is the cycle's most severe
    finding: a split-signed module truncated at any delimiter verified, through
    plain `wsc verify`, with Function+Code deleted and no key involved.
  * REQ-31 / #302 under a new Changed section — toolchain 1.96.1, wasmtime
    49.0.4, the 9.3 CRITICAL retired rather than excepted, and the MSRV
    consequence stated for consumers (`runtime` now needs rustc >= 1.96).
  * the two webpki advisories published within 48 hours of the release, with
    why they are not housekeeping: both land on step 1 of
    PinnedCertVerifier::verify_server_cert.
  * #284 — the real cause (rivet 0.3.0 byte-slicing an em-dashed title during
    Export), the 22 validate errors, the unresolvable `../synth` external, and
    the duplicate CV-25 id that had kept one verification artifact out of the
    trace entirely.

Corrected:
  * **"Unmasked and therefore potent: kani varint, kani dsse, kani
    wasm_module" was FALSE** — and false because it copied
    formal-verification.yml's own summary comment, which contradicted the
    matrix three lines below it. One module is unmasked. Replaced with the
    measured table: pre-mask exit codes read out of the run logs (the API
    reports a masked step as success), showing SEVEN failing Kani harnesses
    behind a green board, `format.rs` — this release's largest piece of new
    attacker-facing code — among them. Publishing the original sentence would
    have shipped a false verification claim in the release notes.
  * the same paragraph now records that EVERY gate here is advisory in a
    second sense: main's required_status_checks.contexts is empty, so nothing
    blocks a merge. This release's merges were verified green by hand, and the
    notes say so rather than implying CI enforced them.
  * #301's falsification note: #305's terminal check subsumed its guard, so
    its mutation verification was true when written and stopped being true
    afterwards. The variant-pinning fix and the matrix.rs case that CANNOT be
    separated are both stated.
  * #285's wasmtime claim is marked superseded within this same release, and
    credited with #274's committed example lockfile, which is the half that
    makes it stay fixed.

Release date moved to 2026-10-21.

Refs #284, #302, #305, #274, #145

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
avrabe added a commit that referenced this pull request Oct 21, 2026
`rust.yml` runs `verification/vacuous-oracle-check/check.py` in its
`Vacuous-oracle gate` job, but its path filters listed every input EXCEPT that
checker. So the previous commit changed the gate's own source and the job that
runs it did not re-run — the fix was verified locally (red with the script
untracked, green with it tracked) and by nothing in CI.

A gate scoped to everything but itself is the same shape as #285 (`examples/**`
missing from these very filters, which let a dependabot MSRV break merge
unvalidated) and #286 (Mythos tier-5 paths left behind by the v0.11.0 crate
split, so the gate over the untrusted WASM parser matched zero files and
reported clean). The pattern is a filter list that was correct when written and
silently stopped covering its target.

`verification/**` added to both the push and pull_request filters, which also
means the witness harness and claim-check sources now re-run the jobs that
consume them.

Costs one more CI cycle on a saturated runner pool, which is the right trade: I
changed a gate's source, and landing that unverified by CI is precisely the
thing this repo's methodology exists to refuse.

Noted while checking something else — the head commit's board had lost
`cargo on *`, `bazel on *` and `Cargo Audit` because the preceding commits
touched none of their filtered paths. That part is fine and now mechanically
justified rather than assumed: `git diff --name-only 4ee630d HEAD` over exactly
those filters is EMPTY, so those green results still describe this tree. The
general version of that check — verify a required context's green still
describes the head tree before merging — belongs in the aggregator and is
noted on #317.

Refs #258, #285, #286, #302, #317, REQ-30

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant