Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/nornir-release-core/Cargo.toml

# nornir-release-core — the warehouse-SEAM release READ MODEL: the shared PODs,
# the pure analysis, and the portable gates that BOTH the release conductor
# (dwarves) and the warehouse owner (nornir) reason over.
#
# WHY A LEAF. The release ORCHESTRATION is dwarves' (PRE-PROMPT §L5a — every
# constructive/publishing operation goes to the forge) and the WAREHOUSE is
# nornir's. But the *model* both halves argue about — `RepoGraph`, `DoctorReport`,
# `SkewStatus`, `DepPolicy`, the dep-DAG, the pure graph theory, the portable
# gates — is neither. For eight months it lived inside dwarves and nornir reached
# it with a `dwarves = { path = … }` crate edge, which meant dwarves could never
# compile nornir IN: `nornir → dwarves → nornir` is a cargo cycle and cargo
# rejects those for normal deps regardless of features.
#
# So the model is a primitive, it lives here ONCE, and both conductors consume
# it (L5a's litmus: "a genuine primitive a third unrelated consumer would want
# as-is → an edda leaf"). With the edge gone in the nornir → dwarves direction,
# the forge is free to embed nornir + skade for a real fat build.
#
# WHAT IS *NOT* HERE — deliberately. Nothing constructive. `publish`, `promote`,
# `ramp`, `rehearse`, `preflight`, `finalize`, `undo`, `dirty_sweep`,
# `iso_sandbox` and the Cargo.toml MUTATORS all stay in dwarves, which is the only
# process allowed to *do* a release. This crate READS and JUDGES; it never edits a
# manifest, never spawns a publish, never cuts a branch.
#
# The warehouse is named ONLY through the engine-agnostic
# `nornir-warehouse-trait` seam (never a concrete `IcebergWarehouse`), which is
# what lets a leaf host the warehouse-coupled analysis without depending on
# nornir.
[package]
name = "nornir-release-core"
version = "0.2.2"
edition = "2021"
description = "The shared release read-model: RepoGraph / DoctorReport / SkewStatus PODs, the pure graph theory (Tarjan SCC, publish waves, MFAS cycle cuts), the dep-DAG, semantic blast radius, API-skew, and the portable release gates — over the backend-neutral nornir Warehouse seam. One definition, consumed by both the release orchestrator and the warehouse owner."
license = "MIT OR Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/edda"
keywords = ["release", "dependency-graph", "semver", "cargo", "gate"]
categories = ["development-tools"]
exclude = ["/.nornir/"]

[features]
default = []
# Route this crate's own self-checks into real nornir test-matrix rows. Off by
# default (no `nornir-testmatrix` link); additive, test-only.
testmatrix = ["dep:nornir-testmatrix", "nornir-testmatrix/testmatrix"]
# NOTE — the `cozo` / `falkordb` features are GONE (2026-08-01). They gated
# `cozo_stub` / `falkordb_stub`: config-holder `DepGraph` impls whose query bodies
# were `// TODO` over `Vec::new()`, pulling no dependency and able only ever to
# report green (an empty graph has no cycles and linearizes trivially). The real,
# tested backends now live in the `nornir-graph` leaf behind ITS off-by-default
# features, so there is nothing to gate here.

