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.
Dwarves tune — the Heimdall tuner
dwarves tune measures a Build Thing row's programs into seccomp profiles, has a person review them, and gates on drift. <artifact> is a row (rusternetes-node, in the checkout you stand in) or <repo>:<row> (tunnr:rusternetes-node, a checkout beside it or under --checkouts).
dwarves tune probe rusternetes-node # probe + gen: profiles beside the row
dwarves tune probe rusternetes-node --workload smoke # + the runs of the [[driver]] "smoke"
dwarves tune gen rusternetes-node # regenerate from the probe evidence (no probe)
dwarves tune approve rusternetes-node --note "reviewed" # record the review in approved.toml
dwarves tune check rusternetes-node # fail on a new call or an unapproved profile
dwarves tune check tunnr:rusternetes-node --json # the same, as the stable JSON document
dwarves tune show rusternetes-node # the review: calls, near-misses, approval, kernel join
The row lives in .nornir/profiles/<row>/measure.toml (its programs, runs, optional [[driver]] workload drivers, and the heimdall tool pinned by version and sha256). approve writes approved.toml beside it: per program and libc, the sha256 of each reviewed .json / .oci.json, the reviewer's name from git config user.name (never an e-mail address), the date and the note. After that, check fails on any profile that changed since its approval: not approved: <program> <file> changed since <date>.
A workload driver without command adds corpus runs, named <driver>/<run>. A driver with command drives a served app (the served-app runner comes from lane HEIM-APP; until it lands, such a driver is refused by name). gen and check reuse the drivers the last probe used.
Every verb prints text, or one JSON document with --json (schema dwarves.tune/1: ok, tool, programs, checked, drift, out_of_sync, vm_later, approval, review, problems, next, text; a refusal is {ok: false, error}). The exit code is 0 when ok, 1 on findings and 2 on a refusal. A missing tool, an unbuilt binary or an unknown row is one line that names the fix.
Review in the UI
The Build Thing UI (dwarves-gui) has a Syscall profiles tab in the Build area. Pick a <repo>:<row> (every row under $DWARVES_CHECKOUTS, else $DWARVES_CONSTELLATION, else beside the checkout the UI runs in) and it shows what dwarves tune show answers:
- per program and libc, every call of the profile with its action; a call seen only on error paths is marked near-miss (with the test), a bare allow is marked BARE;
- what the probe cannot cover off a VM (the programs and paths that wait for the boot);
- each reviewed file's approval: approved by whom and when, changed since a date, or never approved;
- the drift the last check found, by call and test;
- the kernel options each call needs and the drops a measured call vetoes, when the row has a saved join:
kernel needs <row> --json > .nornir/profiles/<row>/kernel-needs.json.
The Check, Probe and Approve buttons (Approve takes a note; the reviewer is git config user.name) run the same verbs through dwarves::tune, each as a queued jera job (dwarves::tune::jobs, kind dwarves_tune). The pane is redrawn from the verb's own JSON document; it reads no profile itself.
The licence boundary: Heimdall is AGPL-3.0-only and dwarves is MIT OR Apache-2.0. dwarves tune calls edda's nornir_build_thing::measure, which runs the heimdall binary as a separate process and reads its JSON. No heimdall crate is linked.
Every crate in the constellation is held to Brokkr's Software Criteria — baremetal, minimal-dependency, zero-copy / multi-core / SIMD.