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

nordisk/nornir

.nornir/reasoning.md

Reasoning

Class: reasoning · audience: "why is nornir shaped like this?" This is the f0 file — why the overall shape, and the big rejected alternatives that cut across functions. Per-function "why" lives in each *-reasoning.md. The descriptive what is in design.md; nothing here restates it — this file is only the forks in the road and the reasons we took the branch we took.

f0 — why one warehouse, peer functions, few surfaces

The whole design falls out of one commitment: every fact nornir knows is an append-only Iceberg row, keyed by the git SHA it was true at. Given that, the rest is forced.

Rejected: shelling out (and Mermaid, and JS)

nornir is 100% Rust with no subprocess and no JavaScript: git via gix/russh, Iceberg via skade, docs/diagrams via embedded typst. We rejected the pragmatic "just call the git binary / a Node renderer / Mermaid" path because a shellout makes the tool non-hermetic — it can't run in the airgap, its behaviour depends on what's on PATH, and it can't be a single static binary. The one accepted C exception is the vector embedder's ONNX/tokenizer (opt-in, isolated) — see vector.md. Diagrams are never Mermaid (NUKE-MERMAID): every figure is a static SVG, so the README renders on any git host and the book renders with no diagram engine. The full docbook rationale is in docbook-reasoning.md.

Rejected: reconstructing state from a git walk

The tempting cheap version of "past state" is to git checkout <sha> and re-derive. We rejected it: it is slow (a full re-scan per query), it is lossy (test results, bench numbers and coverage were never in git), and it cannot answer "what did we know at SHA X" — only "what was the source at SHA X". The warehouse records the derived facts too, so a past state is a warehouse read, not a rebuild. Why Iceberg specifically, why a single-writer redb catalog, and the rejected service-catalog (Nessie/Polaris) alternative are in warehouse-reasoning.md.

Rejected: one fat book

The docs used to render to a single book.pdf. We split it into three books by audience — manual.pdf (design + guide, thin), idiot_guide.pdf (every step), unsorted.pdf (the why + the record) — because a single lump forces one reader's needs on every reader, and it made the manual grow every time someone added rationale. The chosen-design rule (a design section names only the design we run; every alternative moves here, to reasoning) is the discipline that keeps manual.pdf thin. This file, and every *-reasoning.md, is where the pruned "why" lives — kept, never thrown away. Full argument: docbook-reasoning.md.

Where each "why" lives

the question answered in
why a workspace is a redb-registry set, not a TOML file workspace-reasoning.md
why Iceberg + single-writer redb + SHA keys warehouse-reasoning.md
why one gate matrix, bench-as-gate, headless robot test-reasoning.md
why rehearse-before-promote, gates-as-code, the publish traps release-reasoning.md
why typst + three books + suffix-routing docbook-reasoning.md
why a single-writer in-process job ledger jobs-reasoning.md
why sealed bundles over a registry mirror airgap-reasoning.md