{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://mmdflux.dev/mmds/v1",
"title": "MMDS — Machine-Mediated Diagram Specification",
"description": "Structured JSON output for graph-family Mermaid diagrams produced by mmdflux.",
"type": "object",
"required": [
"version",
"defaults",
"geometry_level",
"metadata",
"nodes",
"edges"
],
"properties": {
"version": {
"const": 1,
"description": "Integer schema version. Incremented on breaking MMDS changes."
},
"profiles": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Optional behavior bundles used for profile negotiation (for example 'mmds-core-v1', 'mmdflux-svg-v1', or 'mmdflux-node-style-v1')."
},
"extensions": {
"type": "object",
"default": {},
"propertyNames": {
"pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*(?:\\.[a-z0-9]+(?:[.-][a-z0-9]+)*)*\\.v[0-9]+$",
"description": "Namespaced extension key ending with '.v{number}', for example 'org.mmdflux.render.svg.v1'."
},
"properties": {
"org.mmdflux.node-style.v1": {
"$ref": "#/$defs/NodeStyleExtension"
}
},
"additionalProperties": {
"type": "object"
},
"description": "Optional namespaced extension payloads keyed by versioned namespace ID."
},
"defaults": {
"$ref": "#/$defs/Defaults",
"description": "Document-level defaults for omitted node/edge fields."
},
"geometry_level": {
"enum": ["layout", "routed"],
"description": "Geometry detail level. 'layout' includes node geometry + edge topology only. 'routed' adds edge paths, bounds, and routing metadata."
},
"metadata": {
"$ref": "#/$defs/Metadata"
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/$defs/Node"
},
"description": "Node inventory, sorted by ID."
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/Edge"
},
"description": "Edge inventory in declaration order."
},
"subgraphs": {
"type": "array",
"items": {
"$ref": "#/$defs/Subgraph"
},
"default": [],
"description": "Subgraph inventory, sorted by ID."
},
"participants": {
"type": "array",
"items": {
"$ref": "#/$defs/Participant"
},
"description": "Sequence diagram participants (timeline family only)."
},
"messages": {
"type": "array",
"items": {
"$ref": "#/$defs/Message"
},
"description": "Sequence diagram messages (timeline family only)."
},
"notes": {
"type": "array",
"items": {
"$ref": "#/$defs/Note"
},
"description": "Sequence diagram notes (timeline family only)."
},
"activations": {
"type": "array",
"items": {
"$ref": "#/$defs/Activation"
},
"description": "Sequence diagram activation bars (timeline family only)."
},
"blocks": {
"type": "array",
"items": {
"$ref": "#/$defs/Block"
},
"description": "Sequence diagram interaction frames (timeline family only)."
},
"participant_boxes": {
"type": "array",
"items": {
"$ref": "#/$defs/ParticipantBox"
},
"description": "Sequence diagram participant groupings (timeline family only)."
}
},
"$defs": {
"Defaults": {
"type": "object",
"required": ["node", "edge"],
"properties": {
"node": {
"$ref": "#/$defs/NodeDefaults"
},
"edge": {
"$ref": "#/$defs/EdgeDefaults"
}
}
},
"NodeDefaults": {
"type": "object",
"required": ["shape"],
"properties": {
"shape": {
"type": "string",
"description": "Default node shape used when a node omits the shape field."
}
}
},
"EdgeDefaults": {
"type": "object",
"required": ["stroke", "arrow_start", "arrow_end", "minlen"],
"properties": {
"stroke": {
"enum": ["solid", "dotted", "thick", "invisible"],
"description": "Default edge stroke used when an edge omits stroke."
},
"arrow_start": {
"enum": [
"none",
"normal",
"cross",
"circle",
"open_triangle",
"diamond",
"open_diamond"
],
"description": "Default source-end marker used when an edge omits arrow_start."
},
"arrow_end": {
"enum": [
"none",
"normal",
"cross",
"circle",
"open_triangle",
"diamond",
"open_diamond"
],
"description": "Default target-end marker used when an edge omits arrow_end."
},
"minlen": {
"type": "integer",
"description": "Default minimum rank separation used when an edge omits minlen."
}
}
},
"Metadata": {
"type": "object",
"required": ["diagram_type", "bounds"],
"properties": {
"diagram_type": {
"type": "string",
"description": "Diagram type identifier (e.g., 'flowchart', 'class')."
},
"direction": {
"enum": ["TD", "BT", "LR", "RL"],
"description": "Layout direction."
},
"bounds": {
"$ref": "#/$defs/Bounds",
"description": "Overall diagram canvas extents in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned. Not guaranteed to be a tight content bounding box."
},
"engine": {
"type": "string",
"description": "Engine+algorithm identifier that produced this output (e.g., 'flux-layered', 'mermaid-layered'). Present when the output was produced via the solve pipeline."
}
}
},
"Node": {
"type": "object",
"required": ["id", "label", "position", "size"],
"properties": {
"id": {
"type": "string",
"description": "Node identifier from Mermaid source."
},
"label": {
"type": "string",
"description": "Display label."
},
"shape": {
"type": "string",
"default": "rectangle",
"description": "Shape name in snake_case. If omitted, consumers should use defaults.node.shape."
},
"parent": {
"type": "string",
"description": "Parent subgraph ID, if any."
},
"position": {
"$ref": "#/$defs/Position",
"description": "Node center position in unitless MMDS coordinate space, not top-left anchor. In current mmdflux output, values are SVG-pixel-aligned."
},
"size": {
"$ref": "#/$defs/Size",
"description": "Node bounding box dimensions in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
}
}
},
"Edge": {
"type": "object",
"required": ["id", "source", "target"],
"properties": {
"id": {
"type": "string",
"description": "Deterministic edge identifier (e.g., 'e0', 'e1') in declaration order."
},
"source": {
"type": "string",
"description": "Source node ID."
},
"target": {
"type": "string",
"description": "Target node ID."
},
"from_subgraph": {
"type": "string",
"description": "Original source subgraph ID when this edge represented a subgraph-as-source endpoint intent."
},
"to_subgraph": {
"type": "string",
"description": "Original target subgraph ID when this edge represented a subgraph-as-target endpoint intent."
},
"label": {
"type": "string",
"description": "Edge label text."
},
"stroke": {
"enum": ["solid", "dotted", "thick", "invisible"],
"default": "solid",
"description": "Stroke style. If omitted, consumers should use defaults.edge.stroke."
},
"arrow_start": {
"enum": [
"none",
"normal",
"cross",
"circle",
"open_triangle",
"diamond",
"open_diamond"
],
"default": "none",
"description": "Arrow at source end. If omitted, consumers should use defaults.edge.arrow_start."
},
"arrow_end": {
"enum": [
"none",
"normal",
"cross",
"circle",
"open_triangle",
"diamond",
"open_diamond"
],
"default": "normal",
"description": "Arrow at target end. If omitted, consumers should use defaults.edge.arrow_end."
},
"minlen": {
"type": "integer",
"default": 1,
"description": "Minimum rank separation. If omitted, consumers should use defaults.edge.minlen."
},
"path": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 2,
"maxItems": 2
},
"description": "Routed edge path as [x, y] coordinate pairs in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned. Routed level only."
},
"label_position": {
"$ref": "#/$defs/Position",
"description": "Label center position in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned. Routed level only."
},
"is_backward": {
"type": "boolean",
"description": "Whether this edge flows backward in the layout direction. Routed level only."
},
"source_port": {
"$ref": "#/$defs/Port",
"description": "Source endpoint attachment metadata. Routed level only."
},
"target_port": {
"$ref": "#/$defs/Port",
"description": "Target endpoint attachment metadata. Routed level only."
}
}
},
"Subgraph": {
"type": "object",
"required": ["id", "title", "children"],
"properties": {
"id": {
"type": "string",
"description": "Subgraph identifier."
},
"title": {
"type": "string",
"description": "Display title."
},
"children": {
"type": "array",
"items": {
"type": "string"
},
"description": "IDs of nodes directly in this subgraph."
},
"parent": {
"type": "string",
"description": "Parent subgraph ID, if nested."
},
"direction": {
"enum": ["TD", "BT", "LR", "RL"],
"description": "Subgraph direction override."
},
"bounds": {
"$ref": "#/$defs/Bounds",
"description": "Subgraph bounding box. Routed level only."
}
}
},
"Port": {
"type": "object",
"required": ["face", "fraction", "position", "group_size"],
"properties": {
"face": {
"enum": ["top", "bottom", "left", "right"],
"description": "Node boundary face where the edge attaches."
},
"fraction": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Fractional position along the face (0.0 = start, 1.0 = end). For top/bottom faces, 0.0 is left and 1.0 is right. For left/right faces, 0.0 is top and 1.0 is bottom."
},
"position": {
"$ref": "#/$defs/Position",
"description": "Computed position on the node boundary in MMDS coordinate space."
},
"group_size": {
"type": "integer",
"minimum": 1,
"description": "Number of edges attached to this face of this node."
}
}
},
"NodeStyleExtension": {
"type": "object",
"required": ["nodes"],
"properties": {
"nodes": {
"type": "object",
"description": "Node-ID keyed style overrides replayed into renderer-visible node fill/stroke/text colors.",
"additionalProperties": {
"$ref": "#/$defs/NodeStyle"
}
}
}
},
"NodeStyle": {
"type": "object",
"minProperties": 1,
"properties": {
"fill": {
"type": "string",
"description": "Raw color token for node fill."
},
"stroke": {
"type": "string",
"description": "Raw color token for node border stroke."
},
"color": {
"type": "string",
"description": "Raw color token for node label text."
}
},
"additionalProperties": false
},
"Position": {
"type": "object",
"required": ["x", "y"],
"properties": {
"x": {
"type": "number",
"description": "X coordinate in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
},
"y": {
"type": "number",
"description": "Y coordinate in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
}
}
},
"Size": {
"type": "object",
"required": ["width", "height"],
"properties": {
"width": {
"type": "number",
"description": "Width in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
},
"height": {
"type": "number",
"description": "Height in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
}
}
},
"Bounds": {
"type": "object",
"required": ["width", "height"],
"properties": {
"width": {
"type": "number",
"description": "Overall width in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned."
},
"height": {
"type": "number",
"description": "Overall height in unitless MMDS coordinate space. In current mmdflux output, values are SVG-pixel-aligned. Consumers should preserve width/height aspect ratio when scaling."
}
}
},
"Rect": {
"type": "object",
"required": ["x", "y", "width", "height"],
"properties": {
"x": { "type": "number" },
"y": { "type": "number" },
"width": { "type": "number" },
"height": { "type": "number" }
}
},
"Participant": {
"type": "object",
"required": ["id", "label", "kind", "position", "size", "lifeline_x"],
"properties": {
"id": { "type": "string", "description": "Participant identifier from source." },
"label": { "type": "string", "description": "Display label (alias if provided, otherwise id)." },
"kind": { "enum": ["participant", "actor"], "description": "Participant visual kind." },
"position": { "$ref": "#/$defs/Position", "description": "Top-left of header box." },
"size": { "$ref": "#/$defs/Size", "description": "Header box dimensions." },
"lifeline_x": { "type": "number", "description": "Center x of the vertical lifeline." }
}
},
"Message": {
"type": "object",
"required": ["id", "from", "to", "line_style", "arrow_head", "text", "y"],
"properties": {
"id": { "type": "string", "description": "Deterministic message ID (m0, m1, ...)." },
"from": { "type": "integer", "minimum": 0, "description": "Source participant index." },
"to": { "type": "integer", "minimum": 0, "description": "Target participant index." },
"line_style": { "enum": ["solid", "dashed"], "description": "Line style." },
"arrow_head": { "enum": ["filled", "open", "cross", "async"], "description": "Arrowhead shape." },
"text": { "type": "string", "description": "Message label text." },
"y": { "type": "number", "description": "Vertical position of the arrow." }
}
},
"Note": {
"type": "object",
"required": ["placement", "participants", "text", "position", "size"],
"properties": {
"placement": { "enum": ["left_of", "right_of", "over"], "description": "Note placement relative to participants." },
"participants": { "type": "array", "items": { "type": "integer", "minimum": 0 }, "description": "Participant indices the note relates to." },
"text": { "type": "string", "description": "Note text." },
"position": { "$ref": "#/$defs/Position", "description": "Top-left of note box." },
"size": { "$ref": "#/$defs/Size", "description": "Note box dimensions." }
}
},
"Activation": {
"type": "object",
"required": ["participant", "y_start", "y_end", "depth"],
"properties": {
"participant": { "type": "integer", "minimum": 0, "description": "Participant index." },
"y_start": { "type": "number", "description": "Top of the activation bar." },
"y_end": { "type": "number", "description": "Bottom of the activation bar." },
"depth": { "type": "integer", "minimum": 0, "description": "Nesting depth (0 = outermost)." }
}
},
"BlockDivider": {
"type": "object",
"required": ["y", "kind", "label"],
"properties": {
"y": { "type": "number", "description": "Vertical position of the divider." },
"kind": { "enum": ["else", "and", "option"], "description": "Divider kind." },
"label": { "type": "string", "description": "Divider label." }
}
},
"Block": {
"type": "object",
"required": ["kind", "label", "rect"],
"properties": {
"kind": { "enum": ["loop", "alt", "opt", "par", "critical", "break", "rect"], "description": "Interaction operator." },
"label": { "type": "string", "description": "Block header label." },
"rect": { "$ref": "#/$defs/Rect", "description": "Bounding rectangle." },
"dividers": { "type": "array", "items": { "$ref": "#/$defs/BlockDivider" }, "default": [], "description": "Interior dividers (else, and, option)." }
}
},
"ParticipantBox": {
"type": "object",
"required": ["participants", "rect"],
"properties": {
"label": { "type": "string", "description": "Optional grouping label." },
"color": { "type": "string", "description": "Optional fill color." },
"participants": { "type": "array", "items": { "type": "integer", "minimum": 0 }, "description": "Participant indices in this grouping." },
"rect": { "$ref": "#/$defs/Rect", "description": "Bounding rectangle." }
}
}
}
}