Skip to main content

Module diagram

Module diagram 

Source
Expand description

Diagrams, canonically: nodes, edges and groups in Rust, derived from whatever already states the topology, and rendered to Mermaid by a function that is one reader among several.

§The authority this takes away

Before this module the model was the Mermaid. site/data/generated/diagrams.json carried six records shaped {mermaid, source, title}, and mermaid was a source string composed by printf in scripts/generate-site-data:

  lib/finish.sh ── grep ──> "completed|partial|…" ── printf ──> "stateDiagram-v2\n …"
                                                                         │
                                                           the only statement of structure

Nothing downstream could read that. A second rendering of the same lifecycle — a Graphviz export, a Cockpit panel, a check asking whether every outcome the tool accepts is actually drawn — had to re-type the topology, and a diagram the repository publishes is then an independent claim about the system rather than a projection of it. That is exactly what project.a-diagram-is-a-projection forbids everywhere else.

So the canonical form is Diagram, and Mermaid is Diagram::to_mermaid: one renderer, replaceable, with no privilege over any other.

use majordomus_cli::diagram::{Diagram, Edge, Kind, Node, Provenance};

let drawn = Diagram::new("greeting", "Two states", Kind::State,
        Provenance::new("lib/finish.sh", "the outcome vocabulary"))
    .with_node(Node::new("active", "active"))
    .with_node(Node::new("done", "done"))
    .with_edge(Edge::new("active", "done").labelled("finish"));

assert_eq!(drawn.to_mermaid(), "stateDiagram-v2\n    active --> done: finish");
assert!(drawn.validate().is_empty(), "a well-formed model has nothing to report");

§Why the order is the derivation’s and not the ids’

crate::graph sorts its nodes, because a graph is a set and two runs must agree. A diagram is a picture, and Mermaid lays one out in declaration order: sorting would make the drawing a function of how the nodes happen to be named. So a Diagram keeps the order its derivation built it in, and determinism is the derivation’s obligation — the same source text builds the same model, and the same model renders to the same bytes.

Structs§

Diagram
A diagram, canonically. Every renderer is a function of this; nothing is a function of a renderer’s output.
Edge
One edge, from a node id to a node id, with the transition or the reason written on it.
Group
A box drawn around several nodes: Mermaid’s subgraph. A flowchart concept — a state machine has composite states instead, which this model does not carry, and Diagram::validate says so rather than dropping the group in silence.
Node
One node: a state, a step, a store. id is unique within the diagram and is what an Edge names; label is what a reader sees. The two are separate because a label is prose that may hold spaces, punctuation and a line break, and an id is a token a renderer writes into its own syntax:
Provenance
Where the topology came from. A diagram that cannot say this is an authored claim about the system, which is the thing this module exists to stop.

Enums§

EdgeStyle
Whether an edge is what happens or merely what is implied.
Kind
What kind of thing the diagram draws, which is also what Mermaid dialect renders it.
Orientation
Which way a flowchart runs. Ignored by Kind::State, which Mermaid always lays out top-down.
Shape
What a node is drawn as. A shape is meaning, not decoration: a Shape::Cylinder says the thing is stored, a Shape::Terminal says the diagram begins or ends there.

Constants§

DIAGRAM_SCHEMA
The shape every projection of a diagram declares itself to be, so that a record written today can still be read when the fields below change.

Functions§

lifecycle
The task lifecycle as a typed diagram, derived from the text of lib/finish.sh.
outcomes
The outcome vocabulary majordomus finish accepts, read out of the shell source that enforces it.