Back to Blog

Rust & AI Weekly #11: the default is the decision

Decebal D.
September 7, 2026
20 min read
Rust & AI Crate RadarExplore

Welcome back to Rust & AI Weekly, the curated, vetted sweep of crates and tools showing up where Rust meets AI. Today's issue: Cargo stabilized the supply-chain control I called cheap last week, the official MCP SDK went from 1.7 to 3.2 in fifteen weeks and broke builds through a minor bump on the way, and a machine wrote 16,748 proof harnesses where fifteen months of humans wrote 725. The theme this week is the default is the decision: whatever your dependency resolver, your sandbox posture and your proof coverage do without anyone deciding anything is your actual engineering policy, and everything you wrote in a wiki is a preference. Last week I asked what the cheapest control on your build pipeline would be. This week the ecosystem answered in three places at once, and one of those answers is a demonstration that the wrong default costs exactly as much as the right one saves.

(Status lines reflect public signals as of September 7, 2026; stars and downloads are approximate and move fast.)

Rust & AI Crate Radar, tools mapped by Adopt / Trial / Assess / Hold, this week's snapshot

This week's radar: three new entries and two verdict updates, bringing it to 73 tools. Explore the interactive version.

The week's anchor

Cargo stabilized min-publish-age. PR 17335 landed in the week of August 25 to September 1, per This Week in Rust 667, alongside the stabilization of cargo-lints and an implementation of the feature-metadata RFC.

I want to be precise about the causality, because the tempting version of this story is wrong. min-publish-age did not ship because of the arrayref attack. It has been in this newsletter's Language watch section since issue #8, which is before the attack, and the final comment period opened before anyone knew proc-macro1 existed. What the attack did was remove the last reason to argue about it. A minimum age before a newly published version is resolvable turns an 86-minute exposure window into a non-event for anyone who set the knob, and on August 20 a lot of people learned what their exposure window was by reading a blog post.

The reason it belongs at the top of the issue is what kind of control it is. It is not a review process, a checklist, or a quarterly audit. It is a number in a config file that the resolver enforces whether or not anyone is paying attention that morning. That is the only category of control that survives contact with a busy quarter, and the rest of this issue is four more examples of the same argument, including one where the default went the other way.

Pick of the week

wasmi 2.0.0 — Robin Freyler's portable WebAssembly interpreter leads this issue because it is the answer to a question the agent conversation keeps asking badly. When you let a model generate code and then run it, what bounds it? The usual answers are a container, a subprocess, or optimism. Wasmi's answer is an interpreter with fuel metering: you hand it a Wasm module and a fuel budget, and it stops. No JIT means no mmap with exec permissions and no W^X exception, so it runs in the places that forbid those, which is most of embedded, most of the smart-contract world, and a growing amount of anything that has to pass a security review. That is why the users list reads Stellar Soroban, Ripple, Typst plugins, Zellij plugins, Josh and Firefly Zero rather than a list of demos. 2.0 is the payoff of eight months of engine work Freyler promised in the 1.0 post: roughly 2.2x faster than 1.0 on the wasmi-benchmarks geometric mean on an Apple M2 Pro, which puts it level with Wasm3 and Makepad Stitch, the two fastest portable interpreters, and ahead of both on calls. The mechanism is worth understanding because it is a series of deliberate trades. Four instruction dispatch modes now exist behind an auto-dispatch feature, from direct-threaded code (function pointers in the IR, tail calls between handlers) down to the old switch-loop for platforms without tail calls. Three accumulator registers replace the stack-slot decode-load-store dance for the common case, at the cost of new copy instructions, which he then claws back with fused opcodes. The CodeMap went from one mutex-guarded arena to append-only buckets that never move, which is what lets a call_internal be zero look-ups instead of a lock plus an index. And Wasmi keeps module-related rather than instance-related bytecode, so every instance of a module shares one IR and the memory story stays good, which is the opposite of the choice Wasm3 and Stitch made. But the finding I would put on a slide is the one he labels an accidental deoptimization. Rust 1.92 turned on the DestinationPropagation MIR pass by default. It merges MIR locals holding the same value, which collapsed the two dispatch paths of a conditional-branch handler into one csel feeding a single branch site, which means the CPU's branch predictor sees one entry with mixed history instead of two clean ones. Undoing that lifted Wasmi's CoreMark from about 2,800 to over 4,200. A 50% improvement, from stopping the compiler being clever, and it was the single most important optimization in the release. He found it because Stitch had regressed 30% between Rust 1.91 and 1.92 and he went looking. Go deeper with the release post itself, Wasmi 2.0: Engineering of the Fastest Wasm Interpreters, which is 23 minutes and is the best current tour of how a fast interpreter is actually built; the deoptimization section is worth the whole read even if you never ship Wasm. The caveat is not technical. Freyler has worked on Wasmi full-time for two years on Stellar Development Foundation sponsorship, that sponsorship ends in October 2026, and he says plainly at the bottom of the post that he is looking for another sponsorship or a role that leaves room for the project. A one-person dependency with a funding cliff six weeks out is a Trial, not an Adopt, however good the code is.
Maintenance: very actively developed, single maintainer, funding ends October 2026 (Robin Freyler / robbepop; Stellar Development Foundation sponsored full-time work from Oct 2024) · Latest: v2.0.0 (Sep 1, 2026), migration guide published · Adoption: Trial; the 1.0-to-2.0 migration is real work and the exit cost is low because the input is standard Wasm, so this is a cheap bet with an explicit stewardship risk you should name in the ADR rather than discover

