
Dwarves
CI/CD software forge inspired by the dwarven craftsmanship that created Odin's spear Gungnir and the gods' treasures, as recorded in the Icelandic Prose Edda (c. 1220 CE).
It binds tightly to Nornir — handling code's time-space dimensional warehouse — and to Holger, the artifact registry guarding your artifacts at rest.
Measured — the forge's planner hot paths
v0.1.4 · oden · 32 cores · 2026-07-22
| workload | build_ms | builds_per_sec | cache_hits_per_sec | elapsed_ms | ids_per_sec | iters | replan_ms | run_ms | steps | steps_per_sec | telem_cores_busy_avg | telem_cores_busy_max | telem_cpu_pct_avg | telem_cpu_pct_max | telem_elapsed_ms | telem_mem_pct_max | telem_mem_peak_mb | telem_n_cores |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dwarves.dag_build | 0.12 | 8546 | 2340 | 20000 | 150 | 2 | 2 | 6.63 | 7.04 | 2342 | 5.44 | 16.98 | 32 | |||||
| dwarves.incremental_cold | 78 | 200 | 0.39 | 150 | 386271 | 2 | 2 | 6.25 | 6.25 | 79.07 | 5.44 | 17.55 | 32 | |||||
| dwarves.incremental_warm | 520476 | 144 | 500 | 0.29 | 150 | 2 | 2 | 6.44 | 6.44 | 145.91 | 5.45 | 17.55 | 32 | |||||
| dwarves.step_input_id | 361 | 1.38M | 500000 | 2 | 2 | 7.03 | 7.03 | 361.39 | 5.46 | 17.55 | 32 |
Dwarves release — usage
Dwarves release is a multi-language, industrialised implementation of cunning, the cargo/crate spec, and academia — built to solve the Codeberg/Nordisk release: 154 crates across 17 repos, cross-repo cycles and all.
dwarves workspace-release . # DEFAULT dry-run — PLAN ONLY: plan the constellation, no build, no branch
dwarves workspace-release . --verify # + the pre-publish cargo-test suite
dwarves workspace-release . --rehearse # + Gate-B: rehearse the cascade into a throwaway local registry
dwarves workspace-release . --execute # for real — verify + rehearse, then crates.io (only after both gates pass)
The run is tiered and cheap-first, build-last: the default dry-run plans only (deps-first order, ship-versions, the static Gate-A precheck, advisory graph analysis) and STOPS — no build, no cargo test, no branch — in milliseconds. --verify adds the cargo-test suite; --rehearse adds the Gate-B /sparring rehearsal; --execute implies both (a real publish always verifies + rehearses), then uploads. Nothing reaches crates.io until two gates go green — Gate A (static) and Gate B (a rehearsal into a throwaway local registry). A build never runs on an already-failed run, and a --verify/--rehearse dry-run builds into the same target --execute reuses, warming its cache.
In the Dwarves UI, the picture below shows a dry-run error — caught by the static Gate A in milliseconds, before any build. With --rehearse/--execute, Dwarves also builds the whole cascade into a staged Holger (a local repo):

Fix the culprit and run again — green means the cascade publishes deps-first:

Several repositories in one run, and the live dry-run
dwarves release takes several repository paths and runs them in the order given.
--only spans all of them. A name that no path publishes, or that two paths publish,
is refused. monetize-impl is never published: a run that names it, or finds it, is
refused before anything is packaged.
# from the estate's parent directory: read-only, uploads nothing
dwarves release tunnr edda monetize Skidbladnir --only korp-installer,appliance-grow --live-dry-run
# the same line with --execute publishes (byte-identical crates are skipped, a 429 waits and retries)
--live-dry-run asks crates.io what is already published, runs the size gate, and
runs cargo publish --dry-run for each crate that would go up, then runs Gate B (the
loopback /sparring rehearsal) exactly as --execute would.
The pre-flight size gate
dwarves release <repo> weighs every crate it is about to upload before it uploads
anything, because crates.io refuses an oversized upload with a bare HTTP 503 that
names neither a size nor a reason — cargo prints failed to get a 200 OK response, got 503 and nothing else.
dwarves release . # dry-run: prints the registry's limit and where the number came from
dwarves release . --check-size # + packages every crate NOW and weighs the .crate
dwarves release . --execute # the size pass runs automatically, before any upload
dwarves release . --max-upload-mib 20 # a granted limit increase (or another registry's limit)
An over-limit crate refuses the whole cascade — exactly like the same-version drift
halt — naming the crate, its compressed size, the limit and its source, and the
biggest directories and files in the .crate, so the exclude to write is on
screen instead of behind a local cargo package. The two honest remedies are printed
with it: ship less, or get the limit raised and pass --max-upload-mib.
The limit is never a magic number. crates.io's 10 MiB is a documented constant (no
registry endpoint publishes it, and a staff-granted per-crate increase is invisible to
the API); it is overridden by --max-upload-mib, DWARVES_MAX_UPLOAD_BYTES_<ALIAS> or
DWARVES_MAX_UPLOAD_BYTES, and for a non-crates.io --registry with no override the
limit is honestly unknown and refuses nothing. If a 503 still arrives mid-cascade,
it is translated: over the limit ⇒ "this 503 IS the size refusal", within it ⇒ "reads
as transient — retrying", never measured ⇒ it says so.
📖 Release pseudocode (Rust) — the dry-run step by step, the two gates, and the formal model, with diagrams.
📐 Release invariants — what a release guarantees, independent of how it is sequenced: the cross-repo dependency model, the invariants upheld today, the ones measured as absent, and why a gate can state the right condition and still be green by construction.
The release process is AI-free — 100% dwarven-forged: deterministic Rust, no model in the loop.
Every crate in the constellation is held to Brokkr's Software Criteria — baremetal, minimal-dependency, zero-copy / multi-core / SIMD.