// dwarves.runa.ron — the FORGE's OWN CI/CD pipeline, authored in the typed `runa`
// format. Dogfood: the constellation's CI/CD engine describes its own build as DATA.
//
// This is the file the dwarves UI **Pipeline** tab renders by default: it is loaded
// through `dwarves_runa::Pipeline::from_ron_str` (which also runs runa's validator — duplicate
// stage / unknown-`needs` / DAG-cycle check), mapped onto facett's engine-agnostic
// `PipelineModel` by `facett_pipeline::RunaPipelineAdapter`, and lit with LIVE per-stage
// status read back from the run history the forge historises (jera-dispatched steps).
// One viewer, many adapters — the SAME `facett-pipeline` DAG viewer knut's Spark
// pipelines and the brokkr build DAG render on.
//
// It is also executable, exactly as authored:
// dwarves run dwarves.runa.ron
// (`DWARVES_REPO_ROOT=/path/to/dwarves` to point it at another checkout; else the repo
// root defaults to this file's directory). Execution is jera jobs — every step of a
// stage is dispatched concurrently through the shared Scheduler (`crate::runa_exec`),
// and a `Build{variant}` drives `nornir-build-thing::build_variant` IN-PROCESS (a real
// `cargo build`, zero shell) against the variant set dwarves declares in
// `.nornir/build-variants.toml`.
//
// ⛔ SAFETY INVARIANT — a runa pipeline NEVER `--execute`s / publishes to crates.io.
// The forge's in-process release backend hard-codes `execute: false`, so the
// `ReleaseDoctor` step below computes the deps-first publish waves and prints the
// cascade but uploads NOTHING. The real, irreversible publish stays the human-gated
// `dwarves workspace-release --execute` path, off this file.
Pipeline(
name: "dwarves-forge",
// Built on every push to main, and always startable by hand.
triggers: [
Push(branch: "main"),
Manual,
],
stages: [
// ── lint: the format + clippy gate, both typed steps — `Lint(tool: Fmt)` is
// `cargo fmt --check`, clippy runs with `-D warnings`. (This used to be
// `Xtask(cmd: "fmt-check")`, a verb the xtask never had: MEASURED on dwarf
// 2026-10-16, `xtask: unknown verb fmt-check`.)
Stage(
name: "lint",
steps: [
Lint(tool: Fmt),
Lint(tool: Clippy, deny_warnings: true),
],
),
// ── build: forge EVERY declared deployment variant via build-thing in-process.
// `"*"` is the whole-set matrix — it fans out over dwarves' five declared
// variants (dwarves · dwarves-thin · dwarves-server · dwarves-ui ·
// dwarves-default) as N concurrent jera jobs, one per variant. The
// `dwarves-default` arm is the task-#89 regression guard: the LEAN default
// feature surface no other variant builds.
Stage(
name: "build",
needs: ["lint"],
steps: [
Build(variant: "*"),
],
),
// ── test: the fast test matrix, gated behind a green build.
Stage(
name: "test",
needs: ["build"],
steps: [
Nextest(all_features: true),
],
),
// ── ui: the forge's OWN egui shell, robot-driven headless (L4 — every UI
// surface is robot-tested). Drives the `dwarves-ui` member's recorded per-tab
// scenario library over the robot seam and gates on the coverage board having
// no gap.
Stage(
name: "ui",
needs: ["build"],
steps: [
RobotDriveMember(
member: "dwarves-ui",
egui_scenarios: ["Warehouse", "Forge", "Pipeline", "Release"],
),
CoverageGate(workspace: "dwarves"),
],
),
// ── doctor: kick off the release engine in DRY-RUN. `ReleaseDoctor` drives the
// in-process dwarves release engine — discover members, plan the deps-first
// publish waves, print the cascade. Nothing is uploaded; this is the
// pre-publish gate matrix as a pipeline step.
Stage(
name: "doctor",
needs: ["test", "ui"],
steps: [
ReleaseDoctor,
],
),
],
)