Update Workflow Diagram from Mermaid
Purpose
Regenerate the website/ai-workflow.svg file from the canonical mermaid diagram in docs/agents.md . The website uses a hand-crafted blueprint-styled SVG that preserves the exact layout generated by mermaid but applies a custom visual style (technical drawing aesthetic with cyan/white on dark blue).
When to Use
-
After changes to the mermaid diagram in docs/agents.md
-
When adding, removing, or renaming agents/artifacts
-
When modifying the workflow connections
Hard Rules
Must
-
Use mermaid-cli (mmdc ) to render the mermaid diagram to SVG
-
Parse the generated SVG to extract node positions and path definitions
-
Preserve exact node positions and path routing from mermaid output
-
Apply blueprint styling consistently per node type
-
Keep the SVG self-contained (all styles inline or in <style> block)
Must Not
-
Manually calculate node positions (extract from rendered mermaid SVG)
-
Manually recreate path curves (copy exact d attributes from mermaid paths)
-
Change the visual styling without updating this skill documentation
Blueprint Style Reference
Colors
Element Color Notes
Background #0d1b2a
Dark navy blue
Grid lines rgba(255,255,255,0.1)
Subtle white grid
Agent borders #00ffff (cyan) Solid 2px
Agent text #ffffff (white) Monospace font
Meta-agent borders #34d399 (green) Solid 2px
Meta-agent text #34d399 (green) Monospace font
Artifact borders #ffffff (white) Dashed 2px (2,2 )
Artifact fill rgba(0,255,255,0.1)
Subtle cyan
Artifact text #00ffff (cyan) Monospace font
Human borders #ffffff (white) Dashed 2px (4,2 )
Human text #00ffff (cyan) Monospace font
Paths (solid) #00ffff (cyan) 2px with glow
Paths (dashed/feedback) #ff6b6b (coral red) 2px, dasharray 6,3
Arrow markers Same as path color
Node Classes (from mermaid)
Mermaid Class SVG Class Description
human
node-human
Maintainer (dashed white border)
agent
node-agent
Regular agents (solid cyan border)
metaagent
node-metaagent
Workflow Engineer (solid green border)
artifact
node-artifact
Produced documents (dashed white, cyan fill)
Glow Effects
All nodes and paths have CSS filter glow:
/* Nodes */ filter: drop-shadow(0 0 4px rgba(0,255,255,0.6));
/* Paths */ filter: drop-shadow(0 0 2px rgba(0,255,255,0.4));
Actions
- Extract Mermaid Diagram from agents.md
The mermaid diagram is embedded in docs/agents.md within a fenced code block. Extract it to a temporary file:
Create temp directory if needed
scripts/setup-tmp.sh
Extract the mermaid diagram from agents.md
sed -n '/^mermaid$/,/^$/p' docs/agents.md | sed '1d;$d' > .tmp/workflow.mmd
This extracts everything between mermaid and the closing
.
- Render Mermaid to SVG using mermaid-cli
Use the mermaid-cli (mmdc ) to render the diagram to SVG. Install if needed:
Option A: Use npx (no global install needed)
npx -p @mermaid-js/mermaid-cli mmdc -i .tmp/workflow.mmd -o .tmp/workflow-raw.svg -t dark
Option B: Global install
npm install -g @mermaid-js/mermaid-cli mmdc -i .tmp/workflow.mmd -o .tmp/workflow-raw.svg -t dark
Option C: Docker (no Node.js required)
docker run --rm -v "$(pwd)/.tmp:/data" minlag/mermaid-cli -i /data/workflow.mmd -o /data/workflow-raw.svg -t dark
The -t dark flag uses dark theme which matches our target styling better.
- Parse the Generated SVG
The generated .tmp/workflow-raw.svg contains all the positioning data. Parse it to extract:
3a. Get ViewBox
grep -o 'viewBox="[^"]*"' .tmp/workflow-raw.svg
3b. Extract Node Data
Use a script or manual inspection to extract node information. Each node in the mermaid SVG has:
-
A <g> element with class containing the node ID (e.g., flowchart-HUMAN-0 )
-
A transform attribute with the position
-
A <rect> or <polygon> for the shape
-
Text content in <span> or <foreignObject>
Example extraction with grep/sed:
List all node groups with their transforms
grep -E '<g[^>]*class="[^"]node[^"]"' .tmp/workflow-raw.svg
3c. Extract Path Data
Paths are <path> elements with class flowchart-link . Extract the d attributes:
Extract all path d attributes
grep -o 'd="M[^"]*"' .tmp/workflow-raw.svg | head -40
3d. Extract Edge Labels
Edge labels are in <g class="edgeLabel"> elements:
grep -A5 'edgeLabel' .tmp/workflow-raw.svg
- Identify Node Types from Mermaid Source
Read the class definitions from the mermaid source in docs/agents.md :
class HUMAN human; class IA_AGENT,RE,AR,TP_AGENT,QE,DEV,TW,CR,UAT_AGENT,RM,RETRO_AGENT agent; class WE metaagent; class IA,FS,US,ADR,TP,CODE,DOCS,CRR,REL,PR,WD,UAT,RETRO artifact;
Map each node ID to its SVG class:
Node ID Mermaid Class SVG Class
HUMAN
human
node-human
WE
metaagent
node-metaagent
RE , AR , QE , TP_AGENT , DEV , TW , CR , UAT_AGENT , RM , RETRO_AGENT , IA_AGENT
agent
node-agent
FS , IA , WD , ADR , TP , US , CODE , DOCS , CRR , UAT , REL , PR , RETRO
artifact
node-artifact
- Identify Path Types from Mermaid Source
Read the connection definitions to classify paths:
Connection Syntax Path Type Example
==>
path-thick
HUMAN ==> RE
-->
path-solid
RE --> FS --> AR
-- "label" -->
path-solid
CRR -- "Approved" --> UAT_AGENT
-. or -.- or -. "label" .->
path-dashed
CRR -. "Rework" .-> DEV
The dashed paths are feedback loops: "Rework" and "Rendering Issues".
- Build the Blueprint SVG
Create website/ai-workflow.svg using the template structure. The key transformation steps:
-
Copy viewBox from the mermaid-generated SVG
-
Add defs section with grid pattern and arrow markers
-
Add style section with blueprint CSS classes
-
Add background with dark blue fill and grid overlay
-
Copy all paths with their exact d attributes, applying the correct class:
-
First 3 paths (from HUMAN): path-thick
-
Paths with dashed style in source: path-dashed
-
All others: path-solid
-
Copy all nodes with their exact transforms, applying the correct class based on node type
-
Add edge labels at their extracted positions
- Node Text Formatting
When copying node text, apply these transformations:
-
Remove <b> tags
-
For HUMAN node: Use 👤 MAINTAINER (all caps)
-
For agents: Use the agent name as-is
-
For artifacts: Keep the emoji prefix (📄, 📐, ✓, 📋, 💻, 📚, ✅, 🧪, 🚀, 🔀, 📝, 🔍, ⚙️)
- Verify the Result
-
Start local server: python -m http.server 3000
-
Check:
-
All nodes visible with correct styling
-
All paths connect correctly
-
Grid overlay visible
-
Glow effects applied
-
Text readable
-
Run verification: scripts/website-verify.sh --all
SVG Template
<svg xmlns="http://www.w3.org/2000/svg" viewBox="{{VIEWBOX}}" role="graphics-document document" aria-roledescription="flowchart-v2"> <defs> <!-- Blueprint grid pattern --> <pattern id="grid-blueprint" width="20" height="20" patternUnits="userSpaceOnUse"> <path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="0.5"/> </pattern>
<!-- Arrow markers -->
<marker id="arrow-solid" markerWidth="4" markerHeight="4" refX="3.5" refY="2" orient="auto">
<path d="M0,0 L0,4 L4,2 z" fill="#00ffff"/>
</marker>
<marker id="arrow-dashed" markerWidth="4" markerHeight="4" refX="3.5" refY="2" orient="auto">
<path d="M0,0 L0,4 L4,2 z" fill="#ff6b6b"/>
</marker>
<marker id="arrow-thick" markerWidth="4" markerHeight="4" refX="3.5" refY="2" orient="auto">
<path d="M0,0 L0,4 L4,2 z" fill="#00ffff"/>
</marker>
</defs>
<style> /* Human/Maintainer node */ .node-human rect { fill: none; stroke: #ffffff; stroke-width: 2; stroke-dasharray: 4,2; } .node-human text { fill: #00ffff; font-family: monospace; font-size: 13px; font-weight: 600; } .node-human { filter: drop-shadow(0 0 4px rgba(0,255,255,0.6)); }
/* Agent nodes */
.node-agent rect { fill: none; stroke: #00ffff; stroke-width: 2; }
.node-agent text { fill: #ffffff; font-family: monospace; font-size: 13px; font-weight: 600; }
.node-agent { filter: drop-shadow(0 0 4px rgba(0,255,255,0.6)); }
/* Meta-agent nodes */
.node-metaagent rect { fill: none; stroke: #34d399; stroke-width: 2; }
.node-metaagent text { fill: #34d399; font-family: monospace; font-size: 13px; font-weight: 600; }
.node-metaagent { filter: drop-shadow(0 0 4px rgba(52,211,153,0.6)); }
/* Artifact nodes */
.node-artifact rect { fill: rgba(0,255,255,0.1); stroke: #ffffff; stroke-width: 2; stroke-dasharray: 2,2; }
.node-artifact text { fill: #00ffff; font-family: monospace; font-size: 13px; font-weight: 600; }
.node-artifact { filter: drop-shadow(0 0 4px rgba(0,255,255,0.6)); }
/* Paths */
.path-solid { fill: none; stroke: #00ffff; stroke-width: 2; filter: drop-shadow(0 0 2px rgba(0,255,255,0.4)); }
.path-thick { fill: none; stroke: #00ffff; stroke-width: 2; filter: drop-shadow(0 0 2px rgba(0,255,255,0.4)); }
.path-dashed { fill: none; stroke: #ff6b6b; stroke-width: 2; stroke-dasharray: 6,3; filter: drop-shadow(0 0 2px rgba(255,107,107,0.4)); }
/* Edge labels */
.edge-label { fill: rgba(0,255,255,0.8); font-family: monospace; font-size: 10px; font-weight: 500; }
.edge-label-bg { fill: #0d1b2a; }
</style>
<!-- Background with grid --> <rect x="{{X}}" y="{{Y}}" width="{{WIDTH}}" height="{{HEIGHT}}" fill="#0d1b2a"/> <rect x="{{X}}" y="{{Y}}" width="{{WIDTH}}" height="{{HEIGHT}}" fill="url(#grid-blueprint)"/>
<!-- PATHS (render first, behind nodes) --> <!-- Thick paths from HUMAN --> <path class="path-thick" marker-end="url(#arrow-thick)" d="{{PATH_D}}"/>
<!-- Regular solid paths --> <path class="path-solid" marker-end="url(#arrow-solid)" d="{{PATH_D}}"/>
<!-- Dashed paths (feedback loops) --> <path class="path-dashed" marker-end="url(#arrow-dashed)" d="{{PATH_D}}"/>
<!-- Edge labels --> <g transform="translate({{X}}, {{Y}})"> <rect class="edge-label-bg" x="-{{W/2}}" y="-10" width="{{W}}" height="20" rx="3"/> <text class="edge-label" text-anchor="middle" dy="4">{{LABEL_TEXT}}</text> </g>
<!-- NODES --> <!-- Human --> <g class="node-human" transform="translate({{X}}, {{Y}})"> <rect x="-{{W/2}}" y="-{{H/2}}" width="{{W}}" height="{{H}}" rx="2" ry="2"/> <text text-anchor="middle" dy="5">👤 MAINTAINER</text> </g>
<!-- Agent --> <g class="node-agent" transform="translate({{X}}, {{Y}})"> <rect x="-{{W/2}}" y="-{{H/2}}" width="{{W}}" height="{{H}}" rx="2" ry="2"/> <text text-anchor="middle" dy="5">{{AGENT_NAME}}</text> </g>
<!-- Meta-agent --> <g class="node-metaagent" transform="translate({{X}}, {{Y}})"> <rect x="-{{W/2}}" y="-{{H/2}}" width="{{W}}" height="{{H}}" rx="2" ry="2"/> <text text-anchor="middle" dy="5">{{AGENT_NAME}}</text> </g>
<!-- Artifact --> <g class="node-artifact" transform="translate({{X}}, {{Y}})"> <rect x="-{{W/2}}" y="-{{H/2}}" width="{{W}}" height="{{H}}" rx="2" ry="2"/> <text text-anchor="middle" dy="5">{{ARTIFACT_NAME}}</text> </g> </svg>
Updating ai-workflow.html
Ensure website/ai-workflow.html references the SVG:
<section class="workflow-diagram"> <object data="ai-workflow.svg" type="image/svg+xml" style="width: 100%; height: auto; max-height: 80vh;"> <p>Workflow diagram - <a href="ai-workflow.svg">View SVG</a></p> </object> </section>
Prerequisites
-
mermaid-cli: Install via npm install -g @mermaid-js/mermaid-cli or use npx/Docker
-
Local server: Python (python -m http.server ) or similar for verification
Golden Example
The current website/ai-workflow.svg was generated from the mermaid diagram at commit on main branch. Key metrics:
-
ViewBox: -8 -8 686.43359375 2087.03125
-
Nodes: 26 total (1 human, 11 agents, 1 meta-agent, 13 artifacts)
-
Paths: 32 total (3 thick from HUMAN, 27 solid, 2 dashed feedback loops)
-
Edge Labels: 5 (Rework, Approved (UAT needed), Approved (no UAT), Rendering Issues, Approved)
Troubleshooting
Paths don't align with nodes
-
Ensure you're using the exact d attribute from mermaid output, not recalculating
-
Check that node transforms use the same coordinate system
Text is cut off
-
Mermaid may use <foreignObject> for text; extract inner text content
-
Adjust rect width if needed based on text measurement
Glow not visible
-
Check that CSS filter properties are applied to the <g> element, not child elements
-
Some browsers may need vendor prefixes for filters
Colors look wrong
-
Verify the background color is #0d1b2a
-
Check that the grid pattern uses white (rgba(255,255,255,0.1) ), not cyan
References
-
Blueprint design source: website/prototypes/diagram-designs-svg.html (Design 7)
-
Mermaid source: docs/agents.md (search for ```mermaid )
-
Node class mappings: docs/agents.md (search for classDef and class )