1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//! Release gates, publish-order walker, deploy.
//!
//! Each gate is a free function returning `Result<()>`. Generated
//! release binaries call them in the order defined in
//! `workspace_holger/release/SPEC.md`.
/// Release dependency-DAG (crate publish-order graph) assembled as a neutral graph
/// model annotated with per-crate registry state — the deep half of the release
/// dep-DAG viz surface.
/// Graph-theory + optimization core the doctor reasons over: Tarjan SCC,
/// condensation → publish waves, MFAS cycle-cut ranking, and the invertive
/// remedy planner over the outcome-space Ω. Pure, deterministic, extractor-agnostic.
/// Pre-cascade validation (catch ALL blockers before any irreversible
/// `cargo publish`): non-members, missing crates.io metadata, dep-API skew (via
/// `--dry-run` verify), detached workspaces, and registry/version consistency —
/// aggregated into one "preflight: N blocking issue(s)" summary with per-issue fixes.
/// Registry-state check (item #10): a pluggable [`registry::RegistryBackend`]
/// (crates.io sparse-index default, custom/private base URL, both pure-Rust
/// `ureq`) that asks the registry "what version is actually PUBLISHED?" and
/// classifies each publish target local-vs-published — catching the
/// local-behind-registry DESYNC (`gatling` 0.1.4-local vs 0.1.6-published)
/// that today's verify-only preflight lets slip through and tear the cascade.
/// Topological ROOT-CAUSE analysis (item #9): partition a flat failure list from
/// the publish/preflight cascade into the ROOT crate(s) and the downstream
/// symptoms each root explains, so the operator fixes the one un-published
/// dependency instead of chasing N dependents' verify failures.
/// Same-version SOURCE-DRIFT detection: a crate whose local source differs from
/// the copy already published at the same version (the "edited without a bump"
/// trap) — a hard preflight blocker, and the inverse (unchanged ⇒ skip republish).
/// Semantic blast radius (EPIC item 7): cross-reference a version bump against the
/// warehouse SCIP call-graph to find the EXACT call sites that touch the changed
/// crate's API — "what actually breaks", not merely "who depends on it".
/// `nornir release undo` (task #32): reverse a release run's mutating steps from
/// the `release_changes` ledger (un-bump, restore `[patch]`, delete/reset branch,
/// yank an immutable publish) + the record wrappers the release path drives.