| name | state-graph |
| description | Render an existing Stateful state map as a Mermaid diagram, grouped by category (active, failure, interruption, surface) and styled by scope (in, out-with-implication, out). Use whenever a user wants to see their state map as a graph, diagram, or visual overview; wants to embed the map in STATEFUL.md, a README, a PR description, or any other place GitHub-flavoured markdown renders (GitHub renders Mermaid natively); or wants a shareable picture of the map for a stakeholder conversation. Requires an existing state map (state-map.json, a STATEFUL.md state list, or triage tables the user points at). Do not use this skill to create or invent states; the graph is a view of the map, not a source of it. Do not invent transitions between states that the map does not record. |
State Graph
Renders an existing state map as a Mermaid diagram. The diagram is a view; the map stays the source of truth.
Output discipline
No preamble, no narration of the procedure, no restating the map. Deliver the output format below plus only what needs the user's decision. Terse but complete: the Mermaid block, the legend line, the cut note, and nothing else.
Procedure
Before starting. Read STATEFUL.md from the working directory if it exists. Locate the source of truth in this order: state-map.json if present; otherwise the state list and triage recorded in STATEFUL.md or in files the user points at. If no map exists in any form, say so and recommend running state-list first; do not derive states yourself.
- Read the map. Note the count of states, the categories present, and whether scope tags exist (they do after triage; they do not after a bare, untriaged list).
- Choose the diagram shape by size:
- Up to roughly 25 states: one
flowchart TB with a subgraph per category.
- More than that: one diagram per category, or one diagram for in-scope states only, and say which cut was made. A single graph of 50+ nodes is unreadable and helps nobody.
- Generate the Mermaid code:
- One node per state. Use the state id as the node id and the state name as the label. Quote every label; state names contain commas and reserved words (
end in particular breaks Mermaid unquoted).
- Subgraph per category: Active, Failure, Interruption, Surface.
- Style by scope when scope tags exist:
in solid, out-with-implication dashed, out dimmed. Use classDef with names that are not Mermaid keywords (inScope, owi, outScope).
- Draw edges only for transitions the map records. Most Stateful maps record none; a category-grouped map with no edges is a correct and useful output. If the user asks for transition arrows, draft the transitions, show them, and get confirmation before adding them to the map; a transition is map content, not decoration.
- Validate the code renders: no unquoted labels, no keyword collisions, no orphan subgraph syntax.
- Ask where to put it: embedded in
STATEFUL.md under a ## Graph section, a standalone state-graph.md, or returned inline only.
Working memory. If the graph was embedded in STATEFUL.md, stamp Last updated: <date> by state-graph. Record the placement decision in the ## Decisions section (e.g., graph: embedded in STATEFUL.md, including which cut was chosen).
Staying fresh. Once a graph is embedded, the map-writing skills (state-list, state-triage, state-audit) regenerate it as part of their own STATEFUL.md write-back, preserving the recorded cut. You do not need to re-run this skill after every change; run it again only to change the cut, the placement, or to add confirmed transitions.
Inputs required
- An existing state map:
state-map.json, a STATEFUL.md state list, or triage tables (mandatory; the skill does not create states).
- Optional: which cut the user wants (all states, in-scope only, one category).
Output format
```mermaid
flowchart TB
classDef inScope stroke-width:2px
classDef owi stroke-dasharray:5 5
classDef outScope opacity:0.4
subgraph Active
a1["Request form, empty"]:::inScope
a6["Email in inbox, unread"]:::owi
end
subgraph Failure
f22["Link expired"]:::inScope
end
```
<one-line legend: solid = in, dashed = out-with-implication, dimmed = out>
<one-line note on the cut: all states | in-scope only | category X of 4>
Common failure modes
- Inventing transitions. The map records states; most maps record no transitions. Arrows the map does not contain are fabrication, not visualisation. Draft and confirm before adding any.
- One giant graph. 50 nodes in one diagram reads as noise. Cut by category or scope and say so.
- Treating the graph as the artefact. The map is the artefact; the graph is a view of it. If the graph and the map disagree, the graph is wrong.
- Deriving states while graphing. If a state seems missing while building the graph, flag it as a candidate for the state list; do not quietly add a node.
- Unquoted labels. State names contain commas, parentheses, and words Mermaid reserves. Quote every label, always.
Example
Input: The password-reset state-map.json, user asks for in-scope failure states only.
Output (abbreviated):
```mermaid
flowchart TB
classDef inScope stroke-width:2px
subgraph Failure["Failure states (in-scope, 13 of 17)"]
f18["Rate-limited (per email)"]:::inScope
f22["Link expired"]:::inScope
f23["Link already used"]:::inScope
f29["New password fails policy"]:::inScope
f33["Server error during commit"]:::inScope
end
```
Cut: in-scope failure states only (13 of 58 total states). No transitions drawn; the map records none.