status badge — design
Class:
design· Function axis:f0the badge feature (the whole) ·f1the pure renderer (brokkr::badge) ·f2the latest-run selector ·f3theBadgegRPC RPC ·f4thedwarves badgeCLI verb (fat + thin) Strict: this file states only what the status badge IS — its parts and why they are shaped this way. Sibling how-to: status-badge-guide.md; zero-knowledge walkthrough: status-badge-for-idiots.md.
A status badge is the shields-style pill (⟨ pipeline │ passing ⟩) a README or dashboard <img>s to show a pipeline's health at a glance. dwarves already carried the renderer — brokkr::badge::svg — but it was orphaned: reachable only from its own unit test, wired to no CLI verb and no RPC. The parity spec flagged this twice (D2: "badge still pending its RPC"; D1 wishlist: Badge "remains open"). This feature closes both by making the primitive reachable fat (the local warehouse) and thin (over gRPC) through one shared renderer.
The system as one — the function map (f0)
| part | lives in | what it is |
f1 renderer |
crates/dwarves/src/brokkr/badge.rs |
svg(label, status) → a self-contained SVG pill; color_for/status_text map each RunStatus to its shields colour+word |
f2 selector |
crates/dwarves/src/brokkr/badge.rs |
latest_status(runs, project, pipeline) → the newest matching run's Option<RunStatus> (pure) |
f3 Badge RPC |
crates/dwarves/src/server.rs · proto/dwarf.proto |
DwarfSvc::badge: read_runs → selector → renderer → BadgeReply{svg,status,label,found} |
f4 CLI verb |
crates/dwarves/src/main.rs |
dwarves badge <pipeline>: fat badge_cmd (local warehouse), thin thin_badge (the Badge RPC) |
Why it is shaped this way
- One renderer, both paths (Law #1). The SVG is produced by exactly one function,
brokkr::badge::svg. The fat CLI, the thin CLI's optional--labelre-render, and the server handler all call it — so a badge fetched over the wire is byte-identical to one rendered locally. No twin SVG string anywhere. - A pure selector, testable in isolation.
latest_statustakes a&[PipelineRunRow]and returns the newest match's status. It knows nothing of files or gRPC, so its "newest wins / project filter / cold-startNone" contract is asserted with a plain vec (red-when-broken), and both the server and the fat CLI feed it the rows they already read withstore::read_runs. - A badge never 404s. An unrecorded pipeline is not an error — it renders a grey "unknown" pill (
found=false). Only an empty pipeline name is a hardInvalidArgument. This matches how shields.io behaves and means a README<img>never breaks while a pipeline is still cold. - Every status has its own colour (additive correctness fix). The renderer now maps
passed→green,running→amber,skipped→grey,failed→red, none→grey. Before, any non-green mapped to red — a still-runningbuild read as "failing". The distinct arms fix that without changing the passed/failed/none colours the existing test pins, so no consumer (there were none) regresses. - The exit code doubles as a gate.
dwarves badgeprints the SVG regardless, but exits0iff the latest run is green,1on a recorded non-green,2when no run exists — so the same verb is a scriptable latest-run status check, not only a renderer. - Additive + gated. The renderer/selector live in the always-compiled
brokkrmodule (no feature). TheBadgeRPC +thin_badgeclient compile only under--features server(the proto codegen + tonic), exactly like every other RPC; the fat verb needs neither. nornir's lean path-dep and the published forge pull nothing new.
Place in the nordisk constellation
The badge is a dwarves-owned forge surface (the CI half of the parity map). It reads dwarves' own historized runs (store::read_runs, the JSONL/Iceberg-shaped ledger) — no nornir dependency, no warehouse of its own beyond the run history it already keeps. A future nornir/holger dashboard embeds the same SVG over the Badge RPC (thin gRPC), the same cross-app pattern as nornir-funnel-embed.
Deferred
- No UI pane for the badge. The badge is a CLI + RPC surface; it is not yet mounted as an egui atom in
dwarves-gui(so no robot row — the L4 obligation here is met by the pure-fn + handler drive-and-assert tests + thedwarves::server / badgetestmatrix cell). A small "badge preview" strip in the Pipeline pane is a later slice. runningis best-effort. A badge reflects the newest run row; a run mid-flight historizes asrunningand badges amber, but dwarves' Phase-0 runs are synchronous so this is rarely observed. No live-progress polling.- SVG/PDF regen (
assets/*.svgis committed;docs/*.pdf) is left for the Loki bencher'snornir docs bookrender on push, consistent with prior entries.