[dependencies]
anyhow = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
toml = "1"
semver = "1"
# Workspace-member / publish-order derivation off `cargo metadata`.
cargo_metadata = "0.23"
# Pure-Rust registry index poll (sparse index) — no reqwest, no shellout.
ureq = { version = "3", default-features = false, features = ["rustls"] }
# Published `.crate` tarball ingest (the published-API surface reader).
flate2 = "1"
tar = "0.4"
# Pure-Rust git: `changed_crates_since` diffs base..HEAD without shelling `git`.
gix = { version = "0.90", features = ["status"] }
# The ONE graph seam: the `BulkGraph`/`GraphQuery` traits, the pure SCC / topo /
# closure math, and the graph-database backends. `depgraph_trait` is now a
# re-export of it and `graph_math::tarjan_scc` delegates to its Tarjan, so the
# graph theory has exactly one home (LAW 5). Its DEFAULT build is a true leaf
# (std only, zero deps); `petgraph` is the one feature we take, and it is the same
# petgraph 0.6 this crate used to depend on directly — so this adds no new
# dependency, it just moves who owns it.
nornir-graph = { version = "0.2.0", path = "../nornir-graph", features = ["petgraph"] }
# The manifest WALK + the feature→dependency activation graph. This crate used
# to carry its own copy of `walk_cargo_tomls`; the leaf owns it now (LAW 5).
nornir-feature-graph = { version = "0.2.0", path = "../nornir-feature-graph" }
# ── shared edda leaves (never twinned) ──────────────────────────────────────
# The backend-neutral `Warehouse` trait + its POD rows. The ONLY way this crate
# names the warehouse — which is what keeps it a leaf.
nornir-warehouse-trait = { version = "0.2.0", path = "../nornir-warehouse-trait" }
# The ONE knowledge-map reader (`KnowledgeView`, `load_latest`) the semantic-blast
# analysis drives. Consumed, never twinned (L5).
nornir-knowledge-view = { version = "0.2.0", path = "../nornir-knowledge-view" }
# The bench run/result envelope the no-regression + nexus-floor gates reason over.
nornir-bench = { version = "0.2.0", path = "../nornir-bench" }
# The uniform CLI face for the `impacted-crates` READ shaper.
nornir-cli-outcome = { version = "0.1.4", path = "../nornir-cli-outcome" }
# The source-drift detector (same-version "edited without a bump") — re-exported
# from `source_drift` so existing call sites are unchanged.
nornir-release = { version = "0.1.1", path = "../nornir-release" }
# Pure-Rust tag/worktree reads for `git_tag_matches_published` + the dirty check.
nornir-git = { version = "0.2.0", path = "../nornir-git" }
# The tamper-evident guard manifest the `guard_intact` gate verifies. A leaf of
# the nornir REPO, but a standalone crate with no `nornir` edge — no CRATE cycle.
#
# REGISTRY, NOT PATH (fixed 2026-07-31). This used to carry
# `path = "../../../nornir/crates/nornir-guard"`, which always resolves to the
# MAIN nornir checkout. The reasoning above is right about the crate graph and
# misses a different failure entirely: PATH IDENTITY. nornir builds edda, so when
# nornir is built from a git WORKTREE, cargo sees `nornir-guard v0.1.2` twice —
# once as the workspace's own member at the worktree path, once via this line at
# the main-checkout path — and refuses to resolve:
#
#   error: package collision in the lockfile: packages nornir-guard v0.1.2
#   (…/worktrees/<wt>/crates/nornir-guard) and nornir-guard v0.1.2
#   (…/nornir/crates/nornir-guard) are different, but only one can be written
#   to lockfile unambiguously
#
# i.e. ONE line made nornir un-buildable from any worktree, taxing every agent in
# a fleet that works in worktrees by design. It is nastier than it sounds because
# `cargo metadata --no-deps` SUCCEEDS (it never resolves), so a worktree looks
# healthy right up until it builds. The crate is published, so the registry
# version carries the same code with no path identity at all.
# Guarded by tests/no_path_dep_on_our_consumer.rs.
nornir-guard = "0.1.2"
# `testmatrix` only.
nornir-testmatrix = { version = "0.2.8", path = "../nornir-testmatrix", optional = true }

[dev-dependencies]
tempfile = "3"
# The ONE `Warehouse` test double of the seam (never a second hand-written mock).
# NO `version =` on purpose: a versioned path dev-dep is still RESOLVED by
# `cargo publish` even though dev-deps are stripped from the uploaded manifest, so
# it fail-stops whenever the sibling is not already live on the registry — which
# `nornir-release-ledger` is not. Path-only is the shape that publishes.
nornir-release-ledger = { path = "../nornir-release-ledger", features = ["testkit"] }
# Self dev-dep so this crate's OWN tests see `testmatrix` (feature unification
# turns it on for the test build only): it is what makes the `functional_status`
# self-reports inside `#[cfg(test)]` resolve without the normal build ever linking
# the matrix.
nornir-release-core = { path = ".", features = ["testmatrix"] }