Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development

The toolchain version is pinned in rust-toolchain.toml, today at 1.97.0, unsafe is forbidden in every crate, and the lint table denies panics, lossy casts, wildcard matches, and undocumented errors. The version in that sentence is this book’s first live value claim: the definition below pins the pinning line itself, so a toolchain bump that forgets this page fails the repository’s own gate with the corrected expectation in the finding.

Gate-tool versions live in one place, the workspace.metadata.tools tables of the root manifest. Runtime consumers use Cargo’s projection directly: the CI tools composite and ratchet hooks query cargo metadata with jq, GitHub’s hashFiles keys the shared tool cache, and the agent lanes install through the composite. A documentation-contract test parses the manifest independently and refuses any workflow spelling a declared tool at another version. Bumping a tool is one edit.

Hooks run through prek: formatting and the cheap checks on commit, then Clippy with warnings denied, the full test suite, cargo deny, cargo shear, and a similarity-rs twin-function gate on push. The tool compares functions within one file, so the gate also concatenates the deliberately parallel provider transports, lane-test harnesses, service runtimes, and verification files. It maps those generated lines back to their source paths and compares stable pair identities with the base Git tree. Every candidate edge must already exist in that base set, so removals pass while new relationships, including an equal-count remove-and-replace, fail. Main and merge-queue CI cache the derived base manifest by tree and policy identity. Pull requests rescan so their private cache scope cannot shadow the default branch; any missing or invalid cache is likewise regenerated from Git, so no mutable baseline or allowlist lives in the tree. A last push-stage hook runs cargo-sweep over target/, dropping artifacts and incremental sessions older than two days; cargo never collects superseded builds, and this repository mints a fresh copy of every test binary on each lockfile or version change. Five days held 86 GB and the sweep reclaimed nothing from it, because every generation was inside the window. The hook is a no-op where cargo-sweep is not installed. CI runs the same two hook stages, so a hook that passes locally passes remotely unless the hook table itself has a bug. What CI adds on top is the work that does not belong on a developer’s machine: the fuzz packages, whose release builds and separate lockfiles cost minutes, and mutation, which costs ten of them for a change of any size. A push should not buy what a pull request already measures.

Two similarly named files point in opposite directions. .pre-commit-config.yaml is the hook table this repository runs on itself through prek. .pre-commit-hooks.yaml is the hook this repository publishes: a consumer’s own pre-commit configuration names this repository and reads that manifest to discover the amiss staged-index check shown in Running it in CI.

cargo nextest run --workspace --locked
cargo clippy --workspace --all-targets --locked -- -D warnings

cargo test --manifest-path fuzz/Cargo.toml --locked --release
cargo clippy --manifest-path fuzz/Cargo.toml --all-targets --locked -- -D warnings

The first pair checks every crate, engine and provider alike, from one lockfile. The second checks the scanner’s standalone fuzz package, which keeps its own lockfile because coverage-guided runs need nightly. The trust boundary is a dependency boundary rather than a workspace boundary: the compiler-output specialist under api/ and the HTTP, provider API, Git acquisition, credential, storage, and service-runtime crates under controller/ are unpublished. deny-engine.toml drops them from the graph and then bans the network and async stack, so what an amiss user downloads cannot acquire it. The prek hooks run the first pair and Linux CI runs both. The macOS and Windows jobs also run the controller tests, including the cross-process file stores, provider authentication, worker, and supervised-process cases. The supported service deployments are documented in Provider-verified controls.

Tests answer to a house rule called the teeth check: important tests are exercised against deliberately broken behavior before they are trusted. The mutation lanes publish a non-gating measurement of that property, in three sizes: per pull request, per push to main, and on demand, each on its own trigger so no lane ever shows as skipped beside another’s run.

Every pull request measures only the mutants the change itself reaches, over shards counted from the mutants the diff actually reaches rather than from a guess, because listing them needs no build. That lane asks the whole workspace whether each mutant lives, at about twenty seconds per mutant. The shards used to pay a worse floor, a cold workspace build plus a baseline test pass repeated in every shard; now each shard restores the build cache that the baseline job saves on every push to main, and skips its own baseline because ci proves the same commit in the same run, so what remains is the build delta against the last merge and the mutants themselves. A release pull request measures its version and generated-file diff like every other pull request. The code it packages was already measured before each change reached main; measuring the accumulated release again would duplicate that work and eventually exceed the bounded PR lane.

