facett-demo/src/brokkr_tab.rs
//! **The `brokkr` tab** — the brokkr CI/build-pipeline *builder* ([`facett_brokkr`])
//! mounted as a first-class demo surface. A repo declares its pipeline as data in
//! `brokkr.toml` (a name, triggers, and ordered stages of DAG-ordered steps); the
//! builder authors it two ways — a live-parsed **TEXT** editor over the raw TOML, or
//! a structural **CLICK** builder (add/remove stage / step / trigger) with a topo
//! **DAG preview** — kept in sync, with the same structural validation brokkr's own
//! descriptor parser enforces.
//!
//! [`PipelineBuilder`] mirrors the [`Facet`] shape (title / ui / state_json) but
//! lives in a leaf crate free of `facett-core`, so this thin wrapper adopts it into
//! the deck's `Facet` trait (the same pattern `vg_lab_tab` / `sdp_tab` use). Seeded
//! from `PipelineBuilder::demo` so the tab shows a real multi-stage build DAG with
//! no host.
use facett::Facet;
use facett::core::FacetCaps;
use facett_brokkr::PipelineBuilder;
/// The stable tab title (the deck/discovery-contract key + the legend key).
pub const TITLE: &str = "brokkr";
/// The brokkr builder tab: a real [`PipelineBuilder`] seeded with the demo pipeline.
pub struct BrokkrTab {
builder: PipelineBuilder,
}
impl Default for BrokkrTab {
fn default() -> Self {
Self::new()
}
}
impl BrokkrTab {
/// Build the tab over brokkr's demo CI/build pipeline (a multi-stage step DAG).
pub fn new() -> Self {
Self { builder: PipelineBuilder::demo(TITLE) }
}
/// An empty builder (0 stages) — the mega-matrix's `DataState::Empty` cell.
pub fn empty() -> Self {
Self { builder: PipelineBuilder::new(TITLE) }
}
/// The number of stages currently modelled (tests + observability).
pub fn stage_count(&self) -> usize {
self.builder.stage_count()
}
/// The total number of steps across all stages.
pub fn step_count(&self) -> usize {
self.builder.step_count()
}
/// The builder (for deeper assertions).
pub fn builder(&self) -> &PipelineBuilder {
&self.builder
}
}
impl Facet for BrokkrTab {
fn title(&self) -> &str {
self.builder.title()
}
fn caps(&self) -> FacetCaps {
FacetCaps::NONE.themeable()
}
fn kind(&self) -> &'static str {
"brokkr"
}
fn ui(&mut self, ui: &mut egui::Ui) {
self.builder.ui(ui);
}
fn state_json(&self) -> serde_json::Value {
self.builder.state_json()
}
}