How snob checks itself#
This repository is checked by snob, and it adopted snob the way an existing codebase would: it pinned the code as it was, and from then on every change needs its reviews. That is not a certification of the code. Most of it was written before the rules and has not been reviewed against them.
1. Baseline what already exists#
The policies in snob/policies/ were committed with a
review file for every matching file, each entry still "changeme". The
commit that added them is pinned in snob.toml:
# snob.toml
[ratchet]
since = "0123456789abcdef0123456789abcdef01234567" # the adoption commit, in full
Every obligation that existed unchanged at that commit now passes as
exempt. That is the inherited debt: snob pending lists it as EXEMPT,
and it can be paid off one review at a time.
Pinning the commit edited snob.toml, and the coverage policy covers every
file, so the first post-baseline review is snob.toml's own: a reviewer,
person or agent, reads the change and records the claim. The gate never
writes semantic claims.
2. Every change needs its reviews#
A file edited after the baseline, a new file, or a reworded rule loses its exemption. A few of the rules that then apply:
| Policy and rule | Applies to | Asks |
|---|---|---|
source/downstream-effects (must) |
src/, examples/, scripts/ and the docs site's code |
what the change affects elsewhere: callers, public contracts, tests, with the evidence |
rust-errors/actionable-errors (must) |
most of src/ |
errors keep the cause and the context needed to act; failures are never silently replaced by defaults |
rust-trust/uncertainty-not-approval (must) |
claim, evaluation, ratchet and trusted-base code | errors, missing evidence and provider failures never yield a pass |
visual-design/accessible-contrast-and-focus (must) |
the docs site's markup, styles, scripts and SVGs | WCAG 2.2 AA contrast and visible keyboard focus, judged from screenshots (evidence, not source) |
snob pending <file> prints a file's checklist and the subject a claim must
name. The reviewer records a local: claim in snob/claims/ and points the
review file at it. The full list of policies is in the
reference below.
3. Automated checks leave receipts, not judgments#
Some rules only ask whether a check ran and passed. scripts/gate.sh
records those itself, as auto-* claims, after every step of a stage
passed:
| Rule | Receipt | Means |
|---|---|---|
rust-quality/gate-passed on Cargo.toml |
local:auto-gate |
fmt, Clippy, tests and docs passed on the pinned toolchain |
rust-quality/msrv-passed on Cargo.toml |
local:auto-msrv |
tests passed on the declared rust-version |
site/build-passed on docs-site/package.json |
local:auto-site |
the docs site built on its pinned Node |
A receipt is bound to the inputs of its check (sources, lockfiles, toolchain
files, the gate script), so changing any of them needs a new run. Semantic
rules are never bound to a receipt: tests/dogfood.rs fails if a review file
points one at an auto-* claim. Receipts are gitignored; CI produces its
own.
4. Pull requests are judged by the target branch#
CI checks out full history and runs, for a pull request,
$ scripts/gate.sh all --trusted-rev "origin/$GITHUB_BASE_REF"
so the target branch's snob.toml, policies and ratchet pin apply. A pull
request cannot move its own baseline or weaken a rule it is judged by. Other
branches and tags are judged by the default branch; the default branch is
checked as committed, so it must only change through reviewed pull requests.
Reference#
The gate#
$ scripts/gate.sh # stable, msrv, site, then snob check
$ scripts/gate.sh all --trusted-rev REV # the same, judged by REV's configuration
$ scripts/gate.sh stable # pinned toolchain: fmt, clippy -D warnings, test, doc -D warnings
$ scripts/gate.sh msrv # cargo +<rust-version> test --locked
$ scripts/gate.sh site # docs site: npm ci --ignore-scripts, npm run build
Each stage deletes its old receipt, notes the subject snob expects, runs, and
writes snob/claims/auto-gate.claim.toml, auto-msrv.claim.toml or
auto-site.claim.toml only if every step passed (the script stops at the
first failure) and the subject did not change meanwhile. Receipts are written
by examples/record_claim.rs with snob's own TOML serializer; each says it
is automated and records the tool versions. The gate refuses to run if rustc
is not the pinned toolchain or the declared minimum, or if node is not the
exact version in docs-site/.node-version.
The site stage needs that Node version with its bundled npm, and network
access for npm ci. Its receipt is bound to the lockfile, Node pin,
TypeScript and Vite config, site source and assets, and the README and docs
the site imports. The docs-site/package.json review file references it as
local:auto-site.
Trusted runner. The gate refuses to run with variables set that change
what cargo, rustc, rustdoc, Clippy, node or npm do (RUSTFLAGS,
RUSTDOCFLAGS, RUSTC*, RUSTDOC, RUSTUP_TOOLCHAIN, CLIPPY_*, CARGO_*
other than CARGO_HOME, CARGO_TARGET_DIR, CARGO_TERM_*,
CARGO_INCREMENTAL, CARGO_NET_* and CARGO_HTTP_*, NPM_CONFIG_*,
npm_config_*, NODE_OPTIONS and NODE_PATH), or with a Cargo config file
outside the repository. npm runs with no user or global configuration, so
only the repository decides its registry and settings, and with install
scripts disabled. Beyond that the machine is trusted: the gate cannot detect
modified tool binaries, a dishonest runner or edits made after it finishes.
An auto-* receipt means "this machine ran the gate", nothing more.
Tooling configuration#
rust-quality on Cargo.toml keeps reviews of configuration apart from
receipts of runs, so each goes stale for its own reasons:
toolchain-and-lints(review):unsafe_codeforbidden; Clippyallandpedanticplus chosen restriction lints, never therestrictionornurserygroups; rustdoc link lints;rust-version;rust-toolchain.tomlpins an exact release; rustfmt defaults; no Cargo config adding flags or aliases.gate-config(review):scripts/gate.shruns every check with failures fatal, verifies toolchains, refuses untrusted overrides and binds receipts correctly; CI runs it on an approved Blacksmith runner.gate-passedandmsrv-passed: the receipts above.
Editing Cargo.toml invalidates all four. Editing rust-toolchain.toml
invalidates the toolchain review and the stable run. Code edits invalidate
only the runs. Disabling a gate step invalidates the gate review and both
runs. tests/dogfood.rs has a test for each case.
Lint exceptions in code are code. tests/dogfood.rs scans every .rs file
and rejects an exception that targets a lint group or a guard lint, applies
to a whole module (one listed dead_code exception for shared test helpers
aside), is conditional (cfg_attr) or has no reason. The same file has
tripwires for the lint table, the toolchain pin, the gate's commands and
failure handling, CI's trusted base, the release workflow and the CI runner
labels. They catch obvious weakening and do not replace the reviews.
Policies#
| Policy | Rule | Level | Files |
|---|---|---|---|
rust-readability |
readable-idiomatic-rust |
must | Rust in src/, tests/, benches/, examples/, and build.rs |
rust-readability |
useful-code-comments |
must | same |
rust-readability |
examples-for-public-apis |
consider | same |
rust-trust |
uncertainty-not-approval |
must | claim, subject, evaluation, ratchet, trusted-base, provider and entry-point code |
rust-errors |
actionable-errors |
must | src/**/*.rs except hash.rs and render.rs |
rust-boundaries |
bounded-operations |
must | git.rs and the providers |
rust-effects |
explicit-side-effects |
should | orchestration modules |
rust-design |
valid-state-types |
should | src/**/*.rs |
rust-design |
earned-abstractions |
consider | src/**/*.rs |
rust-tests |
behavioral-tests |
must | tests/**/*.rs |
source |
downstream-effects |
must | source surfaces: src/, examples/, scripts/ and the docs site's code; not tests or configuration |
format |
format-coherence |
must | code that defines file formats, the provider protocol and report JSON, with their docs |
cli |
cli-design |
must | src/main.rs and src/render.rs, with docs/cli.md |
docs |
accurate-actionable-docs |
must | README.md, docs/**/*.md |
docs |
reader-first-structure, earns-its-space |
should | same |
release |
release-config |
must | the release workflow |
repo-organization |
module-graph, dependencies-earn-their-place, discoverable-layout |
must | Cargo.toml, with the code, lockfile and layout they describe |
repo-organization |
generated-outputs-accounted-for, supported-commands-listed |
should | same |
visual-design |
accessible-contrast-and-focus, responsive-layout |
must | docs-site/ source, judged from desktop and mobile screenshots |
visual-design |
meaningful-hierarchy, readable-type-and-code, purposeful-controls |
should | same |
policies |
coverage-intent |
must | every policy file |
policies |
useful-requirements |
should | every policy file |
coverage |
policy-coverage |
must | every file (role = "coverage") |
coverage/policy-coverage asks of each file whether the right policies
cover it; policies/coverage-intent asks of each policy whether it matches
the right files. Adding a file does not re-open every policy's review: the
new file's own coverage review asks the question.