Agentic tooling

rmcp 3.2.0 — a downgrade, and the most useful entry in the issue. I put the official Rust MCP SDK at Adopt in issue #1, in June, when it was v1.7.0 and the protocol had been still for a while. It is now 3.2.0, published August 31. Fifteen weeks, three major versions, two migration guides. That alone is a cadence signal rather than a verdict change; what moves it is the shape of one release. rmcp 1.8.0 shipped a source-breaking API change in a minor version bump, and the release notes say so themselves, in a warning box: it "should have been 2.0.0", and if you depended on rmcp = "1.7" then Cargo resolved you to 1.8.0 and your build may have failed. The change was Peer::peer_info() returning Option<Arc<R::PeerInfo>> instead of Option<&R::PeerInfo>, needed because peer info moved behind an RwLock so it could be re-set on a duplicate initialize. A correct fix, a defensible design, published under a version number that told every caret-range dependency in the ecosystem it was safe. I am not scolding anyone: the notes are honest, the migration is one .as_deref(), and the same releases were fixing genuinely serious things (OAuth resource spoofing, metadata SSRF, streamable-HTTP session leaks, redirect header leaks). The point is that this is the same default as the anchor story wearing different clothes. Cargo's job is to resolve you forward inside a major version, and it did. Which means the verdict has to move: rmcp is still the only official SDK and still the right choice, and it is no longer a thing you standardize on and forget. Pin an exact version, read the changelog before you bump, and put MCP migration on the quarterly plan as a line item rather than a surprise. One small friction to know about: the GitHub Releases tab has no notes past rmcp-v2.2.0, so the 3.x history lives in the repo changelog and the migration discussions.
Maintenance: actively maintained, official MCP org (4t145, jokemanfire, alexhancock); ~3.9k stars · Latest: v3.2.0 (Aug 31, 2026), tracking the MCP 2026-07-28 spec; 1.7.0 was May 13 · Adoption: Trial, downgraded from Adopt at #11, for release cadence rather than code quality; pin =3.2.0 and budget the migrations

syd 3.59.0 — returning from issue #9, where it was the lead. Ali Polatel shipped 3.59.0 on September 1. Nothing in it changes the assessment, which is the point of saying so: the application kernel that executes syscalls on behalf of the sandboxed process rather than trapping and continuing them is still the most developed Rust answer to "what confines the coding agent I let run shell commands", still GPL-3.0 so it is a tool you run and not a library you link, and still Linux 5.19 or newer. Second mention, verdict holds at Trial. If you read issue #9, put down the newsletter and go run Pandora learning mode against one agent workload; the reason to mention a routine release is that the tool has not changed and your exposure has not either.
Maintenance: actively developed, effectively solo but long-running (Ali Polatel; 195+ releases; OpenSSF best-practices badge) · Latest: v3.59.0 (Sep 1, 2026) · Adoption: Trial, unchanged; the cost is authoring the policy, not installing the binary

