Skip to content

Developing

How to build the project from a checkout and what the local gate runs before a push. This is the contributor’s page; if you are looking for what the application does, start at Running the app.

Building

A recent stable Rust toolchain (the workspace is edition 2024 — Rust 1.85+) and, for the documentation gates, Node. From the repo root:

Terminal window
cargo build # the everyday build
cargo run -p standalone --release # the app
cargo nextest run --workspace # the whole suite
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check

--workspace is load-bearing on the test and lint rows rather than a flourish: the C ABI crate sits outside the workspace’s default members, so a bare cargo nextest run skips the ABI conformance suite and a bare cargo clippy stops linting the C ABI, and both come back green while covering nothing.

The headless capture CLI and the visual-QA harness have their own page, Headless capture and video.

The pre-push gate

A checked-in .githooks/pre-push runs the fast subset of CI before a push, so a broken push costs seconds locally instead of minutes in CI. It is opt-in per clone — enable it with:

Terminal window
git config core.hooksPath .githooks

An uninstalled clone has no gate. Git will not run a hook from a tracked directory without that config, so until you set it nothing below happens. There is deliberately no auto-install (ADR-0033 Alternative H).

What it runs, stopping at the first failure and naming the step that failed:

StepCommand
Doc linksnode scripts/check-doc-links.mjs
Index rowsnode scripts/check-index-rows.mjs
Index rows (self-test)node scripts/check-index-rows.mjs --self-test
Backlog claimsnode scripts/check-backlog-claims.mjs
Filter figuresnode scripts/check-filter-figures.mjs
Comment hygienenode scripts/check-comment-hygiene.mjs
Contents blocksnode scripts/toc.mjs --check
Contents blocks (self-test)node scripts/toc.mjs --self-test
Reader prosenode scripts/check-reader-prose.mjs
Formatcargo fmt --all --check
Lintcargo clippy --workspace --all-targets -- -D warnings
Testscargo nextest run --workspace -P fast (narrowed — see below)

The Node steps come first because they are the cheapest (tens of milliseconds between them): every relative markdown link in the repo must resolve, every row inside a marked roster region must stay under 320 bytes (ADR-0116), every live design-backlog.md entry must carry a probe that still holds (ADR-0108), the diffusion filter’s cost figures must live in one file (ADR-0122), no .rs comment may carry a relative link or plan-relative narration (ADR-0127), every citation in a reader document must sit inside a link (ADR-0168), and every generated contents block must still match the headings beneath it (ADR-0163). The two that could go green on a rule that had quietly stopped working — a roster detector matching nothing, an anchor rule that is merely plausible — carry a --self-test beside their check. If node is not on your PATH they all skip with a notice rather than failing the push; nothing else here needs Node. That skip is about the hook only — CI’s links job runs the same checks on ubuntu-latest, where they cannot skip and are not bypassable.

Measured warm wall time: ~48.6 s (2026-08-08; dominated by the tests — fmt and clippy are under two seconds between them). The hook excludes the nine GPU-heavy suites that iterate every shipped preset or scene through a real adapter. Which nine is not written here — since ADR-0156 the list is the fast profile’s default-filter in .config/nextest.toml, and the hook and CI’s check job both cite -P fast rather than restating it. The test runner names the skipped binaries itself on every run, on the profile’s authority, so the narrowing is never silent, and CI runs all of them regardless — though since ADR-0073 it runs those nine in the coverage job alone rather than in two Windows jobs, so the promise is now underwritten by one job instead of a redundancy between two.

cargo deny, doctests, Miri, and the coverage job are deliberately not in the hook — they push it into minutes, and a gate that hurts gets disabled (ADR-0033 Alternative F). They are also the checks least likely to break from a local edit.

The spout compile job (ADR-0181) is outside the hook too, and for neither of those reasons. It stages a third-party SDK over the network before it compiles anything, which does not fit the hook’s budget at all — and it is the one CI gate that is likely to break from an ordinary local edit, because code behind #[cfg(feature = "spout")] is not type-checked when the feature is off, so every cargo build, clippy --all-targets and nextest run here is blind to it by construction. If you are refactoring anything standalone/src/stream.rs reaches, compile it yourself before pushing:

Terminal window
powershell -File packaging/spout/fetch-sdk.ps1 # once per checkout
cargo check -p standalone --features spout

Bypass once with git push --no-verify.

What else there is to read

Built from a8ce055 at version 0.115.0. This site tracks main and is not versioned per release.