schematex 0.3.4 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/ai/ai-sdk.cjs +20 -19
- package/dist/ai/ai-sdk.cjs.map +1 -1
- package/dist/ai/ai-sdk.d.cts +2 -2
- package/dist/ai/ai-sdk.d.ts +2 -2
- package/dist/ai/ai-sdk.js +15 -14
- package/dist/ai/ai-sdk.js.map +1 -1
- package/dist/ai/index.cjs +23 -22
- package/dist/ai/index.d.cts +2 -2
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.js +15 -14
- package/dist/{api-BuFilDQB.d.cts → api-BIj9t4Oc.d.cts} +1 -1
- package/dist/{api-BuFilDQB.d.ts → api-BIj9t4Oc.d.ts} +1 -1
- package/dist/browser.cjs +17 -16
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +15 -14
- package/dist/browser.js.map +1 -1
- package/dist/{chunk-4THC4VUA.cjs → chunk-2Z543TC3.cjs} +7 -6
- package/dist/chunk-2Z543TC3.cjs.map +1 -0
- package/dist/{chunk-DNZV4V4R.js → chunk-4SJSIJK2.js} +831 -10
- package/dist/chunk-4SJSIJK2.js.map +1 -0
- package/dist/{chunk-ZKDL6Y3O.js → chunk-5FF2IT3C.js} +5 -4
- package/dist/chunk-5FF2IT3C.js.map +1 -0
- package/dist/chunk-5IKOLUWK.js +89 -0
- package/dist/chunk-5IKOLUWK.js.map +1 -0
- package/dist/{chunk-3RAVPXLN.js → chunk-6URNSB6G.js} +5 -4
- package/dist/chunk-6URNSB6G.js.map +1 -0
- package/dist/{chunk-MIKCKV27.cjs → chunk-BW4KGTV7.cjs} +65 -31
- package/dist/chunk-BW4KGTV7.cjs.map +1 -0
- package/dist/{chunk-DBMZEZLF.cjs → chunk-DHHVYSQX.cjs} +6229 -51
- package/dist/chunk-DHHVYSQX.cjs.map +1 -0
- package/dist/{chunk-6ULC3UHJ.cjs → chunk-E2EJRVWS.cjs} +43 -12
- package/dist/chunk-E2EJRVWS.cjs.map +1 -0
- package/dist/{chunk-5CTERELC.js → chunk-EPKIJEH7.js} +5 -4
- package/dist/chunk-EPKIJEH7.js.map +1 -0
- package/dist/{chunk-IFR34VTL.cjs → chunk-GZY4CJ23.cjs} +5 -4
- package/dist/chunk-GZY4CJ23.cjs.map +1 -0
- package/dist/{chunk-TWAC2IIS.js → chunk-I55HO32M.js} +5 -4
- package/dist/chunk-I55HO32M.js.map +1 -0
- package/dist/{chunk-5SKT7RYR.js → chunk-J7JWMQD5.js} +7 -6
- package/dist/chunk-J7JWMQD5.js.map +1 -0
- package/dist/{chunk-PWI4NFYR.js → chunk-JDBG5DU2.js} +5 -4
- package/dist/chunk-JDBG5DU2.js.map +1 -0
- package/dist/{chunk-VRE5VWDQ.js → chunk-KVP7AORH.js} +43 -12
- package/dist/chunk-KVP7AORH.js.map +1 -0
- package/dist/{chunk-IURM4ZWE.js → chunk-L3CTXXVZ.js} +65 -31
- package/dist/chunk-L3CTXXVZ.js.map +1 -0
- package/dist/chunk-NAGUZFXX.cjs +94 -0
- package/dist/chunk-NAGUZFXX.cjs.map +1 -0
- package/dist/{chunk-H5JYZ5YS.cjs → chunk-OIZ4MYSF.cjs} +5 -4
- package/dist/chunk-OIZ4MYSF.cjs.map +1 -0
- package/dist/{chunk-T47A6XUK.cjs → chunk-QUKVGHN4.cjs} +5 -4
- package/dist/chunk-QUKVGHN4.cjs.map +1 -0
- package/dist/{chunk-V4OVUBLA.cjs → chunk-RYVV5UVI.cjs} +5 -4
- package/dist/chunk-RYVV5UVI.cjs.map +1 -0
- package/dist/{chunk-CQP5YHVK.cjs → chunk-S2KJRHDZ.cjs} +4 -5
- package/dist/chunk-S2KJRHDZ.cjs.map +1 -0
- package/dist/{chunk-5COUZTVA.cjs → chunk-ST5YRTTV.cjs} +5 -4
- package/dist/chunk-ST5YRTTV.cjs.map +1 -0
- package/dist/{chunk-CS67UBP3.cjs → chunk-SUIDD2C5.cjs} +5 -4
- package/dist/chunk-SUIDD2C5.cjs.map +1 -0
- package/dist/{chunk-DHKKDIVT.js → chunk-SZK376QB.js} +5 -4
- package/dist/chunk-SZK376QB.js.map +1 -0
- package/dist/{chunk-WIFGBWET.cjs → chunk-UUBNQV2T.cjs} +4 -5
- package/dist/chunk-UUBNQV2T.cjs.map +1 -0
- package/dist/{chunk-I6VEXSUK.js → chunk-VDSYMSUY.js} +4 -5
- package/dist/chunk-VDSYMSUY.js.map +1 -0
- package/dist/{chunk-J3Y2QDJR.cjs → chunk-WCAADEXJ.cjs} +833 -12
- package/dist/chunk-WCAADEXJ.cjs.map +1 -0
- package/dist/{chunk-XSNNGYXZ.cjs → chunk-YLEVMOK2.cjs} +22 -8
- package/dist/chunk-YLEVMOK2.cjs.map +1 -0
- package/dist/{chunk-HKJRHXGZ.js → chunk-Z5NGIM4Z.js} +6217 -39
- package/dist/chunk-Z5NGIM4Z.js.map +1 -0
- package/dist/{chunk-ZQZNWAHH.js → chunk-ZX74KJPM.js} +4 -5
- package/dist/chunk-ZX74KJPM.js.map +1 -0
- package/dist/{chunk-IZMAZOQI.js → chunk-ZYRCPSBU.js} +22 -8
- package/dist/chunk-ZYRCPSBU.js.map +1 -0
- package/dist/diagrams/blockdiagram/index.cjs +6 -5
- package/dist/diagrams/blockdiagram/index.d.cts +1 -1
- package/dist/diagrams/blockdiagram/index.d.ts +1 -1
- package/dist/diagrams/blockdiagram/index.js +2 -1
- package/dist/diagrams/circuit/index.cjs +8 -7
- package/dist/diagrams/circuit/index.d.cts +1 -1
- package/dist/diagrams/circuit/index.d.ts +1 -1
- package/dist/diagrams/circuit/index.js +2 -1
- package/dist/diagrams/ecomap/index.d.cts +1 -1
- package/dist/diagrams/ecomap/index.d.ts +1 -1
- package/dist/diagrams/entity/index.cjs +6 -5
- package/dist/diagrams/entity/index.d.cts +1 -1
- package/dist/diagrams/entity/index.d.ts +1 -1
- package/dist/diagrams/entity/index.js +2 -1
- package/dist/diagrams/fishbone/index.d.cts +1 -1
- package/dist/diagrams/fishbone/index.d.ts +1 -1
- package/dist/diagrams/flowchart/index.cjs +7 -7
- package/dist/diagrams/flowchart/index.d.cts +2 -2
- package/dist/diagrams/flowchart/index.d.ts +2 -2
- package/dist/diagrams/flowchart/index.js +1 -1
- package/dist/diagrams/genogram/index.d.cts +1 -1
- package/dist/diagrams/genogram/index.d.ts +1 -1
- package/dist/diagrams/ladder/index.cjs +6 -5
- package/dist/diagrams/ladder/index.d.cts +1 -1
- package/dist/diagrams/ladder/index.d.ts +1 -1
- package/dist/diagrams/ladder/index.js +2 -1
- package/dist/diagrams/logic/index.cjs +6 -5
- package/dist/diagrams/logic/index.d.cts +1 -1
- package/dist/diagrams/logic/index.d.ts +1 -1
- package/dist/diagrams/logic/index.js +2 -1
- package/dist/diagrams/orgchart/index.cjs +7 -6
- package/dist/diagrams/orgchart/index.d.cts +1 -1
- package/dist/diagrams/orgchart/index.d.ts +1 -1
- package/dist/diagrams/orgchart/index.js +2 -1
- package/dist/diagrams/pedigree/index.d.cts +1 -1
- package/dist/diagrams/pedigree/index.d.ts +1 -1
- package/dist/diagrams/phylo/index.cjs +7 -6
- package/dist/diagrams/phylo/index.d.cts +1 -1
- package/dist/diagrams/phylo/index.d.ts +1 -1
- package/dist/diagrams/phylo/index.js +2 -1
- package/dist/diagrams/sld/index.cjs +6 -5
- package/dist/diagrams/sld/index.d.cts +1 -1
- package/dist/diagrams/sld/index.d.ts +1 -1
- package/dist/diagrams/sld/index.js +2 -1
- package/dist/diagrams/sociogram/index.cjs +6 -5
- package/dist/diagrams/sociogram/index.d.cts +1 -1
- package/dist/diagrams/sociogram/index.d.ts +1 -1
- package/dist/diagrams/sociogram/index.js +2 -1
- package/dist/diagrams/timing/index.cjs +5 -4
- package/dist/diagrams/timing/index.d.cts +1 -1
- package/dist/diagrams/timing/index.d.ts +1 -1
- package/dist/diagrams/timing/index.js +2 -1
- package/dist/diagrams/venn/index.cjs +9 -8
- package/dist/diagrams/venn/index.d.cts +1 -1
- package/dist/diagrams/venn/index.d.ts +1 -1
- package/dist/diagrams/venn/index.js +2 -1
- package/dist/{index-D3u6vcA4.d.ts → index-CGK0xVls.d.ts} +3 -3
- package/dist/{index-bdfj6FpQ.d.cts → index-OW8eDrKj.d.cts} +3 -3
- package/dist/index.cjs +32 -31
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +14 -13
- package/dist/react.cjs +15 -14
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +14 -13
- package/dist/react.js.map +1 -1
- package/dist/{types-DnU2UlWz.d.ts → types-Gkyab1sL.d.cts} +5 -1
- package/dist/{types-DnU2UlWz.d.cts → types-Gkyab1sL.d.ts} +5 -1
- package/package.json +2 -2
- package/dist/chunk-3RAVPXLN.js.map +0 -1
- package/dist/chunk-4THC4VUA.cjs.map +0 -1
- package/dist/chunk-5COUZTVA.cjs.map +0 -1
- package/dist/chunk-5CTERELC.js.map +0 -1
- package/dist/chunk-5SKT7RYR.js.map +0 -1
- package/dist/chunk-6ULC3UHJ.cjs.map +0 -1
- package/dist/chunk-CQP5YHVK.cjs.map +0 -1
- package/dist/chunk-CS67UBP3.cjs.map +0 -1
- package/dist/chunk-DBMZEZLF.cjs.map +0 -1
- package/dist/chunk-DHKKDIVT.js.map +0 -1
- package/dist/chunk-DNZV4V4R.js.map +0 -1
- package/dist/chunk-H5JYZ5YS.cjs.map +0 -1
- package/dist/chunk-HKJRHXGZ.js.map +0 -1
- package/dist/chunk-I6VEXSUK.js.map +0 -1
- package/dist/chunk-IFR34VTL.cjs.map +0 -1
- package/dist/chunk-IURM4ZWE.js.map +0 -1
- package/dist/chunk-IZMAZOQI.js.map +0 -1
- package/dist/chunk-J3Y2QDJR.cjs.map +0 -1
- package/dist/chunk-MIKCKV27.cjs.map +0 -1
- package/dist/chunk-PWI4NFYR.js.map +0 -1
- package/dist/chunk-T47A6XUK.cjs.map +0 -1
- package/dist/chunk-TWAC2IIS.js.map +0 -1
- package/dist/chunk-V4OVUBLA.cjs.map +0 -1
- package/dist/chunk-VRE5VWDQ.js.map +0 -1
- package/dist/chunk-WIFGBWET.cjs.map +0 -1
- package/dist/chunk-XSNNGYXZ.cjs.map +0 -1
- package/dist/chunk-ZKDL6Y3O.js.map +0 -1
- package/dist/chunk-ZQZNWAHH.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkDHHVYSQX_cjs = require('./chunk-DHHVYSQX.cjs');
|
|
4
4
|
|
|
5
5
|
// src/ai/registry.ts
|
|
6
6
|
var DIAGRAM_REGISTRY = [
|
|
@@ -96,6 +96,24 @@ var DIAGRAM_REGISTRY = [
|
|
|
96
96
|
standard: "IEC 61131-3 Ladder Diagram",
|
|
97
97
|
syntaxKey: "ladder"
|
|
98
98
|
},
|
|
99
|
+
{
|
|
100
|
+
type: "fbd",
|
|
101
|
+
name: "Function Block Diagram (FBD)",
|
|
102
|
+
tagline: "IEC 61131-3 \xA76.4 function blocks wired through named ports.",
|
|
103
|
+
useWhen: "Use for PLC programs that are easier to read as data-flow than as ladder rungs \u2014 boolean logic (AND/OR/NOT/NAND/NOR/XOR), timers (TON/TOF/TP), counters (CTU/CTD), edge detectors (R_TRIG/F_TRIG), comparison (EQ/NE/GT/GE/LT/LE), math (ADD/SUB/MUL/DIV/MOVE), selection (SEL/MUX/MAX/MIN/LIMIT). Inline expression notation `Out = OR(A, AND(B, C))`. Sister language to `ladder` (\xA710) and `sfc` (\xA724); together they form the visual half of IEC 61131-3.",
|
|
104
|
+
cluster: "electrical-industrial",
|
|
105
|
+
standard: "IEC 61131-3:2013 \xA76.4 + \xA72.5 standard FB library; see 23-FBD-STANDARD.md",
|
|
106
|
+
syntaxKey: "fbd"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: "sfc",
|
|
110
|
+
name: "Sequential Function Chart (SFC)",
|
|
111
|
+
tagline: "IEC 61131-3 \xA76.5 step + transition state machine for cyclic PLC sequences.",
|
|
112
|
+
useWhen: "Use for PLC sequential control \u2014 batch reactors, robotic cells, packaging lines, assembly stations \u2014 where the program has explicit phases that hand off to each other on boolean conditions. Steps with action qualifiers (N/S/R/L/D/P), transitions with conditions, alternative branches (single bar, OR semantics) and simultaneous branches (double bar, AND semantics), jumps for loops. Distinct from `state` (UML \u2014 Schematex `state` covers reactive UI/lifecycle FSMs, not cyclic PLC scans) and from `flowchart` (no bars, no qualifiers).",
|
|
113
|
+
cluster: "electrical-industrial",
|
|
114
|
+
standard: "IEC 61131-3:2013 \xA76.5 + IEC 60848 GRAFCET visual subset; see 24-SFC-STANDARD.md",
|
|
115
|
+
syntaxKey: "sfc"
|
|
116
|
+
},
|
|
99
117
|
{
|
|
100
118
|
type: "sld",
|
|
101
119
|
name: "Single-line diagram",
|
|
@@ -114,16 +132,35 @@ var DIAGRAM_REGISTRY = [
|
|
|
114
132
|
standard: "ANSI/ISA-5.1-2009 + ISO 10628-1:2014",
|
|
115
133
|
syntaxKey: "pid"
|
|
116
134
|
},
|
|
135
|
+
{
|
|
136
|
+
type: "breadboard",
|
|
137
|
+
name: "Breadboard / Physical wiring",
|
|
138
|
+
tagline: "Fritzing-style breadboard view \u2014 physical wiring of Arduino / ESP32 / Pi prototypes.",
|
|
139
|
+
useWhen: "Use for maker / Arduino / ESP32 / Raspberry Pi tutorials and lab handouts where the user wants to see *how to physically wire components on a breadboard* \u2014 not the abstract circuit schematic. Address tie-points by `@col-row` (e.g. `@5e`, `@+t8`). Smooth B\xE9zier jumper-wires with conventional colors. Distinct from `circuit` (IEEE 315 schematic \u2014 same prototype, different view).",
|
|
140
|
+
cluster: "electrical-industrial",
|
|
141
|
+
standard: "Fritzing visual conventions + Wokwi DSL precedent (no ISO standard exists for this view; see 26-BREADBOARD-STANDARD.md)",
|
|
142
|
+
syntaxKey: "breadboard"
|
|
143
|
+
},
|
|
117
144
|
// ── Corporate / Legal ────────────────────────────────────────
|
|
118
145
|
{
|
|
119
146
|
type: "entity",
|
|
120
147
|
name: "Entity structure",
|
|
121
148
|
tagline: "Corporate ownership hierarchy with percentage rollup.",
|
|
122
|
-
useWhen: "Use for legal entity structures, holdco/opco charts, international tax charts, Series-A cap-table snapshots. Tiered layout with ownership percentages.",
|
|
149
|
+
useWhen: "Use for legal entity structures, holdco/opco charts, international tax charts, Series-A cap-table snapshots. Tiered layout with ownership percentages. NOT for database schema diagrams \u2014 use `erd` for those.",
|
|
123
150
|
cluster: "corporate-legal",
|
|
124
151
|
standard: "Tier-based ownership hierarchy",
|
|
125
152
|
syntaxKey: "entity"
|
|
126
153
|
},
|
|
154
|
+
// ── Data modeling ────────────────────────────────────────────
|
|
155
|
+
{
|
|
156
|
+
type: "erd",
|
|
157
|
+
name: "Entity-Relationship Diagram (ERD)",
|
|
158
|
+
tagline: "Database schema diagram (crow's-foot tabular entities + cardinality glyphs).",
|
|
159
|
+
useWhen: "Use for relational database schema diagrams \u2014 tables, columns, primary/foreign keys, and cardinality (1..1 / 0..N / 1..N) between tables. DBML-like text DSL plus Mermaid `}o--||` glyph aliases. Distinct from `entity` (which is for corporate/legal ownership). v0.1 supports crow's-foot only; Chen and Barker notations are deferred.",
|
|
160
|
+
cluster: "corporate-legal",
|
|
161
|
+
standard: "Chen 1976 / Everest 1976 (crow's foot) \u2014 implements the crow's-foot subset; see 27-ERD-STANDARD.md",
|
|
162
|
+
syntaxKey: "erd"
|
|
163
|
+
},
|
|
127
164
|
// ── Causality / Analysis ─────────────────────────────────────
|
|
128
165
|
{
|
|
129
166
|
type: "fishbone",
|
|
@@ -162,6 +199,15 @@ var DIAGRAM_REGISTRY = [
|
|
|
162
199
|
standard: "OMG UML 2.5.1 \xA714 + Harel (1987) statechart",
|
|
163
200
|
syntaxKey: "state"
|
|
164
201
|
},
|
|
202
|
+
{
|
|
203
|
+
type: "bpmn",
|
|
204
|
+
name: "BPMN business process",
|
|
205
|
+
tagline: "OMG BPMN 2.0 \u2014 pools and lanes, events, gateways, tasks for organizational processes.",
|
|
206
|
+
useWhen: "Use for business processes that span multiple roles, departments, or systems \u2014 claims handling, hiring, order-to-cash, incident response, ISO-9001 / SOX audits. Pools = participants, lanes = roles, events = start/intermediate/end, gateways = XOR/AND/OR/event-based branches, message flows cross pool boundaries (`~~>`). Distinct from `flowchart` (no pools/lanes/event taxonomy), `state` (mode-centric, not activity-centric), and `pid` (physical equipment, not organisational work).",
|
|
207
|
+
cluster: "behavior-modeling",
|
|
208
|
+
standard: "OMG BPMN 2.0.2 / ISO/IEC 19510:2013 visual subset; see 25-BPMN-STANDARD.md",
|
|
209
|
+
syntaxKey: "bpmn"
|
|
210
|
+
},
|
|
165
211
|
// ── Generic process / flow ───────────────────────────────────
|
|
166
212
|
{
|
|
167
213
|
type: "flowchart",
|
|
@@ -253,6 +299,128 @@ var EXAMPLES = [
|
|
|
253
299
|
"dsl": 'blockdiagram "PID control loop"\nC = block("PID C(s)") [role: controller]\nG = block("Plant G(s)") [role: plant]\nerr = sum(+r, -y)\nr = signal("r (setpoint)")\ny = signal("y (output)")\nin -> r\nr -> err\nerr -> C\nC -> G\nG -> y\nG -> err',
|
|
254
300
|
"notes": '## Scenario\n\nThe standard closed-loop PID block diagram appears in every control systems textbook (Ogata, Franklin, \xC5str\xF6m) and every control system design spec sheet. Schematex renders it from a signal-flow description \u2014 not a generic flowchart \u2014 using proper summing junction symbols and automatic feedback routing.\n\n## Annotation key\n\n- `block("label") [role: ...]` \u2014 transfer function block; `role: controller` and `role: plant` affect visual styling\n- `sum(+r, -y)` \u2014 summing junction: adds the `+r` (reference) signal and subtracts the `-y` (output feedback)\n- `signal("label")` \u2014 named signal node\n- `G -> err` \u2014 the feedback path: plant output `y` routes back to the summing junction\n\n## How to read\n\nThe setpoint `r` enters the summing junction `err`, which subtracts the plant output `y` to compute the error signal. The PID controller `C(s)` processes the error and drives the plant `G(s)`. The plant output `y` is both the system output and the feedback signal. The loop is closed when `G -> err` feeds `y` back to the summing junction.'
|
|
255
301
|
},
|
|
302
|
+
{
|
|
303
|
+
"slug": "bpmn-incident-response",
|
|
304
|
+
"diagram": "bpmn",
|
|
305
|
+
"title": "Production incident response (BPMN)",
|
|
306
|
+
"description": "Three-lane BPMN of an on-call rotation handling a production page \u2014 L1 triage, L2 investigation, and a Comms lane that posts status updates. Exercises timer intermediate event, severity-based XOR routing, and a self-loop on the triage gate.",
|
|
307
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
308
|
+
"tags": [
|
|
309
|
+
"bpmn",
|
|
310
|
+
"business-process",
|
|
311
|
+
"incident-response",
|
|
312
|
+
"timer-event",
|
|
313
|
+
"on-call",
|
|
314
|
+
"sre"
|
|
315
|
+
],
|
|
316
|
+
"complexity": 3,
|
|
317
|
+
"featured": false,
|
|
318
|
+
"dsl": 'bpmn\ndirection: LR\ntitle: "Production incident response"\n\npool "Monitoring" blackbox\n\npool "Engineering" {\n lane "On-call L1" {\n A: start message "Page received"\n ACK: task user "Acknowledge"\n TR: task user "Triage"\n G1: gateway xor "Severity?"\n }\n lane "On-call L2" {\n INV: task user "Investigate"\n ROOT: task service "Root cause"\n FIX: task user "Implement fix"\n DEPLOY: task service "Deploy patch"\n }\n lane "Comms" {\n SP: task send "Status page"\n T1: intermediate timer "30 min"\n UP: task send "Update users"\n PM: task user "Post-mortem"\n Z: end "Resolved"\n }\n}\n\nflows\nA --> ACK\nACK --> TR\nTR --> G1\nG1 --? "P1" --> SP\nG1 --? "P2-P3" --> INV\nG1 --* "info" --> TR\nSP --> INV\nINV --> ROOT\nROOT --> FIX\nFIX --> DEPLOY\nDEPLOY --> T1\nT1 --> UP\nUP --> PM\nPM --> Z\n"Monitoring" ~~> A : "Alert"\nSP ~~> "Monitoring" : "Status"',
|
|
319
|
+
"notes": `The shape of an incident-response runbook is exactly what BPMN was designed for: multiple roles handing off to each other under time pressure, with a clear escalation path and a hard line between "what we did internally" and "what we told users". Generic flowcharts blur those distinctions; BPMN's lanes make them auditable.
|
|
320
|
+
|
|
321
|
+
**Three lanes, three roles.** L1 owns the page-acknowledgement SLA. L2 owns the technical fix. Comms owns the user-facing narrative. Every cross-lane handoff is visible as a sequence-flow that crosses a lane partition. When the post-mortem arrives, you can answer "why did Comms post the all-clear before L2 confirmed?" by reading the lane crossings.
|
|
322
|
+
|
|
323
|
+
**Timer intermediate event.** \`T1: intermediate timer "30 min"\` is a double-ringed circle with a clock-face inner glyph. It says: *wait 30 minutes after the patch deploys before telling users the problem is fixed*. That delay isn't an arbitrary process step \u2014 it's the empirical bake time most SRE teams use to confirm a regression hasn't surfaced. Encoding it as a timer event (rather than a vague "wait" task) lets process-mining tools measure the actual wait distribution in production.
|
|
324
|
+
|
|
325
|
+
**Self-loop on the triage XOR.** The default flow \`G1 --* "info" --> TR\` routes back to triage for info-level pages \u2014 the engineer keeps revisiting the page in their queue rather than escalating. This is a real cycle in the process graph; the layout's DFS cycle-break detects the back edge and lays out the rest as a forward DAG so the columns don't collapse.
|
|
326
|
+
|
|
327
|
+
**Message flow to the monitoring system.** Status-page updates go *out* to the monitoring system as a message flow (\`SP ~~> "Monitoring"\`). The monitoring system is rendered as a black-box pool \u2014 Datadog / PagerDuty / Sentry / whatever your stack uses, you don't model their internals, you just model the message exchange.`
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"slug": "bpmn-loan-approval",
|
|
331
|
+
"diagram": "bpmn",
|
|
332
|
+
"title": "Loan application approval (BPMN)",
|
|
333
|
+
"description": "Single-pool, two-lane BPMN of a bank loan approval workflow. Clerk completeness check feeds underwriter risk-scoring + review with two end states (approved / rejected). Canonical BPMN test case 7.2.",
|
|
334
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
335
|
+
"tags": [
|
|
336
|
+
"bpmn",
|
|
337
|
+
"business-process",
|
|
338
|
+
"loan",
|
|
339
|
+
"banking",
|
|
340
|
+
"xor-gateway"
|
|
341
|
+
],
|
|
342
|
+
"complexity": 2,
|
|
343
|
+
"featured": true,
|
|
344
|
+
"dsl": 'bpmn\ndirection: LR\ntitle: "Loan Application Approval"\n\npool "Bank" {\n lane "Clerk" {\n A: start "Application received"\n B: task user "Check completeness"\n G1: gateway xor "Complete?"\n }\n lane "Underwriter" {\n C: task service "Risk score"\n D: task user "Underwriter review"\n G2: gateway xor "Decision"\n E: end "Approved"\n F: end "Rejected"\n }\n}\n\nflows\nA --> B\nB --> G1\nG1 --? "yes" --> C\nG1 --* "no" --> F\nC --> D\nD --> G2\nG2 --? "approve" --> E\nG2 --* "reject" --> F',
|
|
345
|
+
"notes": 'A real loan approval has more steps \u2014 KYC, fraud screening, document collection, escalation tiers \u2014 but every variant collapses onto this skeleton. The reason a *flowchart* doesn\'t suffice is the **swim-lane semantics**: Clerk and Underwriter are different roles with different SLAs, often different software, sometimes different legal liability. BPMN encodes that division as first-class lanes; a generic flowchart can only hint at it with shape colours.\n\nThe two **XOR gateways** (G1, G2) each have one **conditional flow** (`--?`) and one **default flow** (`--*`). The default flow is rendered with a slash mark at the source \u2014 it\'s the branch taken when no condition matches, and Schematex enforces *exactly one* default per gateway. Both conditional and default flows share the same gateway label ("Complete?" / "Decision"); the branch labels live on the connectors themselves.\n\nThe two end events (Approved / Rejected) sit in the underwriter lane because that\'s who owns the outcome. F is referenced from both gateways \u2014 the rejection path joins from either "incomplete" or "rejected" decisions, which is exactly how a human auditor would expect to read the process.'
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"slug": "bpmn-pizza-order",
|
|
349
|
+
"diagram": "bpmn",
|
|
350
|
+
"title": "Pizza order with black-box customer (BPMN)",
|
|
351
|
+
"description": "Two-pool BPMN \u2014 external Customer (black-box) and a Pizzeria with Clerk / Chef / Delivery lanes. Exercises message flows across pools, manual / send task markers, and a rework loop on the chef's quality check. Canonical BPMN test case 7.1.",
|
|
352
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
353
|
+
"tags": [
|
|
354
|
+
"bpmn",
|
|
355
|
+
"business-process",
|
|
356
|
+
"message-flow",
|
|
357
|
+
"black-box-pool",
|
|
358
|
+
"rework-loop"
|
|
359
|
+
],
|
|
360
|
+
"complexity": 2,
|
|
361
|
+
"featured": true,
|
|
362
|
+
"dsl": 'bpmn\ndirection: LR\ntitle: "Pizza order"\n\npool "Customer" blackbox\n\npool "Pizzeria" {\n lane "Clerk" {\n A: start message "Order received"\n B: task user "Take order"\n }\n lane "Chef" {\n C: task manual "Make pizza"\n G1: gateway xor "Pizza ok?"\n D: task manual "Rework"\n }\n lane "Delivery" {\n E: task send "Deliver"\n F: end "Done"\n }\n}\n\nflows\nA --> B\nB --> C\nC --> G1\nG1 --? "yes" --> E\nG1 --* "no" --> D\nD --> C\nE --> F\n"Customer" ~~> A : "Place order"\nE ~~> "Customer" : "Pizza delivered"',
|
|
363
|
+
"notes": 'This is the OMG-tutorial *hello world* for BPMN \u2014 every BPM textbook and certification course uses some version of it. It\'s a deceptively rich example: in 12 elements it covers every concept that distinguishes BPMN from a generic flowchart.\n\n**Black-box pool.** The customer\'s internal process is unknown (and irrelevant) to the pizzeria, so Customer is rendered as an empty rectangle with no flow objects. Schematex enforces this \u2014 adding a lane or a task inside a `blackbox` pool fails the parse. Black-box pools exist purely as message-flow endpoints.\n\n**Message flows cross pools, sequence flows do not.** The two `~~>` connectors are dashed with an open arrowhead and a small unfilled circle at the source. That\'s the *only* legal way information crosses a pool boundary in BPMN. Schematex\'s parser will reject `A --> "Customer"` with a clear error.\n\n**Rework loop.** `D --> C` creates a back-edge. The layout\'s longest-path layering would normally fail on cycles; Schematex\'s DFS-based cycle-break tags `D \u2192 C` as a back edge, runs longest-path on the remaining DAG, then routes the loop manually. This is exactly how real processes look \u2014 quality gates always have a "go back and redo it" branch.\n\n**Task markers communicate intent.** `start message` (envelope) means "wait for an inbound message before starting"; `task manual` means a person performs the work without software ("hand-toss the dough"); `task send` means "send a message and continue". An LLM picking markers correctly turns a vague flowchart into a precise process spec.'
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"slug": "breadboard-blink-led",
|
|
367
|
+
"diagram": "breadboard",
|
|
368
|
+
"title": "Blink LED on Arduino Uno",
|
|
369
|
+
"description": "The maker hello-world. Arduino Uno + 220\u03A9 resistor + 5mm red LED \u2014 D13 \u2192 resistor \u2192 LED \u2192 GND. Tests basic part placement, beside-left MCU, and the iconic B\xE9zier wire arc.",
|
|
370
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
371
|
+
"tags": [
|
|
372
|
+
"breadboard",
|
|
373
|
+
"arduino",
|
|
374
|
+
"uno",
|
|
375
|
+
"led",
|
|
376
|
+
"blink",
|
|
377
|
+
"tutorial"
|
|
378
|
+
],
|
|
379
|
+
"complexity": 1,
|
|
380
|
+
"featured": true,
|
|
381
|
+
"dsl": 'breadboard\nboard: half\ntitle: "Blink LED \u2014 Arduino Uno hello-world"\n\nparts\n uno: mcu uno @beside-left\n r1: resistor 220 @5e..9e\n d1: led red @10e..10f\n\nwires\n uno:5V --red-- @+t1\n uno:GND --black-- @-t1\n @+t1 --red-- @5a\n uno:D13 --yellow-- @9a\n @10j --black-- @-t1',
|
|
382
|
+
"notes": `The "Blink" sketch is the Arduino equivalent of \`printf("hello\\n")\` \u2014 the smallest program that proves the toolchain, board, and wiring all work. The breadboard wiring routes D13 through a 220\u03A9 current-limiting resistor into the LED's anode (long lead, row e), and pulls the cathode (short lead, row f) down to ground via the bottom rail. Power and ground rails are jumpered from the Uno's 5V and GND pins on the left.
|
|
383
|
+
|
|
384
|
+
If the LED doesn't light up, three things to check, in order: LED polarity (the flat-side flag in the diagram is the cathode); resistor value (220\u2013330\u03A9 works for a 5mm red LED at 5V); and that D13 is the actual pin you're toggling in your sketch.`
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"slug": "breadboard-esp32-oled",
|
|
388
|
+
"diagram": "breadboard",
|
|
389
|
+
"title": "ESP32 + SSD1306 OLED I\xB2C",
|
|
390
|
+
"description": 'ESP32 DevKit driving a 128\xD764 OLED display over I\xB2C \u2014 four wires (3V3 / GND / SDA / SCL). The standard "first display" project for ESP32 learners.',
|
|
391
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
392
|
+
"tags": [
|
|
393
|
+
"breadboard",
|
|
394
|
+
"esp32",
|
|
395
|
+
"oled",
|
|
396
|
+
"ssd1306",
|
|
397
|
+
"i2c",
|
|
398
|
+
"display"
|
|
399
|
+
],
|
|
400
|
+
"complexity": 2,
|
|
401
|
+
"featured": false,
|
|
402
|
+
"dsl": 'breadboard\nboard: half\ntitle: "ESP32 + SSD1306 OLED I\xB2C"\n\nparts\n esp: mcu esp32 @beside-left\n oled: display oled-ssd1306 @8a\n\nwires\n oled:GND --black-- @-t1\n oled:VCC --red-- @+t1\n oled:SCL --white-- @10c\n oled:SDA --green-- @11c\n esp:3V3 --red-- @+t1\n esp:GND --black-- @-t1\n esp:GPIO22 --white-- @10c\n esp:GPIO21 --green-- @11c',
|
|
403
|
+
"notes": "The SSD1306 OLED is the canonical first display project for an ESP32. Four wires get a 128\xD764 pixel monochrome display running over I\xB2C. Two things differ from the equivalent Arduino Uno setup:\n\n**3.3 V supply, not 5 V.** The ESP32 runs at 3.3 V on every pin including its supply rail. Wiring an OLED to the Uno's 5 V will work, but mixing in 5 V signals from a Uno into the same I\xB2C bus as the ESP32 will damage the ESP32. Stay on the 3V3 rail.\n\n**Default I\xB2C pins are GPIO21 (SDA) and GPIO22 (SCL).** The Adafruit / Espressif convention is green for SDA and white for SCL \u2014 preserved here. These pins are remappable in firmware via `Wire.begin(sda, scl)` if you need them elsewhere."
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"slug": "breadboard-hcsr04-distance",
|
|
407
|
+
"diagram": "breadboard",
|
|
408
|
+
"title": "HC-SR04 distance sensor + Arduino Uno",
|
|
409
|
+
"description": "Four-wire ultrasonic distance sensor wiring \u2014 VCC / GND / TRIG / ECHO. The textbook Adafruit / SparkFun tutorial layout used in robotics intro classes.",
|
|
410
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
411
|
+
"tags": [
|
|
412
|
+
"breadboard",
|
|
413
|
+
"arduino",
|
|
414
|
+
"ultrasonic",
|
|
415
|
+
"sensor",
|
|
416
|
+
"hc-sr04",
|
|
417
|
+
"robotics"
|
|
418
|
+
],
|
|
419
|
+
"complexity": 2,
|
|
420
|
+
"featured": true,
|
|
421
|
+
"dsl": 'breadboard\nboard: half\ntitle: "HC-SR04 distance sensor + Arduino Uno"\n\nparts\n uno: mcu uno @beside-left\n s1: sensor hcsr04 @8a\n\nwires\n s1:VCC --red-- @+t1\n s1:GND --black-- @-t1\n s1:TRIG --yellow-- @9c\n s1:ECHO --green-- @10c\n uno:5V --red-- @+t1\n uno:GND --black-- @-t1\n uno:D9 --yellow-- @9c\n uno:D10 --green-- @10c',
|
|
422
|
+
"notes": "The HC-SR04 is the most common ultrasonic distance sensor in beginner Arduino kits. Four pins, four wires, no driver IC needed. The sensor module is rendered as a blue PCB tile with its four pin labels (VCC / TRIG / ECHO / GND) sitting above the breadboard rows where they plug in.\n\nThe TRIG line is a digital output from the Arduino \u2014 pulse it high for 10 \xB5s and the sensor fires an ultrasonic chirp. The ECHO line is a digital input \u2014 its high-time, in microseconds, is twice the round-trip distance divided by the speed of sound. Conventional wiring uses yellow for TRIG and green for ECHO so the two signals are visually distinguishable, though the colors carry no electrical meaning."
|
|
423
|
+
},
|
|
256
424
|
{
|
|
257
425
|
"slug": "circuit-ce-amplifier",
|
|
258
426
|
"diagram": "circuit",
|
|
@@ -271,6 +439,43 @@ var EXAMPLES = [
|
|
|
271
439
|
"dsl": 'circuit "CE Amp (netlist)" netlist\nV1 vcc 0 9V\nRc vcc c 2.2k\nRb vcc b 100k\nQ1 c b e npn\nRe e 0 1k',
|
|
272
440
|
"notes": '## Scenario\n\nThe NPN common-emitter amplifier is the first transistor circuit every electronics student builds. Schematex renders it from a five-line SPICE netlist \u2014 the same format used in LTspice, ngspice, and Cadence \u2014 with automatic component placement and rail routing, so the diagram matches the hand-drawn textbook version without any manual layout.\n\n## Annotation key\n\n- `circuit "..." netlist` \u2014 enables netlist parsing mode (SPICE syntax)\n- `V1 vcc 0 9V` \u2014 voltage source named V1, positive terminal at node `vcc`, negative at `0` (ground), value 9V\n- `Rc vcc c 2.2k` \u2014 resistor Rc between nodes `vcc` and `c` with value 2.2 k\u03A9\n- `Rb vcc b 100k` \u2014 base bias resistor between `vcc` and node `b`\n- `Q1 c b e npn` \u2014 NPN BJT transistor: collector=c, base=b, emitter=e\n- `Re e 0 1k` \u2014 emitter degeneration resistor between node `e` and ground\n\n## How to read\n\nThe supply rail (Vcc = 9 V) connects to the top of both resistors. Rc is the collector load; the output signal is taken across it. Rb biases the base into the active region. Re provides emitter degeneration for stability. Q1 amplifies a small base current into a large collector-to-emitter current flow. The auto-layout positions Vcc at top, ground at bottom, and Q1 in the center.'
|
|
273
441
|
},
|
|
442
|
+
{
|
|
443
|
+
"slug": "decisiontree-buy-vs-lease-ev",
|
|
444
|
+
"diagram": "decisiontree",
|
|
445
|
+
"title": "Buy vs. lease an electric vehicle",
|
|
446
|
+
"description": "Howard-Raiffa expected-value tree for the buy/lease/used-EV decision \u2014 with resale probability and incentive chance nodes.",
|
|
447
|
+
"standard": "Raiffa & Schlaifer (1961)",
|
|
448
|
+
"tags": [
|
|
449
|
+
"decision-analysis",
|
|
450
|
+
"ev",
|
|
451
|
+
"buy-vs-lease",
|
|
452
|
+
"expected-value",
|
|
453
|
+
"consumer"
|
|
454
|
+
],
|
|
455
|
+
"complexity": 3,
|
|
456
|
+
"featured": false,
|
|
457
|
+
"dsl": 'decisiontree:decision "EV Acquisition Decision"\n\ndecision "Which acquisition path?"\n choice "Buy new EV"\n chance "Federal tax credit eligible?"\n prob 0.7 chance "Resale market in 5yr (w/ credit)"\n prob 0.55 end "Strong resale + credit" payoff=28500\n prob 0.45 end "Weak resale + credit" payoff=16000\n prob 0.3 chance "Resale market in 5yr (no credit)"\n prob 0.55 end "Strong resale, no credit" payoff=21000\n prob 0.45 end "Weak resale, no credit" payoff=8500\n choice "Lease EV 3yr"\n end "Predictable lease cost" payoff=14000\n choice "Buy used EV"\n chance "Battery health \u2265 80%?"\n prob 0.6 end "Good battery \u2014 low TCO" payoff=22000\n prob 0.4 end "Battery replacement needed" payoff=8000',
|
|
458
|
+
"notes": '## Scenario\n\nA household is choosing between three electric vehicle acquisition paths: buying new (eligible for a $7,500 federal tax credit with 70% probability, depending on income and vehicle MSRP cap), leasing for three years at a fixed all-in cost, or buying used. The buy-new path carries two sequential chance nodes \u2014 credit eligibility then a five-year resale market outcome \u2014 while used carries battery-health uncertainty. Payoffs represent net five-year economic value (savings versus equivalent ICE ownership, residual value, minus acquisition and maintenance costs).\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; actor chooses a branch\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; nature chooses; `prob N` on children must sum to 1\n- `end "\u2026" payoff=N` \u2014 terminal leaf with net five-year economic value in dollars\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nRoll back from leaves to root. Buy-new EV (with credit branch): 0.55 \xD7 28,500 + 0.45 \xD7 16,000 = **24,075**; without credit: 0.55 \xD7 21,000 + 0.45 \xD7 8,500 = **19,275**. Combined: 0.7 \xD7 24,075 + 0.3 \xD7 19,275 = **22,635**. Lease: flat **14,000**. Used EV: 0.6 \xD7 22,000 + 0.4 \xD7 8,000 = **16,400**. Under these assumptions *Buy new EV* dominates, largely because the 70% credit probability shifts the overall EV substantially upward. Sensitivity analysis on credit eligibility probability and the five-year resale spread is where the real MBA discussion lives.'
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"slug": "decisiontree-go-nogo-product",
|
|
462
|
+
"diagram": "decisiontree",
|
|
463
|
+
"title": "Product launch go/no-go decision",
|
|
464
|
+
"description": "Stage-gate launch decision with market-size chance node, competitor-response chance, and NPV terminal values for a PM strategy review.",
|
|
465
|
+
"standard": "Raiffa & Schlaifer (1961)",
|
|
466
|
+
"tags": [
|
|
467
|
+
"launch",
|
|
468
|
+
"go-nogo",
|
|
469
|
+
"npv",
|
|
470
|
+
"strategy",
|
|
471
|
+
"product",
|
|
472
|
+
"chance"
|
|
473
|
+
],
|
|
474
|
+
"complexity": 3,
|
|
475
|
+
"featured": false,
|
|
476
|
+
"dsl": 'decisiontree:decision "Product Launch Strategy"\n\ndecision "Launch strategy?"\n choice "Launch Q1 (full)"\n chance "Market reception"\n prob 0.4 chance "Competitor copies within 6mo? (strong)"\n prob 0.5 end "Strong + copied" payoff=3200000\n prob 0.5 end "Strong + defended" payoff=5800000\n prob 0.35 chance "Competitor copies within 6mo? (moderate)"\n prob 0.5 end "Moderate + copied" payoff=1400000\n prob 0.5 end "Moderate + defended" payoff=2600000\n prob 0.25 end "Weak reception" payoff=400000\n choice "Launch Q3 (scoped)"\n chance "Market reception (scoped)"\n prob 0.45 end "Strong scoped" payoff=3100000\n prob 0.35 end "Moderate scoped" payoff=1800000\n prob 0.20 end "Weak scoped" payoff=600000\n choice "No launch"\n end "Saved development cost" payoff=900000',
|
|
477
|
+
"notes": '## Scenario\n\nA PM team is evaluating three paths ahead of an annual planning cycle: a full Q1 launch with the complete feature set, a scoped Q3 launch targeting the highest-confidence segments, and a no-launch option that recovers the estimated development spend. The Q1 full-launch path carries two sequential chance nodes \u2014 market reception (strong/moderate/weak) followed, for the non-weak outcomes, by a competitor-response chance (copies vs. defends). Payoffs are five-year NPV estimates in dollars, net of launch and ongoing operating costs.\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; PM team chooses a branch\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; market or competitor behavior; `prob N` sums to 1 per node\n- `end "\u2026" payoff=N` \u2014 terminal leaf with five-year NPV in dollars\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nFor Q1 full launch: strong-reception EV = 0.5 \xD7 3,200,000 + 0.5 \xD7 5,800,000 = **4,500,000**; moderate EV = 0.5 \xD7 1,400,000 + 0.5 \xD7 2,600,000 = **2,000,000**. Full-launch EV = 0.40 \xD7 4,500,000 + 0.35 \xD7 2,000,000 + 0.25 \xD7 400,000 = **2,600,000**. Scoped-Q3 EV = 0.45 \xD7 3,100,000 + 0.35 \xD7 1,800,000 + 0.20 \xD7 600,000 = **2,118,000**. No launch: **900,000**. Q1 full launch produces the highest EV, but the moderate-reception + copied scenario at $1.4M is a painful downside worth stress-testing \u2014 reducing competitor copy probability from 0.5 to 0.3 in that branch raises the EV meaningfully and may justify a launch accelerator investment.'
|
|
478
|
+
},
|
|
274
479
|
{
|
|
275
480
|
"slug": "decisiontree-investment-analysis",
|
|
276
481
|
"diagram": "decisiontree",
|
|
@@ -289,6 +494,44 @@ var EXAMPLES = [
|
|
|
289
494
|
"dsl": 'decisiontree:decision "Platform Vendor Choice"\n\ndecision "Which vendor?"\n choice "Build in-house"\n chance "Project outcome"\n prob 0.6 end "On-time delivery" payoff=900000\n prob 0.4 end "Over budget / delayed" payoff=150000\n choice "Managed SaaS vendor"\n end "Predictable cost" payoff=500000\n choice "Hybrid approach"\n chance "Integration complexity"\n prob 0.5 end "Smooth integration" payoff=700000\n prob 0.5 end "Integration rework" payoff=300000',
|
|
290
495
|
"notes": '## Scenario\n\nA CTO is deciding how to stand up a new data-platform layer: build internally, buy managed SaaS, or take a hybrid. Each path has outcomes with probabilities and net-value estimates. The decision-analysis tree rolls the expected value back to the decision node so the optimal branch is identified automatically.\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 actor chooses a branch\n- `chance "\u2026"` \u2014 nature chooses; `prob N` on each child (must sum to 1)\n- `end "\u2026" payoff=N` \u2014 terminal payoff\n- `choice "label"` \u2014 label on an outgoing decision branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nEvaluate each branch\'s expected value. Build in-house: 0.6 \xD7 900k + 0.4 \xD7 150k = **600k**. Managed SaaS: flat **500k**. Hybrid: 0.5 \xD7 700k + 0.5 \xD7 300k = **500k**. Under these estimates the optimal branch is *Build in-house* \u2014 the parser flags it on render. The chart\'s real value is in forcing stakeholders to state probabilities explicitly; sensitivity to them is where the interesting argument happens.'
|
|
291
496
|
},
|
|
497
|
+
{
|
|
498
|
+
"slug": "decisiontree-iris-sklearn",
|
|
499
|
+
"diagram": "decisiontree",
|
|
500
|
+
"title": "Iris species classifier (scikit-learn CART)",
|
|
501
|
+
"description": "The classic sklearn Iris CART decision tree \u2014 three species, two splits on petal length and width, rendered from a functional ML-tree description.",
|
|
502
|
+
"standard": "Breiman CART (1984)",
|
|
503
|
+
"tags": [
|
|
504
|
+
"cart",
|
|
505
|
+
"sklearn",
|
|
506
|
+
"iris",
|
|
507
|
+
"classification",
|
|
508
|
+
"ml",
|
|
509
|
+
"decision-tree"
|
|
510
|
+
],
|
|
511
|
+
"complexity": 2,
|
|
512
|
+
"featured": false,
|
|
513
|
+
"dsl": 'decisiontree:ml "Iris Classifier"\n\nsplit "petal length (cm) \u2264 2.45"\n true leaf "Setosa" [support=50, impurity=0.0, class=setosa]\n false split "petal width (cm) \u2264 1.75"\n true leaf "Versicolor" [support=47, impurity=0.168, class=versicolor]\n false leaf "Virginica" [support=45, impurity=0.043, class=virginica]',
|
|
514
|
+
"notes": '## Scenario\n\nThe Iris dataset \u2014 150 samples of three species (Iris setosa, versicolor, and virginica) measured across four features \u2014 is the canonical teaching example for classification. A CART tree trained with scikit-learn `DecisionTreeClassifier(max_depth=2)` produces exactly this two-level tree. Setosa is perfectly linearly separable on petal length alone; versicolor and virginica require a second split on petal width. The resulting tree achieves ~96% cross-validated accuracy.\n\n## Annotation key\n\n- `split "condition"` \u2014 internal node; routes left (`true`) when condition holds, right (`false`) when it does not\n- `true` / `false` \u2014 branch direction prefix indicating which child is reached when the split condition evaluates to that boolean\n- `leaf "label"` \u2014 terminal classification node\n- `[support=N]` \u2014 number of training samples reaching this leaf\n- `[impurity=N]` \u2014 Gini impurity at the node (0 = pure, 0.5 = maximally impure for binary)\n- `[class=\u2026]` \u2014 majority class label at the leaf\n\n## How to read\n\nStart at the root split. If petal length \u2264 2.45 cm, the sample is classified as **Setosa** immediately (Gini = 0, perfectly pure \u2014 all 50 setosa training samples land here). Otherwise, evaluate petal width: \u2264 1.75 cm predicts **Versicolor** (47 samples, Gini = 0.168 \u2014 a small number of virginica blur this boundary); > 1.75 cm predicts **Virginica** (45 samples, Gini = 0.043 \u2014 nearly pure). This tree is shallow enough to fit on an index card and remains the first model every ML course deploys.'
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"slug": "decisiontree-litigation-settle",
|
|
518
|
+
"diagram": "decisiontree",
|
|
519
|
+
"title": "Litigation vs. settlement analysis",
|
|
520
|
+
"description": "Expected-value analysis of settling a $2M breach-of-contract claim vs. going to trial \u2014 with verdict probability and appeal chance nodes.",
|
|
521
|
+
"standard": "Raiffa & Schlaifer (1961)",
|
|
522
|
+
"tags": [
|
|
523
|
+
"litigation",
|
|
524
|
+
"settlement",
|
|
525
|
+
"legal",
|
|
526
|
+
"expected-value",
|
|
527
|
+
"trial",
|
|
528
|
+
"appeal"
|
|
529
|
+
],
|
|
530
|
+
"complexity": 3,
|
|
531
|
+
"featured": false,
|
|
532
|
+
"dsl": 'decisiontree:decision "Litigation Strategy"\n\ndecision "Litigation strategy?"\n choice "Settle now"\n end "Settlement payment" payoff=-350000\n choice "Proceed to trial"\n chance "Verdict"\n prob 0.55 chance "Plaintiff appeals? (defense wins)"\n prob 0.3 chance "Appeal outcome"\n prob 0.4 end "Reversed on appeal" payoff=0\n prob 0.6 end "Upheld on appeal" payoff=-2200000\n prob 0.7 end "No appeal \u2014 defense prevails" payoff=0\n prob 0.45 end "Plaintiff verdict \u2014 damages + fees" payoff=-2000000',
|
|
533
|
+
"notes": '## Scenario\n\nA corporate defendant faces a $2 million breach-of-contract claim. Outside counsel has assessed a 55% probability of a defense verdict at trial and a 45% probability of a plaintiff verdict (full damages plus attorney fees). If the defense wins, there is a 30% chance the plaintiff appeals; an appeal resolves with a 40% probability of reversal (cost: zero) and a 60% probability of affirmance, which adds appellate costs bringing total exposure to $2.2M. The client can alternatively settle immediately for $350,000. All payoffs are expressed as costs to the defendant (negative = outflow).\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; counsel and client choose the path\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; court or opposing party behavior; `prob N` sums to 1\n- `end "\u2026" payoff=N` \u2014 terminal leaf; negative values represent costs to defendant\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV (least negative)\n\n## How to read\n\nRoll back from leaves. Appeal-outcome EV: 0.4 \xD7 0 + 0.6 \xD7 \u22122,200,000 = **\u22121,320,000**. Defense-wins-verdict branch EV: 0.3 \xD7 \u22121,320,000 + 0.7 \xD7 0 = **\u2212396,000**. Trial EV: 0.55 \xD7 \u2212396,000 + 0.45 \xD7 \u22122,000,000 = **\u22121,117,800**. Settlement: **\u2212350,000**. Under these probability estimates, settling for $350,000 is the rational choice \u2014 it avoids the \u2212$1.12M expected cost of going to trial. The key sensitivity is the defense-verdict probability: if counsel is more than ~75% confident of winning at trial, the EV of proceeding drops below \u2212350,000 and trial becomes preferred.'
|
|
534
|
+
},
|
|
292
535
|
{
|
|
293
536
|
"slug": "decisiontree-support-triage",
|
|
294
537
|
"diagram": "decisiontree",
|
|
@@ -307,6 +550,45 @@ var EXAMPLES = [
|
|
|
307
550
|
"dsl": 'decisiontree "Customer Support Triage"\ndirection: top-down\n\nquestion "Is the service completely down?"\n yes: question "Outage confirmed on status page?"\n yes: answer "Follow incident protocol \u2014 page on-call"\n no: answer "Check monitoring \u2014 open severity-1 ticket"\n no: question "Is the issue affecting billing?"\n yes: answer "Escalate to billing team \u2014 SLA breach risk"\n no: question "Can user reproduce consistently?"\n yes: answer "Collect HAR trace \u2014 file bug report"\n no: answer "Ask for screenshot \u2014 watch for recurrence"',
|
|
308
551
|
"notes": '## Scenario\n\nThe support lead bakes this tree into the agent runbook so new hires can triage in week one without a buddy. Three gates \u2014 outage, billing, reproducibility \u2014 route 90% of tickets deterministically. The remaining 10% (edge cases, multi-category) get flagged for human escalation instead of guessed at.\n\n## Annotation key\n\n- `question "text"` \u2014 internal decision node\n- `answer "text"` \u2014 terminal outcome\n- `yes:` / `no:` \u2014 branch label\n- Indentation (2 spaces) \u2014 parent-child nesting\n\n## How to read\n\nStart at the root. At each `question` node the agent answers yes or no and follows the matching branch. Every path terminates in an `answer` \u2014 a concrete next action, not another decision. The tree is deliberately shallow (max depth 3) so agents can hold it in their head; deeper branches would push into a runbook rather than a decision tree.'
|
|
309
552
|
},
|
|
553
|
+
{
|
|
554
|
+
"slug": "decisiontree-triage-chest-pain",
|
|
555
|
+
"diagram": "decisiontree",
|
|
556
|
+
"title": "ED chest pain triage",
|
|
557
|
+
"description": "Emergency department chest-pain triage algorithm \u2014 HEART score pathway, STEMI/NSTEMI rule-out, and disposition decision for the ED physician.",
|
|
558
|
+
"standard": "AHA/ACC 2021 Chest Pain Guidelines",
|
|
559
|
+
"tags": [
|
|
560
|
+
"triage",
|
|
561
|
+
"chest-pain",
|
|
562
|
+
"ed",
|
|
563
|
+
"stemi",
|
|
564
|
+
"heart-score",
|
|
565
|
+
"clinical",
|
|
566
|
+
"aha"
|
|
567
|
+
],
|
|
568
|
+
"complexity": 4,
|
|
569
|
+
"featured": false,
|
|
570
|
+
"dsl": 'decisiontree:taxonomy "ED Chest Pain Triage"\n\nquestion "ECG: ST elevation present?"\n yes: answer "Activate cath lab \u2014 STEMI protocol"\n no: question "Troponin elevated at 0h or 3h?"\n yes: question "Dynamic troponin rise (\u2265 3 ng/L delta)?"\n yes: answer "NSTEMI confirmed \u2014 cardiology consult, anticoagulate"\n no: answer "Possible NSTEMI \u2014 repeat troponin at 6h"\n no: question "HEART score \u2265 4?"\n yes: answer "High risk \u2014 observation unit + stress test or CTA"\n no: question "All low-risk features present?"\n yes: answer "Discharge \u2014 outpatient follow-up within 72h"\n no: answer "Observation \u2014 shared decision making with patient"',
|
|
571
|
+
"notes": '## Scenario\n\nChest pain accounts for roughly 8 million ED visits per year in the United States. The AHA/ACC 2021 Chest Pain Guidelines provide a tiered rule-out pathway: first exclude STEMI via ECG, then use high-sensitivity troponin at 0h and 3h to distinguish NSTEMI from unstable angina or non-cardiac causes, and finally apply the HEART score (History, ECG, Age, Risk factors, Troponin) to stratify remaining patients into high-risk observation vs. safe discharge. This tree encodes the core algorithmic structure for a busy ED attending.\n\n## Annotation key\n\n- `question "\u2026"` \u2014 internal clinical decision node; physician evaluates the criterion\n- `answer "\u2026"` \u2014 terminal disposition or action\n- `yes:` / `no:` \u2014 branch label indicating the clinical finding\n- HEART score: 0\u20133 low risk, 4\u20136 moderate, 7\u201310 high risk\n- Dynamic troponin: delta \u2265 3 ng/L between 0h and 3h draws meets ESC high-sensitivity criterion\n\n## How to read\n\nEntry is the 12-lead ECG. ST elevation routes directly to cath-lab activation \u2014 time is myocardium and no further branching is needed. Absence of ST elevation triggers the troponin pathway: a positive draw at either time point prompts delta assessment to distinguish true NSTEMI from a chronic elevation; a negative troponin advances to HEART score stratification. A score of 4 or higher mandates observation-unit admission with functional testing; a score below 4 with all low-risk clinical features present supports discharge with prompt outpatient follow-up. The final branch \u2014 observation with shared decision making \u2014 captures the borderline-HEART-score patient where physician judgment, patient preference, and social circumstances all contribute to disposition.'
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
"slug": "decisiontree-xgboost-churn",
|
|
575
|
+
"diagram": "decisiontree",
|
|
576
|
+
"title": "Customer churn prediction tree (XGBoost)",
|
|
577
|
+
"description": "One tree from an XGBoost churn model \u2014 days since last login, MRR tier, support tickets \u2014 showing how gradient boosting splits differ from CART.",
|
|
578
|
+
"standard": "Chen & Guestrin XGBoost (2016)",
|
|
579
|
+
"tags": [
|
|
580
|
+
"xgboost",
|
|
581
|
+
"churn",
|
|
582
|
+
"ml",
|
|
583
|
+
"gradient-boosting",
|
|
584
|
+
"saas",
|
|
585
|
+
"prediction"
|
|
586
|
+
],
|
|
587
|
+
"complexity": 3,
|
|
588
|
+
"featured": false,
|
|
589
|
+
"dsl": 'decisiontree:ml "Churn Prediction Tree (XGBoost)"\n\nsplit "days_since_login > 21"\n true split "mrr_tier < 2"\n true leaf "High churn risk" [score=0.72, class=churn]\n false leaf "Medium risk \u2014 monitor" [score=0.41, class=churn]\n false split "support_tickets_30d > 3"\n true leaf "Medium risk \u2014 support-driven" [score=0.38, class=churn]\n false leaf "Low churn risk" [score=0.09, class=retain]',
|
|
590
|
+
"notes": '## Scenario\n\nA SaaS company trains an XGBoost churn model on 90 days of product usage data. This is one representative tree from the ensemble, illustrating the three strongest churn signals in the dataset: recency of login (days since last login > 21 is the dominant split), MRR tier (lower-tier accounts churn faster when disengaged), and recent support ticket volume (elevated tickets correlate with frustration even among recently active users). Unlike a standalone CART tree, XGBoost trees output raw scores (log-odds contributions) that are summed across the ensemble before sigmoid transformation \u2014 the `score` values shown are per-tree contributions, not final probabilities.\n\n## Annotation key\n\n- `split "condition"` \u2014 internal split node; `true` branch when condition holds\n- `true` / `false` \u2014 branch direction prefix\n- `leaf "label"` \u2014 terminal node with a descriptive risk label\n- `[score=N]` \u2014 raw XGBoost leaf score (log-odds contribution from this tree)\n- `[class=\u2026]` \u2014 dominant class assignment at this leaf\n- XGBoost does not use Gini/entropy impurity; splits are chosen to maximize second-order gradient gain\n\n## How to read\n\nStart at the root. Accounts with more than 21 days since last login are immediately flagged: if they are also on MRR tier 0 or 1 (lowest-value tiers), the leaf score is 0.72 \u2014 the highest churn signal in this tree. High-tier disengaged accounts score 0.41, indicating meaningful but lower risk, consistent with higher switching costs. For recently active accounts (login \u2264 21 days), elevated support tickets (> 3 in 30 days) push score to 0.38 \u2014 a product-experience alert \u2014 while accounts that are both active and support-quiet score 0.09, the healthiest segment. In production, this tree\'s scores are summed with hundreds of sibling trees and passed through a sigmoid to yield a final churn probability between 0 and 1.'
|
|
591
|
+
},
|
|
310
592
|
{
|
|
311
593
|
"slug": "ecomap-refugee-resettlement",
|
|
312
594
|
"diagram": "ecomap",
|
|
@@ -413,6 +695,102 @@ var EXAMPLES = [
|
|
|
413
695
|
"dsl": 'entity-structure "Acme Inc. \u2014 post Series A"\nentity acme "Acme Inc." corp@DE\nentity founders "Founders (2)" individual\nentity seed "Seed Fund I" lp@DE\nentity lead "Sequoia Series A" lp@DE\nentity angels "Angel group" individual\nentity esop "Employee Option Pool" trust@DE\nfounders -> acme : 45%\nseed -> acme : 12%\nlead -> acme : 22%\nangels -> acme : 6%\nesop -> acme : 15%',
|
|
414
696
|
"notes": "## Scenario\n\nA startup attorney or CFO documents the post-Series A ownership table for a 409A valuation, board consent, or investor report. The cap table diagram makes the dilution story visual \u2014 founders can immediately see their post-money percentage, and the VC can verify their ownership stake before signing the term sheet.\n\n## Annotation key\n\n- `-> acme : 45%` \u2014 ownership arrow with percentage label; all percentages should sum to 100%\n- `individual` \u2014 natural person (founder, angel)\n- `lp` \u2014 institutional investor entity (fund/LP)\n- `trust` \u2014 the ESOP/option pool (typically a Delaware trust or reserved pool)\n- `corp@DE` \u2014 the issuer (Delaware C-corp)\n\n## How to read\n\nAcme Inc. (Delaware C-corp) sits at the bottom as the issuer. Five shareholder classes flow down with their ownership arrows: founders at 45%, the lead Series A investor at 22%, the employee option pool at 15%, the seed fund at 12%, and angels at 6%. Percentages sum to 100%, representing a clean fully-diluted cap table on the day of Series A close."
|
|
415
697
|
},
|
|
698
|
+
{
|
|
699
|
+
"slug": "erd-ecommerce-schema",
|
|
700
|
+
"diagram": "erd",
|
|
701
|
+
"title": "E-commerce schema",
|
|
702
|
+
"description": "Production-style schema with Customer / Order / OrderLine / Product / Category \u2014 typical mid-complexity backend ERD with composite PK on the line-item table.",
|
|
703
|
+
"standard": "Crow's-foot (Everest 1976) / DBML compatible",
|
|
704
|
+
"tags": [
|
|
705
|
+
"ERD",
|
|
706
|
+
"crow's-foot",
|
|
707
|
+
"schema",
|
|
708
|
+
"e-commerce",
|
|
709
|
+
"FK",
|
|
710
|
+
"composite-PK"
|
|
711
|
+
],
|
|
712
|
+
"complexity": 2,
|
|
713
|
+
"featured": false,
|
|
714
|
+
"dsl": 'erd\ntitle: "E-commerce Schema"\ndirection: LR\n\ntable Customer {\n customer_id int PK\n email varchar UK\n name varchar\n created_at timestamp\n}\n\ntable Address {\n address_id int PK\n customer_id int FK -> Customer.customer_id\n line1 varchar\n city varchar\n zip varchar\n}\n\ntable Category {\n category_id int PK\n name varchar\n}\n\ntable Product {\n product_id int PK\n category_id int FK -> Category.category_id\n name varchar\n price decimal\n}\n\ntable Order {\n order_id int PK\n customer_id int FK -> Customer.customer_id\n placed_at timestamp\n status varchar\n}\n\ntable OrderLine {\n order_id int PK FK -> Order.order_id\n line_no int PK\n product_id int FK -> Product.product_id\n qty int\n price decimal\n}\n\nref Address.customer_id many-mandatory -- one-mandatory Customer.customer_id\nref Order.customer_id many-mandatory -- one-mandatory Customer.customer_id : "places"\nref Product.category_id many-mandatory -- one-mandatory Category.category_id\nref OrderLine.order_id many-mandatory -- one-mandatory Order.order_id\nref OrderLine.product_id many-mandatory -- one-mandatory Product.product_id',
|
|
715
|
+
"notes": 'A six-table schema spanning four FK-depth layers: Category and Customer at the root; Product and Address at depth one; Order at depth two; OrderLine at depth three with a composite PK `(order_id, line_no)`. Demonstrates layered LR routing and labelled relationships ("places").'
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
"slug": "erd-university-schema",
|
|
719
|
+
"diagram": "erd",
|
|
720
|
+
"title": "University schema (academic ERD)",
|
|
721
|
+
"description": "Classic textbook schema with Student / Course / Enrollment associative entity and labelled relationships \u2014 the canonical Elmasri & Navathe ch.3 example.",
|
|
722
|
+
"standard": "Crow's-foot (Everest 1976) / DBML compatible",
|
|
723
|
+
"tags": [
|
|
724
|
+
"ERD",
|
|
725
|
+
"crow's-foot",
|
|
726
|
+
"schema",
|
|
727
|
+
"associative-entity",
|
|
728
|
+
"M-N"
|
|
729
|
+
],
|
|
730
|
+
"complexity": 1,
|
|
731
|
+
"featured": true,
|
|
732
|
+
"dsl": 'erd\ntitle: "University Schema"\n\ntable Student {\n student_id int PK\n name varchar\n email varchar UK\n major_id int FK -> Major.major_id\n}\n\ntable Major {\n major_id int PK\n name varchar\n}\n\ntable Course {\n course_id int PK\n title varchar\n credits int\n}\n\ntable Enrollment {\n student_id int PK FK -> Student.student_id\n course_id int PK FK -> Course.course_id\n grade char\n}\n\nref Student.major_id many-mandatory -- one-mandatory Major.major_id : "majors in"\nref Enrollment.student_id many-mandatory -- one-mandatory Student.student_id\nref Enrollment.course_id many-mandatory -- one-mandatory Course.course_id',
|
|
733
|
+
"notes": "The university schema is the canonical introduction to associative entities. The M:N relationship between Student and Course is resolved through Enrollment, which carries the relationship attribute `grade`. Both Student and Course join Enrollment via composite primary keys (each FK column doubles as part of the PK)."
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
"slug": "fbd-bottle-counter",
|
|
737
|
+
"diagram": "fbd",
|
|
738
|
+
"title": "Bottle counter \u2014 debounce \u2192 edge \u2192 count (FBD)",
|
|
739
|
+
"description": "Three-network FBD pipeline that debounces a bottle sensor with a 50ms TON, takes the rising edge with R_TRIG, counts up to 24 bottles per case with CTU, and self-resets when the case is full. A real production-line pattern that exercises timer + edge-detector + counter + named-instance references in sequence.",
|
|
740
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
741
|
+
"tags": [
|
|
742
|
+
"fbd",
|
|
743
|
+
"plc",
|
|
744
|
+
"ton",
|
|
745
|
+
"ctu",
|
|
746
|
+
"r-trig",
|
|
747
|
+
"debounce",
|
|
748
|
+
"sensor",
|
|
749
|
+
"packaging"
|
|
750
|
+
],
|
|
751
|
+
"complexity": 3,
|
|
752
|
+
"featured": true,
|
|
753
|
+
"dsl": 'fbd "Bottle Counter"\n\nvar BottleSensor: bool\nvar BatchDone: bool\nvar BatchSize: counter\nvar DwellTimer: timer\n\nnetwork 0 "Debounce sensor with 50ms dwell":\n Dwell = TON(IN: BottleSensor, PT: T#50ms)\n\nnetwork 1 "Count one bottle on rising edge of debounced signal":\n Pulse = R_TRIG(CLK: Dwell.Q)\n BatchSize = CTU(CU: Pulse.Q, R: BatchDone, PV: 24)\n\nnetwork 2 "Latch batch done":\n BatchDone = MOVE(BatchSize.Q)',
|
|
754
|
+
"notes": "Counting bottles on a conveyor sounds trivial \u2014 the photoelectric sensor goes high when a bottle interrupts the beam, increment the counter, done. In practice it's where most beginner PLC code first goes wrong, because real sensors *bounce*: the beam is broken, then briefly restored as light reflects off the bottle's edge, then broken again. Without debounce, a single bottle can register as three or four counts. This FBD captures the canonical fix in three short networks, and shows how named-instance references chain timers, edge-detectors, and counters into a pipeline.\n\n**Network 0 \u2014 debounce.** A TON (on-delay timer) ignores the sensor unless it stays high for at least 50ms continuously. `PT: T#50ms` is the IEC duration literal for the preset; it renders as a small yellow constant box at the PT input port. The Q output goes true 50ms after the IN goes true and resets immediately when IN drops \u2014 exactly the \"is this signal *really* asserted, or just noise?\" semantic the line needs.\n\n**Network 1 \u2014 edge \u2192 count.** Two named instances chain together. `Pulse = R_TRIG(CLK: Dwell.Q)` references the debounced output from network 0 by its instance.port name. R_TRIG emits a one-scan pulse on the rising edge \u2014 without it, the counter would increment continuously while the sensor is held high (e.g. if the conveyor jammed with a bottle in the beam). `BatchSize = CTU(CU: Pulse.Q, R: BatchDone, PV: 24)` then increments on each pulse, and resets when `BatchDone` goes true. The PV=24 is the case size for a six-pack of four-packs.\n\n**Network 2 \u2014 feedback latch.** The counter's Q output (true when CV \u2265 PV) is moved into the `BatchDone` variable, which feeds back to network 1's reset input. This is one full case cycle: count to 24 \u2192 done \u2192 reset \u2192 start over. As with the motor latch, Schematex doesn't simulate the scan order; it renders the graph. The \"feedback\" appears in the wire from network 2 back to network 1's CTU.R.\n\n**What the data-type colors are telling you.** The TON.IN wire is BOOL (black). The TON.PT wire is TIME (magenta \u2014 but it's an inline constant here, so no wire). R_TRIG.CLK is BOOL (black). CTU.CV would be INT (blue) if it were wired anywhere \u2014 it's left dangling here because we only need Q. Different wire colors per data type are the TIA Portal de-facto convention, ported over to Schematex for at-a-glance validation: if a REAL wire (orange) lands on a BOOL port, you have a type error in your DSL."
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"slug": "fbd-motor-latch",
|
|
758
|
+
"diagram": "fbd",
|
|
759
|
+
"title": "Motor start/stop latch (FBD)",
|
|
760
|
+
"description": "Two-network FBD of the canonical PLC seal-in circuit \u2014 start-button rising edge sets a latch, stop and emergency-stop break it. Exercises declared variables, multi-network programs, inline expression notation, and negation bubbles.",
|
|
761
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
762
|
+
"tags": [
|
|
763
|
+
"fbd",
|
|
764
|
+
"plc",
|
|
765
|
+
"iec-61131-3",
|
|
766
|
+
"latch",
|
|
767
|
+
"motor-control"
|
|
768
|
+
],
|
|
769
|
+
"complexity": 2,
|
|
770
|
+
"featured": true,
|
|
771
|
+
"dsl": 'fbd "Motor Control"\n\nvar Start: bool\nvar Stop: bool\nvar EmergencyStop: bool\nvar MotorOut: bool\nvar Latch: bool\n\nnetwork 0 "Start latch":\n Latch = OR(Start, AND(Latch, ~Stop, ~EmergencyStop))\n\nnetwork 1 "Drive output":\n MotorOut = MOVE(Latch)',
|
|
772
|
+
"notes": 'The seal-in circuit \u2014 also called a start/stop latch \u2014 is the most common pattern in PLC code. Once the operator presses Start, the motor stays running even after they release the button, until either Stop or an emergency-stop input goes high. Every controls engineer writes this on day one, and every PLC textbook opens with the ladder version. The FBD form is just as concise but reads like data flow rather than like a relay schematic.\n\n**Network 0 \u2014 the latch.** `Latch = OR(Start, AND(Latch, ~Stop, ~EmergencyStop))` is the entire seal-in expressed as one nested call. The OR fires when *either* the start button is pressed *or* the latch is already set AND neither stop button is held. The `~` prefix on Stop and EmergencyStop adds a **negation bubble** at each input port \u2014 equivalent to inserting a NOT block on that wire, but rendered inline. The variadic AND expands automatically to three inputs because three positional arguments were passed.\n\n**The `Latch` feedback edge.** Notice that `Latch` appears on both the left side (as an input to the AND) and the right side (as the output of the OR). This is the *seal-in* feedback that gives the circuit its name. In a real PLC, the previous scan\'s `Latch` value is what feeds back \u2014 the current scan reads it, evaluates the boolean expression, and writes the new value. Schematex doesn\'t simulate the scan cycle; it just renders the data-flow graph faithfully, which is exactly what an engineer reviewing the program needs to see.\n\n**Network 2 \u2014 drive output.** `MotorOut = MOVE(Latch)` is a separate concern: take the latch state and assign it to the physical output that energises the motor contactor. Splitting it into its own network is a real engineering practice \u2014 it keeps the "logic" (when should the motor be on?) separate from the "actuation" (what physical output gets driven?), so swapping in test harnesses or fault-injection logic only requires modifying network 1, not network 0.\n\n**Why this is FBD and not ladder.** Both languages can express this circuit, and many PLC projects mix them. FBD wins when the engineer is thinking in terms of "this signal flows into that operator"; ladder wins when thinking in terms of "this contact closes the path to that coil." For the seal-in pattern specifically, FBD\'s three-input AND collapses what ladder requires drawing as three series contacts on one rung \u2014 a small win, but a representative one.'
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
"slug": "fbd-tank-setpoint-limiter",
|
|
776
|
+
"diagram": "fbd",
|
|
777
|
+
"title": "Tank setpoint limiter + alarm (FBD)",
|
|
778
|
+
"description": "Two-network FBD that clamps an operator-entered tank-level setpoint to the safe range [0, 95]% via LIMIT, and raises an alarm if the operator types an out-of-range value. Uses LT and GT comparison blocks, the LIMIT selection block, and demonstrates REAL (orange) and BOOL (black) wires carrying different data types in one diagram.",
|
|
779
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
780
|
+
"tags": [
|
|
781
|
+
"fbd",
|
|
782
|
+
"plc",
|
|
783
|
+
"comparison",
|
|
784
|
+
"limit",
|
|
785
|
+
"real",
|
|
786
|
+
"hmi",
|
|
787
|
+
"operator-input"
|
|
788
|
+
],
|
|
789
|
+
"complexity": 2,
|
|
790
|
+
"featured": false,
|
|
791
|
+
"dsl": 'fbd "Tank Level Setpoint Limiter"\n\nvar DesiredSetpoint: real\nvar SafeSetpoint: real\nvar Alarm: bool\n\nnetwork 0 "Clamp setpoint to safe range":\n SafeSetpoint = LIMIT(MN: 0.0, IN: DesiredSetpoint, MX: 95.0)\n\nnetwork 1 "Alarm on out-of-range request":\n OutOfRange = OR(LT(DesiredSetpoint, 0.0), GT(DesiredSetpoint, 95.0))\n Alarm = MOVE(OutOfRange.OUT)',
|
|
792
|
+
"notes": "When an operator types a tank-level setpoint into the HMI, you can't just trust the number. Maybe they meant to type 75 and hit 750. Maybe they typed -5 because they were copying from a spec sheet that used a different reference. Maybe the HMI's input field doesn't have validation and the value is whatever bit-pattern the OPC UA bridge happened to land on. The PLC always validates, and the canonical pattern is: clamp to a safe range, then raise an alarm if the requested value was out of range so a human knows to check.\n\n**Network 0 \u2014 LIMIT.** `SafeSetpoint = LIMIT(MN: 0.0, IN: DesiredSetpoint, MX: 95.0)` is the clamp. LIMIT takes three REAL inputs and returns a REAL: the value of `IN` if it's in [MN, MX], otherwise MN or MX. Both bounds are inline constants \u2014 they render as yellow boxed text at their ports, no wire needed. The downstream control loop reads `SafeSetpoint`, never `DesiredSetpoint` directly. Even if the operator's input is corrupted, the tank can never be commanded outside the physically safe range.\n\n**Network 1 \u2014 out-of-range alarm.** `OutOfRange = OR(LT(DesiredSetpoint, 0.0), GT(DesiredSetpoint, 95.0))` is an inline expression that nests two comparison blocks inside an OR. LT (less-than) returns BOOL when its first input is less than the second; GT (greater-than) is the opposite. The OR fires when *either* fires \u2014 the operator's value was either too low or too high. The `Alarm = MOVE(OutOfRange.OUT)` then drives whatever HMI alarm channel \u2014 a red banner, a Slack notification, a SCADA event log entry.\n\n**Two data types in one diagram.** Look at the wire colors in the rendered SVG: the wire from `DesiredSetpoint` into LIMIT.IN is REAL (orange \u2014 IEEE 754 floating-point); the wires from LT.OUT and GT.OUT into OR are BOOL (black). The LIMIT.OUT is also REAL (orange). One of the FBD engine's small but pleasant features: the renderer infers each wire's type from the source port and colors it accordingly, following the TIA Portal convention. If you accidentally wired an INT to a REAL port the colors would mismatch at the junction and you'd notice immediately.\n\n**Why not ladder?** Ladder logic excels at boolean signal routing \u2014 contacts in series and parallel feeding into output coils. It has zero affordance for REAL arithmetic and comparison; you'd write the LIMIT expression as a structured-text \"function block\" call inside a ladder rung, which kills the visual semantic. FBD makes the math first-class. For per-scan combinational logic involving any non-BOOL signal, FBD is what the IEC 61131-3 standard expects you to use."
|
|
793
|
+
},
|
|
416
794
|
{
|
|
417
795
|
"slug": "fishbone-website-traffic",
|
|
418
796
|
"diagram": "fishbone",
|
|
@@ -430,6 +808,63 @@ var EXAMPLES = [
|
|
|
430
808
|
"dsl": 'fishbone "Fishbone diagram \u2014 Website traffic drop"\n\neffect "Traffic decline"\n\ncategory content "Content"\ncategory tech "Technical"\ncategory links "Backlinks"\ncategory ux "UX"\ncategory competition "Competition"\ncategory algo "Algorithm"\n\ncontent : "Publishing frequency down"\ncontent : "Content too generic"\ncontent : "Keyword gaps"\ncontent : "Low-quality AI content"\n\ntech : "Core Web Vitals failing"\ntech : "Crawl coverage drop"\ntech : "Crawler blocked by WAF"\ntech : "Missing structured data"\n\nlinks : "High-quality backlinks lost"\nlinks : "High ratio of low-quality links"\nlinks : "Referring domain growth stalled"\nlinks : "Low anchor text diversity"\n\nux : "Bounce rate rising"\nux : "Poor mobile experience"\nux : "Slow above-fold load"\nux : "Excessive popup ads"\n\ncompetition : "New competitors entering"\ncompetition : "AI tools replacing search"\ncompetition : "Weakening brand recall"\ncompetition : "Competitors publishing faster"\n\nalgo : "Core Update penalty"\nalgo : "Weak E-E-A-T signals"\nalgo : "AI Overviews / SGE cutoff"\nalgo : "Search intent drift"',
|
|
431
809
|
"notes": '## Scenario\n\nAn ops lead runs a growth post-mortem after a 30% organic traffic drop. The Ishikawa (fishbone) diagram structures the team\'s brainstorm into six standard causal categories, preventing the meeting from fixating on the most vocal hypothesis while ignoring systemic causes. The completed diagram becomes the project brief for the remediation sprint.\n\n## Annotation key\n\n- `effect "..."` \u2014 the problem statement, placed at the fish\'s head (right side)\n- `category id "Label"` \u2014 defines a major causal branch (a "bone"); use a short `id` to assign causes\n- `id : "cause text"` \u2014 assigns a cause string to the named category branch\n- Each category renders as a diagonal rib pointing toward the effect\n- Sub-causes (second-order) can be added by nesting if the DSL supports it\n\n## How to read\n\nThe effect (traffic decline) sits at the right. Six causal ribs branch from the spine: Content, Technical, Backlinks, UX, Competition, and Algorithm. Each rib lists four specific hypotheses. In a workshop, the team votes on each cause, color-codes high-confidence ones, and converts the highest-priority items into action items. The diagram serves as both a brainstorming artifact and a living post-mortem document.'
|
|
432
810
|
},
|
|
811
|
+
{
|
|
812
|
+
"slug": "flowchart-algo-binary-search",
|
|
813
|
+
"diagram": "flowchart",
|
|
814
|
+
"title": "Binary search algorithm",
|
|
815
|
+
"description": "Iterative binary search over a sorted array \u2014 the classic CS teaching flowchart, from array + target input to found/not-found output.",
|
|
816
|
+
"standard": "ISO 5807:1985",
|
|
817
|
+
"tags": [
|
|
818
|
+
"algorithm",
|
|
819
|
+
"binary-search",
|
|
820
|
+
"teaching",
|
|
821
|
+
"cs",
|
|
822
|
+
"sorted-array",
|
|
823
|
+
"iterative"
|
|
824
|
+
],
|
|
825
|
+
"complexity": 2,
|
|
826
|
+
"featured": false,
|
|
827
|
+
"dsl": "flowchart TD\n input([Input: sorted array A, target T]) --> init[low = 0, high = n \u2212 1]\n init --> loopcheck{low \u2264 high?}\n loopcheck -->|No| notfound([Return \u22121 \u2014 target not found])\n loopcheck -->|Yes| mid[mid = floor((low + high) / 2)]\n mid --> eqcheck{A[mid] == T?}\n eqcheck -->|Yes| found([Return mid \u2014 target found at index mid])\n eqcheck -->|No| ltcheck{A[mid] < T?}\n ltcheck -->|Yes \u2014 search right half| newlow[low = mid + 1]\n newlow --> loopcheck\n ltcheck -->|No \u2014 search left half| newhigh[high = mid \u2212 1]\n newhigh --> loopcheck",
|
|
828
|
+
"notes": "## Scenario\n\nA CS teacher is preparing lecture slides on divide-and-conquer algorithms and wants a textbook-quality flowchart students can annotate alongside the pseudocode. The iterative formulation makes the loop invariant \u2014 the search space halving each iteration \u2014 visually explicit, and the two boundary-update branches give students a concrete mental model for why the algorithm runs in O(log n) time.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; algorithm entry with inputs and terminal return values\n- `{\u2026}` \u2014 diamond; loop-continuation test and value-comparison decisions\n- `[\u2026]` \u2014 rectangle; variable initialization and index update assignments\n- `-->|label|` \u2014 branch labels stating the condition outcome and which half is selected\n- Back edges from `newlow` and `newhigh` to `loopcheck` form the iterative loop body\n\n## How to read\n\nThe algorithm initializes two index pointers \u2014 `low` at zero and `high` at the last index \u2014 then enters the main loop gate. If `low` exceeds `high` the search space is exhausted and \u22121 is returned. Otherwise `mid` is computed as the floor average of the two pointers and the element at that index is compared to the target. An exact match terminates with the index; a mismatch routes to the less-than check, which moves `low` one past `mid` to discard the left half, or moves `high` one below `mid` to discard the right half. Either update sends control back to the loop gate, halving the remaining search space on every iteration."
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
"slug": "flowchart-approval-bpmn",
|
|
832
|
+
"diagram": "flowchart",
|
|
833
|
+
"title": "Purchase order approval",
|
|
834
|
+
"description": "Employee submits PO \u2192 manager review \u2192 finance approval \u2192 payment \u2014 BPMN gateway shapes for a business approval workflow.",
|
|
835
|
+
"standard": "ISO 5807:1985",
|
|
836
|
+
"tags": [
|
|
837
|
+
"approval",
|
|
838
|
+
"bpmn",
|
|
839
|
+
"purchase-order",
|
|
840
|
+
"workflow",
|
|
841
|
+
"finance",
|
|
842
|
+
"gateway"
|
|
843
|
+
],
|
|
844
|
+
"complexity": 2,
|
|
845
|
+
"featured": false,
|
|
846
|
+
"dsl": "flowchart TD\n submit([Employee submits purchase order]) --> amtcheck{Amount > $10,000?}\n amtcheck -->|Yes \u2014 CFO track| cfo[CFO review queue]\n amtcheck -->|No \u2014 standard track| mgr[Department manager review]\n mgr --> mapproved{Manager approved?}\n mapproved -->|No| revise[Request revision from employee]\n revise --> submit\n mapproved -->|Yes| cfo\n cfo --> capproved{CFO approved?}\n capproved -->|No| reject([Reject PO \u2014 notify employee with reason])\n capproved -->|Yes| finance[Finance processes payment]\n finance --> vendor[Send payment confirmation to vendor]\n vendor --> done([PO closed \u2014 archived to ERP])",
|
|
847
|
+
"notes": "## Scenario\n\nA business analyst is documenting a company's purchase order workflow to support an ERP implementation and audit readiness review. The diagram makes explicit the dollar-amount threshold that gates which approval track a PO enters, the revision loop that keeps rejected items in flight rather than discarding them, and the two possible terminal outcomes \u2014 closed PO or formal rejection with written rationale.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; employee-initiated event and terminal closure or rejection nodes\n- `{\u2026}` \u2014 diamond; BPMN-style exclusive gateways branching on amount threshold or approval decision\n- `[\u2026]` \u2014 rectangle; human review steps and system actions (payment, notification, archival)\n- `-->|label|` \u2014 branch label showing threshold condition or approval outcome\n- Loop from `revise` back to `submit` keeps the PO in flight through the standard track after revision\n\n## How to read\n\nEvery PO enters the amount-check gateway immediately after submission. Orders above ten thousand dollars skip manager review and go directly to the CFO queue; orders at or below the threshold must first receive manager approval. A manager rejection sends the PO back to the employee for revision, which re-enters the same gateway \u2014 the amount does not change, so revised orders under the threshold loop through manager review again. Once the CFO approves (either from the high-value track or an escalated standard-track PO), finance executes payment and notifies the vendor, closing the PO in the ERP. A CFO rejection terminates the flow with a formal notice to the employee."
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
"slug": "flowchart-auth-flow",
|
|
851
|
+
"diagram": "flowchart",
|
|
852
|
+
"title": "OAuth 2.0 authorization code + PKCE",
|
|
853
|
+
"description": "OAuth 2.0 authorization code flow with PKCE \u2014 the recommended grant for SPAs and mobile apps, per RFC 7636.",
|
|
854
|
+
"standard": "ISO 5807:1985",
|
|
855
|
+
"tags": [
|
|
856
|
+
"oauth",
|
|
857
|
+
"pkce",
|
|
858
|
+
"authorization-code",
|
|
859
|
+
"security",
|
|
860
|
+
"spa",
|
|
861
|
+
"rfc7636"
|
|
862
|
+
],
|
|
863
|
+
"complexity": 4,
|
|
864
|
+
"featured": false,
|
|
865
|
+
"dsl": 'flowchart LR\n subgraph "Client App"\n start([User initiates login]) --> gen[Generate code verifier + SHA-256 challenge]\n gen --> redirect[Redirect to authorization endpoint with challenge + state]\n callback[Receive authorization code] --> exchange[POST /token \u2014 code + code verifier]\n tokens[Store access + refresh tokens] --> bearer[Attach Bearer token to API request]\n end\n subgraph "Authorization Server"\n redirect --> login[Present login + consent UI]\n login --> consent{User consents?}\n consent -->|No| deny([Authorization denied \u2014 redirect with error])\n consent -->|Yes| issue[Issue authorization code \u2014 redirect to callback]\n issue --> callback\n exchange --> verify{code_challenge matches verifier hash?}\n verify -->|No| err([400 Bad Request \u2014 PKCE mismatch])\n verify -->|Yes| mint[Mint access token + refresh token]\n mint --> tokens\n end\n subgraph "Resource Server"\n bearer --> validate{Bearer token valid + not expired?}\n validate -->|No| unauth([401 Unauthorized])\n validate -->|Yes| data([Return protected resource])\n end',
|
|
866
|
+
"notes": '## Scenario\n\nA security engineer is reviewing a team\'s SPA authentication implementation against RFC 7636 to verify that the implicit grant has been fully removed in favor of authorization code with PKCE. The diagram makes the cryptographic handshake \u2014 code verifier generated client-side, challenge sent to the authorization server, verifier submitted at token exchange \u2014 visible alongside the three distinct server boundaries, helping reviewers confirm that no secret is ever stored in browser memory.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; user-initiated events and terminal success/error responses\n- `{\u2026}` \u2014 diamond; server-side validation gates (consent, PKCE hash match, token validity)\n- `[\u2026]` \u2014 rectangle; client or server processing steps\n- `subgraph "\u2026"` \u2014 trust boundary lanes for Client App, Authorization Server, and Resource Server\n- `-->|label|` \u2014 branch labels showing consent outcome or validation result\n\n## How to read\n\nThe flow starts in the Client App lane where the application generates a random code verifier and derives its SHA-256 challenge before redirecting the user. In the Authorization Server lane the user authenticates and consents; the server returns an authorization code bound to the challenge. The client then submits the original verifier in the token exchange request \u2014 the Authorization Server hashes it and compares it to the stored challenge, rejecting mismatches with a 400. Valid exchanges produce short-lived access and refresh tokens. The Resource Server lane shows the final step: every API call presents the Bearer token and the server validates its signature and expiry before returning data, enforcing a clean separation between authorization and resource access.'
|
|
867
|
+
},
|
|
433
868
|
{
|
|
434
869
|
"slug": "flowchart-cicd-pipeline",
|
|
435
870
|
"diagram": "flowchart",
|
|
@@ -448,6 +883,62 @@ var EXAMPLES = [
|
|
|
448
883
|
"dsl": "flowchart TD\n commit([Push to main]) --> build[Build artifact]\n build --> unit{Unit tests pass?}\n unit -->|No| fail([Fail build])\n unit -->|Yes| scan[Security scan]\n scan --> vuln{High-severity CVEs?}\n vuln -->|Yes| fail\n vuln -->|No| stage[Deploy to staging]\n stage --> smoke{Smoke tests green?}\n smoke -->|No| fail\n smoke -->|Yes| approve{Manual approval?}\n approve -->|No| wait([Await approver])\n approve -->|Yes| prod[Deploy to production]\n prod --> health{Post-deploy health check?}\n health -->|Yes| done([Release complete])\n health -->|No| rollback[Automatic rollback]\n rollback --> done",
|
|
449
884
|
"notes": "## Scenario\n\nA platform engineer is documenting the team's trunk-based pipeline for a new-hire runbook. The diagram makes the four automated gates (tests \u2192 scan \u2192 smoke \u2192 post-deploy health) and the single human gate (manual approval) obvious at a glance, and shows that every failure path terminates the pipeline rather than silently continuing.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; start and terminal nodes\n- `{\u2026}` \u2014 diamond; automated or manual gate\n- `[\u2026]` \u2014 rectangle; build / deploy / scan step\n- `-->|Yes/No|` \u2014 branch labels on each gate\n\n## How to read\n\nStart at *Push to main*. Every diamond is a gate \u2014 a *No* on any of unit tests, CVE scan, or smoke tests terminates at *Fail build*. Manual approval is the only human gate; it can park the pipeline at *Await approver* without failing. The post-deploy health check guards production: a failure triggers automatic rollback, which still completes at *Release complete* because the rollback itself is a successful outcome."
|
|
450
885
|
},
|
|
886
|
+
{
|
|
887
|
+
"slug": "flowchart-etl-pipeline",
|
|
888
|
+
"diagram": "flowchart",
|
|
889
|
+
"title": "ETL data pipeline",
|
|
890
|
+
"description": "Source extraction through transform, validation, load, and warehouse notification \u2014 the standard data-engineering pipeline diagram.",
|
|
891
|
+
"standard": "ISO 5807:1985",
|
|
892
|
+
"tags": [
|
|
893
|
+
"etl",
|
|
894
|
+
"pipeline",
|
|
895
|
+
"data",
|
|
896
|
+
"warehouse",
|
|
897
|
+
"validation",
|
|
898
|
+
"transform"
|
|
899
|
+
],
|
|
900
|
+
"complexity": 3,
|
|
901
|
+
"featured": false,
|
|
902
|
+
"dsl": 'flowchart LR\n subgraph "Sources"\n pg[(PostgreSQL)] --> extract\n s3[(S3 bucket)] --> extract\n api[REST API] --> extract\n end\n extract[Extract to raw staging] --> clean[Clean \u2014 strip nulls, deduplicate]\n clean --> normalize[Normalize \u2014 cast types, unify schemas]\n normalize --> enrich[Enrich \u2014 join lookup tables]\n enrich --> validate{Error rate > 1%?}\n validate -->|Yes| quarantine[Quarantine bad rows]\n quarantine --> notify[Alert data-quality Slack channel]\n notify --> retry{Retry batch?}\n retry -->|Yes| extract\n retry -->|No| abort([Abort run \u2014 log to incident tracker])\n validate -->|No| load[Load to data warehouse]\n load --> qcheck[Run row-count and sum reconciliation]\n qcheck --> passed{Reconciliation passed?}\n passed -->|No| rollback[Rollback warehouse load]\n rollback --> abort\n passed -->|Yes| publish[Publish partition metadata]\n publish --> downstream([Notify downstream consumers \u2014 dbt, BI, ML])',
|
|
903
|
+
"notes": '## Scenario\n\nA data engineer is documenting a nightly batch ETL job that ingests transactional records from three heterogeneous sources into a central warehouse. The diagram serves as both a runbook and a stakeholder communication artifact, showing data-quality enforcement points that prevent silent corruption from propagating to reporting dashboards and machine-learning feature stores.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; terminal run outcomes (abort, notify consumers)\n- `{\u2026}` \u2014 diamond; quality gates with quantitative thresholds\n- `[\u2026]` \u2014 rectangle; processing steps or system actions\n- `[(\u2026)]` \u2014 cylinder; external data stores\n- `subgraph "Sources"` \u2014 groups the three ingestion connectors into one tier\n- Loop from `retry -->|Yes|` back to `extract` models full-batch reprocessing after quarantine\n\n## How to read\n\nThe pipeline fans in from three source connectors into a single extract step that writes to raw staging. The transform chain \u2014 clean, normalize, enrich \u2014 runs sequentially; each step narrows and standardizes the data before passing it forward. The validation gate measures the bad-row error rate: if it exceeds one percent, bad rows are quarantined, an alert fires, and the operator decides whether to retry or abort the run. Rows that pass validation are loaded to the warehouse, then verified with a row-count and sum reconciliation; a failed reconciliation triggers a rollback and abort rather than leaving inconsistent data in place. A successful reconciliation publishes partition metadata and fans out notifications to downstream consumers.'
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
"slug": "flowchart-incident-response",
|
|
907
|
+
"diagram": "flowchart",
|
|
908
|
+
"title": "On-call incident response",
|
|
909
|
+
"description": "SRE on-call decision tree from alert page through triage, escalation, mitigation, and post-mortem \u2014 BPMN-shaped TD flow.",
|
|
910
|
+
"standard": "ISO 5807:1985",
|
|
911
|
+
"tags": [
|
|
912
|
+
"incident",
|
|
913
|
+
"sre",
|
|
914
|
+
"on-call",
|
|
915
|
+
"escalation",
|
|
916
|
+
"mitigation",
|
|
917
|
+
"postmortem"
|
|
918
|
+
],
|
|
919
|
+
"complexity": 3,
|
|
920
|
+
"featured": false,
|
|
921
|
+
"dsl": "flowchart TD\n page([Alert fires \u2014 on-call paged]) --> ack{Acknowledged within 5 min?}\n ack -->|No| escalate[Escalate to secondary on-call]\n escalate --> sev\n ack -->|Yes| sev{Severity assessment}\n sev -->|SEV1 \u2014 customer-facing outage| sev1[Wake CTO + open war room bridge]\n sev -->|SEV2 \u2014 degraded service| sev2[Notify team lead + Slack channel]\n sev -->|SEV3 \u2014 internal only| sev3[Self-resolve within shift]\n sev1 --> mitigate[Apply mitigation \u2014 rollback or hotfix]\n sev2 --> mitigate\n sev3 --> mitigate\n mitigate --> health{Service health restored?}\n health -->|No| mitigate\n health -->|Yes| resolved([Incident resolved \u2014 close bridge])\n resolved --> postmortem{SEV1 or SEV2?}\n postmortem -->|Yes| pm[Write post-mortem within 48 h]\n postmortem -->|No| log[Log in incident tracker]\n pm --> done([Done])\n log --> done",
|
|
922
|
+
"notes": "## Scenario\n\nAn SRE team uses this flowchart as the canonical on-call runbook embedded in their incident-management wiki. When an alert fires at 3 AM the responder can follow the diagram top to bottom without improvising, ensuring that acknowledgment, severity triage, escalation paths, and post-mortem obligations are never skipped regardless of who is on duty.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; trigger events and terminal closure nodes\n- `{\u2026}` \u2014 diamond; time-boxed decisions and severity gates\n- `[\u2026]` \u2014 rectangle; prescribed human actions (escalate, notify, mitigate, document)\n- `-->|label|` \u2014 branch label showing condition or severity band\n- Loop back from `health -->|No|` to `mitigate` represents the retry-until-resolved mitigation cycle\n\n## How to read\n\nThe flow begins the moment an alert fires. The first gate enforces the five-minute acknowledgment SLA; a miss immediately escalates to the secondary responder who then re-enters the severity triage diamond. Severity determines the escalation audience \u2014 SEV1 wakes executive leadership, SEV2 notifies the team lead, SEV3 is self-contained. All three paths converge on the mitigation loop, which repeats until health is restored. The final diamond routes only SEV1 and SEV2 incidents to a formal post-mortem; SEV3 incidents close with a tracker log entry."
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
"slug": "flowchart-microservices-request",
|
|
926
|
+
"diagram": "flowchart",
|
|
927
|
+
"title": "Microservices request flow",
|
|
928
|
+
"description": "API gateway routing a request through auth, rate-limit, and three backend services to a shared DB \u2014 LR subgraph layout.",
|
|
929
|
+
"standard": "ISO 5807:1985",
|
|
930
|
+
"tags": [
|
|
931
|
+
"microservices",
|
|
932
|
+
"api-gateway",
|
|
933
|
+
"request-flow",
|
|
934
|
+
"backend",
|
|
935
|
+
"subgraph"
|
|
936
|
+
],
|
|
937
|
+
"complexity": 3,
|
|
938
|
+
"featured": false,
|
|
939
|
+
"dsl": 'flowchart LR\n subgraph "API Layer"\n client([Client request]) --> gateway[API Gateway]\n gateway --> auth{Auth valid?}\n auth -->|No| reject([401 Unauthorized])\n auth -->|Yes| rate{Rate limit ok?}\n rate -->|No| throttle([429 Too Many Requests])\n end\n subgraph "Services"\n rate -->|Yes| route{Route by path}\n route -->|/users| user[User Service]\n route -->|/orders| order[Order Service]\n order --> notify[Notification Service]\n end\n subgraph "Data"\n user --> db[(PostgreSQL)]\n order --> db\n end\n user -->|200 response| client\n order -->|200 response| client\n db -->|query error| dberr([500 DB Error])',
|
|
940
|
+
"notes": '## Scenario\n\nA backend engineer is documenting the runtime topology of a decomposed e-commerce platform so that new team members can trace a request end to end without reading source code. The diagram exposes the two pre-routing gates (authentication and rate limiting) and the downstream fan-out to specialized services, making it clear why a client might receive a 401, 429, or 500 before any business logic executes.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; entry points and terminal error/success nodes\n- `{\u2026}` \u2014 diamond; routing and policy decision gates\n- `[\u2026]` \u2014 rectangle; service or infrastructure processing step\n- `[(\u2026)]` \u2014 cylinder; persistent data store\n- `-->|label|` \u2014 labeled directed edge showing condition or path name\n- `subgraph "name"` \u2014 swimlane grouping API, service, and data tiers\n\n## How to read\n\nStart at *Client request* and follow the arrow into the API Layer subgraph. The request must clear two sequential gates \u2014 authentication then rate limiting \u2014 before reaching the route diamond. The route diamond dispatches to *User Service* or *Order Service* based on the URL path; an order request additionally triggers the *Notification Service* asynchronously. Both services share the same *PostgreSQL* store; a database error at that layer surfaces as a 500 terminal node independent of which service triggered the query.'
|
|
941
|
+
},
|
|
451
942
|
{
|
|
452
943
|
"slug": "flowchart-order-fulfillment",
|
|
453
944
|
"diagram": "flowchart",
|
|
@@ -466,6 +957,44 @@ var EXAMPLES = [
|
|
|
466
957
|
"dsl": "flowchart LR\n start([New order received])\n start --> validate{Inventory available?}\n validate -->|Yes| reserve[Reserve items]\n validate -->|No| notify[Notify customer]\n notify --> done([End])\n reserve --> payment{Payment authorized?}\n payment -->|Yes| ship[Ship order]\n payment -->|No| cancel[Cancel & release]\n ship --> confirm[Send confirmation email]\n confirm --> done\n cancel --> done",
|
|
467
958
|
"notes": '## Scenario\n\nA product ops lead circulates this flowchart during an ops-review meeting to align engineering, customer support, and fulfillment on the single source of truth for what happens when a new order comes in. It surfaces the two decision gates (inventory, payment) and the three exception paths (out-of-stock notification, payment failure with released hold, successful ship with confirmation).\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium / terminal; used for Start and End\n- `{\u2026}` \u2014 diamond; decision node\n- `[\u2026]` \u2014 rectangle; process step\n- `-->|label|` \u2014 edge with a branch label (`Yes` / `No`)\n\n## How to read\n\nStart at the top-left terminal. Inventory check gates the first branch \u2014 a "No" routes straight to the End after notification. A "Yes" reserves stock then hits the payment gate. Payment failure releases the reservation and goes to End; success ships and emails the customer. Every path terminates at the same End node, so nothing dangles.'
|
|
468
959
|
},
|
|
960
|
+
{
|
|
961
|
+
"slug": "flowchart-prisma-systematic-review",
|
|
962
|
+
"diagram": "flowchart",
|
|
963
|
+
"title": "PRISMA 2020 systematic review flow",
|
|
964
|
+
"description": "Canonical PRISMA 2020 flow diagram for a systematic review \u2014 records identified across databases, screened, assessed for eligibility, and included in synthesis.",
|
|
965
|
+
"standard": "PRISMA 2020 (Page et al., BMJ 2021)",
|
|
966
|
+
"tags": [
|
|
967
|
+
"flowchart",
|
|
968
|
+
"prisma",
|
|
969
|
+
"systematic-review",
|
|
970
|
+
"meta-analysis",
|
|
971
|
+
"research",
|
|
972
|
+
"evidence-synthesis"
|
|
973
|
+
],
|
|
974
|
+
"complexity": 3,
|
|
975
|
+
"featured": true,
|
|
976
|
+
"dsl": 'flowchart TD\n classDef excluded fill:#fef2f2,stroke:#b91c1c,stroke-width:1px,color:#7f1d1d\n\n subgraph ID ["Identification"]\n pubmed["PubMed (n = 482)"]\n embase["Embase (n = 314)"]\n cochrane["Cochrane (n = 91)"]\n registers["Trial registers (n = 38)"]\n end\n\n subgraph SCREEN ["Screening"]\n dedup["After duplicates removed (n = 712)"]\n titles["Title and abstract screened (n = 712)"]\n excl_titles["Records excluded (n = 598)"]\n fulltext["Full-text sought (n = 114)"]\n retrieved["Assessed for eligibility (n = 109)"]\n not_retrieved["Not retrieved (n = 5)"]\n end\n\n subgraph ELIG ["Eligibility"]\n assessed["Full-text articles assessed (n = 109)"]\n excl_reasons["Excluded with reasons (n = 60)"]\n r1["Wrong population (n = 18)"]\n r2["Wrong intervention (n = 22)"]\n r3["Wrong outcome (n = 11)"]\n r4["Conference abstract only (n = 9)"]\n end\n\n included(["Studies in qualitative synthesis (n = 49)"])\n meta(["Studies in meta-analysis (n = 31)"])\n\n pubmed --> dedup\n embase --> dedup\n cochrane --> dedup\n registers --> dedup\n dedup --> titles\n titles -->|excluded| excl_titles\n titles -->|kept| fulltext\n fulltext --> retrieved\n fulltext -->|paywall / no response| not_retrieved\n retrieved --> assessed\n assessed -->|excluded with reasons| excl_reasons\n excl_reasons --> r1\n excl_reasons --> r2\n excl_reasons --> r3\n excl_reasons --> r4\n assessed -->|met inclusion criteria| included\n included --> meta\n\n class excl_titles,not_retrieved,excl_reasons,r1,r2,r3,r4 excluded',
|
|
977
|
+
"notes": '## Scenario\n\nA research librarian working with a clinical team produces the PRISMA 2020 flow diagram for an upcoming Cochrane review submission. The journal **requires** the diagram in this exact four-phase structure (Identification \u2192 Screening \u2192 Eligibility \u2192 Included), with the count `(n = \u2026)` shown explicitly in every box and the excluded-with-reasons box itemizing rejection reasons. Authoring this in a DSL (rather than redrawing in Word or BioRender) means the counts can be regenerated as the screening team updates the search.\n\n## Annotation key\n\n- **Subgraphs** name the four PRISMA phases: `subgraph ID ["Identification"]`, etc. \u2014 the rendered output groups boxes inside a labeled cluster border.\n- **`(n = N)` inline** \u2014 keep the count in the same label (PRISMA 2020 requires the count to be visible in every box; inline is the simplest layout that survives wide labels).\n- **`classDef excluded`** + **`class A,B excluded`** \u2014 applies the red-tinted class to the "records excluded" boxes so the eliminated stream is visually separated from the surviving stream.\n- **Edge labels** (`-->|excluded|`, `-->|met inclusion criteria|`) annotate the screening decision on each fork.\n- **Stadium nodes** (`(["\u2026"])`) mark the two terminal outcomes (qualitative synthesis count, meta-analysis count) so readers\' eyes land there.\n\n## How to read\n\nTop to bottom, the four phases mirror the PRISMA 2020 template exactly:\n\n1. **Identification** \u2014 every database and register the team searched, with raw record counts before deduplication.\n2. **Screening** \u2014 after deduplication, records pass through title/abstract screening (most are excluded here), then eligible records advance to full-text retrieval. Records lost at retrieval (paywall, no response from authors) are split into a separate "not retrieved" box per PRISMA 2020 reporting requirements.\n3. **Eligibility** \u2014 full-text articles are assessed against inclusion/exclusion criteria. Exclusions **must** be itemized with reasons \u2014 this is the box reviewers most often flag if missing.\n4. **Included** \u2014 final study count for the qualitative synthesis, with a sub-count for studies that contributed to the meta-analysis (not all included studies always do).\n\n## Standard reference\n\nPage MJ, McKenzie JE, Bossuyt PM, et al. *The PRISMA 2020 statement: an updated guideline for reporting systematic reviews.* BMJ 2021;372:n71. The flow-diagram template lives at [prisma-statement.org/prisma-2020-flow-diagram](https://www.prisma-statement.org/prisma-2020-flow-diagram).'
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
"slug": "flowchart-user-onboarding",
|
|
981
|
+
"diagram": "flowchart",
|
|
982
|
+
"title": "User onboarding flow",
|
|
983
|
+
"description": "Signup through email verification, profile setup, first-action tutorial, and activation milestone \u2014 a product manager's north-star flow.",
|
|
984
|
+
"standard": "ISO 5807:1985",
|
|
985
|
+
"tags": [
|
|
986
|
+
"onboarding",
|
|
987
|
+
"activation",
|
|
988
|
+
"signup",
|
|
989
|
+
"tutorial",
|
|
990
|
+
"user-flow",
|
|
991
|
+
"product"
|
|
992
|
+
],
|
|
993
|
+
"complexity": 2,
|
|
994
|
+
"featured": false,
|
|
995
|
+
"dsl": "flowchart TD\n signup([User submits signup form]) --> email[Send verification email]\n email --> verified{Email verified?}\n verified -->|No \u2014 after 24 h| resend[Resend verification email]\n resend --> verified\n verified -->|Yes| profile[Profile setup wizard]\n profile --> skipped{Wizard completed?}\n skipped -->|Skip| tour[Feature tour \u2014 3 tooltip steps]\n skipped -->|Complete| tour\n tour --> action{First core action taken?}\n action -->|No \u2014 after 48 h| nudge[Send nudge email with shortcut link]\n nudge --> action\n action -->|Yes| activate[Record activation event]\n activate --> welcome([Welcome milestone reached])",
|
|
996
|
+
"notes": '## Scenario\n\nA product manager is mapping the critical path from sign-up to activation to align engineering, growth, and design on what "activated user" means. The diagram makes every drop-off risk visible \u2014 email verification friction, wizard abandonment, and first-action hesitation \u2014 so each team can own the metric that corresponds to their part of the funnel.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; user-triggered entry and milestone terminal nodes\n- `{\u2026}` \u2014 diamond; binary or conditional state checks\n- `[\u2026]` \u2014 rectangle; system or product actions (send email, show wizard, record event)\n- `-->|label|` \u2014 branch labels showing condition, time trigger, or user choice\n- Loop edges from `resend` and `nudge` model retry cycles that resolve when the user acts\n\n## How to read\n\nThe flow starts at form submission and immediately hits the email verification gate. Users who do not verify within 24 hours loop through a resend step; this loop continues until verification succeeds. Once verified, all users \u2014 whether they complete the profile wizard or skip it \u2014 enter the three-step feature tour. The first-action gate determines activation: users who have not acted within 48 hours receive a nudge email that links directly to the core feature, shortening the path back into the loop. Activation fires a single analytics event that marks the user as "activated" and terminates the onboarding sequence.'
|
|
997
|
+
},
|
|
469
998
|
{
|
|
470
999
|
"slug": "genogram-brca-cancer",
|
|
471
1000
|
"diagram": "genogram",
|
|
@@ -611,6 +1140,26 @@ var EXAMPLES = [
|
|
|
611
1140
|
"dsl": 'logic "1-bit Full Adder"\ninput A, B, Cin\noutput Sum, Cout\ns1 = XOR(A, B)\nSum = XOR(s1, Cin)\nc1 = AND(A, B)\nc2 = AND(s1, Cin)\nCout = OR(c1, c2)',
|
|
612
1141
|
"notes": "## Scenario\n\nThe 1-bit full adder is the foundational building block of every arithmetic logic unit. Digital logic students derive it in lecture; FPGA engineers instantiate it in RTL. Schematex renders it from a purely functional description \u2014 no manual gate placement, no wire routing \u2014 making it easy to embed in textbooks, datasheets, or AI-generated hardware documentation.\n\n## Annotation key\n\n- `input A, B, Cin` \u2014 declare named input ports\n- `output Sum, Cout` \u2014 declare named output ports\n- `s1 = XOR(A, B)` \u2014 intermediate signal `s1` is the XOR of inputs A and B\n- `Sum = XOR(s1, Cin)` \u2014 the sum bit is the XOR of the partial sum and carry-in\n- `c1 = AND(A, B)` \u2014 carry generated when both A and B are 1\n- `c2 = AND(s1, Cin)` \u2014 carry propagated when partial sum is 1 and Cin is 1\n- `Cout = OR(c1, c2)` \u2014 carry-out is 1 if either generate or propagate carry is active\n\n## How to read\n\nThe diagram renders two XOR gates for the sum path (A\u2295B, then \u2295Cin) and two AND gates feeding an OR for the carry-out (the standard generate/propagate structure). The layout is automatically ranked so data flows left to right, inputs on the left edge, outputs on the right. Every 4-bit or 8-bit ripple-carry adder in textbooks is just this circuit chained together."
|
|
613
1142
|
},
|
|
1143
|
+
{
|
|
1144
|
+
"slug": "matrix-9-box-talent",
|
|
1145
|
+
"diagram": "matrix",
|
|
1146
|
+
"title": "9-box talent grid",
|
|
1147
|
+
"description": "3\xD73 performance \xD7 potential talent grid \u2014 the GE/McKinsey HR review tool used to plan promotions, succession, and performance management.",
|
|
1148
|
+
"standard": "9-Box Talent Grid (GE / McKinsey)",
|
|
1149
|
+
"tags": [
|
|
1150
|
+
"matrix",
|
|
1151
|
+
"9-box",
|
|
1152
|
+
"talent",
|
|
1153
|
+
"hr",
|
|
1154
|
+
"succession",
|
|
1155
|
+
"performance",
|
|
1156
|
+
"table"
|
|
1157
|
+
],
|
|
1158
|
+
"complexity": 2,
|
|
1159
|
+
"featured": false,
|
|
1160
|
+
"dsl": 'matrix 9-box "Engineering \u2014 H1 Talent Review"\nstyle: table\ncell (0,2) label: "Enigma"\ncell (0,2) label: "Samir K. (sr. eng)"\ncell (1,2) label: "Growth Employee"\ncell (1,2) label: "Priya R. (eng II)"\ncell (1,2) label: "Tom\xE1s L. (eng II)"\ncell (2,2) label: "Future Leader"\ncell (2,2) label: "Maya O. (sr. eng)"\ncell (0,1) label: "Dilemma"\ncell (0,1) label: "David C. (eng II)"\ncell (1,1) label: "Core Player"\ncell (1,1) label: "Lin H. (sr. eng)"\ncell (1,1) label: "Kofi A. (eng II)"\ncell (2,1) label: "High Impact"\ncell (2,1) label: "Reina S. (staff)"\ncell (0,0) label: "Under-performer"\ncell (0,0) label: "\u2014 PIP candidate \u2014"\ncell (1,0) label: "Effective"\ncell (1,0) label: "Jordan P. (eng I)"\ncell (2,0) label: "Trusted Pro"\ncell (2,0) label: "Elena V. (staff)"',
|
|
1161
|
+
"notes": "## Scenario\n\nA VP of People runs the half-year talent review with eng managers. Each direct report lands in one of nine cells based on **performance** (the x-axis: how they're doing today) and **potential** (the y-axis: how much room they have to grow). The three top-row cells are the succession bench. The three bottom-row cells are the performance-management agenda. The middle row is the steady-state core that holds the org together.\n\n## Annotation key\n\n- `matrix 9-box` \u2014 preset 3\xD73 grid (the canonical nine cell names ship with the template)\n- `style: table` \u2014 top-aligned bullet-list rendering inside each cell\n- `cell (col, row) label: \"...\"` \u2014 each line adds one bullet to that cell. First line per cell is the canonical role name (Enigma / Future Leader / Core Player / \u2026); subsequent lines list the people in that cell\n- Coordinates: `(0, 0)` is bottom-left (low performance, low potential); `(2, 2)` is top-right (high performance, high potential)\n\n## How to read\n\n**Future Leader** (top-right) is the natural-successor cell \u2014 the person you'd promote if a senior role opens tomorrow. **Dilemma** (top-left) and **Enigma** (top-middle-left) are the high-potential / low-performance cells: stuck in the wrong role, or under-coached, or in a bad team-fit \u2014 usually a managerial action item, not a performance issue. **Under-performer** (bottom-left) is the only cell that should ever be empty; if it has names, plan the next conversation now.\n\nThe canonical 9-box discipline is to **anchor each calibration discussion on observable evidence** \u2014 a recent shipped project, a missed deadline, a mentee promotion. Without that anchor, the grid drifts into bias. The table format is what the calibration committee literally prints and marks up in the room."
|
|
1162
|
+
},
|
|
614
1163
|
{
|
|
615
1164
|
"slug": "matrix-bcg-portfolio",
|
|
616
1165
|
"diagram": "matrix",
|
|
@@ -633,19 +1182,58 @@ var EXAMPLES = [
|
|
|
633
1182
|
"slug": "matrix-eisenhower-week",
|
|
634
1183
|
"diagram": "matrix",
|
|
635
1184
|
"title": "Eisenhower week prioritization",
|
|
636
|
-
"description": "2\xD72 Eisenhower
|
|
1185
|
+
"description": "2\xD72 Eisenhower table grouping a week's tasks into Do First / Schedule / Delegate / Delete \u2014 the canonical text-in-cell layout, not a scatter chart.",
|
|
637
1186
|
"standard": "Eisenhower (1954)",
|
|
638
1187
|
"tags": [
|
|
639
1188
|
"matrix",
|
|
640
1189
|
"eisenhower",
|
|
641
1190
|
"prioritization",
|
|
642
1191
|
"productivity",
|
|
643
|
-
"planning"
|
|
1192
|
+
"planning",
|
|
1193
|
+
"table"
|
|
644
1194
|
],
|
|
645
|
-
"complexity":
|
|
1195
|
+
"complexity": 1,
|
|
646
1196
|
"featured": true,
|
|
647
|
-
"dsl": 'matrix eisenhower "This Week"\
|
|
648
|
-
"notes": '## Scenario\n\nAn engineering manager
|
|
1197
|
+
"dsl": 'matrix eisenhower "This Week"\nstyle: table\nQ2: "Ship hotfix"\nQ2: "Customer demo prep"\nQ1: "Write Q3 OKRs"\nQ1: "Refactor auth layer"\nQ4: "LinkedIn updates"\nQ4: "Inbox zero"\nQ3: "Reorganize Slack channels"',
|
|
1198
|
+
"notes": '## Scenario\n\nAn engineering manager triages her week at Monday planning. The point of an Eisenhower matrix in real use isn\'t a scatter plot \u2014 it\'s a **four-cell list**: tasks dropped into the quadrant that matches their urgency \xD7 importance. The table tells her at a glance where her attention should go this week (Do First + Schedule), what to push down (Delegate), and what to drop (Delete).\n\n## Annotation key\n\n- `matrix eisenhower` \u2014 preset axes (urgency \xD7 importance) and four quadrant titles\n- `style: table` \u2014 text-in-cell layout: hides axes/arrows/grid, renders quadrant titles as cell headers, lists each item as a bullet\n- `Q1:` \u2026 `Q4:` \u2014 shorthand for `cell (col, row) label: \u2026`. Q1=top-right (Schedule), Q2=top-left (Do First), Q3=bottom-left (Delete), Q4=bottom-right (Delegate)\n- Repeating `Q2:` stacks multiple tasks in the same cell as a bullet list\n\n## How to read\n\nThe "Do First" cell (top-left in eisenhower\'s convention with urgent on the left axis) is the urgent + important pile \u2014 work the morning sprint. "Schedule" is the trap quadrant: important but not yet urgent (Q3 OKRs, refactor) \u2014 it silently slips until it becomes urgent and badly done. "Delegate" is the busy-work the AI generates \u2014 urgent on someone\'s calendar but not actually load-bearing for the org. "Delete" is the candidate for "no": neither urgent nor important.\n\n## Why a table, not a chart\n\nThe classic Eisenhower output is a 2\xD72 grid with task lists, not a scatter of dots. If you want to encode a third dimension (time cost, owner) on top of the cell layout, drop `style: table` and use `"Label" at (x, y) size: N` instead \u2014 that switches to bubble mode.'
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
"slug": "matrix-impact-effort",
|
|
1202
|
+
"diagram": "matrix",
|
|
1203
|
+
"title": "Impact-effort feature prioritization",
|
|
1204
|
+
"description": "2\xD72 impact \xD7 effort table sorting a backlog into Quick Wins / Major Projects / Fill-ins / Thankless \u2014 the classic PM prioritization grid.",
|
|
1205
|
+
"standard": "Impact\u2013Effort (Sondhi 1999)",
|
|
1206
|
+
"tags": [
|
|
1207
|
+
"matrix",
|
|
1208
|
+
"impact",
|
|
1209
|
+
"effort",
|
|
1210
|
+
"prioritization",
|
|
1211
|
+
"product",
|
|
1212
|
+
"table"
|
|
1213
|
+
],
|
|
1214
|
+
"complexity": 1,
|
|
1215
|
+
"featured": false,
|
|
1216
|
+
"dsl": 'matrix impact-effort "Sprint Planning \u2014 Q2 Backlog"\nstyle: table\nQ2: "Add bulk-delete to inbox"\nQ2: "Surface error message inline"\nQ2: "Fix mobile menu z-index bug"\nQ1: "Rebuild billing on new stripe API"\nQ1: "Multi-tenant workspace support"\nQ3: "Brand color audit"\nQ3: "Update tooltip copy"\nQ4: "Animated empty-state illustrations"\nQ4: "Internal admin dashboard polish"',
|
|
1217
|
+
"notes": "## Scenario\n\nA solo PM running quarterly planning ranks the backlog. The table form is what stakeholders actually want to see in the planning doc \u2014 a sortable list per quadrant, not a scatter plot. Quick Wins go in the top-left (high impact, low effort) \u2014 ship them this sprint. Major Projects are the bets (high impact, high effort) \u2014 pick at most one per quarter. Thankless work (low impact, high effort) is where teams accidentally burn quarters.\n\n## Annotation key\n\n- `matrix impact-effort` \u2014 preset axes (effort \xD7 impact) with the four PM-canonical quadrant names\n- `style: table` \u2014 render as a 4-cell text grid, no axis arrows, no chart\n- `Q1` \u2026 `Q4` \u2014 Q1=high impact + high effort (Major Projects), Q2=high impact + low effort (Quick Wins), Q3=low impact + low effort (Fill-ins), Q4=low impact + high effort (Thankless)\n\n## How to read\n\nIf your Quick Wins cell is empty, that's a smell \u2014 it usually means the PM hasn't broken down work small enough. If your Major Projects cell has more than one item per engineer-quarter, you're overcommitting. The Thankless cell is where you have the conversation about cutting scope or pushing to next quarter."
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
"slug": "matrix-johari-window",
|
|
1221
|
+
"diagram": "matrix",
|
|
1222
|
+
"title": "Johari window \u2014 manager self-assessment",
|
|
1223
|
+
"description": "2\xD72 Johari window placing self-traits across Open / Blind / Hidden / Unknown \u2014 the classic coaching exercise rendered as a four-cell table.",
|
|
1224
|
+
"standard": "Johari window (Luft & Ingham 1955)",
|
|
1225
|
+
"tags": [
|
|
1226
|
+
"matrix",
|
|
1227
|
+
"johari",
|
|
1228
|
+
"coaching",
|
|
1229
|
+
"self-awareness",
|
|
1230
|
+
"hr",
|
|
1231
|
+
"table"
|
|
1232
|
+
],
|
|
1233
|
+
"complexity": 1,
|
|
1234
|
+
"featured": false,
|
|
1235
|
+
"dsl": 'matrix johari "Self vs. Team \u2014 Q2 Reflection"\nstyle: table\nQ2: "Strong technical instincts"\nQ2: "Direct in code review"\nQ2: "Patient with juniors"\nQ1: "Interrupts in meetings"\nQ1: "Hard to read when stressed"\nQ3: "Imposter syndrome about leadership"\nQ3: "Anxiety about cross-team politics"\nQ4: "Capacity for difficult conversations under pressure"',
|
|
1236
|
+
"notes": "## Scenario\n\nA newly-promoted engineering manager runs a Johari exercise with her team during a 1:1 retro. She populates the **Open** cell (things both she and the team see); the team adds to **Blind** (things they see that she doesn't); she fills **Hidden** privately; **Unknown** is the open hypothesis space \u2014 capabilities and limitations that haven't surfaced yet.\n\nThe table form is the canonical Johari output. Coaches print it on a single page and walk through it with the coachee \u2014 a scatter plot of dots would defeat the entire purpose.\n\n## Annotation key\n\n- `matrix johari` \u2014 preset axes (Known to Self \xD7 Known to Others) with the four window panes\n- `style: table` \u2014 flips off axes/grid, places each pane title as a cell header, lists items as bullets\n- `Q1` = Blind (top-right: not known to self, known to others)\n- `Q2` = Open / Arena (top-left: known to self + others)\n- `Q3` = Hidden / Fa\xE7ade (bottom-left: known to self, not to others)\n- `Q4` = Unknown (bottom-right: not known to either \u2014 the growth hypothesis space)\n\n## How to read\n\nThe classic Johari coaching prompt: **how do you move items from Hidden \u2192 Open** (vulnerability work) **and from Blind \u2192 Open** (feedback-acceptance work)? An overstuffed Hidden pane signals psychological-safety debt; an empty Blind pane usually means the team hasn't been asked."
|
|
649
1237
|
},
|
|
650
1238
|
{
|
|
651
1239
|
"slug": "mindmap-product-launch",
|
|
@@ -683,6 +1271,83 @@ var EXAMPLES = [
|
|
|
683
1271
|
"dsl": "mindmap\n\n# Q4 Company OKRs\n\n## Grow ARR 30%\n### Expand enterprise pipeline\n- 10 new qualified logos\n- Win rate \u2265 25%\n### Increase expansion\n- Net revenue retention \u2265 120%\n- Seat adoption +40%\n\n## Ship Platform v2\n### Core migration\n- 100% API coverage\n- Zero-downtime cutover\n### Developer experience\n- Sub-5-min quickstart\n- 95% doc satisfaction\n\n## Strengthen team\n### Hiring\n- 8 senior engineers\n- 2 staff PMs\n### Retention\n- Voluntary attrition < 5%\n- eNPS \u2265 40",
|
|
684
1272
|
"notes": "## Scenario\n\nThe chief of staff projects this during the Q4 all-hands. Three objectives radiate from the centre; every key result is a leaf with a specific number. The mindmap format reads fast \u2014 every person in the company can find their team's objective within three seconds \u2014 and it tolerates mid-quarter edits without disturbing other branches.\n\n## Annotation key\n\n- `#` \u2014 root; company-level frame\n- `##` \u2014 objective (qualitative direction)\n- `###` \u2014 key-result cluster\n- `-` bullets \u2014 specific measurable KRs\n\n## How to read\n\nThe root names the quarter. The three `##` branches are the objectives \u2014 the things that will be judged at the end of the quarter. Each `###` groups key results by theme; the bullets are the actual measurable targets. If a KR can't be reduced to a number, it probably belongs in a planning doc rather than on this mindmap."
|
|
685
1273
|
},
|
|
1274
|
+
{
|
|
1275
|
+
"slug": "orgchart-board-committees",
|
|
1276
|
+
"diagram": "orgchart",
|
|
1277
|
+
"title": "Corporate board and committee structure",
|
|
1278
|
+
"description": "Public-company board governance \u2014 full board with audit, compensation, nominating/governance, and risk subcommittees per SEC requirements.",
|
|
1279
|
+
"standard": "SEC / NYSE governance",
|
|
1280
|
+
"tags": [
|
|
1281
|
+
"orgchart",
|
|
1282
|
+
"board",
|
|
1283
|
+
"governance",
|
|
1284
|
+
"audit",
|
|
1285
|
+
"compensation",
|
|
1286
|
+
"sec",
|
|
1287
|
+
"committee"
|
|
1288
|
+
],
|
|
1289
|
+
"complexity": 3,
|
|
1290
|
+
"featured": false,
|
|
1291
|
+
"dsl": 'orgchart "Acme Corp \u2014 Board & Committee Structure"\nchair: "Victoria Harmon" | Board Chair [role: advisor]\n audit_chair: "Ellen Frost, CPA" | Audit Committee Chair [role: finance]\n audit_m1: "James Liu" | Audit Committee Member [role: finance]\n audit_m2: "Priya Mehta" | Audit Committee Member [role: finance]\n comp_chair: "Thomas Osei" | Compensation Committee Chair [role: hr]\n comp_m1: "Sarah Nakamura" | Compensation Committee Member [role: hr]\n comp_m2: "Rafael Dominguez" | Compensation Committee Member [role: hr]\n nom_chair: "Linda Abramowitz" | Nom. & Governance Chair [role: legal]\n nom_m1: "Derek Abubakar" | Nom. & Governance Member [role: legal]\n nom_m2: "Yuki Fernandez" | Nom. & Governance Member [role: legal]\n risk_chair: "Raj Mehta" | Risk Committee Chair [role: ops]\n risk_m1: "Cynthia Okonkwo" | Risk Committee Member [role: ops]\n risk_m2: "Simon Park" | Risk Committee Member [role: ops]\nboard_ceo: "David Park" | CEO (Management) [role: ceo]\n mgmt_cfo: "Angela Torres" | CFO [role: finance]\n mgmt_clo: "Marcus Reyes" | Chief Legal Officer [role: legal]\nboard_ceo -.-> audit_chair\nboard_ceo -.-> comp_chair\nboard_ceo -.-> nom_chair\nboard_ceo -.-> risk_chair',
|
|
1292
|
+
"notes": '## Scenario\n\nThe corporate secretary is preparing the annual proxy statement and needs to document the board\'s committee structure as required by SEC Regulation S-K Item 407 and NYSE Listed Company Rules. The four standing committees \u2014 Audit, Compensation, Nominating & Governance, and Risk \u2014 each consist entirely of independent directors. The CEO and CFO participate in committee meetings by invitation and report to the relevant committees, but are not members. The dotted lines from the CEO to each committee chair represent this management reporting relationship for operational matters.\n\n## Annotation key\n\n- `chair: "Victoria Harmon" | Board Chair [role: advisor]` \u2014 independent chair; non-executive\n- Committee chairs and members use `[role: finance]`, `[role: hr]`, `[role: legal]`, `[role: ops]` to visually distinguish oversight focus\n- `board_ceo: "David Park" | CEO (Management)` \u2014 management side; inside-the-box CEO distinct from the independent board\n- `board_ceo -.-> audit_chair` \u2014 dotted lines represent management\'s accountability to each committee, not reporting hierarchy\n- All committee members must be independent directors under SEC Rule 10A-3 (Audit) and NYSE Section 303A\n\n## How to read\n\nThe board chart has two distinct clusters. The upper cluster \u2014 Board Chair and the four committees \u2014 is the governance structure: independent directors exercising fiduciary oversight. The lower cluster \u2014 CEO and management \u2014 represents the executive team that is accountable to the board. Dotted lines from the CEO to each committee chair indicate that management attends and reports to committees without being members or having voting rights. The Audit Committee chair (Ellen Frost, CPA) satisfies the SEC\'s financial expert disclosure requirement. NYSE rules require that Compensation and Nom/Gov committees be composed solely of independent directors; the Risk Committee follows the same practice here but is not legally mandated to be fully independent.'
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
"slug": "orgchart-engineering-dept",
|
|
1296
|
+
"diagram": "orgchart",
|
|
1297
|
+
"title": "Engineering department \u2014 platform, product, infra squads",
|
|
1298
|
+
"description": "Engineering org with three squad leads under a VP Eng \u2014 platform, product, and infrastructure, with open headcount flagged.",
|
|
1299
|
+
"standard": "HR convention",
|
|
1300
|
+
"tags": [
|
|
1301
|
+
"orgchart",
|
|
1302
|
+
"engineering",
|
|
1303
|
+
"squad",
|
|
1304
|
+
"platform",
|
|
1305
|
+
"infra",
|
|
1306
|
+
"product"
|
|
1307
|
+
],
|
|
1308
|
+
"complexity": 3,
|
|
1309
|
+
"featured": false,
|
|
1310
|
+
"dsl": 'orgchart "Engineering Department \u2014 Q3 Headcount Plan"\nstaff_pe: "Diana Okonkwo" | Staff Principal Engineer [role: engineer]\nvp_eng: "Sarah Chen" | VP Engineering [role: cto]\n platform_lead: "Marco Rossi" | Platform Lead [role: engineer]\n pe1: "Kenji Watanabe" | Senior Engineer | Platform [role: engineer]\n pe2: "Aaliya Hassan" | Engineer | Platform [role: engineer]\n pe3: "Lucas Ferreira" | Engineer | Platform [role: engineer]\n open_sr: open "TBH" | Senior Engineer | Platform [role: engineer]\n product_lead: "Aisha Okafor" | Product Eng Lead [role: engineer]\n pe4: "Rohan Mehta" | Senior Engineer | Product [role: engineer]\n pe5: "Chloe Martin" | Engineer | Product [role: engineer]\n pe6: "Jae-won Oh" | Engineer | Product [role: engineer]\n pe7: "Fatima Al-Rashid" | Engineer | Product [role: engineer]\n draft_staff: draft "TBH" | Staff Engineer | Product [role: engineer]\n infra_lead: "Dev Patel" | Infra Lead [role: engineer]\n ie1: "Nadia Kowalski" | Senior SRE [role: engineer]\n ie2: "Emre Yilmaz" | SRE [role: engineer]\n open_sre: open "TBH" | Site Reliability Engineer [role: engineer]\nstaff_pe -.-> platform_lead\nstaff_pe -.-> product_lead\nstaff_pe -.-> infra_lead',
|
|
1311
|
+
"notes": '## Scenario\n\nThe engineering director is presenting the Q3 headcount plan to the CFO. The chart shows three squads \u2014 platform, product engineering, and infrastructure \u2014 each under a dedicated lead reporting to the VP of Engineering. A Staff Principal Engineer provides technical oversight across all three squads via dotted-line relationships. Two open reqs are actively being recruited (Platform Senior Engineer, SRE), and one Staff Engineer seat in the product squad is planned for Q4 but not yet approved.\n\n## Annotation key\n\n- `vp_eng: "Sarah Chen" | VP Engineering [role: cto]` \u2014 VP-level node coloured with the cto role style\n- Indentation (2 spaces) \u2014 solid-line reporting hierarchy\n- `open "TBH"` \u2014 approved open requisition, currently recruiting\n- `draft "TBH"` \u2014 planned headcount, not yet approved or posted\n- `staff_pe -.-> platform_lead` \u2014 dotted line; technical authority without HR reporting chain\n\n## How to read\n\nThe tree root is the VP of Engineering. The three squad leads sit at the second level \u2014 equal peers in the org, differentiated only by domain. Headcount marked `open` (Platform Senior Eng, SRE) represents approved budget the director is actively spending; `draft` (Product Staff) is the ask for the next planning cycle. The staff principal at the top of the chart is neither the VP\'s direct report nor a squad lead: the dotted lines to all three leads signal that she sets technical standards and does architecture review across squads without owning any head count.'
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
"slug": "orgchart-hospital-dept",
|
|
1315
|
+
"diagram": "orgchart",
|
|
1316
|
+
"title": "Hospital clinical department hierarchy",
|
|
1317
|
+
"description": "Hospital clinical org \u2014 Chief Medical Officer, department heads, attendings, residents, and nursing leads for a teaching hospital.",
|
|
1318
|
+
"standard": "JCAHO / hospital convention",
|
|
1319
|
+
"tags": [
|
|
1320
|
+
"orgchart",
|
|
1321
|
+
"hospital",
|
|
1322
|
+
"clinical",
|
|
1323
|
+
"physician",
|
|
1324
|
+
"nursing",
|
|
1325
|
+
"hierarchy"
|
|
1326
|
+
],
|
|
1327
|
+
"complexity": 4,
|
|
1328
|
+
"featured": false,
|
|
1329
|
+
"dsl": 'orgchart "General Hospital \u2014 Clinical Leadership"\ncmo: "Dr. Patricia Williams" | Chief Medical Officer [role: medical]\n chief_med: "Dr. James Park" | Chief of Medicine [role: medical]\n cardio_head: "Dr. Amara Nwosu" | Division Chief | Cardiology [role: medical]\n att_card1: "Dr. Elena Sousa" | Attending Physician [role: medical]\n att_card2: "Dr. Ravi Gupta" | Attending Physician [role: medical]\n res_card1: "Dr. Yuki Tanaka" | PGY-3 Resident [role: medical]\n res_card2: "Dr. Malik Johnson" | PGY-2 Resident [role: medical]\n neuro_head: "Dr. Ingrid Larsen" | Division Chief | Neurology [role: medical]\n att_neuro1: "Dr. Omar Sharif" | Attending Physician [role: medical]\n att_neuro2: "Dr. Priya Krishnan" | Attending Physician [role: medical]\n res_neuro1: "Dr. Tom\xE1s Rivera" | PGY-3 Resident [role: medical]\n res_neuro2: "Dr. Aisha Conteh" | PGY-2 Resident [role: medical]\n chief_surg: "Dr. Amara Diallo" | Chief of Surgery [role: medical]\n gen_surg_head: "Dr. Wei Zhang" | Division Chief | General Surgery [role: medical]\n att_gs1: "Dr. Sofia Reyes" | Attending Surgeon [role: medical]\n att_gs2: "Dr. Kwame Mensah" | Attending Surgeon [role: medical]\n ortho_head: "Dr. Henrik Svensson" | Division Chief | Orthopedics [role: medical]\n att_orth1: "Dr. Nalini Patel" | Attending Surgeon [role: medical]\n att_orth2: "Dr. Seun Adeyemi" | Attending Surgeon [role: medical]\n cno: "Maria Gonzalez, RN, MSN" | Chief Nursing Officer [role: medical]\n med_surg_mgr: "Lisa Park, RN" | Nurse Manager | Med-Surg [role: medical]\n icu_mgr: "Robert Osei, RN" | ICU Nurse Manager [role: medical]',
|
|
1330
|
+
"notes": "## Scenario\n\nA hospital administrator is preparing a JCAHO accreditation submission and needs to document the clinical governance structure. The chart shows the three-pillar model common to teaching hospitals: Medicine and Surgery under the CMO handle physician credentialing and clinical protocols, while Nursing reports separately to ensure independent oversight of nursing practice standards. Attendings supervise residents directly; residents rotate between divisions but report to their division chief.\n\n## Annotation key\n\n- `[role: medical]` \u2014 all clinical staff rendered with the medical colour coding\n- Indentation \u2014 solid-line administrative and clinical reporting chain\n- `PGY-2 / PGY-3` \u2014 Post-Graduate Year, the standard US resident designation (PGY-1 = intern)\n- `RN, MSN` \u2014 inline credentials appended to the name field, common in nursing leadership notation\n- Division Chiefs sit between the department Chief and individual attendings \u2014 the standard academic medical centre layer\n\n## How to read\n\nThe CMO owns clinical quality across all departments. Medicine and Surgery are equal pillars \u2014 each Chief has autonomous credentialing authority within their specialty. Within Medicine, Cardiology and Neurology each run their own attending\u2013resident teaching structure: attendings carry clinical responsibility; residents operate under supervision with authority expanding by PGY year. Nursing reports up through the CNO rather than through either clinical chief \u2014 a deliberate governance separation required by Magnet hospital standards. The two nurse managers (Med-Surg floor, ICU) translate CNO policy to unit-level staffing and care protocols."
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
"slug": "orgchart-law-firm-partnership",
|
|
1334
|
+
"diagram": "orgchart",
|
|
1335
|
+
"title": "Law firm partnership structure",
|
|
1336
|
+
"description": "AmLaw 100-style law firm org \u2014 equity and non-equity partners, counsel, associates, and professional staff by practice group.",
|
|
1337
|
+
"standard": "NALP convention",
|
|
1338
|
+
"tags": [
|
|
1339
|
+
"orgchart",
|
|
1340
|
+
"law-firm",
|
|
1341
|
+
"partnership",
|
|
1342
|
+
"counsel",
|
|
1343
|
+
"associate",
|
|
1344
|
+
"legal"
|
|
1345
|
+
],
|
|
1346
|
+
"complexity": 3,
|
|
1347
|
+
"featured": false,
|
|
1348
|
+
"dsl": 'orgchart "Chen & Associates LLP \u2014 Partnership Structure"\nmanaging_partner: "Robert Chen" | Managing Partner [role: ceo]\n corp_chair: "Jennifer Wu" | Corporate Practice Chair [role: coo]\n corp_ep1: "David Okafor" | Equity Partner | M&A [role: legal]\n corp_ep1_sa1: "Mei-Ling Torres" | Senior Associate [role: legal]\n corp_ep1_a1: "Brendan Nwosu" | Associate [role: legal]\n corp_ep1_a2: "Priya Sharma" | Associate [role: legal]\n corp_ep2: "Simone Beaumont" | Equity Partner | Securities [role: legal]\n corp_ep2_sa1: "Aleksei Volkov" | Senior Associate [role: legal]\n corp_ep2_a1: "Fatou Diallo" | Associate [role: legal]\n corp_nep: "Marcus Tran" | Non-Equity Partner | Corporate [role: legal]\n corp_nep_a1: "Yuna Kim" | Associate [role: legal]\n corp_para1: "Sandra Lopez" | Paralegal [role: ops]\n lit_chair: "Marcus Johnson" | Litigation Practice Chair [role: coo]\n lit_ep1: "Amara Osei" | Equity Partner | Commercial Lit [role: legal]\n lit_ep1_sa1: "Tobias Gruber" | Senior Associate [role: legal]\n lit_ep1_a1: "Chimamanda Eze" | Associate [role: legal]\n lit_ep2: "Hiroshi Nakamura" | Equity Partner | White Collar [role: legal]\n lit_ep2_sa1: "Valentina Cruz" | Senior Associate [role: legal]\n lit_ep2_a1: "Daniel Abioye" | Associate [role: legal]\n lit_counsel: "Rachel Goldstein" | Counsel | Litigation [role: legal]\n cfo: "Dana Kim" | COO / CFO [role: finance]\n mkt: "Alex Torres" | Chief Marketing Officer [role: ops]',
|
|
1349
|
+
"notes": "## Scenario\n\nThe managing partner is preparing materials for the annual partnership meeting, including the governance deck and lateral-hire pitch collateral. The chart shows the two-track attorney structure common to AmLaw 100 firms: equity partners share in firm profits and have capital accounts; non-equity partners are on fixed compensation; counsel are senior attorneys on a permanent non-partnership track. Associates are levelled as first-through-fifth-year and senior (sixth-plus). Professional staff \u2014 COO/CFO and CMO \u2014 sit as firm-level directs to the managing partner.\n\n## Annotation key\n\n- `[role: legal]` \u2014 attorney nodes; `[role: finance]` and `[role: ops]` \u2014 professional staff\n- Equity Partner \u2014 profit-sharing, voting interest in firm governance\n- Non-Equity Partner \u2014 title parity without capital account; typically earns a fixed bonus-eligible salary\n- Counsel \u2014 senior non-partner track: often former partners, domain specialists, or attorneys who opted out of the equity track\n- Senior Associate \u2014 sixth year or above; on the partnership evaluation clock\n- `corp_chair` / `lit_chair` \u2014 practice group chairs own lateral hiring, billing rate setting, and matter assignment within their group\n\n## How to read\n\nRobert Chen, as managing partner, chairs the firm's executive committee and carries final governance authority. The two practice chairs report to him and run their groups as semi-autonomous profit centres. Within each group, equity partners own client relationships and sign off on fee arrangements; associates bill under partner supervision. The non-equity partner in Corporate adds capacity without diluting the equity pool \u2014 a common structure when a client relationship is stable but not large enough to justify a new equity slot. Counsel in Litigation handles specialized motions work that would otherwise require lateral-hiring a lateral partner. The COO/CFO and CMO report directly to the managing partner rather than through a practice chair \u2014 they serve the whole firm, not a single group."
|
|
1350
|
+
},
|
|
686
1351
|
{
|
|
687
1352
|
"slug": "orgchart-matrix-reporting",
|
|
688
1353
|
"diagram": "orgchart",
|
|
@@ -790,6 +1455,62 @@ var EXAMPLES = [
|
|
|
790
1455
|
"dsl": 'phylo "Bacterial Diversity"\n newick: "((((Ecoli:0.1,Salmonella:0.12):0.05[&&NHX:B=98],Vibrio:0.2):0.08[&&NHX:B=85],((Bacillus:0.15,Staph:0.18):0.06[&&NHX:B=92],Listeria:0.22):0.1):0.15,((Myco_tb:0.3,Myco_leprae:0.28):0.12[&&NHX:B=100],(Strepto:0.25,Lactobacillus:0.2):0.08[&&NHX:B=78]):0.2);"\n clade Gamma = (Ecoli, Salmonella, Vibrio) [color: "#1E88E5", label: "\u03B3-Proteobacteria"]\n clade Firmi = (Bacillus, Staph, Listeria, Strepto, Lactobacillus) [color: "#E53935", label: "Firmicutes"]\n clade Actino = (Myco_tb, Myco_leprae) [color: "#43A047", label: "Actinobacteria"]\n scale "substitutions/site"',
|
|
791
1456
|
"notes": '## Scenario\n\nA microbiologist or bioinformatician pastes a Newick tree string exported from RAxML, IQ-TREE, or MEGA and immediately gets a publication-ready SVG with clade highlights and a branch-length scale bar \u2014 no manual layout required.\n\n## Annotation key\n\n- `newick: "..."` \u2014 standard Newick format tree string; branch lengths follow `:` after each taxon name\n- `[&&NHX:B=98]` \u2014 NHX annotation; `B=` is the bootstrap support value (0\u2013100), rendered on internal nodes\n- `clade id = (taxon, ...)` \u2014 defines a named clade by listing its leaf members\n- `[color: "#hex", label: "..."]` \u2014 colors the clade\'s subtree and adds a labeled arc\n- `scale "..."` \u2014 draws a calibrated scale bar with the given unit label\n\n## How to read\n\nThe tree shows three major bacterial clades. Blue (\u03B3-Proteobacteria): *E. coli*, *Salmonella*, and *Vibrio* cluster with 98% bootstrap support. Red (Firmicutes): *Bacillus*, *Staph*, *Listeria*, *Streptococcus*, and *Lactobacillus*. Green (Actinobacteria): the two *Mycobacterium* species form a highly supported clade (bootstrap 100). Branch lengths represent substitutions per site \u2014 longer branches indicate faster evolutionary rates.'
|
|
792
1457
|
},
|
|
1458
|
+
{
|
|
1459
|
+
"slug": "sfc-bake-cool-concurrent",
|
|
1460
|
+
"diagram": "sfc",
|
|
1461
|
+
"title": "Bake & cool concurrent batch (SFC)",
|
|
1462
|
+
"description": "Simultaneous-branch SFC of a batch oven that bakes (15-minute D-qualified action) and cools the chamber jacket (5-minute L-qualified action) concurrently after a heat-up phase. Both branches must complete before the converge bar fires. Exercises the IEC 61131-3 \xA76.5.4 double-bar simultaneous divergence and time-parameterized action qualifiers.",
|
|
1463
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1464
|
+
"tags": [
|
|
1465
|
+
"sfc",
|
|
1466
|
+
"plc",
|
|
1467
|
+
"simultaneous-branch",
|
|
1468
|
+
"time-qualified",
|
|
1469
|
+
"batch-reactor",
|
|
1470
|
+
"oven"
|
|
1471
|
+
],
|
|
1472
|
+
"complexity": 3,
|
|
1473
|
+
"featured": true,
|
|
1474
|
+
"dsl": 'sfc "Bake and cool concurrently"\n\nvar BakeReady: bool\nvar Bake_Done: bool\nvar Cool_Done: bool\n\nstep S0 [initial]\n\nstep S_Heat\n N Heater_On\n\nsim from: S_Heat: TRUE\n branch:\n step S_Bake\n D Oven_Run T#15m\n branch:\n step S_Cool\n L Cooler_On T#5m\nmerge_to: S_Done: Bake_Done AND Cool_Done\n\nstep S_Done\n N AnnounceDone\n\ntransition from: S0 to: S_Heat: BakeReady\ntransition from: S_Done to: S0: NOT BakeReady',
|
|
1475
|
+
"notes": "A real batch reactor or industrial oven rarely runs phases one at a time \u2014 once the chamber is hot, you want to start the bake timer and the chamber-jacket cooling cycle simultaneously, because the cooling jacket protects equipment downstream and has its own independent timeout. SFC's simultaneous-branch construct captures this exactly: one entry transition fires both branches in lockstep, both branches run concurrently, and the chart waits at the convergence until *every* branch is done.\n\n**Two parallel horizontal lines = simultaneous bar.** The IEC 61131-3 \xA76.5.4 grammar uses **single-line bars** for alternative (OR-semantic) branches and **double-line bars** for simultaneous (AND-semantic) branches \u2014 visually distinct so an experienced eye can tell at a glance which kind of fork they're looking at. Schematex renders the double bar with a 4px gap between the two lines, exactly per spec.\n\n**The shared transition above and below.** Notice the `TRUE` transition just above the simultaneous divergence \u2014 that's the *single shared* condition that triggers the fork. Both branches start at once when `TRUE` fires (in this case unconditionally, because the heater step's job was already complete). At the bottom, the `Bake_Done AND Cool_Done` is the merge condition: the chart waits at the simultaneous convergence until *both* branch outcomes are asserted, then moves to S_Done. This shared-transition placement (above the divergence, below the convergence) is the inverse of how alternative branches work \u2014 alternative branches have their condition *between* the bar and each branch.\n\n**D vs L qualifiers \u2014 different time semantics.** S_Bake's `D Oven_Run T#15m` is a **time-delayed** action: when the step becomes active, wait 15 minutes, *then* start running `Oven_Run`. This matches a real oven: you want a soak interval before the heating element actually fires. S_Cool's `L Cooler_On T#5m` is **time-limited**: start running `Cooler_On` immediately on step entry, but stop after 5 minutes regardless. Both qualifiers render with a small bottom row inside the action block showing the duration literal \u2014 `T#15m` and `T#5m` \u2014 so anyone reviewing the chart can read the timing at a glance without cross-referencing a separate timing table.\n\n**Why concurrency matters here.** If the bake and cool ran sequentially, the total recipe time would be `15m + 5m = 20m` per batch. Running them in parallel cuts to `max(15m, 5m) = 15m`. Across 50 batches per shift, that's nearly an extra hour of throughput \u2014 the kind of optimization that's invisible in ladder-only programs but obvious in SFC. The reason most plants don't have it: the engineer didn't have a graphical sequential language in their toolbox. Schematex fills that gap."
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
"slug": "sfc-bottle-filling",
|
|
1479
|
+
"diagram": "sfc",
|
|
1480
|
+
"title": "Bottle filling sequence (SFC)",
|
|
1481
|
+
"description": "Three-step sequential function chart for a bottle-filling station \u2014 idle with valve closed, fill while tank level rises, signal done. Exercises the IEC 61131-3 \xA76.5 initial-step double border, N-qualified actions, and condition expressions on transitions.",
|
|
1482
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1483
|
+
"tags": [
|
|
1484
|
+
"sfc",
|
|
1485
|
+
"plc",
|
|
1486
|
+
"iec-61131-3",
|
|
1487
|
+
"sequential-control",
|
|
1488
|
+
"packaging"
|
|
1489
|
+
],
|
|
1490
|
+
"complexity": 1,
|
|
1491
|
+
"featured": true,
|
|
1492
|
+
"dsl": 'sfc "Bottle Filling"\n\nvar StartBtn: bool\nvar TankLevel: real\nvar DoneBtn: bool\n\nstep S0 [initial]\n N FillValve_Closed\n\nstep S1 [label: "Filling"]\n N FillValve_Open\n\nstep S2 [label: "Done"]\n N Confirm_Done\n\ntransition from: S0 to: S1: StartBtn\ntransition from: S1 to: S2: TankLevel >= 80.0\ntransition from: S2 to: S0: DoneBtn',
|
|
1493
|
+
"notes": "Sequential function charts are the most underused PLC language. Most automation code is written in ladder, but ladder describes per-scan combinational logic \u2014 it can't express \"we're in the *fill* phase right now and the next phase begins when the tank hits 80%.\" Engineers fake state machines in ladder using auxiliary boolean tags (one per state, set/reset by transition logic), and the result is unreadable six months later. SFC makes the state machine explicit: each step is a phase, each transition is a boolean condition that triggers the handoff.\n\n**Three steps, three phases.** S0 is the **initial step** \u2014 drawn with a double border per IEC 61131-3 \xA76.5.1.2, marking the entry point when the program starts. While S0 is active, its single N-qualified action `FillValve_Closed` runs every scan. The chart sits in S0 until the StartBtn transition fires; then control moves to S1.\n\n**S1 \u2014 filling phase.** While in S1, the action `FillValve_Open` runs every scan. The chart waits in S1 until the transition `TankLevel >= 80.0` evaluates true. Note that condition is just plain text \u2014 Schematex doesn't parse or evaluate IEC structured-text expressions; it stores them verbatim and renders them next to the bar. The PLC runtime is what actually evaluates.\n\n**S2 \u2014 done phase.** S2 holds with `Confirm_Done` running until the operator presses the DoneBtn (or whatever signals the cycle complete) \u2014 at which point we loop back to S0. Because S0 is not linearly adjacent to S2 in the body, this transition renders as a **margin jump arrow** on the side of the chart, with the target step id and the condition both labeled.\n\n**N qualifier \u2014 non-stored.** The `N` letter on each action means *non-stored*: the action runs only while its owning step is active, and stops automatically when the step deactivates. This is by far the most common qualifier \u2014 about 80% of real SFC actions use it. The SFC standard supports ten others (S/R for stored, L/D for time-limited/delayed, P for one-scan pulses, etc.) but for this example N is exactly right.\n\n**Why this is SFC and not a flowchart.** A flowchart of the same machine would show diamond decisions (\"is start pressed? if yes, ...\") and you'd lose the explicit \"we're *in* phase X\" semantics. SFC's active-step token model \u2014 one step holds the token at any moment, transitions move it \u2014 is the formal definition of *cyclic sequential control*, and it maps directly to how real PLC scan engines execute. When you bring this diagram to a code review with the maintenance team, they'll instantly recognize the pattern."
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
"slug": "sfc-order-routing-alt",
|
|
1497
|
+
"diagram": "sfc",
|
|
1498
|
+
"title": "Order routing \u2014 express vs standard shipping (SFC)",
|
|
1499
|
+
"description": "Alternative-branch SFC of an order-fulfillment routing decision. After picking the product, exactly one branch fires per scan based on the leftmost-true entry transition (priority 1 = express shipping first). Both branches converge to a common shipping step. Exercises the IEC 61131-3 \xA76.5.4 single-bar OR semantics, branch priority annotations, and per-branch entry/exit transitions.",
|
|
1500
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1501
|
+
"tags": [
|
|
1502
|
+
"sfc",
|
|
1503
|
+
"plc",
|
|
1504
|
+
"alternative-branch",
|
|
1505
|
+
"priority",
|
|
1506
|
+
"routing",
|
|
1507
|
+
"e-commerce"
|
|
1508
|
+
],
|
|
1509
|
+
"complexity": 2,
|
|
1510
|
+
"featured": false,
|
|
1511
|
+
"dsl": 'sfc "Order routing"\n\nvar ProductOrdered: bool\nvar IsExpressShipping: bool\nvar IsStandardShipping: bool\nvar Shipped: bool\n\nstep S0 [initial]\n\nstep S_Pick\n N PickFromBin\n\nalt from: S_Pick:\n branch [priority: 1]:\n transition: IsExpressShipping\n step S_Express\n N PrepExpressBox\n transition: TRUE\n branch [priority: 2]:\n transition: IsStandardShipping\n step S_Standard\n N PrepStandardBox\n transition: TRUE\nmerge_to: S_Ship\n\nstep S_Ship\n N CarrierPickup\n\ntransition from: S0 to: S_Pick: ProductOrdered\ntransition from: S_Ship to: S0: Shipped',
|
|
1512
|
+
"notes": "A modern fulfillment center handles both express (next-day) and standard (3\u20135 day) shipping on the same physical line, with the same picking robots and the same carrier-pickup conveyor. The only divergence is the boxing step: express boxes are different sizes, use rigid corrugate, and get extra tracking labels. SFC's alternative branch is the right shape for this: one step (picking) splits into two paths (express boxing OR standard boxing) and they converge back to a common end step (carrier pickup).\n\n**Single horizontal bar = alternative.** IEC 61131-3 \xA76.5.4 uses a **single horizontal line** for alternative (OR-semantic) divergence and convergence. Visually it's the simpler cousin of the double-bar simultaneous fork; semantically it's the opposite \u2014 only *one* branch fires per scan, picked by which entry transition's condition evaluates true first under the priority order.\n\n**Priority annotation matters.** Both branches have `[priority: N]` markers \u2014 express is priority 1, standard is priority 2. If both `IsExpressShipping` and `IsStandardShipping` were somehow true at the same time (a bug, but a common one in early integration), the priority forces the express path. The renderer puts a small red number near each branch entry to make the priority visible at review time.\n\n**Per-branch entry and exit transitions.** Inside each branch, there are two `transition: ...` lines \u2014 the first is the **entry transition** (fires when control reaches the divergence bar; renders between the bar and the first step in that branch), and the second is the **exit transition** (fires when the branch's last step completes; renders between that step and the convergence bar). Most exit transitions are `TRUE` (unconditional) because the *step* itself is what's gating the work \u2014 once the step completes, you want to leave the branch. The entry transitions are where the actual decision logic lives.\n\n**Why not flowchart?** A flowchart of this would render the routing as a diamond with two branches and labels on each branch. You'd lose the explicit step semantics \u2014 in flowchart, the diamond *is* the decision point and there's no notion of \"the picking step is currently active and the next step depends on shipping type.\" That distinction matters for PLC code: while the picking step is active, the picking robot is physically holding the product, and you need to know exactly when the routing decision happens (at step exit, not step entry) to coordinate the conveyor handoff. SFC's \"step active \u2192 transition \u2192 next step active\" semantics are what real PLC scan engines do; flowchart's diamond/box semantics are not.\n\n**The shared S_Ship destination.** Both branches converge to S_Ship, where `CarrierPickup` runs. This is one of the strengths of alternative-branch SFC: the post-routing step is shared infrastructure, drawn exactly once. If you moved to multiple destinations (e.g. express has its own carrier door, standard has another), you'd skip the convergence and let each branch end at its own terminal step \u2014 also a valid SFC pattern."
|
|
1513
|
+
},
|
|
793
1514
|
{
|
|
794
1515
|
"slug": "sld-generator-ats",
|
|
795
1516
|
"diagram": "sld",
|
|
@@ -919,6 +1640,27 @@ var EXAMPLES = [
|
|
|
919
1640
|
"dsl": 'timing "SPI Transaction"\nCLK: pppppppp\nCS_N: 10000001\nMOSI: x======= data: ["0xAB","0xCD","0xEF","0x01","0x02","0x03","0x04","0x05"]\nMISO: zzzz==== data: ["","","","","0xFF","0x12","0x34","0x56"]',
|
|
920
1641
|
"notes": "## Scenario\n\nA firmware engineer or hardware designer documents an 8-byte SPI master-to-slave transaction for a device driver review or datasheet. The WaveDrom-compatible syntax means the same DSL can be pasted directly into WaveDrom's online editor or embedded in documentation pipelines.\n\n## Annotation key\n\n- `p` \u2014 clock pulse (high period followed by low); each `p` is one clock cycle\n- `1` / `0` \u2014 logic high / logic low\n- `=` \u2014 data bus: stable data (value unchanged from previous cycle)\n- `x` \u2014 don't-care or undefined state (transition state)\n- `z` \u2014 high-impedance (floating / tri-state)\n- `data: [...]` \u2014 optional data labels for each stable segment, rendered inside the bus bar\n- `CS_N` \u2014 active-low chip select; `1` = deselected, `0` = selected\n\n## How to read\n\nThe clock runs for 8 cycles. CS_N goes low at cycle 1 and returns high at cycle 8, framing the transaction. MOSI (master out) sends 8 bytes starting at cycle 1. MISO (slave in) is high-Z for the first 4 cycles (slave preparing the response) then transitions to stable data bytes 5\u20138. The transaction completes when CS_N de-asserts."
|
|
921
1642
|
},
|
|
1643
|
+
{
|
|
1644
|
+
"slug": "venn-audience-overlap-marketing",
|
|
1645
|
+
"diagram": "venn",
|
|
1646
|
+
"title": "Paid audience overlap \u2014 Meta \xD7 Google \xD7 TikTok",
|
|
1647
|
+
"description": "Three ad-platform audience overlap for performance marketing \u2014 Meta, Google, and TikTok intersection counts to guide budget allocation.",
|
|
1648
|
+
"standard": "Venn (1880)",
|
|
1649
|
+
"tags": [
|
|
1650
|
+
"venn",
|
|
1651
|
+
"audience",
|
|
1652
|
+
"meta",
|
|
1653
|
+
"google",
|
|
1654
|
+
"tiktok",
|
|
1655
|
+
"marketing",
|
|
1656
|
+
"overlap",
|
|
1657
|
+
"paid"
|
|
1658
|
+
],
|
|
1659
|
+
"complexity": 2,
|
|
1660
|
+
"featured": false,
|
|
1661
|
+
"dsl": 'venn "Q4 Holiday Campaign \u2014 Paid Audience Overlap"\nset meta "Meta (FB + IG)" [color: "#1877F2"]\nset google "Google Ads" [color: "#EA4335"]\nset tiktok "TikTok" [color: "#010101"]\nmeta & google : 18400\nmeta & tiktok : 24700\ngoogle & tiktok : 9200\nmeta & google & tiktok : 5100\nmeta only : 61000\ngoogle only : 38500\ntiktok only : 42300',
|
|
1662
|
+
"notes": '## Scenario\n\nA performance marketing manager is finalising the Q4 holiday campaign budget across three platforms. The Venn reveals that a meaningful audience of 5,100 users is targetable on all three channels simultaneously \u2014 this cohort will see the brand multiple times, so frequency capping is critical. The 61k Meta-exclusive pool is the largest single-platform opportunity, while TikTok\'s 42k exclusive reach justifies keeping it in the mix even at a higher CPM.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 one ad platform per circle\n- `A & B : n` \u2014 users reachable on both platforms (multi-touch risk)\n- `A only : n` \u2014 users reachable exclusively on one platform\n\n## How to read\n\nEach circle represents the targetable audience on one platform. Intersection counts show users reachable across multiple channels \u2014 useful for setting frequency caps and coordinating creative sequencing. The triple intersection (5,100) is the most saturated segment and should receive unified messaging. Exclusive regions show where each platform provides unique incremental reach that the others cannot access.'
|
|
1663
|
+
},
|
|
922
1664
|
{
|
|
923
1665
|
"slug": "venn-customer-segments",
|
|
924
1666
|
"diagram": "venn",
|
|
@@ -937,6 +1679,65 @@ var EXAMPLES = [
|
|
|
937
1679
|
"dsl": 'venn "Customer Segments \u2014 Q3 2025"\nset email "Email subscribers" [color: "#1E88E5"]\nset paid "Paid users" [color: "#E53935"]\nset mobile "Mobile app users" [color: "#43A047"]\nemail & paid : 1840\nemail & mobile : 920\npaid & mobile : 2100\nemail & paid & mobile : 650\nemail only : 12400\npaid only : 3200\nmobile only : 8700',
|
|
938
1680
|
"notes": '## Scenario\n\nA lifecycle marketer is planning Q4 campaigns and needs to see which audiences overlap before deciding where to spend budget. The 650-strong triple intersection is the highest-LTV segment; the 12.4k email-only group is the biggest conversion opportunity. Putting the numbers on one Venn makes the gaps and overlaps argue for themselves in a 30-second leadership review.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 declare a circle\n- `A & B : n` \u2014 count in the intersection of A and B\n- `A only : n` \u2014 count exclusive to A\n\n## How to read\n\nEach circle is a total audience; each overlap is people who belong to multiple audiences. The triple intersection (email \u2229 paid \u2229 mobile, 650 users) is your most engaged cohort \u2014 the obvious group to upsell. The *email only* and *mobile only* exclusive regions are your largest activation opportunities because each represents users who have not yet crossed into the other channels.'
|
|
939
1681
|
},
|
|
1682
|
+
{
|
|
1683
|
+
"slug": "venn-euler-taxonomy",
|
|
1684
|
+
"diagram": "venn",
|
|
1685
|
+
"title": "Euler diagram \u2014 animal kingdom containment",
|
|
1686
|
+
"description": "Euler containment diagram showing Animals \u2283 Vertebrates \u2283 Mammals \u2283 Primates \u2014 a nested subset visualization for biology class.",
|
|
1687
|
+
"standard": "Euler (1768)",
|
|
1688
|
+
"tags": [
|
|
1689
|
+
"euler",
|
|
1690
|
+
"venn",
|
|
1691
|
+
"taxonomy",
|
|
1692
|
+
"mammals",
|
|
1693
|
+
"vertebrates",
|
|
1694
|
+
"biology",
|
|
1695
|
+
"containment"
|
|
1696
|
+
],
|
|
1697
|
+
"complexity": 1,
|
|
1698
|
+
"featured": false,
|
|
1699
|
+
"dsl": 'venn "Animal Kingdom \u2014 Nested Containment"\nmode: euler\nset animals "Animals" [color: "#43A047"]\nset vertebrates "Vertebrates" [subset-of: animals, color: "#1E88E5"]\nset mammals "Mammals" [subset-of: vertebrates, color: "#FB8C00"]\nset primates "Primates" [subset-of: mammals, color: "#E53935"]',
|
|
1700
|
+
"notes": "## Scenario\n\nA biology teacher uses this Euler diagram to introduce taxonomic hierarchy on the first day of a classification unit. Unlike a Venn diagram \u2014 which implies partial overlap between circles \u2014 an Euler diagram shows true containment: every primate is a mammal, every mammal is a vertebrate, and every vertebrate is an animal. Students can immediately see that the sets are nested, not intersecting.\n\n## Annotation key\n\n- `mode: euler` \u2014 enables containment (subset) layout instead of partial overlap\n- `subset-of: ID` \u2014 declares that this set is fully enclosed within another\n- Nested rings from outermost to innermost: Animals \u2192 Vertebrates \u2192 Mammals \u2192 Primates\n\n## How to read\n\nRead from the outside in. The outermost ring (Animals) contains all others. Each inner ring is a strict subset of the ring enclosing it \u2014 no element can be in Primates without also being in Mammals, Vertebrates, and Animals. The space between Vertebrates and Mammals represents vertebrates that are not mammals (fish, amphibians, reptiles, birds). The space between Mammals and Primates represents mammals that are not primates (dogs, cats, whales, bats)."
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
"slug": "venn-feature-comparison-tools",
|
|
1704
|
+
"diagram": "venn",
|
|
1705
|
+
"title": "Feature comparison \u2014 Notion vs. Obsidian vs. Roam",
|
|
1706
|
+
"description": "Three-way Venn of knowledge-management features across Notion, Obsidian, and Roam Research \u2014 for product teams benchmarking a new tool.",
|
|
1707
|
+
"standard": "Venn (1880)",
|
|
1708
|
+
"tags": [
|
|
1709
|
+
"venn",
|
|
1710
|
+
"feature-comparison",
|
|
1711
|
+
"notion",
|
|
1712
|
+
"obsidian",
|
|
1713
|
+
"roam",
|
|
1714
|
+
"product",
|
|
1715
|
+
"competitive"
|
|
1716
|
+
],
|
|
1717
|
+
"complexity": 2,
|
|
1718
|
+
"featured": false,
|
|
1719
|
+
"dsl": 'venn "Knowledge Management Tools \u2014 Feature Overlap"\nset notion "Notion" [color: "#000000"]\nset obsidian "Obsidian" [color: "#7C3AED"]\nset roam "Roam Research" [color: "#3B82F6"]\nnotion & obsidian : 3\nnotion & roam : 2\nobsidian & roam : 2\nnotion & obsidian & roam : 3\nnotion only : 8\nobsidian only : 6\nroam only : 4',
|
|
1720
|
+
"notes": "## Scenario\n\nA product manager is building a competitive teardown before a roadmap review. Rather than a spreadsheet of checkboxes, the Venn communicates at a glance which features are table stakes (the triple intersection), which are differentiators (exclusive regions), and which signal partnership opportunities or feature gaps. The counts here represent clusters of related capabilities, not raw feature counts.\n\n## Annotation key\n\n- `set ID \"Label\"` \u2014 one tool per circle\n- `A & B : n` \u2014 number of feature clusters shared by both tools\n- `A only : n` \u2014 feature clusters unique to one tool\n\n## How to read\n\nEach circle represents one tool's total feature set grouped into capability clusters. The triple intersection (3 clusters: block-based editing, bidirectional links, tagging) represents the baseline every modern knowledge tool must ship. Notion's exclusive region (8 clusters) reflects its broader collaboration and database surface area. Obsidian's exclusive region (6) reflects its plugin ecosystem and local-first architecture. Roam's exclusive region (4) reflects its outliner-first and daily-notes conventions."
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
"slug": "venn-prisma-screening",
|
|
1724
|
+
"diagram": "venn",
|
|
1725
|
+
"title": "PRISMA systematic review \u2014 database screening",
|
|
1726
|
+
"description": "Three-database PRISMA deduplication Venn showing PubMed, Embase, and Cochrane overlap counts for a systematic literature review.",
|
|
1727
|
+
"standard": "PRISMA 2020",
|
|
1728
|
+
"tags": [
|
|
1729
|
+
"venn",
|
|
1730
|
+
"prisma",
|
|
1731
|
+
"systematic-review",
|
|
1732
|
+
"literature",
|
|
1733
|
+
"pubmed",
|
|
1734
|
+
"embase"
|
|
1735
|
+
],
|
|
1736
|
+
"complexity": 2,
|
|
1737
|
+
"featured": false,
|
|
1738
|
+
"dsl": 'venn "Database Screening \u2014 PRISMA Deduplication"\nset pubmed "PubMed" [color: "#1E88E5"]\nset embase "Embase" [color: "#E53935"]\nset cochrane "Cochrane" [color: "#43A047"]\npubmed & embase : 1240\npubmed & cochrane : 340\nembase & cochrane : 280\npubmed & embase & cochrane : 180\npubmed only : 4200\nembase only : 2800\ncochrane only : 620',
|
|
1739
|
+
"notes": '## Scenario\n\nA systematic reviewer searches PubMed, Embase, and Cochrane before title/abstract screening. Before any reading begins, duplicates must be removed \u2014 the same paper indexed in multiple databases would inflate the apparent evidence base. This Venn shows where the three databases overlap so the reviewer can report the PRISMA 2020 deduplication step with exact counts and transparently justify why 2,040 records were removed before screening began.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 one database per circle\n- `A & B : n` \u2014 records indexed in both databases (potential duplicates)\n- `A only : n` \u2014 records unique to a single database\n\n## How to read\n\nEach circle represents one database\'s raw retrieval. Overlapping regions are records that appear in more than one source and are the primary deduplication targets. The triple intersection (180) means those papers were found in all three databases simultaneously. After removing all intersections as duplicates, the unique record count is 4 200 + 2 800 + 620 = 7 620 \u2014 the number that proceeds to title/abstract screening and is recorded in the PRISMA flow diagram.'
|
|
1740
|
+
},
|
|
940
1741
|
{
|
|
941
1742
|
"slug": "venn-programming-paradigms",
|
|
942
1743
|
"diagram": "venn",
|
|
@@ -1023,7 +1824,7 @@ var SYNTAX = {
|
|
|
1023
1824
|
},
|
|
1024
1825
|
"matrix": {
|
|
1025
1826
|
"title": "Matrix / Quadrant diagram",
|
|
1026
|
-
"content": '## 1. Your first matrix\n\nThe smallest useful matrix: a custom 2\xD72 with two labeled axes and three points.\n\n```\nmatrix "Feature Prioritization"\nx-axis: Low Effort \u2192 High Effort\ny-axis: Low Value \u2192 High Value\n\n"Add search" at (0.3, 0.8)\n"Rebuild pipeline" at (0.85, 0.7)\n"Update footer" at (0.2, 0.2)\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `matrix`, optionally followed by a template name or a quoted title.\n2. Set the axes with `x-axis:` and `y-axis:` \u2014 or use a built-in template and skip this step entirely.\n3. Each point is `"Label" at (x, y)` where `x` and `y` are decimal fractions from 0.0 (low/left/bottom) to 1.0 (high/right/top).\n4. Add optional properties \u2014 `size:`, `category:`, `color:`, `shape:`, `highlight:` \u2014 after the coordinates.\n\n> Comments must start with `#` anywhere on a line (outside quoted strings).\n\n---\n\n## 2. Built-in templates\n\nA template pre-configures axes, quadrant labels, and grid size. Just use the template name as the second token on the header line.\n\n| Template | Grid | Use case |\n|---|---|---|\n| `eisenhower` | 2\xD72 | Urgency / Importance task prioritization |\n| `impact-effort` | 2\xD72 | Feature prioritization by impact vs. effort |\n| `rice` | 2\xD72 | RICE scoring \u2014 Reach \xD7 Impact vs. Effort |\n| `bcg` | 2\xD72 | Portfolio \u2014 Market Share vs. Growth rate |\n| `ansoff` | 2\xD72 | Product/market growth strategy |\n| `johari` | 2\xD72 | Self-awareness \u2014 known-to-self vs. known-to-others |\n| `9-box` | 3\xD73 | HR talent review \u2014 Performance vs. Potential |\n| `risk-matrix` | 5\xD75 | Risk assessment \u2014 Likelihood vs. Severity (heatmap) |\n\n```\nmatrix eisenhower "This Week"\n"Ship hotfix" at (0.1, 0.9) size: 5 highlight: true\n"Team 1:1s" at (0.1, 0.7) size: 3\n"Write Q3 OKRs" at (0.8, 0.85) size: 4\n"Inbox zero" at (0.1, 0.3) size: 2\n"Refactor auth" at (0.75, 0.4) size: 3\n```\n\nAxes and quadrant labels from a template can be overridden with explicit `x-axis:` / `y-axis:` / `quadrant` directives.\n\n---\n\n## 3. Axes\n\nAxis lines declare the semantic poles of each dimension.\n\n```\nx-axis: Low Effort \u2192 High Effort\ny-axis: Low Value \u2192 High Value\n```\n\nThe arrow separates the low label (left / bottom) from the high label (right / top). All of these separators are equivalent:\n\n| Separator | Example |\n|---|---|\n| `\u2192` (Unicode) | `x-axis: Rare \u2192 Certain` |\n| `->` (ASCII) | `x-axis: Rare -> Certain` |\n| `\u2191` | `y-axis: Cheap \u2191 Expensive` |\n| `\u2190` / `<-` / `<` | Reversed axis \u2014 high label is on the left |\n\nA **reversed axis** is for conventions where the "high" value sits at the left or bottom:\n\n```\nx-axis: High Market Share \u2190 Low Market Share\n```\n\n```\nmatrix "Product Portfolio"\nx-axis: High Market Share \u2190 Low Market Share\ny-axis: Low Growth \u2192 High Growth\n\nquadrant Q1 "Question Marks"\nquadrant Q2 "Stars"\nquadrant Q3 "Cash Cows"\nquadrant Q4 "Dogs"\n\n"Analytics Suite" at (0.25, 0.35) size: 5\n"ChatBot Pro" at (0.2, 0.8) size: 4 highlight: true\n"Legacy CRM" at (0.75, 0.25) size: 6\n"Mobile App" at (0.65, 0.75) size: 3\n```\n\n---\n\n## 4. Points\n\nEach point is a bubble positioned by a normalized (x, y) coordinate pair.\n\n```\n"Label" at (x, y)\n"Label" at (x, y) size: 4 category: design color: #7B1FA2 highlight: true note: "clarify spec"\n```\n\n| Property | Values | Meaning |\n|---|---|---|\n| `size:` | positive number | Bubble area weight (default: 3) |\n| `category:` | bareword | Color group; drives the legend |\n| `color:` | hex string | Override bubble color for this point |\n| `shape:` | `circle` \\| `square` \\| `triangle` \\| `diamond` | Bubble shape (default: `circle`) |\n| `highlight:` | `true` | Draws an emphasis ring around the bubble |\n| `note:` | quoted string | Tooltip annotation |\n| `label:` | quoted string | Replaces the display label (different from the ID) |\n\nCoordinates outside `[0, 1]` are clamped to the chart boundary and flagged with a badge \u2014 the original value is stored for tooltip display.\n\n```\nmatrix "Risk Register"\nx-axis: Low Impact \u2192 High Impact\ny-axis: Rare \u2192 Certain\n\n"Vendor delay" at (0.45, 0.7) size: 4 category: schedule highlight: true\n"Security breach" at (0.9, 0.3) size: 5 category: security shape: diamond\n"Budget overrun" at (0.5, 0.65) size: 3 category: finance\n"Key hire falls through" at (0.6, 0.55) size: 3 category: people\n"Scope creep" at (0.4, 0.8) size: 4 category: schedule\n```\n\n---\n\n## 5. Quadrant labels\n\nLabel each quadrant with a name and an optional subtitle.\n\n```\nquadrant Q1 "Do First"\nquadrant Q2 "Schedule"\nquadrant Q3 "Delete"\nquadrant Q4 "Delegate"\n\n# With an optional subtitle:\nquadrant Q1 "Do First" description: "High urgency, high importance"\n```\n\nQuadrant numbering follows the standard mathematical convention: **Q1 = top-right, Q2 = top-left, Q3 = bottom-left, Q4 = bottom-right**. The `Q` prefix is optional \u2014 `quadrant 1 "Label"` is equally valid.\n\n---\n\n## 6. Heatmap mode\n\nHeatmap mode fills N\xD7M cells with color intensity instead of plotting bubble positions.\n\n```\nmatrix heatmap 4x3 "Skill Matrix"\nrows: [Strategy, Execution, Communication, Technical]\ncols: [Junior, Mid, Senior]\n\ncell (0,0) level: weak\ncell (1,0) level: medium\ncell (2,0) level: strong\ncell (0,1) value: 7\ncell (1,2) label: "Top 10%"\n```\n\n- `matrix heatmap COLxROW` \u2014 header sets the grid dimensions.\n- `rows:` and `cols:` \u2014 comma-separated or bracket-list of axis labels.\n- `cell (col, row)` \u2014 zero-indexed, column first, row second (row 0 = bottom).\n- `level:` \u2014 `strong` (3), `medium` (2), or `weak` (1) \u2014 shorthand for heat intensity.\n- `value:` \u2014 explicit numeric value (overrides `level:`).\n- `label:` \u2014 quoted text placed inside the cell.\n\n```\nmatrix heatmap 4x4 "Competency Heat Map"\nrows: [Leadership, Execution, Communication, Technical]\ncols: [Junior, Mid, Senior, Staff]\n\ncell (0,0) level: weak\ncell (1,0) level: medium\ncell (2,0) level: strong\ncell (3,0) level: strong\ncell (0,1) level: medium\ncell (1,1) level: medium\ncell (2,1) level: strong\ncell (3,1) level: strong\ncell (0,2) level: weak\ncell (1,2) level: medium\ncell (2,2) level: medium\ncell (3,2) level: strong\ncell (0,3) level: weak\ncell (1,3) level: weak\ncell (2,3) level: medium\ncell (3,3) level: strong\n```\n\n---\n\n## 7. Correlation mode\n\nCorrelation mode renders an N\xD7M dot matrix where intensity represents the relationship strength between row and column variables.\n\n```\nmatrix correlation 4x4 "Product Metrics"\nrows: [DAU, Retention, Revenue, NPS]\ncols: [DAU, Retention, Revenue, NPS]\n\ncell (0,0) value: 1\ncell (1,0) value: 0.82\ncell (2,0) value: 0.54\ncell (3,0) value: 0.71\n```\n\nThe same `cell` syntax applies. `level: strong | medium | weak` is also accepted in correlation mode.\n\n---\n\n## 8. Config options\n\nA `config:` block tunes visual rendering. Each option goes on its own indented line below the `config:` header.\n\n```\nconfig:\n quadrantBg: true\n gridLines: true\n axisArrows: true\n bubbleScale: area\n legendPosition: bottom-right\n```\n\n| Key | Values | Default | Effect |\n|---|---|---|---|\n| `quadrantBg` | `true` \\| `false` | `true` | Colored quadrant background fills |\n| `gridLines` | `true` \\| `false` | `true` | Grid lines overlay |\n| `axisArrows` | `true` \\| `false` | `true` | Arrows at axis ends |\n| `bubbleScale` | `area` \\| `radius` | `area` | Whether `size:` scales bubble area or radius |\n| `quadrantAnnotations` | `true` \\| `false` | `true` | Show quadrant label text in corners |\n| `legendPosition` | `bottom-right` \\| `right` \\| `bottom-center` \\| `none` | `bottom-right` | Category legend placement |\n| `labelCollision` | `auto` \\| `offset-only` \\| `leader-only` \\| `off` | `auto` | Overlap avoidance strategy for point labels |\n| `offChartPolicy` | `clamp-badge` \\| `drop` | `clamp-badge` | What to do with points outside [0,1] |\n\nTwo shorthand directives also work at the top level (not inside the `config:` block):\n\n```\naxis: off # off | on | auto \u2014 show or hide the axis lines\nmargins: true # true | false \u2014 show Score + Rank margins (correlation mode)\n```\n\n---\n\n## 9. Labels & comments\n\n- **Title:** `matrix "My Title"` or `title: My Title` as a standalone line.\n- **Point label:** the quoted string before `at (\u2026)`.\n- **Axis labels:** `x-axis:` and `y-axis:` directives.\n- **Quadrant labels:** `quadrant Q1 "Name"` directive.\n- **Comments:** `#` anywhere on a line, outside quoted strings.\n\n```\nmatrix "Prioritization"\n# This is a comment\nx-axis: Low Cost \u2192 High Cost # inline comment after a directive\n"Fix bug" at (0.1, 0.9) size: 3 # comment after a point\n```\n\n---\n\n## 10. Reserved words & escaping\n\n**Reserved at line start:** `matrix` (header), `x-axis:`, `y-axis:`, `quadrant`, `config:`, `title:`, `rows:`, `cols:`, `grid:`, `axis:`, `margins:`, `cell`.\n\n**Point lines must start with a quote character** (`"` or `\'`). A line that does not start with a quote is not treated as a point.\n\n**Strings with spaces** in axis labels do not need quoting \u2014 the text after the colon (and after the arrow) is taken verbatim. In `note:` and `label:` point properties, use double quotes.\n\n---\n\n## 11. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `"Fix bug" at (1, 2)` | Point parsed; x=1 clamped, y=1 clamped; off-chart badge shown | Keep coordinates in [0.0, 1.0] or accept the clamp-badge |\n| `quadrant 1 "Quick Wins"` (no Q prefix) | Accepted \u2014 `Q` prefix is optional | Both `quadrant 1` and `quadrant Q1` work |\n| `config: gridLines: false` (on same line) | Only `config:` keyword recognized; `gridLines: false` silently ignored | Put options on their own indented lines below `config:` |\n| `x-axis: "Low" \u2192 "High"` (quoted labels) | Arrow not found inside quotes \u2014 treated as plain text | Remove quotes: `x-axis: Low \u2192 High` |\n| `matrix heatmap` without dimensions | Defaults to 2\xD72; rows/cols directives set actual size | Specify dimensions on the header: `matrix heatmap 4x4` |\n| `cell (0, 0) level: Strong` (capital S) | `level` match is case-insensitive \u2014 accepted | Both `strong` and `Strong` work |\n| `shape: oval` | Unknown shape value \u2014 silently ignored | Use `circle`, `square`, `triangle`, or `diamond` |\n\n---\n\n## 12. Grammar (EBNF)\n\n```text\ndocument = header directive*\n\nheader = "matrix" ( template-name | mode-header | title )? NEWLINE\ntemplate-name = "eisenhower"|"impact-effort"|"rice"|"bcg"|"ansoff"|"johari"|"9-box"|"risk-matrix"\nmode-header = ( "heatmap" | "correlation" ) ( number "x" number )? title?\ntitle = quoted-string | bare-text\n\ndirective = x-axis | y-axis | quadrant-dir | config-block\n | point | cell | rows-dir | cols-dir | grid-dir\n | title-dir | axis-dir | margins-dir | comment | blank\n\nx-axis = "x-axis:" WS axis-spec NEWLINE\ny-axis = "y-axis:" WS axis-spec NEWLINE\naxis-spec = text arrow text | text # plain text \u2192 high label only\narrow = "\u2192" | "->" | "\u2191" | "\u2190" | "<-" | "<" | "\u2193"\n\nquadrant-dir = "quadrant" WS "Q"? digit WS quoted-string ( WS "description:" quoted-string )? NEWLINE\n\nconfig-block = "config:" NEWLINE ( INDENT key ":" WS value NEWLINE )*\n\npoint = quoted-string WS "at" WS "(" number "," number ")" ( WS point-prop )* NEWLINE\npoint-prop = "size:" number\n | "category:" bareword\n | "color:" hex-color\n | "shape:" ( "circle"|"square"|"triangle"|"diamond" )\n | "highlight:" "true"\n | "note:" quoted-string\n | "label:" quoted-string\n\ncell = "cell" WS "(" digit "," digit ")" ( WS cell-prop )* NEWLINE\ncell-prop = "value:" number\n | "label:" quoted-string\n | "level:" ( "strong" | "medium" | "weak" )\n\nrows-dir = "rows:" WS label-list NEWLINE\ncols-dir = "cols:" WS label-list NEWLINE\ngrid-dir = "grid:" WS number "x" number NEWLINE\naxis-dir = "axis:" WS ( "off" | "on" | "auto" ) NEWLINE\nmargins-dir = "margins:" WS ( "true" | "false" | "on" | "1" ) NEWLINE\n\nlabel-list = "[" text ("," text)* "]" | text ("," text)*\nquoted-string = \'"\' any-char-but-quote* \'"\' | "\'" any-char-but-quote* "\'"\ncomment = "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/matrix/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1827
|
+
"content": '## 1. Your first matrix\n\nThe smallest useful matrix: a custom 2\xD72 with two labeled axes and three points.\n\n```\nmatrix "Feature Prioritization"\nx-axis: Low Effort \u2192 High Effort\ny-axis: Low Value \u2192 High Value\n\n"Add search" at (0.3, 0.8)\n"Rebuild pipeline" at (0.85, 0.7)\n"Update footer" at (0.2, 0.2)\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `matrix`, optionally followed by a template name or a quoted title.\n2. Set the axes with `x-axis:` and `y-axis:` \u2014 or use a built-in template and skip this step entirely.\n3. Each point is `"Label" at (x, y)` where `x` and `y` are decimal fractions from 0.0 (low/left/bottom) to 1.0 (high/right/top).\n4. Add optional properties \u2014 `size:`, `category:`, `color:`, `shape:`, `highlight:` \u2014 after the coordinates.\n\n> Comments must start with `#` anywhere on a line (outside quoted strings).\n\n---\n\n## 2. Built-in templates\n\nA template pre-configures axes, quadrant labels, and grid size. Just use the template name as the second token on the header line.\n\n| Template | Grid | Use case |\n|---|---|---|\n| `eisenhower` | 2\xD72 | Urgency / Importance task prioritization |\n| `impact-effort` | 2\xD72 | Feature prioritization by impact vs. effort |\n| `rice` | 2\xD72 | RICE scoring \u2014 Reach \xD7 Impact vs. Effort |\n| `bcg` | 2\xD72 | Portfolio \u2014 Market Share vs. Growth rate |\n| `ansoff` | 2\xD72 | Product/market growth strategy |\n| `johari` | 2\xD72 | Self-awareness \u2014 known-to-self vs. known-to-others |\n| `9-box` | 3\xD73 | HR talent review \u2014 Performance vs. Potential |\n| `risk-matrix` | 5\xD75 | Risk assessment \u2014 Likelihood vs. Severity (heatmap) |\n\n```\nmatrix eisenhower "This Week"\n"Ship hotfix" at (0.1, 0.9) size: 5 highlight: true\n"Team 1:1s" at (0.1, 0.7) size: 3\n"Write Q3 OKRs" at (0.8, 0.85) size: 4\n"Inbox zero" at (0.1, 0.3) size: 2\n"Refactor auth" at (0.75, 0.4) size: 3\n```\n\nAxes and quadrant labels from a template can be overridden with explicit `x-axis:` / `y-axis:` / `quadrant` directives.\n\n---\n\n## 3. Axes\n\nAxis lines declare the semantic poles of each dimension.\n\n```\nx-axis: Low Effort \u2192 High Effort\ny-axis: Low Value \u2192 High Value\n```\n\nThe arrow separates the low label (left / bottom) from the high label (right / top). All of these separators are equivalent:\n\n| Separator | Example |\n|---|---|\n| `\u2192` (Unicode) | `x-axis: Rare \u2192 Certain` |\n| `->` (ASCII) | `x-axis: Rare -> Certain` |\n| `\u2191` | `y-axis: Cheap \u2191 Expensive` |\n| `\u2190` / `<-` / `<` | Reversed axis \u2014 high label is on the left |\n\nA **reversed axis** is for conventions where the "high" value sits at the left or bottom:\n\n```\nx-axis: High Market Share \u2190 Low Market Share\n```\n\n```\nmatrix "Product Portfolio"\nx-axis: High Market Share \u2190 Low Market Share\ny-axis: Low Growth \u2192 High Growth\n\nquadrant Q1 "Question Marks"\nquadrant Q2 "Stars"\nquadrant Q3 "Cash Cows"\nquadrant Q4 "Dogs"\n\n"Analytics Suite" at (0.25, 0.35) size: 5\n"ChatBot Pro" at (0.2, 0.8) size: 4 highlight: true\n"Legacy CRM" at (0.75, 0.25) size: 6\n"Mobile App" at (0.65, 0.75) size: 3\n```\n\n---\n\n## 4. Points\n\nEach point is a bubble positioned by a normalized (x, y) coordinate pair.\n\n```\n"Label" at (x, y)\n"Label" at (x, y) size: 4 category: design color: #7B1FA2 highlight: true note: "clarify spec"\n```\n\n| Property | Values | Meaning |\n|---|---|---|\n| `size:` | positive number | Bubble area weight (default: 3) |\n| `category:` | bareword | Color group; drives the legend |\n| `color:` | hex string | Override bubble color for this point |\n| `shape:` | `circle` \\| `square` \\| `triangle` \\| `diamond` | Bubble shape (default: `circle`) |\n| `highlight:` | `true` | Draws an emphasis ring around the bubble |\n| `note:` | quoted string | Tooltip annotation |\n| `label:` | quoted string | Replaces the display label (different from the ID) |\n\nCoordinates outside `[0, 1]` are clamped to the chart boundary and flagged with a badge \u2014 the original value is stored for tooltip display.\n\n```\nmatrix "Risk Register"\nx-axis: Low Impact \u2192 High Impact\ny-axis: Rare \u2192 Certain\n\n"Vendor delay" at (0.45, 0.7) size: 4 category: schedule highlight: true\n"Security breach" at (0.9, 0.3) size: 5 category: security shape: diamond\n"Budget overrun" at (0.5, 0.65) size: 3 category: finance\n"Key hire falls through" at (0.6, 0.55) size: 3 category: people\n"Scope creep" at (0.4, 0.8) size: 4 category: schedule\n```\n\n---\n\n## 5. Quadrant labels\n\nLabel each quadrant with a name and an optional subtitle.\n\n```\nquadrant Q1 "Do First"\nquadrant Q2 "Schedule"\nquadrant Q3 "Delete"\nquadrant Q4 "Delegate"\n\n# With an optional subtitle:\nquadrant Q1 "Do First" description: "High urgency, high importance"\n```\n\nQuadrant numbering follows the standard mathematical convention: **Q1 = top-right, Q2 = top-left, Q3 = bottom-left, Q4 = bottom-right**. The `Q` prefix is optional \u2014 `quadrant 1 "Label"` is equally valid.\n\n---\n\n## 6. Heatmap mode\n\nHeatmap mode fills N\xD7M cells with color intensity instead of plotting bubble positions.\n\n```\nmatrix heatmap 4x3 "Skill Matrix"\nrows: [Strategy, Execution, Communication, Technical]\ncols: [Junior, Mid, Senior]\n\ncell (0,0) level: weak\ncell (1,0) level: medium\ncell (2,0) level: strong\ncell (0,1) value: 7\ncell (1,2) label: "Top 10%"\n```\n\n- `matrix heatmap COLxROW` \u2014 header sets the grid dimensions.\n- `rows:` and `cols:` \u2014 comma-separated or bracket-list of axis labels.\n- `cell (col, row)` \u2014 zero-indexed, column first, row second (row 0 = bottom).\n- `level:` \u2014 `strong` (3), `medium` (2), or `weak` (1) \u2014 shorthand for heat intensity.\n- `value:` \u2014 explicit numeric value (overrides `level:`).\n- `label:` \u2014 quoted text placed inside the cell.\n\n```\nmatrix heatmap 4x4 "Competency Heat Map"\nrows: [Leadership, Execution, Communication, Technical]\ncols: [Junior, Mid, Senior, Staff]\n\ncell (0,0) level: weak\ncell (1,0) level: medium\ncell (2,0) level: strong\ncell (3,0) level: strong\ncell (0,1) level: medium\ncell (1,1) level: medium\ncell (2,1) level: strong\ncell (3,1) level: strong\ncell (0,2) level: weak\ncell (1,2) level: medium\ncell (2,2) level: medium\ncell (3,2) level: strong\ncell (0,3) level: weak\ncell (1,3) level: weak\ncell (2,3) level: medium\ncell (3,3) level: strong\n```\n\n---\n\n## 7. Correlation mode\n\nCorrelation mode renders an N\xD7M dot matrix where intensity represents the relationship strength between row and column variables.\n\n```\nmatrix correlation 4x4 "Product Metrics"\nrows: [DAU, Retention, Revenue, NPS]\ncols: [DAU, Retention, Revenue, NPS]\n\ncell (0,0) value: 1\ncell (1,0) value: 0.82\ncell (2,0) value: 0.54\ncell (3,0) value: 0.71\n```\n\nThe same `cell` syntax applies. `level: strong | medium | weak` is also accepted in correlation mode.\n\n---\n\n## 8. Config options\n\nA `config:` block tunes visual rendering. Each option goes on its own indented line below the `config:` header.\n\n```\nconfig:\n quadrantBg: true\n gridLines: true\n axisArrows: true\n bubbleScale: area\n legendPosition: bottom-right\n```\n\n| Key | Values | Default | Effect |\n|---|---|---|---|\n| `quadrantBg` | `true` \\| `false` | `true` | Colored quadrant background fills |\n| `gridLines` | `true` \\| `false` | `true` | Grid lines overlay |\n| `axisArrows` | `true` \\| `false` | `true` | Arrows at axis ends |\n| `bubbleScale` | `area` \\| `radius` | `area` | Whether `size:` scales bubble area or radius |\n| `quadrantAnnotations` | `true` \\| `false` | `true` | Show quadrant label text in corners |\n| `legendPosition` | `bottom-right` \\| `right` \\| `bottom-center` \\| `none` | `bottom-right` | Category legend placement |\n| `labelCollision` | `auto` \\| `offset-only` \\| `leader-only` \\| `off` | `auto` | Overlap avoidance strategy for point labels |\n| `offChartPolicy` | `clamp-badge` \\| `drop` | `clamp-badge` | What to do with points outside [0,1] |\n\nTwo shorthand directives also work at the top level (not inside the `config:` block):\n\n```\naxis: off # off | on | auto \u2014 show or hide the axis lines\nmargins: true # true | false \u2014 show Score + Rank margins (correlation mode)\n```\n\n---\n\n## 9. Labels & comments\n\n- **Title:** `matrix "My Title"` or `title: My Title` as a standalone line.\n- **Point label:** the quoted string before `at (\u2026)`.\n- **Axis labels:** `x-axis:` and `y-axis:` directives.\n- **Quadrant labels:** `quadrant Q1 "Name"` directive.\n- **Comments:** `#` anywhere on a line, outside quoted strings.\n\n```\nmatrix "Prioritization"\n# This is a comment\nx-axis: Low Cost \u2192 High Cost # inline comment after a directive\n"Fix bug" at (0.1, 0.9) size: 3 # comment after a point\n```\n\n---\n\n## 10. Table mode (`style: table`)\n\nThe default matrix rendering is a **scatter / bubble chart** \u2014 points float at (x, y) coordinates. For frameworks where the output is a list of items grouped by quadrant (Eisenhower, Johari, Impact-Effort, 9-box), use `style: table` to switch to a **text-in-cell layout** instead.\n\n```\nmatrix eisenhower "This Week"\nstyle: table\nQ2: "Ship hotfix"\nQ2: "Customer demo prep"\nQ1: "Write Q3 OKRs"\nQ1: "Refactor auth layer"\nQ4: "LinkedIn updates"\nQ3: "Reorganize Slack channels"\n```\n\n`style: table` applies these changes automatically:\n\n| Effect | Detail |\n|---|---|\n| Axes and arrows hidden | No axis lines, labels, or arrowheads |\n| Grid lines hidden | Only the outer border and cell dividers remain |\n| Quadrant titles move inside cells | Each title becomes a cell header instead of a corner overlay |\n| Items stack as a bullet list | Multiple entries for the same quadrant stack top-down |\n\n### `Q1` \u2026 `Q4` shorthand (2\xD72 only)\n\nFor 2\xD72 templates, use `Qn: "item"` instead of the longer `cell (col, row) label: "item"` form. Mapping:\n\n| Shorthand | Cell | Eisenhower | Johari |\n|---|---|---|---|\n| `Q1:` | top-right | Schedule | Blind |\n| `Q2:` | top-left | Do First | Open / Arena |\n| `Q3:` | bottom-left | Delete | Hidden / Fa\xE7ade |\n| `Q4:` | bottom-right | Delegate | Unknown |\n\nRepeat a shorthand key to add multiple items to the same cell:\n\n```\nQ2: "Ship hotfix"\nQ2: "Customer demo prep"\n```\n\nFor 3\xD73 grids (9-box), use `cell (col, row) label: "\u2026"` directly \u2014 the `Q` shorthand is 2\xD72 only.\n\n### When to use table vs scatter\n\n| Use `style: table` for | Use scatter (default) for |\n|---|---|\n| Eisenhower with task lists | Eisenhower with `size:` effort weights |\n| Johari window coaching | Impact-Effort with bubble = revenue |\n| Backlog grouping (no numeric third dimension) | RICE / BCG portfolio (third dimension IS the bubble size) |\n| 9-box talent review | Risk heatmap (5\xD75 with numeric severity) |\n\n```\nmatrix eisenhower "This Week"\nstyle: table\nQ2: "Ship hotfix"\nQ2: "Customer demo prep"\nQ1: "Write Q3 OKRs"\nQ1: "Refactor auth layer"\nQ4: "LinkedIn updates"\nQ3: "Reorganize Slack channels"\n```\n\n---\n\n## 11. Reserved words & escaping\n\n**Reserved at line start:** `matrix` (header), `x-axis:`, `y-axis:`, `quadrant`, `config:`, `title:`, `rows:`, `cols:`, `grid:`, `axis:`, `margins:`, `cell`.\n\n**Point lines must start with a quote character** (`"` or `\'`). A line that does not start with a quote is not treated as a point.\n\n**Strings with spaces** in axis labels do not need quoting \u2014 the text after the colon (and after the arrow) is taken verbatim. In `note:` and `label:` point properties, use double quotes.\n\n---\n\n## 12. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `"Fix bug" at (1, 2)` | Point parsed; x=1 clamped, y=1 clamped; off-chart badge shown | Keep coordinates in [0.0, 1.0] or accept the clamp-badge |\n| `quadrant 1 "Quick Wins"` (no Q prefix) | Accepted \u2014 `Q` prefix is optional | Both `quadrant 1` and `quadrant Q1` work |\n| `config: gridLines: false` (on same line) | Only `config:` keyword recognized; `gridLines: false` silently ignored | Put options on their own indented lines below `config:` |\n| `x-axis: "Low" \u2192 "High"` (quoted labels) | Arrow not found inside quotes \u2014 treated as plain text | Remove quotes: `x-axis: Low \u2192 High` |\n| `matrix heatmap` without dimensions | Defaults to 2\xD72; rows/cols directives set actual size | Specify dimensions on the header: `matrix heatmap 4x4` |\n| `cell (0, 0) level: Strong` (capital S) | `level` match is case-insensitive \u2014 accepted | Both `strong` and `Strong` work |\n| `shape: oval` | Unknown shape value \u2014 silently ignored | Use `circle`, `square`, `triangle`, or `diamond` |\n| `"Fix bug" at (0.1, 0.9)` on an Eisenhower with a task list | Valid scatter point \u2014 but you probably wanted a list in a cell | Add `style: table` and use `Q2: "Fix bug"` instead |\n| `Q1: "item"` on a 3\xD73 template | `Q` shorthand is parsed as a point line \u2014 silently dropped | Use `cell (col, row) label: "item"` for 3\xD73 grids |\n\n---\n\n## 13. Grammar (EBNF)\n\n```text\ndocument = header directive*\n\nheader = "matrix" ( template-name | mode-header | title )? NEWLINE\ntemplate-name = "eisenhower"|"impact-effort"|"rice"|"bcg"|"ansoff"|"johari"|"9-box"|"risk-matrix"\nmode-header = ( "heatmap" | "correlation" ) ( number "x" number )? title?\ntitle = quoted-string | bare-text\n\ndirective = x-axis | y-axis | quadrant-dir | config-block\n | point | cell | q-short | rows-dir | cols-dir | grid-dir\n | style-dir | title-dir | axis-dir | margins-dir | comment | blank\n\nx-axis = "x-axis:" WS axis-spec NEWLINE\ny-axis = "y-axis:" WS axis-spec NEWLINE\naxis-spec = text arrow text | text # plain text \u2192 high label only\narrow = "\u2192" | "->" | "\u2191" | "\u2190" | "<-" | "<" | "\u2193"\n\nquadrant-dir = "quadrant" WS "Q"? digit WS quoted-string ( WS "description:" quoted-string )? NEWLINE\n\nconfig-block = "config:" NEWLINE ( INDENT key ":" WS value NEWLINE )*\n\npoint = quoted-string WS "at" WS "(" number "," number ")" ( WS point-prop )* NEWLINE\npoint-prop = "size:" number\n | "category:" bareword\n | "color:" hex-color\n | "shape:" ( "circle"|"square"|"triangle"|"diamond" )\n | "highlight:" "true"\n | "note:" quoted-string\n | "label:" quoted-string\n\ncell = "cell" WS "(" digit "," digit ")" ( WS cell-prop )* NEWLINE\ncell-prop = "value:" number\n | "label:" quoted-string\n | "level:" ( "strong" | "medium" | "weak" )\n\nstyle-dir = "style:" WS "table" NEWLINE\nq-short = "Q" ( "1" | "2" | "3" | "4" ) ":" WS quoted-string NEWLINE # 2\xD72 only\n\nrows-dir = "rows:" WS label-list NEWLINE\ncols-dir = "cols:" WS label-list NEWLINE\ngrid-dir = "grid:" WS number "x" number NEWLINE\naxis-dir = "axis:" WS ( "off" | "on" | "auto" ) NEWLINE\nmargins-dir = "margins:" WS ( "true" | "false" | "on" | "1" ) NEWLINE\n\nlabel-list = "[" text ("," text)* "]" | text ("," text)*\nquoted-string = \'"\' any-char-but-quote* \'"\' | "\'" any-char-but-quote* "\'"\ncomment = "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/matrix/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1027
1828
|
},
|
|
1028
1829
|
"orgchart": {
|
|
1029
1830
|
"title": "Org chart",
|
|
@@ -1044,6 +1845,26 @@ var SYNTAX = {
|
|
|
1044
1845
|
"pid": {
|
|
1045
1846
|
"title": "P&ID (Piping & Instrumentation Diagram)",
|
|
1046
1847
|
"content": '## 1. Your first P&ID\n\nA minimal P&ID has at least one piece of equipment and one process line.\n\n```\npid\n\nequip T-1 : tank_atm\nequip P-1 : pump_centrifugal\nequip V-1 : vessel_v\n\nline L1 from T-1.bottom to P-1.in [size: "2\\\\"", type: "process"]\nline L2 from P-1.out to V-1.in [size: "2\\\\"", type: "process"]\n```\n\nThree rules cover 80% of usage:\n\n1. Start the document with `pid` (optional title and `[direction: LR]` attrs).\n2. Declare each piece of equipment: `equip : <type> [tag: "label"]`.\n3. Connect them with `line from <equip>.<port> to <equip>.<port> [type: "process", size: "4\\""]`.\n\nInstrumentation is added separately with `inst : <category>` plus indented `measures` / `controls` clauses.\n\n> Comments use `#` at the start of a line.\n\n---\n\n## 2. Equipment\n\nThe `equip` statement declares process equipment. The catalog follows ISO 10628 / ISA-5.1 conventions.\n\n```\nequip T-101 : tank_atm [tag: "Feed Tank"]\nequip P-101 : pump_centrifugal\nequip E-201 : hx_shell_tube [tag: "Overhead Cond"]\nequip T-201 : column_tray [tag: "Stripper"]\n```\n\n### 2.1 Equipment catalog\n\n| Type | Symbol | Purpose |\n|---|---|---|\n| `tank_atm` | Cylinder + dome top | Atmospheric storage tank |\n| `tank_cone_roof` | Cylinder + cone roof | Cone-roof storage tank |\n| `vessel_v` | Vertical capsule | Vertical pressure vessel |\n| `vessel_h` | Horizontal capsule | Horizontal pressure vessel |\n| `sphere` | Filled circle | LPG / ammonia sphere |\n| `column_tray` | Tall capsule + horizontal tray lines | Distillation tray column |\n| `column_packed` | Tall capsule + cross-hatch | Packed absorption column |\n| `hx_shell_tube` | Horizontal capsule + tube bundle | Shell-and-tube heat exchanger |\n| `hx_air_cooled` | Rectangle + fan circle | Air-cooled (fin-fan) cooler |\n| `reboiler` | Capsule + parallel tube lines | Kettle reboiler |\n| `condenser` | Horizontal capsule + tubes | Overhead condenser |\n| `pump_centrifugal` | Circle + right-side triangle outlet | Centrifugal pump |\n| `pump_pd` | Circle + internal gears | Positive-displacement pump |\n| `compressor` | Trapezoid (narrow on right) | Centrifugal compressor |\n| `blower` | Circle + 3-blade fan | Blower / fan |\n| `reactor_cstr` | Vertical capsule + agitator | Stirred tank reactor (CSTR) |\n| `reactor_pfr` | Horizontal capsule + packed bed dots | Plug-flow / fixed-bed reactor |\n| `filter` | Rectangle + diagonal hatch | Filter |\n| `cyclone` | Cylinder + cone bottom | Cyclone separator |\n| `flare` | Tall stack + flame | Flare stack |\n| `cooling_tower` | Hourglass | Induced-draft cooling tower |\n\n### 2.2 Valve catalog\n\nValves are equipment that sit on the piping line. Render in `bowtie` style with type-specific actuator decoration.\n\n| Type | Decoration | Purpose |\n|---|---|---|\n| `valve_gate` | Plain bowtie | Manual on/off (full-port) |\n| `valve_ball` | Bowtie + filled center circle | Manual on/off (quarter-turn) |\n| `valve_globe` | Bowtie + small top circle | Manual flow control |\n| `valve_butterfly` | Bowtie + center vertical line | Quarter-turn throttle |\n| `valve_check` | Bowtie + arc | Non-return check valve |\n| `valve_control` | Bowtie + diaphragm actuator | Pneumatic control valve (paired with FIC) |\n| `valve_psv` | Bowtie + 45\xB0 outlet + spring stack | Pressure safety relief valve |\n\n```\nequip V-101 : valve_control [tag: "V-101 (FC)"]\nequip V-303 : valve_psv [tag: "V-303 \xB7 150 psig"]\n```\n\n---\n\n## 3. Piping & signal lines\n\nThe `line` statement connects two anchor points (equipment ports or instrument tags).\n\n```\nline L1 from T-101.bottom to P-101.in [size: "4\\"", service: "water", type: "process"]\nline s1 from FT-101 to FIC-101 [type: "electric"]\nline s2 from FIC-101 to V-101 [type: "pneumatic"]\n```\n\n### 3.1 Anchor syntax\n\nEach end of a line is either:\n- `<equip-id>.<port>` \u2014 port name from \xA72.2 (`in`, `out`, `top`, `bottom`, `feed`, `shell_in`, `tube_out`, `reflux`, etc.)\n- `<equip-id>` \u2014 port omitted; defaults to `in` (target) / `out` (source) per equipment family\n- `<inst-tag>` \u2014 instrument bubble center (signal lines)\n\n### 3.2 Line types (ISA-5.1 \xA75)\n\n| `type:` | Stroke | Use |\n|---|---|---|\n| `process` | Solid, thick | Major process line (default) |\n| `process_minor` | Solid, thin | Auxiliary / utility |\n| `pneumatic` | Solid + diagonal tick marks | Air-actuator signal |\n| `electric` | Long-dash | Electric / 4\u201320 mA signal |\n| `hydraulic` | Long-dash + pause | Hydraulic actuator |\n| `capillary` | Dotted (round caps) | Filled-system temperature |\n| `software` | Short-dash, light | DCS / PLC internal data link |\n| `mechanical` | Mixed dash | Mechanical linkage |\n\n### 3.3 Line tags\n\nThe standard PIP PIC001 tag format is `<size>"-<service>-<sequence>-<spec>`. Pass it via the `tag:` attribute and the renderer places a small white tag rectangle at the line midpoint.\n\n```\nline L1 from T-101.bottom to P-101.in [size: "4\\"", service: "PG", tag: "4\\"-PG-101-A1B"]\n```\n\n---\n\n## 4. Instrumentation (ISA-5.1 \xA74)\n\nThe `inst` statement declares an instrument bubble. The **tag** uses the ISA letter-code convention: first letter is the *measured variable*, subsequent letters are *modifiers* and *function*.\n\n```\ninst FT-101 : field_discrete %% Flow Transmitter, loop 101\ninst FIC-101 : cr_shared %% Flow Indicating Controller (DCS)\ninst PSHH-301: cr_plc %% Pressure Switch High-High (PLC)\ninst LIC-201 : cr_shared\n measures D-201\n controls V-202\n```\n\n### 4.1 Letter codes (first letter)\n\nMost-used: `F` flow \xB7 `L` level \xB7 `P` pressure \xB7 `T` temperature \xB7 `A` analysis \xB7 `S` speed \xB7 `H` hand \xB7 `Y` event/state. Full list in ISA-5.1 Table 1.\n\n### 4.2 Function modifiers\n\n`I` indicator \xB7 `R` recorder \xB7 `C` controller \xB7 `T` transmitter \xB7 `E` element \xB7 `V` valve \xB7 `S` switch \xB7 `A` alarm \xB7 `H`/`L` high/low. Combine into the multi-letter tag: `FIC` = Flow Indicating Controller; `PSHH` = Pressure Switch High-High.\n\n### 4.3 Bubble categories\n\nISA-5.1 distinguishes **location** (where the instrument lives) and **type** (analog vs. shared vs. computer vs. PLC). Schematex implements the four most common combinations:\n\n| Category | Bubble shape | Use |\n|---|---|---|\n| `field_discrete` | Plain circle | Field-mounted analog instrument (FT, PT) |\n| `cr_shared` | Circle + horizontal line + inscribed hexagon | DCS-controlled HMI display |\n| `cr_computer` | Circle + horizontal line + inscribed diamond | Computer function (FY, calculation) |\n| `cr_plc` | Circle + horizontal line + inscribed square | PLC-driven logic |\n\n`field_*` variants omit the horizontal centerline; `local_*` variants use a dashed centerline; `cr_*` variants use a solid centerline indicating "main control panel \u2014 front."\n\n### 4.4 measures / controls\n\nIndented under an `inst` declaration:\n\n| Clause | Effect |\n|---|---|\n| `measures <equip-id>` | Auto-routed dashed-electric signal line from the equipment to the bubble |\n| `controls <equip-id>` | Auto-routed pneumatic signal line from the bubble to the equipment (typically a `valve_control`) |\n\n```\ninst FT-101 : field_discrete\n measures P-101\ninst FIC-101 : cr_shared\n controls V-101\n```\n\nThese auto-signals are independent of the explicit `line` statements \u2014 they get rendered with the appropriate signal-line style based on the relation type.\n\n---\n\n## 5. Layout direction\n\nThe default direction is **`LR`** (left-to-right) \u2014 process feed enters on the left, product exits on the right. Override on the header:\n\n```\npid "Distillation Tower" [direction: TB]\n\nequip T-201 : column_tray\n\u2026\n```\n\nThe MVP layout places equipment in declaration order along the primary direction with Manhattan signal-line routing. **Multi-row / parallel-flow layouts and tee junctions are roadmap items** \u2014 see \xA79.\n\n---\n\n## 6. Worked example: Distillation column\n\nA real overhead-condenser loop with reboiler, reflux drum, and instrumentation:\n\n```\npid "Distillation T-201"\n\nequip T-201 : column_tray [tag: "T-201"]\nequip E-201 : condenser [tag: "Overhead Cond"]\nequip D-201 : vessel_h [tag: "Reflux Drum"]\nequip P-201 : pump_centrifugal [tag: "Reflux Pump"]\nequip E-202 : reboiler [tag: "Reboiler"]\n\nline L1 from T-201.top to E-201.shell_in [size: "8\\\\"", service: "vapor", type: "process"]\nline L2 from E-201.shell_out to D-201.in [size: "8\\\\"", type: "process"]\nline L3 from D-201.bottom to P-201.in [size: "3\\\\"", type: "process"]\nline L4 from P-201.out to T-201.reflux [size: "3\\\\"", type: "process"]\nline L5 from T-201.bottom to E-202.in [size: "6\\\\"", type: "process"]\n\ninst PT-201 : field_discrete\n measures T-201\ninst LIC-201 : cr_shared\n measures D-201\ninst TIC-201 : cr_shared\n measures T-201\n```\n\n---\n\n## 7. Grammar (EBNF)\n\n```text\ndocument = header statement*\nheader = "pid" ( title )? ( "[" attrs "]" )? NEWLINE\nattrs = attr ("," attr)*\nattr = "direction:" ("LR" | "TB")\n | "units:" ("imperial" | "metric")\n\nstatement = comment\n | equipment-decl\n | line-decl\n | instrument-decl\n\nequipment-decl = "equip" ID ":" equip-type ( "[" attr-list "]" )? NEWLINE\nequip-type = "tank_atm" | "tank_cone_roof"\n | "vessel_v" | "vessel_h" | "sphere"\n | "column_tray" | "column_packed"\n | "hx_shell_tube" | "hx_air_cooled" | "reboiler" | "condenser"\n | "pump_centrifugal" | "pump_pd"\n | "compressor" | "blower"\n | "reactor_cstr" | "reactor_pfr"\n | "filter" | "cyclone" | "flare" | "cooling_tower"\n | "valve_gate" | "valve_ball" | "valve_globe" | "valve_butterfly"\n | "valve_check" | "valve_control" | "valve_psv"\n\nline-decl = "line" ID "from" anchor "to" anchor ( "[" attr-list "]" )? NEWLINE\nanchor = ID ( "." port )?\nport = "in" | "out" | "top" | "bottom" | "left" | "right"\n | "feed" | "reflux" | "shell_in" | "shell_out"\n | "tube_in" | "tube_out" | "vapor_out" | "liquid_out"\n | "bottom_return"\n\ninstrument-decl = "inst" tag ":" inst-category ( "[" attr-list "]" )? NEWLINE\n ( indented "measures" anchor NEWLINE )*\n ( indented "controls" ID NEWLINE )*\ntag = letter-code "-" loop-num %% e.g., "FIC-101"\ninst-category = "field_discrete" | "field_shared" | "field_computer" | "field_plc"\n | "cr_discrete" | "cr_shared" | "cr_computer" | "cr_plc"\n | "local_discrete" | "local_shared"\n\nattr-list = attr ("," attr)*\nattr = key ":" value\nkey = "tag" | "size" | "service" | "type" | "set_pressure"\n | "actuator" | "fail" | "trays" | \u2026\nvalue = quoted-string | bare-word\n\nID = [A-Za-z] [A-Za-z0-9_-]*\n```\n\nAuthoritative source: `src/diagrams/pid/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1848
|
+
},
|
|
1849
|
+
"erd": {
|
|
1850
|
+
"title": "ERD (Entity-Relationship Diagram)",
|
|
1851
|
+
"content": '## 1. Your first ERD\n\nThe smallest useful ERD: a parent table referenced by a child via foreign key.\n\n```\nerd\ntable Customer {\n customer_id int PK\n email varchar UK\n}\ntable Order {\n order_id int PK\n customer_id int FK -> Customer.customer_id\n}\nref Order.customer_id many-mandatory -- one-mandatory Customer.customer_id : "places"\n```\n\nFour rules cover 80 % of usage:\n\n1. Start with `erd`. Optional headers `title:`, `direction: LR | TB`.\n2. Each table is a block: `table Name { col type marker }`. Markers are `PK`, `FK`, `UK`, `NN` (or `*`) for NOT NULL.\n3. Inline foreign-key target: append `FK -> Other.column` to a column. The renderer adds an `FK` pill automatically.\n4. Connect tables with a `ref` line: `ref Source <left-card> -- <right-card> Target [: "label"]`. Cardinality is one of `one-mandatory`, `one-optional`, `many-mandatory`, `many-optional` (named form), `1..1` / `0..1` / `1..N` / `0..N` (Min-Max), or Mermaid glyphs (`}o--||`, etc.) as alias.\n\n> Comments use `//` or `#`. Block forms can be either multi-line (one column per line) or inline (`table A { id int PK; name varchar }`).\n\n---\n\n## 2. Cardinality glyphs\n\nCrow\'s foot encodes the cardinality at each end of the relationship line:\n\n| Glyph | Reading | Min..Max | Named token |\n|---|---|---|---|\n| `\u2500\u2503` (perpendicular bar) | Exactly one (mandatory one) | 1..1 | `one-mandatory` |\n| `\u2500\u25CB` (open circle) | Zero or one (optional one) | 0..1 | `one-optional` |\n| `\u2500\u2503<` (bar + crow\'s foot) | One or more (mandatory many) | 1..N | `many-mandatory` |\n| `\u2500\u25CB<` (circle + crow\'s foot) | Zero or more (optional many) | 0..N | `many-optional` |\n\nEach end of a line is annotated independently. A typical 1:N relationship reads "exactly one CUSTOMER places zero-or-more ORDERs":\n\n```\nref Order.customer_id many-mandatory -- one-mandatory Customer.customer_id : "places"\n```\n\nReading right-to-left: the **right end** of the line attaches to Customer with a single bar (one-mandatory); the **left end** attaches to Order with a bar + crow\'s foot (many-mandatory).\n\n---\n\n## 3. Mermaid alias\n\nIf you already use Mermaid `erDiagram`, the same glyphs work as input:\n\n```\nerd\ntable Customer { customer_id int PK; email varchar UK }\ntable Order { order_id int PK; customer_id int FK -> Customer.customer_id }\ntable Product { product_id int PK; name varchar }\n\nref Order }o--|| Customer : "places"\nref Order }o--o{ Product : "contains"\n```\n\n| Mermaid token | Schematex meaning |\n|---|---|\n| `\\|o` left / `o\\|` right | 0..1 |\n| `\\|\\|` | 1..1 |\n| `}o` left / `o{` right | 0..N |\n| `}\\|` left / `\\|{` right | 1..N |\n| `--` | identifying / solid line |\n| `..` | non-identifying / dashed line |\n\n---\n\n## 4. Identifying vs non-identifying\n\nUse `--` for identifying relationships (solid line) and `..` for non-identifying (dashed):\n\n```\nerd\ntable User { id int PK; email varchar }\ntable SessionLog { id int PK; user_id int FK -> User.id; created_at timestamp }\n\nref SessionLog.user_id many-optional .. one-optional User.id : "logs (optional FK)"\n```\n\nThe dashed line follows the Barker / IDEF1X non-identifying convention.\n\n---\n\n## 5. Composite primary keys (associative tables)\n\nAssociative ("junction") tables resolve M:N relationships. Mark each PK + FK column with both `PK` and `FK`:\n\n```\nerd\ntable Student { student_id int PK; name varchar }\ntable Course { course_id int PK; title varchar }\ntable Enrollment {\n student_id int PK FK -> Student.student_id\n course_id int PK FK -> Course.course_id\n grade char\n}\nref Enrollment.student_id many-mandatory -- one-mandatory Student.student_id\nref Enrollment.course_id many-mandatory -- one-mandatory Course.course_id\n```\n\nSchematex renders both pills (PK + FK) on the same row. The PK underline applies to the column name when any `PK` marker is present.\n\n---\n\n## 6. Layout direction\n\n`direction: LR` (default) places parent tables left, child tables right. `direction: TB` flips to top-to-bottom \u2014 useful for narrow embeds:\n\n```\nerd\ntitle: "Library (top-down)"\ndirection: TB\n\ntable Member { id int PK; name varchar; email varchar UK }\ntable Book { id int PK; title varchar; author varchar }\ntable Loan { id int PK; member_id int FK -> Member.id; book_id int FK -> Book.id; due_date date }\n\nref Loan.member_id many-mandatory -- one-mandatory Member.id : "borrowed by"\nref Loan.book_id many-mandatory -- one-mandatory Book.id : "of"\n```\n\nLayered orthogonal Manhattan routing with single-bend edges. v0.1 uses appearance-order stacking inside layers; barycenter crossing-reduction is deferred to v0.2.\n\n---\n\n## 7. Notation modes\n\nThe DSL header can pin the notation:\n\n```\nerd\nnotation: crowsfoot // default \u2014 only mode supported in v0.1\n```\n\n`notation: chen` (rectangle-diamond-oval, weak entities, ternary, ISA) and `notation: barker` (per-half dashed) are documented in `27-ERD-STANDARD.md` but rejected by the parser today. Targets v0.2.\n\n---\n\n## 8. Limitations of v0.1\n\n- **Crow\'s foot only.** Chen and Barker rendering deferred.\n- **No edge-crossing minimization.** Layered placement uses declaration order within layers; large ERDs (10+ tables, dense FKs) will show some crossings. Reorder `table` blocks if a specific layout matters.\n- **No self-referential C-loops.** Recursive relationships (`Employee.manager_id -> Employee.id`) parse but route as straight orthogonal lines, not the canonical C-shape.\n- **No M:N auto-resolution.** Express the associative entity explicitly (this is the standard practice in production schemas anyway).\n\nFor the full standard reference, see `docs/reference/27-ERD-STANDARD.md`.'
|
|
1852
|
+
},
|
|
1853
|
+
"breadboard": {
|
|
1854
|
+
"title": "Breadboard / Physical Wiring",
|
|
1855
|
+
"content": "## 1. Your first breadboard\n\nThree sections: a one-line `breadboard` header, a `parts` block, and a `wires` block. Optional `board:` and `title:` lines come right after the header.\n\n```\nbreadboard\nparts\n uno: mcu uno @beside-left\n r1: resistor 220 @5e..9e\n d1: led red @10e..10f\n\nwires\n uno:5V --red-- @+t1\n uno:GND --black-- @-t1\n uno:D13 --yellow-- @5a\n @10j --black-- @-t1\n```\n\nEvery part is `id: kind [args] @placement`. Every wire is `<endpoint> --color-- <endpoint>`. That's the whole grammar.\n\n---\n\n## 2. Coordinates\n\nBreadboards have a 2D address grid. Schematex coordinates always start with `@`.\n\n| Form | Meaning | Example |\n|---|---|---|\n| `@<col><row>` | Main grid hole. Rows `a\u2013e` (top half), `f\u2013j` (bottom half). | `@5e`, `@12g` |\n| `@+t<col>` | Top **positive** rail (red stripe). | `@+t8` |\n| `@-t<col>` | Top **negative / GND** rail (blue stripe). | `@-t8` |\n| `@+b<col>` | Bottom positive rail. | `@+b14` |\n| `@-b<col>` | Bottom negative rail. | `@-b14` |\n| `@<a>..<b>` | Span \u2014 used in part placement (resistor, diode, LED). | `@5e..9e` |\n| `@beside-left` | Off-board placement for MCU boards. | `mcu uno @beside-left` |\n\nMini boards (`board: mini`) have **no power rails** \u2014 `@+t\u2026` / `@-b\u2026` are rejected by the parser.\n\n---\n\n## 3. Board sizes\n\n```\nbreadboard\nboard: half // default \u2014 30 columns, 400 tie-points, rails (continuous)\n```\n\n| Form | Tie points | Columns | Power rails |\n|---|---|---|---|\n| `mini` | 170 | 17 | none |\n| `half` (default) | 400 | 30 | continuous |\n| `full` | 830 | 63 | break at column 30/31 |\n\n> **Pitfall** \u2014 on full-size boards the rails break at the middle. If your circuit uses both halves you must jumper the rails together explicitly.\n\n---\n\n## 4. Parts catalog\n\nEach part is `id: <kind> [args] @<placement>`. The catalog covers the most common Arduino / ESP32 maker components:\n\n**Discrete components** (sit on the breadboard):\n\n| DSL | Args | Example |\n|---|---|---|\n| `resistor` | `value` (\u03A9; supports `k`/`M`) | `r1: resistor 220 @5e..9e` |\n| `led` | `color` (red/green/blue/yellow/white/orange) | `d1: led red @10e..10f` |\n| `cap-elec` | \u2014 | `c1: cap-elec @4e..4f` |\n| `cap-ceramic` | \u2014 | `c2: cap-ceramic @6e..6f` |\n| `diode` | \u2014 | `d2: diode @5e..8e` |\n| `button` | \u2014 | `btn: button @8e` |\n| `dip` | `pins=N` | `ic: dip pins=8 @4e` |\n| `header` | `pins=N` | `h1: header pins=4 @20a` |\n\n**Microcontroller boards** (placed beside / above / below the substrate):\n\n| DSL | Pin labels |\n|---|---|\n| `mcu uno` | `5V`, `3V3`, `GND`, `VIN`, `RST`, `D2\u2026D13`, `A0\u2026A5`, `RX`, `TX` |\n| `mcu nano` | Subset of Uno labels |\n| `mcu esp32` | `3V3`, `GND`, `VIN`, `GPIO2`, `GPIO4`, `GPIO5`, `GPIO12\u2026GPIO33` |\n| `mcu pico` | Same generic GPIO labels |\n\n**Sensors / displays / actuators** (modules sit on the breadboard with pin row anchored at the supplied coordinate):\n\n| DSL | Pins |\n|---|---|\n| `sensor hcsr04` | `VCC`, `TRIG`, `ECHO`, `GND` |\n| `sensor dht11` / `sensor dht22` | `VCC`, `DATA`, `GND` |\n| `display oled-ssd1306` | `GND`, `VCC`, `SCL`, `SDA` |\n| `display lcd-1602-i2c` | `GND`, `VCC`, `SDA`, `SCL` |\n| `module rotary-ky040` | `CLK`, `DT`, `SW`, `VCC`, `GND` |\n| `actuator servo-sg90` | `GND`, `VCC`, `SIG` |\n\nResistor color bands are decorated automatically from `value` \u2014 `220` \u2192 red-red-brown-gold, `10000` \u2192 brown-black-orange-gold.\n\n---\n\n## 5. Wires\n\nEvery wire connects two endpoints. An endpoint is either a **part pin** (`partId:pinName`) or a **breadboard coordinate** (`@\u2026`).\n\n```\nwires\n uno:5V --red-- @+t1\n uno:GND --black-- @-t1\n uno:D9 --yellow-- @9c\n @9a --green-- @+t9\n```\n\n| Color | Conventional role |\n|---|---|\n| `red` | +V (5V, 3.3V, VCC) |\n| `black` / `blue` | GND |\n| `yellow` / `orange` / `green` / `white` / `purple` | Signal |\n| `brown` / `grey` | Arbitrary signal |\n\nColor is purely visual \u2014 the engine does not validate it against electrical role.\n\nFor visually crowded boards, `via @<coord>` lets you pin an intermediate hole that biases the B\xE9zier control points:\n\n```\nwires\n uno:D13 --yellow-- @9a via @8c\n```\n\nMost wires don't need `via` \u2014 the layout engine produces a natural arc on its own.\n\n---\n\n## 6. Sensor with pull-up resistor (DHT11 motif)\n\nThe iconic Arduino tutorial pattern: a 10 k\u03A9 pull-up between VCC and the sensor's data line.\n\n```\nbreadboard\nboard: half\ntitle: \"DHT11 + 10k\u03A9 pull-up\"\n\nparts\n uno: mcu uno @beside-left\n s1: sensor dht11 @6a\n r1: resistor 10000 @8e..14e\n\nwires\n s1:VCC --red-- @+t1\n s1:GND --black-- @-t1\n s1:DATA --yellow-- @8e\n @14e --red-- @+t14\n uno:5V --red-- @+t1\n uno:GND --black-- @-t1\n uno:D2 --yellow-- @8a\n```\n\n---\n\n## 7. ESP32 + I\xB2C OLED\n\nESP32 runs at 3.3 V (not 5 V). I\xB2C convention: green = SDA, white = SCL.\n\n```\nbreadboard\nboard: half\ntitle: \"ESP32 + SSD1306 OLED I\xB2C\"\n\nparts\n esp: mcu esp32 @beside-left\n oled: display oled-ssd1306 @8a\n\nwires\n oled:GND --black-- @-t1\n oled:VCC --red-- @+t1\n oled:SCL --white-- @10c\n oled:SDA --green-- @11c\n esp:3V3 --red-- @+t1\n esp:GND --black-- @-t1\n esp:GPIO22 --white-- @10c\n esp:GPIO21 --green-- @11c\n```\n\n---\n\n## 8. Limitations of v0.1\n\n- **No leader-line callouts** \u2014 reference designators (R1, C2) are drawn near the part body. Off-board callout boxes are deferred.\n- **No `.fzz` import** \u2014 Schematex consumes only its own DSL; Fritzing files are not parsed.\n- **No simulation** \u2014 this is a renderer, not a Wokwi-style simulator. Component-value validation (Ohm's law, current limits) is out of scope.\n- **No PCB / schematic round-trip** \u2014 `breadboard` and `circuit` are independent engines. Authoring two views of the same prototype currently means writing two DSLs.\n- **Fixed parts catalog** \u2014 user-defined part types are deferred. v0.1 ships the maker-tutorial 80% catalog (resistors, LEDs, caps, DIPs, headers, four MCU families, six sensor / display / actuator modules).\n- **Power-rail break visual** \u2014 full-size boards mark the 30/31 break with a hole-wide gap; the rail stripes still draw through the gap (cosmetic)."
|
|
1856
|
+
},
|
|
1857
|
+
"bpmn": {
|
|
1858
|
+
"title": "BPMN / Business Process",
|
|
1859
|
+
"content": '## 1. Your first BPMN diagram\n\nThree sections: a one-line `bpmn` header, one or more `pool { \u2026 }` blocks, and a `flows` block. Inside each pool you put `lane { \u2026 }` blocks, and inside each lane you list flow objects as `id: kind "label"`.\n\n```\nbpmn\npool "Service" {\n lane "Worker" {\n A: start "Request"\n B: task service "Process"\n F: end "Done"\n }\n}\n\nflows\nA --> B\nB --> F\n```\n\nEvery flow object starts with an **id**, a colon, the **kind**, an optional sub-keyword (trigger / marker / gateway type), and a quoted **label**. Ids are referenced by flow lines.\n\n---\n\n## 2. Pools and lanes\n\nA **pool** represents one participant \u2014 an organisation, a department, or a system. A **lane** subdivides a pool into roles. The pool label is rendered rotated 90\xB0 on the left edge of a horizontal pool.\n\n```\npool "Customer" blackbox // black-box pool \u2014 no internal flow\npool "Bank" {\n lane "Clerk" { \u2026 }\n lane "Underwriter" { \u2026 }\n}\n```\n\nA **black-box pool** is a participant whose internal process you don\'t model \u2014 typically an external customer or partner. Black-box pools must contain zero flow objects (Schematex enforces this in the parser).\n\nSequence flow (`-->`) is **not allowed** to cross pool boundaries. Use a message flow (`~~>`) for cross-pool communication.\n\n---\n\n## 3. Events\n\nEvents are circles. Stroke weight encodes lifecycle role:\n\n| Kind | Stroke | DSL |\n|---|---|---|\n| Start | thin (1px) | `start` |\n| Intermediate | thin double ring | `intermediate` |\n| End | thick (3px) | `end` |\n\nThe optional **trigger** keyword adds an inner glyph. v0.1 supports the three most common triggers \u2014 `none` (no glyph), `message` (envelope), and `timer` (clock face):\n\n```\nA: start // none-trigger\nA: start message "Inbound" // message-catch (unfilled envelope)\nT: intermediate timer "60 min" // timer (clock face)\nF: end "Done"\n```\n\nFilled glyph = **throw**, unfilled glyph = **catch**. Schematex picks the right fill automatically based on event kind.\n\n---\n\n## 4. Activities \u2014 tasks and subprocesses\n\nActivities are rounded rectangles. The two v0.1 forms are `task` and a **collapsed** subprocess (the `+` marker indicates expandable detail):\n\n```\nB: task "Generic abstract task"\nU: task user "User decides"\nS: task service "API call"\nSE: task send "Send email"\nRE: task receive "Wait for reply"\nM: task manual "Hand-stamp the form"\nSC: task script "Run rule engine"\n\nX: subprocess "Verify identity" collapsed\n```\n\nThe **task marker** (small icon top-left) communicates *who or what* performs the work \u2014 a person (`user`), a software service (`service`), an outbound message (`send`), an inbound wait (`receive`), an out-of-system manual step (`manual`), or an automated script (`script`). When in doubt, omit the marker \u2014 it defaults to abstract.\n\n---\n\n## 5. Gateways\n\nGateways are diamonds. The inner glyph encodes branching semantics:\n\n| Kind | Glyph | Meaning | DSL |\n|---|---|---|---|\n| Exclusive (XOR) | **X** | Take exactly one outgoing branch (data-based) | `gateway xor` |\n| Inclusive (OR) | **O** | Take one or more outgoing branches | `gateway or` |\n| Parallel (AND) | **+** | Take all outgoing branches concurrently | `gateway and` |\n| Event-based | pentagon-in-circle | Pick the branch whose event fires first | `gateway event` |\n\nSchematex uses Bruce Silver\'s **X glyph** for XOR by default \u2014 that\'s the convention real BPMN audits expect. Most diagrams use XOR (data branch) and AND (parallel split / join); OR is rare and event-based mostly appears in race-condition models.\n\n---\n\n## 6. Connectors\n\nFour connector types. Three of them stay inside a pool; only message flow is allowed to cross pool boundaries.\n\n```\nA --> B // sequence flow (default)\nG --? "yes" --> C // conditional sequence (label is a guard)\nG --* "default" --> D // default flow (one per gateway, max)\n"Customer" ~~> A : "Submit application" // message flow\nE ~~> "Customer" : "Notify approval" // message flow back\n```\n\n- `-->` is the workhorse \u2014 solid line + filled triangle arrowhead.\n- `--? "label" -->` adds a small unfilled diamond at the source. Use it when leaving an activity *directly* on a guarded outcome. (At a gateway, the conditional label suffices; the diamond glyph isn\'t drawn.)\n- `--* "label" -->` adds a slash mark at the source. **One default flow maximum per gateway** \u2014 Schematex enforces this.\n- `~~>` is dashed with an open arrowhead and a small unfilled circle at the source. Source or target may be a quoted **pool name** (for black-box participants) or an object id.\n\n---\n\n## 7. Validation\n\nThe parser refuses diagrams that violate BPMN semantics, with line-numbered errors:\n\n| Rule | Error |\n|---|---|\n| Sequence flow crosses pool | `sequence flow \'A --> B\' crosses pool boundary \u2014 use message flow (~~>)` |\n| Message flow inside one pool | `message flow \'A ~~> B\' must cross pool boundaries` |\n| Black-box pool has internals | `black-box pool "X" cannot contain lanes` |\n| Two default flows from same gateway | `gateway \'G\' has 2 default flows (max 1)` |\n| Duplicate id within a pool | `duplicate id \'A\'` |\n| Unknown source / target | `unknown source \'X\' in sequence flow` |\n\nThese checks fire during parse, so an LLM gets a usable signal before the layout pass.\n\n---\n\n## 8. Larger example \u2014 pizza order with black-box customer\n\nA canonical BPMN tutorial: an external customer (whose process we don\'t model) places an order with a pizzeria split into Clerk / Chef / Delivery lanes, with a rework loop on the chef\'s quality check.\n\n```\nbpmn\ndirection: LR\ntitle: "Pizza order"\n\npool "Customer" blackbox\n\npool "Pizzeria" {\n lane "Clerk" {\n A: start message "Order received"\n B: task user "Take order"\n }\n lane "Chef" {\n C: task manual "Make pizza"\n G1: gateway xor "Pizza ok?"\n D: task manual "Rework"\n }\n lane "Delivery" {\n E: task send "Deliver"\n F: end "Done"\n }\n}\n\nflows\nA --> B\nB --> C\nC --> G1\nG1 --? "yes" --> E\nG1 --* "no" --> D\nD --> C\nE --> F\n"Customer" ~~> A : "Place order"\nE ~~> "Customer" : "Pizza delivered"\n```\n\nThe rework loop (`D --> C`) creates a back-edge that the layout\'s cycle-break detects via DFS \u2014 the longest-path layering then proceeds on the forward DAG so columns stay sensible.\n\n---\n\n## 9. Limitations of v0.1\n\nThese are deferred to a later release. If your diagram needs one, file an issue with the use case:\n\n- **Boundary events** \u2014 events attached to an activity edge (timer, error, escalation, compensation). Currently you have to model the boundary as a free-floating intermediate event with manual flows.\n- **Expanded subprocesses** \u2014 collapsed `subprocess` works; expanded inline blocks (`subprocess "X" { \u2026 }`) are deferred.\n- **Rare event triggers** \u2014 error / escalation / cancel / compensation / signal / link / conditional / multiple / parallel-multiple. Use `none` or `message` as a placeholder.\n- **Transaction / call activities** \u2014 render as normal tasks for v0.1.\n- **Loop and multi-instance markers** \u2014 bottom-center activity glyphs; deferred.\n- **Artifacts** \u2014 data object / data store / group / text annotation. Deferred.\n- **BPMN 2.0 XML import / export** \u2014 out of scope. Schematex computes layout from DSL; no DI layer to round-trip.'
|
|
1860
|
+
},
|
|
1861
|
+
"fbd": {
|
|
1862
|
+
"title": "Function Block Diagram (FBD)",
|
|
1863
|
+
"content": '## 1. Your first FBD network\n\nThe smallest useful FBD network: one block, two inputs, one output.\n\n```\nfbd\nnetwork 0:\n Out = AND(A, B)\n```\n\n`A` and `B` are auto-declared as BOOL inputs (left-side terminals), and `Out` is auto-wired to the AND block\'s `OUT` port (right-side terminal). The block sits between them with port stubs and labels.\n\n---\n\n## 2. Variables\n\nDeclare variables before any networks. Each variable has a name, an IEC data type, and an optional initial value.\n\n```\nfbd "Tank Control"\n\nvar StartBtn: bool\nvar TankLevel: real\nvar SetPoint: real = 80.0\nvar DwellTimer: timer\nvar Pulse: counter\n```\n\nSupported types: `bool`, `int`, `dint`, `uint`, `udint`, `real`, `lreal`, `time`, `date`, `tod`, `string`, `wstring`, `byte`, `word`, `dword`, `timer`, `counter`. Any other identifier is treated as a user-defined function-block type.\n\nOptional scope prefixes (default = local): `var_input`, `var_output`, `var_in_out`, `var_global`, `var_external`.\n\n---\n\n## 3. Networks\n\nA **network** is one independent piece of data flow, evaluated left-to-right within itself; networks evaluate top-to-bottom across the program per scan.\n\n```\nnetwork 0 "Start latch":\n ...\n\nnetwork 1:\n ...\n```\n\nThe number is optional \u2014 networks are auto-numbered if absent. The title (in quotes) renders at the top-left of the network frame.\n\n---\n\n## 4. Block calls \u2014 inline expression notation\n\nThe clearest way to write a combinational network is as a single nested expression:\n\n```\nnetwork 0:\n Out = OR(A, AND(B, ~C))\n```\n\nThe parser builds the call tree: outer OR with `A` on input 1 and the AND result on input 2; the AND has `B` and the negated `C`. The renderer lays them out left-to-right (inputs at layer 0, AND at layer 1, OR at layer 2, output at layer 3).\n\n`~C` adds a **negation bubble** (small open circle) at the input port \u2014 equivalent to inserting a NOT block on that wire, but cleaner.\n\n---\n\n## 5. Block calls \u2014 instance-named notation\n\nWhen you need to reference a block\'s outputs from elsewhere, give it an instance tag:\n\n```\nnetwork 0:\n Pulse = R_TRIG(CLK: Sensor)\n Count = CTU(CU: Pulse.Q, R: Reset, PV: 100)\n Done = GE(IN1: Count.CV, IN2: 100)\n```\n\n`Pulse.Q`, `Count.CV` reference output ports of named instances. The instance tag renders italicized above the block header.\n\nArgument lists accept **named ports** (`CU: Pulse.Q`) or **positional** (`CTU(Pulse.Q, Reset, 100)`) \u2014 named is recommended for readability and required when you skip a port.\n\n---\n\n## 6. Inline constants\n\nInput ports can take literals directly \u2014 no wire needed:\n\n```\nnetwork 0:\n Dwell = TON(IN: BottleSensor, PT: T#50ms)\n Cap = LIMIT(MN: 0.0, IN: Setpoint, MX: 95.0)\n Mode = SEL(G: ManualSwitch, IN0: AutoMode, IN1: ManualMode)\n```\n\n`T#50ms`, `0.0`, `95.0` render as small yellow boxed text to the left of their port. Time literals follow IEC 61131-3: `T#10ms`, `T#5s`, `T#3m20s`, `T#1h`. Booleans are `true` / `false` (case-insensitive).\n\n---\n\n## 7. Standard block library\n\n| Category | Blocks |\n|---|---|\n| Boolean | `AND`, `OR`, `NOT`, `NAND`, `NOR`, `XOR`, `XNOR`, `BUF` |\n| Edge detect | `R_TRIG`, `F_TRIG` |\n| Bistable | `SR`, `RS` |\n| Timer | `TON`, `TOF`, `TP` |\n| Counter | `CTU`, `CTD` |\n| Math | `ADD`, `SUB`, `MUL`, `DIV`, `MOD`, `ABS`, `NEG`, `MOVE` |\n| Comparison | `EQ`, `NE`, `GT`, `GE`, `LT`, `LE` |\n| Selection | `SEL`, `MUX`, `MAX`, `MIN`, `LIMIT` |\n\nAND, OR, NAND, NOR, ADD, MUL, MAX, MIN accept any number of inputs (default 2). Pass extra positional args or use `[inputs: N]` to extend.\n\n```\nnetwork 0:\n All4 = AND(A, B, C, D)\n Sum = ADD(X, Y, Z)\n```\n\n---\n\n## 8. Larger example \u2014 bottle counter\n\n```\nfbd "Bottle Counter"\n\nvar ConveyorRunning: bool\nvar BottleSensor: bool\nvar BatchDone: bool\nvar BatchSize: counter\nvar DwellTimer: timer\n\nnetwork 0 "Debounce sensor with 50ms dwell":\n Dwell = TON(IN: BottleSensor, PT: T#50ms)\n\nnetwork 1 "Count one bottle on rising edge of debounced signal":\n Pulse = R_TRIG(CLK: Dwell.Q)\n BatchSize = CTU(CU: Pulse.Q, R: BatchDone, PV: 24)\n\nnetwork 2 "Batch done":\n BatchDone = MOVE(BatchSize.Q)\n```\n\nThree networks: debounce \u2192 edge-detect \u2192 count \u2192 flag. Each network is one DAG; the renderer routes wires through Manhattan paths.\n\n---\n\n## 9. v0.1 limitations\n\nThe current engine implements the standard-block subset most teams use day-to-day. The following are deferred and will be added in a follow-up:\n\n- **EN/ENO power-flow rails** (`[en]` block attribute, `[rail: on]` header) \u2014 adds a top-of-network enable rail, vendor convention from Studio 5000 / TIA Portal.\n- **User-defined function blocks** with `pins_in:` / `pins_out:` declarations \u2014 for custom motor controllers, PID instances, etc.\n- **Page connectors** (`connector_out` / `connector_in`) for wires that span multiple pages.\n- **Bit-string blocks** (SHL, SHR, ROL, ROR, AND_BIT, OR_BIT, etc.).\n- **Extended math** (SQRT, LN, LOG, EXP, SIN, COS, TAN, ASIN, ACOS, ATAN).\n- **ANSI distinctive shape mode** (`[shape: ansi]`) \u2014 the `logic` engine already provides this for pure-Boolean diagrams.\n- **CTUD** bidirectional counter, **TP** retentive timer (RTO).\n\nIf you need any of these now, open an issue or use the `ladder` engine for the full IEC 61131-3 LD subset.'
|
|
1864
|
+
},
|
|
1865
|
+
"sfc": {
|
|
1866
|
+
"title": "Sequential Function Chart (SFC)",
|
|
1867
|
+
"content": '## 1. Your first chart\n\nTwo steps, one transition, an initial marker:\n\n```\nsfc\nstep S0 [initial]\nstep S1\ntransition from: S0 to: S1: Trigger\n```\n\n`S0` renders as a **double-bordered rectangle** (the IEC initial-step convention); `S1` as a single-border rectangle. Between them is a horizontal **transition bar** with the condition text `Trigger` to its right.\n\nIf you forget `[initial]`, the first declared step is auto-promoted to initial.\n\n---\n\n## 2. Steps\n\n```\nstep S_Filling [label: "Filling tank"]\n N FillValve_Open\n D Mixer_Run T#30s\n P StartChime\n```\n\nA step has:\n\n- An **id** (unique across the chart) \u2014 used in transitions and jumps.\n- An optional `[label: "..."]` for display.\n- An optional `[initial]` (one allowed) or `[final]` (vendor stop step, three borders).\n- Zero or more **action blocks**, indented one level, each with a qualifier letter.\n\n---\n\n## 3. Transitions\n\nA **transition** declares a directed link between two steps with a boolean condition:\n\n```\ntransition from: S0 to: S1: StartBtn\ntransition from: S1 to: S2: TankLevel >= 80.0 AND NOT EmergencyStop\ntransition T_Reset from: S5 to: S0: ResetBtn\n```\n\nThe condition text is opaque \u2014 Schematex stores it verbatim and renders it next to the bar. Every transition must have a non-empty condition; use `TRUE` for unconditional links.\n\nTransitions whose `from` and `to` are linearly adjacent in the body render as inline bars between the steps. Transitions whose pair is *not* linearly adjacent (e.g. a jump back to an earlier step) render as **margin arrows** on the left or right side of the chart.\n\n---\n\n## 4. Action qualifiers\n\nActions attach to the right side of a step and run according to their qualifier letter:\n\n| Qualifier | Behavior |\n|---|---|\n| `N` | Active while step is active (most common) |\n| `S` | Stored \u2014 set true on entry, stays until matching `R` |\n| `R` | Reset \u2014 clears a previously-stored action |\n| `L` | Time-Limited \u2014 active up to T after step entry |\n| `D` | Time-Delayed \u2014 activates T after entry |\n| `P` | Pulse \u2014 true for one PLC scan only |\n| `P0` | Pulse on deactivate (Siemens) |\n| `P1` | Synonym for `P` (Siemens) |\n| `SD` | Stored & Delayed |\n| `DS` | Delayed & Stored |\n| `SL` | Stored & Time-Limited |\n\nTime-parameterized qualifiers (L, D, SD, DS, SL) take a duration literal:\n\n```\nstep S1\n L LimitedRun T#5s\n D DelayedRun T#2s\n```\n\n---\n\n## 5. Alternative branches (single bar \u2014 OR)\n\nOnly **one** branch fires per scan, picked by transition condition:\n\n```\nstep S0 [initial]\nstep S_Pick\n\nalt from: S_Pick:\n branch [priority: 1]:\n transition: IsExpressShipping\n step S_Express\n N PrepExpressBox\n transition: TRUE\n branch [priority: 2]:\n transition: IsStandardShipping\n step S_Standard\n N PrepStandardBox\n transition: TRUE\nmerge_to: S_Ship\n\nstep S_Ship\n\ntransition from: S0 to: S_Pick: ProductOrdered\ntransition from: S_Ship to: S0: Shipped\n```\n\nThe single horizontal lines above and below the branches are the divergence and convergence bars. Each branch starts with its **entry transition** (between div bar and first step) and ends with an **exit transition** (between last step and conv bar).\n\n---\n\n## 6. Simultaneous branches (double bar \u2014 AND)\n\n**All** branches run concurrently; the chart waits at the convergence until every branch finishes:\n\n```\nsim from: S_Heat: TRUE\n branch:\n step S_Bake\n D Oven_Run T#15m\n branch:\n step S_Cool\n L Cooler_On T#5m\nmerge_to: S_Done: Bake_Done AND Cool_Done\n```\n\nThe two parallel horizontal lines (gap 4px) above and below the branches are the simultaneous bars. The shared **transition above** (`TRUE` here) triggers the divergence; the shared **transition below** (`Bake_Done AND Cool_Done`) is checked before convergence fires.\n\n---\n\n## 7. Jumps (loops)\n\nA transition whose target is an earlier step renders as a margin arrow:\n\n```\nstep S0 [initial]\nstep S1\nstep S2\ntransition from: S0 to: S1: A\ntransition from: S1 to: S2: B\ntransition T_Reset from: S2 to: S0: ResetBtn\ntransition from: S2 to: S1: NOT ResetBtn\n```\n\nThe forward `S2 \u2192 S1` (back-edge) gets the margin arrow on the right; the `T_Reset` jump back to `S0` goes on the left. Each margin arrow shows its target id and condition.\n\n---\n\n## 8. Variables\n\nReused from `ladder` and `fbd`:\n\n```\nvar StartBtn: bool\nvar TankLevel: real\nvar BakeReady: bool\nvar Counter: counter\nvar T1: timer\n```\n\nVariables declared in conditions and actions are not validated \u2014 Schematex treats condition / action body text as opaque strings, matching how `state` handles guards and actions.\n\n---\n\n## 9. v0.1 limitations\n\n- **Nested branches** (alt-in-sim, sim-in-alt) parse but layout collapse heuristics are basic; deep nests may overlap.\n- **S/R action-pair dashed connectors** (visually link an `S` action with its matching `R` elsewhere) are deferred.\n- **Active-step runtime indicator** (yellow fill on the currently active step) is deferred \u2014 useful for debugging integrations that surface PLC runtime state.\n- **GRAFCET forcing orders** (out-of-scope per IEC 60848-only feature).\n- **Final step** parses with `[final]` but renders with the same double border as initial; the IEC triple-border convention is deferred.'
|
|
1047
1868
|
}
|
|
1048
1869
|
};
|
|
1049
1870
|
|
|
@@ -1123,7 +1944,7 @@ function getExamples(type, opts = {}) {
|
|
|
1123
1944
|
function validateDsl(type, dsl) {
|
|
1124
1945
|
const config = type ? { type } : void 0;
|
|
1125
1946
|
try {
|
|
1126
|
-
|
|
1947
|
+
chunkDHHVYSQX_cjs.parse(dsl, config);
|
|
1127
1948
|
return { ok: true, type: type ?? resolveTypeFromText(dsl) };
|
|
1128
1949
|
} catch (err) {
|
|
1129
1950
|
return {
|
|
@@ -1139,7 +1960,7 @@ function renderDsl(type, dsl, options = {}) {
|
|
|
1139
1960
|
...type ? { type } : {}
|
|
1140
1961
|
};
|
|
1141
1962
|
try {
|
|
1142
|
-
const svg =
|
|
1963
|
+
const svg = chunkDHHVYSQX_cjs.render(dsl, config);
|
|
1143
1964
|
return { ok: true, type: type ?? resolveTypeFromText(dsl), svg };
|
|
1144
1965
|
} catch (err) {
|
|
1145
1966
|
return {
|
|
@@ -1163,5 +1984,5 @@ exports.getSyntax = getSyntax;
|
|
|
1163
1984
|
exports.listDiagrams = listDiagrams;
|
|
1164
1985
|
exports.renderDsl = renderDsl;
|
|
1165
1986
|
exports.validateDsl = validateDsl;
|
|
1166
|
-
//# sourceMappingURL=chunk-
|
|
1167
|
-
//# sourceMappingURL=chunk-
|
|
1987
|
+
//# sourceMappingURL=chunk-WCAADEXJ.cjs.map
|
|
1988
|
+
//# sourceMappingURL=chunk-WCAADEXJ.cjs.map
|