Verification

Kani 0.63.0 — the Rust Foundation and AWS published a program update on the standard library verification contest, written by Michael Tautschnig with support from Rahul Kumar and Felipe Monteiro, and the numbers in it are the strongest version of this week's argument. For the first fifteen months, verification of the standard library was hand-written: contributors produced 725 manual Kani harnesses, 694 of them backed by formal function contracts, plus more than 50 VeriFast proofs. Real work, and it is what convinced the language team to accept contracts as an experimental feature. It also plateaued around October 2025, because the standard library is roughly 34,000 functions across core, alloc and std and it ships every six weeks, and no quantity of diligence scales to that. Then AWS built Autoharness, which generates proof harnesses at MIR level with no source changes, enumerating every eligible function in a crate and calling it with fully symbolic inputs. It produced 16,748 harnesses, of which 11,970 verified against Kani's supported classes of undefined behavior: out-of-bounds access, null and dangling dereferences, uninitialized memory, and arithmetic overflow in unsafe contexts. An order of magnitude past what the humans managed, from a machine that does not get bored. What makes the write-up worth your time rather than just a press release is that it refuses to round that number up. Only 989 functions, combining automatic and manual harnesses, are verified against full contracts with explicit preconditions and postconditions. Around 10,200 of the verified functions are safe functions, where Kani symbolically executes through every callee including unsafe code reached transitively, which is real assurance. But some verified unsafe functions passed only because they were exercised on unconstrained bit-valid inputs with no stated precondition, and the paper calls that a useful triage signal rather than a safety proof. That distinction is the whole difference between a verification programme and a dashboard. The honest ceiling is stated too: Autoharness skips over 9,600 generic functions because Rust monomorphizes at compile time and instantiation-based checking does not scale there, and the challenges targeting atomics and Arc remain unsolved, because reasoning about lock-free structures under a relaxed memory model is still hard. Fifteen months of this found zero previously unknown memory-safety vulnerabilities, which the authors read as a quiet endorsement of the existing tests and Miri. What it did find was specification drift: an incorrect SIMD shift result, missing unsafe annotations, incorrect SAFETY comments, and a documentation error in panic behavior, all fixed upstream. Writing a formal specification forces a precision a natural-language comment does not.
Maintenance: actively maintained (AWS applied-science team; Rahul Kumar, Felipe Monteiro, Michael Tautschnig); four tools now in CI (Kani, ESBMC, VeriFast, Flux) with Verus, Creusot, KRust and RAPx under review · Latest: v0.63.0, with Autoharness argument validation and regex pattern options · Adoption: Trial; it runs on every change in Firecracker and s2n-quic, so the tool is proven, and the right first move is Autoharness against your own unsafe blocks rather than a contracts programme

Data plumbing

buf_read_splitter 1.0.0 — This Week in Rust 667's Crate of the Week, self-suggested by flo, who is refreshingly proud of it and notes the algorithm was harder to design than expected. It wraps a reader and splits it into sub-streams on a byte pattern, where each segment is itself a Read you consume to EOF before calling next(). Small, MIT, and it reached 1.0.0 and says so, which is more version discipline than some considerably larger crates managed this week. The detail I would steal even if I never used the crate is Options::set_limit_read, a per-segment byte cap: point it at a stream that never contains your separator and it refuses to eat your heap, by default, rather than because someone remembered to bound it. If you are framing a byte stream you do not control, which in this newsletter usually means SSE frames coming off an inference endpoint or separator-delimited documents heading into an embedding pipeline, that is the failure mode you actually hit at 3am.
Maintenance: single author, small surface (flo); MIT · Latest: v1.0.0, self-suggested Aug 28, 2026; exact publish date unverified this run · Adoption: Assess; one author, no named adopters, and the author's own note that the algorithm was tricky is where you should expect the remaining bugs

