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

nordisk/knut

.nornir/design.md

knut — design (f0, the whole)

Class: design · Function axis: f0 — how the seven functions wire into one system. Each function has its own *-design.md chapter; this file is the map that joins them. Strict: it states only the shape we run — every why and every rejected alternative lives in reasoning.md.

knut is a knytpunkt (Swedish: hub/junction) over property graphs: it carries graph data the whole way from the columnar world (Arrow, Iceberg, GraphAr files) to a live, queryable graph (FalkorDB) and back out over Arrow Flight SQL — one Arrow pipe, no JVM required. The through-line is Arrow 58, one tree workspace-wide (Cargo.toml [workspace.dependencies]), so every seam is zero-copy or a plain Arc bump.

The seven functions

function crate one-line chapter
graphar graphar the GraphAr gar/v1 chunked-file substrate over object_store graphar-design.md
falkordb graphar-falkordb Arrow RecordBatch → FalkorDB via UNWIND … CREATE/MERGE falkordb-design.md
flight graphar-flight Cypher over Arrow Flight SQL; graph → GraphAr / Iceberg export flight-design.md
bifrost knut-bifrost watch lakehouse tables, materialise them as a graph by CDC bifrost-design.md
thund knut-thund Arrow-native streaming dataflow engine, pluggable backend thund-design.md
pipelines knut-pipelines viewer for Spark Declarative Pipelines + Spark Connect jobs pipelines-design.md
popviz knut-popviz (+knut-popsim) population bulk-loader + headless-introspectable GUI popviz-design.md

The reuse graph (how they fit)

The functions are a layered stack, not a flat list. Each declares what it uses; nothing below depends on anything above it:

graphar            (leaf — object_store only)
  ├─ falkordb      uses graphar          (_gar_id identity)
  │   ├─ flight    uses falkordb, graphar (Flight SQL front + export)
  │   ├─ bifrost   uses falkordb, graphar (table→graph CDC fabric)
  │   └─ popviz    uses falkordb, graphar, popsim
  pipelines        (standalone Spark viewer; facett adapter optional)
  └─ thund         uses pipelines         (IR ⊃ DataflowGraph; SparkBackend reuses the connector)

The Arrow-58 invariant (the seams)

seam where shape
chunk file ↔ Arrow graphar/src/io/mod.rs:read_chunk/write_chunk five formats, one Arrow schema
Arrow → graph graphar-falkordb/src/cypher.rs:ColRenderer per-column downcast, one pre-sized buffer
graph → Arrow graphar-flight/src/convert.rs:response_to_batch FalkorDB RESP → RecordBatch
Arrow → Iceberg graphar-flight/src/export.rs:bridge_56_to_57 identity clone() — knut + skade share Arrow 58
Iceberg → Arrow knut-bifrost/src/source.rs:IcebergSource (feature skade) reverse read of an Iceberg snapshot
Spark ↔ Arrow knut-pipelines/src/client.rs Spark Connect transports results as Arrow batches

Because there is one Arrow major across the workspace, the skade/Iceberg boundary (bridge_56_to_57) is a plain Arc bump, not a copy — the export and its round-trip test read the same seam.

Locked laws (system-wide)

Surfaces (system)

binary / entry function verb
knutpipe pipelines show / watch / gui / pipeline
bifrost bifrost run / gen-sample (feature cli)
knut-popviz popviz GUI loader (feature gui)
Flight SQL server flight run_server / run_server_with
python/knut — thin Flight SQL client → pandas / NetworkX (networkx-export.md)
xtask — the nornir bench suite (benching-benchmarks.md)

See also

Which recipe reader this repo uses, and why (2026-09-20: the code is the source)

Reader: nornir-build-thing 0.1.18, REGISTRY, from crates/knut-build-thing.

knut no longer READS a recipe at all. The impl BuildThing in that crate IS the declaration, and .nornir/build-variants.toml is EMITTED from it (cargo run -p knut-build-thing -- emit) — code → toml, one-directional, never read back as authority. Until 2026-09-20 it ran the other way: the toml was include_str!-ed into crates/knut-build and parsed back, so the file was the build thing and the Rust was a reader of it. The crate's NAME changed with the direction, because dwarves' forge finds a recipe as <repo>-build-thing (a cdylib) and knut-build matched neither — knut's code road was closed by name.

The dependency is the REGISTRY and never a ../edda path: a path dep is read at manifest-load time, so on a box without the sibling it aborts resolution for the WHOLE workspace (measured 2026-09-10). 0.1.18 is the first published version that carries the emitter.

Why: in-constellation; recipe is schema 1. The requirement had been the floating "0.1", and knut's graph carried a registry copy at 0.1.8 beside the path copy at 0.1.9 — two readers of the same file, one repo. The registry half closes on the release cascade (the pull comes through published transitives).

The rule itself — [nornir-build-thing] schema = N, a refusal that names the version to upgrade to, and a loader that refuses to DROP a key it cannot read — lives once, in edda .nornir/build-design.md, "THE COMPATIBILITY RULE". The cross-version guard that would have caught the 2026-08-30 skew is edda/nornir-build-thing-skew.