dwarves release strategy
Emitted from release_doctor::strategy::REGISTRY — the same table the run is driven from. This document is generated, never written by hand: a hand-written spec drifts from the code the way F_loc drifted from F_pub.
Invariants
| # | invariant | judged against | scope | on | dry run | verdict |
| 1 | Feature-Availability (4th Package-Calculus condition) | F_pub (crates.io) | cross-repo | ON | INERT | BLOCKS (non-forceable) |
| 2 | API-skew: we call what the published dependency exports | F_pub (crates.io) | member-scoped | ON | INERT | BLOCKS (non-forceable) |
| 3 | Minimum-requirement floor | F_pub (crates.io) | member-scoped | ON | INERT | BLOCKS (non-forceable) |
| 4 | Packaging, metadata and policy | F_loc (local source) | single crate | ON | runs | BLOCKS (non-forceable) |
| 5 | Forward semver: the bump signals the break we ship | F_loc vs F_pub (drift) | single crate | ON | INERT | blocks (forceable) |
| 6 | No known-vulnerable dependency in the locked graph | F_loc (local source) | single crate | ON | runs | blocks (forceable) |
| 7 | No uncommitted source on the eve of a publish | F_loc (local source) | member-scoped | off | runs | blocks (forceable) |
| 8 | The compiled artifact did not regress | built artifact | single crate | off | runs | blocks (forceable) |
Read the
dry runcolumn before trusting a clean dry run. Anything short of--executeinstalls an offline registry stub whose every answer isNone, and a registry-backed leg reads that as "not a candidate, skip". Those legs pass vacuously — wired, but inert, which looks exactly like green. The invariants that can answer "can anyone outside this machine build this?" are precisely the ones that cannot answer it on the advisory run.
Detail
Feature-Availability (4th Package-Calculus condition) (--gate-a feature)
- Condition — for every ACTIVE dependency edge e = (u → v), the features Φ(e) the consumer requires ON the provider must be exposed by the provider at the version that will ship: Φ(e) ⊆ F(v)
- Judged against — F_pub (crates.io)
- Scope — cross-repo
- Measures — F(v) is read from the crates.io sparse index (features ∪ features2, yanked versions excluded) for a version already frozen, and from local source only for a version that does not exist on the registry yet. Φ is read from BOTH request syntaxes: a dependency entry's
features = [...]AND the[features]table'spkg/feat/pkg?/feattokens. - Does NOT cover — A provider absent from the registry read is SKIPPED, not guessed — an unreachable registry yields an inconclusive note, never a red. The implicit
defaultrequirement is NOT synthesized (see the module doc on why that would be a false red). - On a dry run — INERT — the offline registry stub answers
None, so this passes vacuously; only--executeexercises it - State — ENABLED
API-skew: we call what the published dependency exports (--gate-a skew)
- Condition — every symbol a member references from a sibling dependency must be exported by the version that sibling RESOLVES TO on the registry
- Judged against — F_pub (crates.io)
- Scope — member-scoped
- Measures — the published sibling's extracted public surface, compared against the referencing member's call sites — statically, before the multi-minute verify build
- Does NOT cover — a glob re-export makes the surface non-enumerable ⇒ INCONCLUSIVE, never a false breaking verdict
- On a dry run — INERT — the offline registry stub answers
None, so this passes vacuously; only--executeexercises it - State — ENABLED
Minimum-requirement floor (--gate-a minreq)
- Condition — the LOWEST published version a declared requirement admits must carry the API the crate calls
- Judged against — F_pub (crates.io)
- Scope — member-scoped
- Measures — the enumerated published version list, resolved to the floor the requirement admits — not the max, which is what every other leg proves
- Does NOT cover — a backend that cannot enumerate versions returns empty ⇒ inconclusive
- On a dry run — INERT — the offline registry stub answers
None, so this passes vacuously; only--executeexercises it - State — ENABLED
Packaging, metadata and policy (--gate-a packaging)
- Condition — the .crate that ships must carry the crates.io-required metadata, a permitted licence, no leaked fixtures, and must fit the upload limit
- Judged against — F_loc (local source) (cannot answer "can a third party resolve this?")
- Scope — single crate
- Measures — the packaged file list from
cargo package --listplus the manifest fields, withdescriptionmeasured in BYTES (an em dash costs 3, so a 996-character description can still be rejected with a 400) - Does NOT cover — judges the local tree — which is correct here, because the question is about the artifact we are about to build, not about the registry
- On a dry run — runs normally
- State — ENABLED
Forward semver: the bump signals the break we ship (--gate-a semver)
- Condition — a breaking public-API change must be released under a bump that semver requires for it
- Judged against — F_loc vs F_pub (drift)
- Scope — single crate
- Measures —
cargo-semver-checksover the prior released version versus the tree being shipped - Does NOT cover — a missing dev tool degrades to an inconclusive note, never a false block
- On a dry run — INERT — the offline registry stub answers
None, so this passes vacuously; only--executeexercises it - State — ENABLED
No known-vulnerable dependency in the locked graph (--gate-a advisory)
- Condition — no crate in the committed lockfile carries a RUSTSEC/OSV advisory
- Judged against — F_loc (local source) (cannot answer "can a third party resolve this?")
- Scope — single crate
- Measures — the lockfile's transitive pins scanned against a vendored advisory-db
- Does NOT cover — an un-vendored advisory-db degrades to a note; a resolver-level yank check reads the index and cannot see a lockfile pinning a vulnerable version
- On a dry run — runs normally
- State — ENABLED
No uncommitted source on the eve of a publish (--gate-a dirty)
- Condition — a member repo must carry no uncommitted NON-lock changes when a real publish runs
- Judged against — F_loc (local source) (cannot answer "can a third party resolve this?")
- Scope — member-scoped
- Measures — the working-tree status walk, with
Cargo.lockchurn always tolerated - Does NOT cover — OFF by default — strictly opt-in
- On a dry run — runs normally
- State — disabled in this configuration
The compiled artifact did not regress (--gate-a binary)
- Condition — the shipped binary must not exceed its size budget nor drop an exported ABI symbol versus the prior release
- Judged against — built artifact (cannot answer "can a third party resolve this?")
- Scope — single crate
- Measures — the built artifact compared against the prior released binary
- Does NOT cover — OFF by default — needs a built artifact plus the prior binary, so it never rides a plain green release
- On a dry run — runs normally
- State — disabled in this configuration