Language watch

  • The never type stabilization is in T-types final comment periodrust issue 161925, opened this week. A correction to issue #10, where I wrote that the never type was stabilized: the implementation work merged, the stabilization decision did not, and it is being made right now. My error, and it is the kind that matters, because "stabilized" is the single word that tells you whether you can use a thing on stable.
  • min-publish-age is stabilizedCargo PR 17335, merged in the week of August 25 to September 1. It has been in this section since issue #8 and it is now out of it.
  • cargo-lints is stabilizedCargo PR 17298, same week. Manifest-level lint configuration stops being a nightly conversation.
  • core::mem::DropGuard is in final comment periodPR 161520. Also in FCP: an 8-byte alignment guarantee for RawWakerVTable and re-exporting core::fmt::NumBuffer in alloc and std.
  • i686-pc-windows-msvc drops to Tier 1 without host toolsRFC 3999, approved this week. If you ship a 32-bit Windows toolchain, read it now rather than when it bites.

In brief

Nine Rules for Compile-Time Work with Rust const fn — Carl Kadie on parsing files and building tables at compile time, subtitled "without a build script", which after last week's issue reads less like a style preference and more like a threat model · How we saved 100 terabytes of memory by optimizing 1.1.1.1's DNS cache — Cloudflare, and the number is not a typo · How I made Rustdoc 33% faster in one week by Noah Lev · How we developed the world's first safety-certified product written in Rust, and why we went bare metal — Sonair, which is the certification-evidence conversation most Rust-in-safety threads skip · Could Cargo's scheduler be better? · Pinning Down Rust's Pin · Software That Must Not Be Wrong: Property Tests for a Pediatric Dosing Calculator — the same argument as the Kani entry, at a scale you could copy on Monday · The 'rnull' Rust block driver on LWN · A Self-Baked Async FFI Framework for Rust C# Interop from ScyllaDB · Ubuntu Rust: How Canonical Is Modernizing Core System Tools · two GPUI walkthroughs landed the same week, Your First GPUI App and Drawing Shapes with GPUI's Canvas · and two videos worth the time: An Agentic VM in Rust by Cristian Sánchez, which is the same idea as this week's pick approached from the agent side, and Making Progress on AsyncIterator by Jack O'Connor · rustup 1.29.1 shipped, and the Rust Foundation welcomed Tomáš Šedovič as Program Manager and Jess Izen as Engineer in Residence · compiler perf triage by @panstromek: 5 regressions, 4 improvements, 4 mixed across 39 artifact comparisons, primary mean -0.5%, most of it from type-system micro-optimization and a dead_code lint propagation fix.

Elsewhere

  • Go 1.27 can now find leaked goroutines, and Rust has no equivalent. Go Weekly #616 led with goroutine leak profiles, which spot goroutines permanently blocked on channels or sync primitives, in production, by piggybacking on the garbage collector's reachability tracing. Vlad Saioc was lead author on the academic paper behind it, out of Aarhus, WashU and Uber. The Rust seat at that table is empty, and the reason is structural rather than a gap someone forgot to fill: tokio-console will show you a task that has not been polled in a while, but that is instrumentation and a heuristic, not a proof of unreachability, and there is no GC traversal to hitch a ride on. If you want to know whether a JoinHandle you dropped is a leak or just slow, you are still reading code. I am recording this as a genuine ecosystem gap rather than a nice-to-have, because "the task is stuck forever" is one of the two or three failure modes that actually take down async Rust services, and the current answer is vigilance.
  • Tailscale published its data plane as a library, and Rust's answer is already on this radar. Tailcat, by Brad Fitzpatrick, is WireGuard plus NAT traversal plus DERP as a Go library with the control plane removed: hole-punched connections between any two machines. The Rust pairing is iroh, which was issue #2's entry and hit 1.0 in June with wire-protocol and API stability, QUIC-NAT-Traversal from the IETF draft, and bindings for Python, Node, Swift and Kotlin. It sits at Trial and stays there. Worth noting what is different: Tailcat gives you Tailscale's battle-tested data plane and asks you to bring your own identity story, while iroh's whole premise is that the public key is the address. If you are building agent-to-agent transport, that is not a performance comparison, it is a decision about where identity lives.
  • The Go SDK for MCP hit 1.0 the same week the Rust one hit 3.2. MCP-Go 1.0 shipped from mark3labs. Set that next to the rmcp entry above and you have a fair summary of the protocol's state: two ecosystems, two very different version numbers, one spec that moved in July. Also from Go Weekly, and worth reading whichever language you write: Russ Cox says frontier LLMs are "much better and dramatically faster" than he is at finding and fixing Go bugs, and publishes the agent transcripts rather than asking to be believed. He also mentions he is no longer at Google. And TinyGo 0.42 added an early UEFI target so Go can run before the OS does, which Rust has been able to do via x86_64-unknown-uefi for years; a rare case of the Rust answer being the boring, already-shipped one.