The sweep over every mutant in both workspaces runs only when someone asks for it, through workflow_dispatch. It is split across shards sized from the mutant count rather than a fixed number, it takes tens of minutes, and it exists to find gaps in code that no longer changes, which is not something a release should pay for. Fixture crates are excluded, because code that exists to be exercised by its callers says nothing about the tests. Unlike the smaller lanes it runs each mutant against its own package’s tests, which is what makes it affordable and also means a mutant that a sibling package covers is reported as surviving. Its output is a list to verify, not a verdict.

The sweep of 2026-07-28 is the reading to compare against: 6,523 mutants, 4,103 caught, 1,335 missed, 1,085 unviable, no timeouts. Roughly half of those missed are the scoping artifact above, measured at 43% on one file and 62% on another, so the number of real gaps is nearer seven hundred. A later sweep that misses far more has either lost tests or gained untested code, and the point of writing the figure down is to be able to tell which.

None of the three gates a merge and none certifies a global mutation threshold: a surviving mutant is a place where a lie would go unnoticed, to be judged against whether the perturbed value is observable through real behavior, not a score to raise.

Three agent lanes sit beside the gates, none of them gating, written as gh-aw workflows whose agents hold no write token at all: they run read-only on DeepSeek inside the repository’s runners, and a separate harness job posts what their structured outputs request, nothing else. A new issue gets its premise checked against the tree before a maintainer reads it, whoever opened it. Every push to a same-repository, non-draft pull request gets one consolidated review, summary and line-anchored comments in a single card, and a review can be dispatched by hand for any PR number. And /oc in a comment summons the agent, which can answer, fix, and propose a pull request through the same structured channel. What the lanes read is a claim under test, never instructions; only the mention lane takes tasks, and only from a collaborator’s comment. Each comment carries its run link, and the full agent log survives as a run artifact. The parsers sit under a vendored test corpus, pinned by digest, whose manifest records node counts, extraction results, and byte positions for every case from the upstream CommonMark, GFM, and MDX suites; the corpus notes document every known difference. Scanner parsers that take untrusted bytes have targets under fuzz/. The controller fuzz package signs generated provider requests before varying their facts, so its account-free targets reach the provider identity and binding checks. Both suites carry committed seeds and a nightly coverage-guided run.

The scanner runs on its own repository under --profile enforce in CI. This documentation passes through that same gate: every relative link in this book resolves in the tree, or the pull request that broke it fails.

Every pull request also packages what a release would upload. cargo package over the publishable members resolves their siblings through a temporary local registry and builds every tarball, so a file dropped from a package, a path dependency missing a version, or a new crate its dependants cannot see fails on the pull request instead of halfway through an upload that cannot be taken back. It is cargo package rather than cargo publish --dry-run because the dry run prefers a version already on crates.io over the tree, which makes it blind to exactly the crate a change is adding.

Releases are automated. A bot keeps a release pull request current with the version bump, changelog, and exact Action-dispatch ref. Merging it publishes the crates and source tag while the GitHub release remains a draft. The release workflow then assembles the immutable action/vX.Y.Z tree and exercises both that exact tree and the source-tag dispatcher on Linux, both macOS architectures, and Windows. Only a green smoke matrix advances the stable major ref without rewriting history and makes the release public; prereleases never advance the major ref. The same gate governs the release assets: the per-platform engine and prober binaries, their SHA256SUMS, and the sigstore bundle attesting that file attach to the draft, so a release that fails the matrix never publishes a binary. If a forge outage leaves that pull request stale, manually dispatching the release automation on main refreshes its metadata without running the publishing job; crate publication remains restricted to pushes on main. Security checks layer in CI as well. Dependency update PRs arrive with a cooldown, a weekly advisory re-check runs against a fresh database, and CodeQL covers both the Rust and the workflows. Scorecard, secret scanning with push protection, and build provenance attestations on release binaries round it out.

Last change: , commit: 0156d3ce