holger build-matrix pane — design
Class:
design· Function axis:f0the cockpit pane (the whole) ·f1theResolveHolgerBuildthin-gRPC fetch ·f2the wire→matrix projection ·f3the reused facett-table render ·f4the honest-state classification Strict: this file states only what the holger build-matrix surface IS — its parts and why.
The holger build-matrix pane is the forge cockpit's "which of holger's deployment executables are wired to build, and are they complete" (separation-spec item B2). holger ships ONE source tree built three ways — the deployment tiers embedded · mini · full, each producing its own distinctly-named binary (holger-embedded / holger-mikro / holger-full). dwarves ORCHESTRATES that build; the ResolveHolgerBuild RPC resolves the 3-tier plan against holger's declared build-space (.nornir/build-variants.toml) WITHOUT compiling holger — each tier mapped onto its build target (bin · package · materialized cargo argv), which resolve, and whether the plan is complete. This pane renders that MATRIX (tier × target × status) so a forge operator sees the build landscape in the dwarves UI.
The system as one — the function map (f0)
| part | lives in | what it is |
f0 the pane |
crates/dwarves-embed/src/holgerbuild.rs HolgerBuildPanel |
a Facet/Panel: the matrix table + a status line + auto-poll |
f1 fetch leg |
fetch_holger_build |
thin gRPC ResolveHolgerBuild (Bearer, 3s connect timeout, private current-thread rt) → pb::HolgerBuildReply |
f2 projection |
tiers_from_wire → TierRow |
pure wire→domain map (order preserved); tier_cells formats each tier to the table's string cells |
f3 render |
table_from_tiers → facett_table::Table |
the REUSED generic data-table (columns tier·status·bin·package·cargo, one row per tier, keyed on the tier name) |
f4 honest states |
BuildErr + Conn |
connect ⇒ unreachable, Unauthenticated/PermissionDenied ⇒ auth_failed, Unimplemented ⇒ not_served, found=false ⇒ no_build_space, other ⇒ error/empty |
The RPC seam (server side, unchanged — consumed, not edited): crates/dwarves/proto/dwarf.proto rpc ResolveHolgerBuild(HolgerBuildRequest) returns (HolgerBuildReply) → HolgerBuildReply{ tiers[HolgerTier{tier,step,resolved,bin,package,command_line}], resolved, missing, complete, found }, resolved in crates/dwarves/src/holger_build.rs. The embed's proto/dwarf.proto carries a field-number-exact copy of those three messages + the rpc so the thin client talks to a live dwarves-server WITHOUT the dwarves server feature and with NO holger/nornir dep (that would be a cycle — nornir already depends on dwarves).
Why it is shaped this way
- Consume the existing seam, do NOT twin it (L5).
ResolveHolgerBuildalready exists and is the wire twin of thedwarves holger-buildCLI verb — a COMPILE-FREE plan check. This pane is a thin READ host over it; it never builds holger and never hand-rolls acargoinvocation. The renderer is the sharedfacett_table::Table(the same grid nornir's warehouse uses) — the pane owns only the tier→string-cell formatting. - The
<guest>-embedshape. Mirrors the siblingForgePanel(GetRunReport) andJobsFleetPanel(AgentPool) exactly: a thin tonic client, a pure wire→domain mapping, a reused viewer, an eager first fetch, auto-poll, and astate_json/update_jsonseam. - Honest states — never a silent blank. Every non-render outcome is a DISTINCT, named state folded into
state_json.statusand shown on a coloured status line:loaded(green when the plan is complete, amber when a tier is unwired),no_build_space/empty(grey — connected but holger declares no tiers),unreachable/auth_failed/not_served/error(red). A dropped/renamed tier renders as anunwiredrow with a—placeholder, so a silently-dropped deployment target is VISIBLE, never a false green. - Additive (L2). A new
Buildstab in the dwarves-gui shell; nothing removed.
The seam (robot-testable, headless)
The pane drives over state_json (out) / update_json (in) — the same channel a nornir-robotui scenario and a thin gRPC client use. state_json publishes {status, tiers[], tier_count, resolved, missing, complete, found, error, auto_poll, table:<facett-table state>}; update_json accepts {refresh}, {poll}, {auto_poll}, {holger_root} (pin the server-side checkout + re-resolve) and forwards anything else onto the inner table. The apply_fetch(Result<HolgerBuildReply, BuildErr>) split lets a test drive every state with NO server.
RED-when-broken
robot_build_matrix_shows_live_rows_red_when_empty: a full 3-tier reply throughapply_fetchyieldsstatus:"loaded",tier_count==3,complete==true, and the reused table holds 3 rows; the paired negative leg (an unreachable resolve) is the zero-tier state the oracle rejects — so the test can only pass when real data renders.a_dropped_tier_renders_incomplete_and_unwired: a reply missing thefulltier renders (loaded) but withcomplete==falseand thefulltierresolved==false— no false green.honest_states_are_all_distinct: the four failure legs +no_build_space+emptyeach map to their own status key.robot_pane_drives_over_the_seam: live-reply render + auto-poll toggle +holger_rootpin + a down leg, all over the seam.- Host-level:
dwarves-guirobot_zone_framework_rollout_no_duality_no_demo_buttonnow asserts theBuildstab is HOSTED (kind:"holger_build_matrix") and drives tounreachableoffline.
testmatrix cells: dwarves-embed/holger_build_matrix_shows_live_rows_red_when_empty, dwarves-embed/holger_build_matrix_honest_states, dwarves-embed/holger_build_matrix_pane_drivable.