A thought for the week

Your defaults are your policy. Everything else is a preference.

I keep meeting teams with an excellent security posture written down and a mediocre one in production, and the gap is never laziness. It is that the written posture requires someone to do something at a moment when they are busy, and the production posture requires nothing from anyone. Cargo resolves you forward inside a major version whether or not you read the changelog. A build script runs with your credentials whether or not you meant to grant them. Verification covers whichever functions someone had time to write a harness for. None of that is a decision anybody made; all of it is a decision that got made.

Which is why the three good things in this issue are the same thing. min-publish-age is a number the resolver enforces at 3am. Wasmi's fuel metering is a bound the interpreter enforces on code nobody read. Autoharness generated 16,748 harnesses because a machine does not need to be reminded on a Friday. Each replaces vigilance with a mechanism, and mechanisms are the only controls whose effectiveness does not decay with team tenure, headcount changes, or an unusually bad quarter.

And rmcp is the counterweight that makes the point honest, because it shows the default cutting the other way. Nobody at the MCP org decided that everyone on rmcp = "1.7" should get a breaking change; caret resolution decided it, correctly, according to a version number. The maintainers noticed and documented it in a warning box, which is more than most would do. But the lesson is not "be careful with semver". It is that a default you did not choose is still yours to own, and the two questions worth asking in your next architecture review are what your defaults currently do, and which single one of them you could change this quarter so that being busy stops being a security event.

Pick the boring one. min-publish-age in your .cargo/config.toml is a line of TOML, it would have made August 20 a non-event for you, and it is available today rather than after a working group.

Before I go

RustConf is this week in Montréal, September 8 to 11, with the Rust Teams Health Summit alongside it on the 8th, and Oxidize follows in Berlin September 14 to 16. If you are there, Felipe Monteiro is giving the full verification program update, which covers the breakdown by function category and the compilation performance work that made thousands of proofs in CI practical, neither of which fit in the blog post. Rust Bytes is on its bi-weekly cadence and led with RustConf's tenth anniversary, so I have deliberately not led with the conference.

Two things I would like to be wrong about. The first is the leaked-task gap above: if there is a Rust tool that proves a task is unreachable rather than reporting that it looks idle, I want to know and I will feature it. The second is Wasmi's funding. A single maintainer carrying the interpreter that Soroban, Ripple, Typst and Zellij all run, with sponsorship ending in six weeks, is the kind of thing the ecosystem notices in retrospect. If your company ships anything on top of Wasmi, his email is at the bottom of the release post, and this is cheaper to fix now than to discover later.

That's the issue. Got a Rust+AI crate or tool I should feature next week? Reply and tell me; reader picks shape the list.

Keep shipping, Decebal

Rust & AI Crate Radar

Every tool I feature, mapped by verdict· 73 tools

Decebal Dobrica

Let's Connect!

Have questions or want to discuss this further? I'd love to hear from you.