dwarves — the build-pipeline DAG (one adapter, the reused viewer)
The dwarves UI shows the forge's build pipeline as a live DAG — the same animated, themed dependency-graph viewer knut renders its Spark/SDP pipelines on. It is not a new viewer. The doctrine (facett_pipeline::model) is explicit: "show another engine's pipeline = a new ADAPTER, not a new viewer." So dwarves ships exactly one new thing — a PipelineAdapter — and hands it to the existing facett-pipeline.
The adapter
dwarves::brokkr::facett_adapter::ForgePipelineAdapter (crate dwarves, feature facett-adapter, off by default) is the ONLY place dwarves touches facett, and facett's model types never leak into dwarves' own public API — it takes brokkr types in and hands a facett_pipeline::PipelineModel out. It mirrors knut's SparkPipelineAdapter one-for-one.
Inputs: a planned brokkr::dag::Dag (structure) + the live job-ledger rows (brokkr::history::BuildRow) + the optional parent PipelineRunRow. The mapping:
| brokkr / ledger | → | PipelineModel |
each step / sub-job (DagNode) |
→ | a Stage (id = step name) |
the run backend (variant/container/vm) |
→ | the stage kind sublabel |
the step's needs |
→ | a PipelineEdge (need → step, source → consumer) |
the ledger RunStatus (Passed/Failed/Running/Skipped) |
→ | StageStatus (Done/Failed/Running/Idle) |
a failed step's summary |
→ | the stage error |
per-step build duration_ms |
→ | the edge throughput label ("0.8s") |
| the run's steps/passed/duration + ledger counts | → | PipelineMetrics (the progress bar) |
Two honesty rules, both asserted in tests:
Skipped(never started — upstream failed / gate skipped) maps to Idle, never a false green; the failure is surfaced on the step that actually failed.- a CI build processes no rows and reads no dataset bytes, so
rows/bytes_readare a hard0("not applicable"), never a fabricated stand-in.
A partial (in-flight) ledger is fine: a DAG node with no matching row renders Idle ("not yet started"), so the DAG animates a run as it progresses.
Where it is wired
dwarves-gui/src/pipeline.rs::pipeline_view() builds the adapter over the forge's own build pipeline fixture and returns PipelineView::from_adapter(&adapter) — a facett_core::Facet (⇒ a Panel). main.rs mounts it as the "Pipeline" tab of the native TabbedView, alongside Forge | Funnel | Claude | Jobs. Native-only, exactly like the Funnel/Claude/Jobs panes; the wasm web demo keeps the single Forge panel.
Coverage (in code, RED-when-broken)
dwarves::brokkr::facett_adapter::tests(featurefacett-adapter, 5 tests): steps→nodes + needs→edges + all-green status; a failed step surfacesFailed+error and poisons the downstream toIdle; build durations → edge labels + pipeline metrics (rows not fabricated); partial ledger → unstarted stepsIdle; feedsPipelineView::from_adapterend-to-end (proving the viewer is reused).dwarves-gui/src/pipeline.rs::tests::forge_pipeline_renders_on_the_reused_viewer+tabbed.rs::tests::robot_pipeline_dag_pane_wired_into_the_host— the pane is wired into the tabbed host and drives over thestate_json/update_jsonremote seam; emitsnornir-testmatrixcells (build_pipeline_dag_renders,pipeline_dag_pane_wired).
Green default AND --features facett-adapter / --features testmatrix.
Diagram: assets/build-pipeline-dag.svg.