schematex 0.3.4 → 0.4.0
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-3ADSXODY.js} +428 -10
- package/dist/chunk-3ADSXODY.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-J3Y2QDJR.cjs → chunk-7LNIBHO6.cjs} +430 -12
- package/dist/chunk-7LNIBHO6.cjs.map +1 -0
- package/dist/{chunk-MIKCKV27.cjs → chunk-BW4KGTV7.cjs} +65 -31
- package/dist/chunk-BW4KGTV7.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-DBMZEZLF.cjs → chunk-O2HN4WRG.cjs} +6229 -51
- package/dist/chunk-O2HN4WRG.cjs.map +1 -0
- package/dist/{chunk-HKJRHXGZ.js → chunk-O4RHSAHR.js} +6217 -39
- package/dist/chunk-O4RHSAHR.js.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-XSNNGYXZ.cjs → chunk-YLEVMOK2.cjs} +22 -8
- package/dist/chunk-YLEVMOK2.cjs.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,4 +1,4 @@
|
|
|
1
|
-
import { parse, render } from './chunk-
|
|
1
|
+
import { parse, render } from './chunk-O4RHSAHR.js';
|
|
2
2
|
|
|
3
3
|
// src/ai/registry.ts
|
|
4
4
|
var DIAGRAM_REGISTRY = [
|
|
@@ -94,6 +94,24 @@ var DIAGRAM_REGISTRY = [
|
|
|
94
94
|
standard: "IEC 61131-3 Ladder Diagram",
|
|
95
95
|
syntaxKey: "ladder"
|
|
96
96
|
},
|
|
97
|
+
{
|
|
98
|
+
type: "fbd",
|
|
99
|
+
name: "Function Block Diagram (FBD)",
|
|
100
|
+
tagline: "IEC 61131-3 \xA76.4 function blocks wired through named ports.",
|
|
101
|
+
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.",
|
|
102
|
+
cluster: "electrical-industrial",
|
|
103
|
+
standard: "IEC 61131-3:2013 \xA76.4 + \xA72.5 standard FB library; see 23-FBD-STANDARD.md",
|
|
104
|
+
syntaxKey: "fbd"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: "sfc",
|
|
108
|
+
name: "Sequential Function Chart (SFC)",
|
|
109
|
+
tagline: "IEC 61131-3 \xA76.5 step + transition state machine for cyclic PLC sequences.",
|
|
110
|
+
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).",
|
|
111
|
+
cluster: "electrical-industrial",
|
|
112
|
+
standard: "IEC 61131-3:2013 \xA76.5 + IEC 60848 GRAFCET visual subset; see 24-SFC-STANDARD.md",
|
|
113
|
+
syntaxKey: "sfc"
|
|
114
|
+
},
|
|
97
115
|
{
|
|
98
116
|
type: "sld",
|
|
99
117
|
name: "Single-line diagram",
|
|
@@ -112,16 +130,35 @@ var DIAGRAM_REGISTRY = [
|
|
|
112
130
|
standard: "ANSI/ISA-5.1-2009 + ISO 10628-1:2014",
|
|
113
131
|
syntaxKey: "pid"
|
|
114
132
|
},
|
|
133
|
+
{
|
|
134
|
+
type: "breadboard",
|
|
135
|
+
name: "Breadboard / Physical wiring",
|
|
136
|
+
tagline: "Fritzing-style breadboard view \u2014 physical wiring of Arduino / ESP32 / Pi prototypes.",
|
|
137
|
+
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).",
|
|
138
|
+
cluster: "electrical-industrial",
|
|
139
|
+
standard: "Fritzing visual conventions + Wokwi DSL precedent (no ISO standard exists for this view; see 26-BREADBOARD-STANDARD.md)",
|
|
140
|
+
syntaxKey: "breadboard"
|
|
141
|
+
},
|
|
115
142
|
// ── Corporate / Legal ────────────────────────────────────────
|
|
116
143
|
{
|
|
117
144
|
type: "entity",
|
|
118
145
|
name: "Entity structure",
|
|
119
146
|
tagline: "Corporate ownership hierarchy with percentage rollup.",
|
|
120
|
-
useWhen: "Use for legal entity structures, holdco/opco charts, international tax charts, Series-A cap-table snapshots. Tiered layout with ownership percentages.",
|
|
147
|
+
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.",
|
|
121
148
|
cluster: "corporate-legal",
|
|
122
149
|
standard: "Tier-based ownership hierarchy",
|
|
123
150
|
syntaxKey: "entity"
|
|
124
151
|
},
|
|
152
|
+
// ── Data modeling ────────────────────────────────────────────
|
|
153
|
+
{
|
|
154
|
+
type: "erd",
|
|
155
|
+
name: "Entity-Relationship Diagram (ERD)",
|
|
156
|
+
tagline: "Database schema diagram (crow's-foot tabular entities + cardinality glyphs).",
|
|
157
|
+
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.",
|
|
158
|
+
cluster: "corporate-legal",
|
|
159
|
+
standard: "Chen 1976 / Everest 1976 (crow's foot) \u2014 implements the crow's-foot subset; see 27-ERD-STANDARD.md",
|
|
160
|
+
syntaxKey: "erd"
|
|
161
|
+
},
|
|
125
162
|
// ── Causality / Analysis ─────────────────────────────────────
|
|
126
163
|
{
|
|
127
164
|
type: "fishbone",
|
|
@@ -160,6 +197,15 @@ var DIAGRAM_REGISTRY = [
|
|
|
160
197
|
standard: "OMG UML 2.5.1 \xA714 + Harel (1987) statechart",
|
|
161
198
|
syntaxKey: "state"
|
|
162
199
|
},
|
|
200
|
+
{
|
|
201
|
+
type: "bpmn",
|
|
202
|
+
name: "BPMN business process",
|
|
203
|
+
tagline: "OMG BPMN 2.0 \u2014 pools and lanes, events, gateways, tasks for organizational processes.",
|
|
204
|
+
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).",
|
|
205
|
+
cluster: "behavior-modeling",
|
|
206
|
+
standard: "OMG BPMN 2.0.2 / ISO/IEC 19510:2013 visual subset; see 25-BPMN-STANDARD.md",
|
|
207
|
+
syntaxKey: "bpmn"
|
|
208
|
+
},
|
|
163
209
|
// ── Generic process / flow ───────────────────────────────────
|
|
164
210
|
{
|
|
165
211
|
type: "flowchart",
|
|
@@ -251,6 +297,128 @@ var EXAMPLES = [
|
|
|
251
297
|
"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',
|
|
252
298
|
"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.'
|
|
253
299
|
},
|
|
300
|
+
{
|
|
301
|
+
"slug": "bpmn-incident-response",
|
|
302
|
+
"diagram": "bpmn",
|
|
303
|
+
"title": "Production incident response (BPMN)",
|
|
304
|
+
"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.",
|
|
305
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
306
|
+
"tags": [
|
|
307
|
+
"bpmn",
|
|
308
|
+
"business-process",
|
|
309
|
+
"incident-response",
|
|
310
|
+
"timer-event",
|
|
311
|
+
"on-call",
|
|
312
|
+
"sre"
|
|
313
|
+
],
|
|
314
|
+
"complexity": 3,
|
|
315
|
+
"featured": false,
|
|
316
|
+
"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"',
|
|
317
|
+
"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.
|
|
318
|
+
|
|
319
|
+
**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.
|
|
320
|
+
|
|
321
|
+
**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.
|
|
322
|
+
|
|
323
|
+
**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.
|
|
324
|
+
|
|
325
|
+
**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.`
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"slug": "bpmn-loan-approval",
|
|
329
|
+
"diagram": "bpmn",
|
|
330
|
+
"title": "Loan application approval (BPMN)",
|
|
331
|
+
"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.",
|
|
332
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
333
|
+
"tags": [
|
|
334
|
+
"bpmn",
|
|
335
|
+
"business-process",
|
|
336
|
+
"loan",
|
|
337
|
+
"banking",
|
|
338
|
+
"xor-gateway"
|
|
339
|
+
],
|
|
340
|
+
"complexity": 2,
|
|
341
|
+
"featured": true,
|
|
342
|
+
"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',
|
|
343
|
+
"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.'
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"slug": "bpmn-pizza-order",
|
|
347
|
+
"diagram": "bpmn",
|
|
348
|
+
"title": "Pizza order with black-box customer (BPMN)",
|
|
349
|
+
"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.",
|
|
350
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
351
|
+
"tags": [
|
|
352
|
+
"bpmn",
|
|
353
|
+
"business-process",
|
|
354
|
+
"message-flow",
|
|
355
|
+
"black-box-pool",
|
|
356
|
+
"rework-loop"
|
|
357
|
+
],
|
|
358
|
+
"complexity": 2,
|
|
359
|
+
"featured": true,
|
|
360
|
+
"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"',
|
|
361
|
+
"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.'
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"slug": "breadboard-blink-led",
|
|
365
|
+
"diagram": "breadboard",
|
|
366
|
+
"title": "Blink LED on Arduino Uno",
|
|
367
|
+
"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.",
|
|
368
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
369
|
+
"tags": [
|
|
370
|
+
"breadboard",
|
|
371
|
+
"arduino",
|
|
372
|
+
"uno",
|
|
373
|
+
"led",
|
|
374
|
+
"blink",
|
|
375
|
+
"tutorial"
|
|
376
|
+
],
|
|
377
|
+
"complexity": 1,
|
|
378
|
+
"featured": true,
|
|
379
|
+
"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',
|
|
380
|
+
"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.
|
|
381
|
+
|
|
382
|
+
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.`
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
"slug": "breadboard-esp32-oled",
|
|
386
|
+
"diagram": "breadboard",
|
|
387
|
+
"title": "ESP32 + SSD1306 OLED I\xB2C",
|
|
388
|
+
"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.',
|
|
389
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
390
|
+
"tags": [
|
|
391
|
+
"breadboard",
|
|
392
|
+
"esp32",
|
|
393
|
+
"oled",
|
|
394
|
+
"ssd1306",
|
|
395
|
+
"i2c",
|
|
396
|
+
"display"
|
|
397
|
+
],
|
|
398
|
+
"complexity": 2,
|
|
399
|
+
"featured": false,
|
|
400
|
+
"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',
|
|
401
|
+
"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."
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"slug": "breadboard-hcsr04-distance",
|
|
405
|
+
"diagram": "breadboard",
|
|
406
|
+
"title": "HC-SR04 distance sensor + Arduino Uno",
|
|
407
|
+
"description": "Four-wire ultrasonic distance sensor wiring \u2014 VCC / GND / TRIG / ECHO. The textbook Adafruit / SparkFun tutorial layout used in robotics intro classes.",
|
|
408
|
+
"standard": "Fritzing visual conventions (no ISO standard)",
|
|
409
|
+
"tags": [
|
|
410
|
+
"breadboard",
|
|
411
|
+
"arduino",
|
|
412
|
+
"ultrasonic",
|
|
413
|
+
"sensor",
|
|
414
|
+
"hc-sr04",
|
|
415
|
+
"robotics"
|
|
416
|
+
],
|
|
417
|
+
"complexity": 2,
|
|
418
|
+
"featured": true,
|
|
419
|
+
"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',
|
|
420
|
+
"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."
|
|
421
|
+
},
|
|
254
422
|
{
|
|
255
423
|
"slug": "circuit-ce-amplifier",
|
|
256
424
|
"diagram": "circuit",
|
|
@@ -411,6 +579,102 @@ var EXAMPLES = [
|
|
|
411
579
|
"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%',
|
|
412
580
|
"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."
|
|
413
581
|
},
|
|
582
|
+
{
|
|
583
|
+
"slug": "erd-ecommerce-schema",
|
|
584
|
+
"diagram": "erd",
|
|
585
|
+
"title": "E-commerce schema",
|
|
586
|
+
"description": "Production-style schema with Customer / Order / OrderLine / Product / Category \u2014 typical mid-complexity backend ERD with composite PK on the line-item table.",
|
|
587
|
+
"standard": "Crow's-foot (Everest 1976) / DBML compatible",
|
|
588
|
+
"tags": [
|
|
589
|
+
"ERD",
|
|
590
|
+
"crow's-foot",
|
|
591
|
+
"schema",
|
|
592
|
+
"e-commerce",
|
|
593
|
+
"FK",
|
|
594
|
+
"composite-PK"
|
|
595
|
+
],
|
|
596
|
+
"complexity": 2,
|
|
597
|
+
"featured": false,
|
|
598
|
+
"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',
|
|
599
|
+
"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").'
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
"slug": "erd-university-schema",
|
|
603
|
+
"diagram": "erd",
|
|
604
|
+
"title": "University schema (academic ERD)",
|
|
605
|
+
"description": "Classic textbook schema with Student / Course / Enrollment associative entity and labelled relationships \u2014 the canonical Elmasri & Navathe ch.3 example.",
|
|
606
|
+
"standard": "Crow's-foot (Everest 1976) / DBML compatible",
|
|
607
|
+
"tags": [
|
|
608
|
+
"ERD",
|
|
609
|
+
"crow's-foot",
|
|
610
|
+
"schema",
|
|
611
|
+
"associative-entity",
|
|
612
|
+
"M-N"
|
|
613
|
+
],
|
|
614
|
+
"complexity": 1,
|
|
615
|
+
"featured": true,
|
|
616
|
+
"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',
|
|
617
|
+
"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)."
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
"slug": "fbd-bottle-counter",
|
|
621
|
+
"diagram": "fbd",
|
|
622
|
+
"title": "Bottle counter \u2014 debounce \u2192 edge \u2192 count (FBD)",
|
|
623
|
+
"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.",
|
|
624
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
625
|
+
"tags": [
|
|
626
|
+
"fbd",
|
|
627
|
+
"plc",
|
|
628
|
+
"ton",
|
|
629
|
+
"ctu",
|
|
630
|
+
"r-trig",
|
|
631
|
+
"debounce",
|
|
632
|
+
"sensor",
|
|
633
|
+
"packaging"
|
|
634
|
+
],
|
|
635
|
+
"complexity": 3,
|
|
636
|
+
"featured": true,
|
|
637
|
+
"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)',
|
|
638
|
+
"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."
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"slug": "fbd-motor-latch",
|
|
642
|
+
"diagram": "fbd",
|
|
643
|
+
"title": "Motor start/stop latch (FBD)",
|
|
644
|
+
"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.",
|
|
645
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
646
|
+
"tags": [
|
|
647
|
+
"fbd",
|
|
648
|
+
"plc",
|
|
649
|
+
"iec-61131-3",
|
|
650
|
+
"latch",
|
|
651
|
+
"motor-control"
|
|
652
|
+
],
|
|
653
|
+
"complexity": 2,
|
|
654
|
+
"featured": true,
|
|
655
|
+
"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)',
|
|
656
|
+
"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.'
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
"slug": "fbd-tank-setpoint-limiter",
|
|
660
|
+
"diagram": "fbd",
|
|
661
|
+
"title": "Tank setpoint limiter + alarm (FBD)",
|
|
662
|
+
"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.",
|
|
663
|
+
"standard": "IEC 61131-3:2013 \xA76.4 + \xA72.5",
|
|
664
|
+
"tags": [
|
|
665
|
+
"fbd",
|
|
666
|
+
"plc",
|
|
667
|
+
"comparison",
|
|
668
|
+
"limit",
|
|
669
|
+
"real",
|
|
670
|
+
"hmi",
|
|
671
|
+
"operator-input"
|
|
672
|
+
],
|
|
673
|
+
"complexity": 2,
|
|
674
|
+
"featured": false,
|
|
675
|
+
"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)',
|
|
676
|
+
"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."
|
|
677
|
+
},
|
|
414
678
|
{
|
|
415
679
|
"slug": "fishbone-website-traffic",
|
|
416
680
|
"diagram": "fishbone",
|
|
@@ -464,6 +728,25 @@ var EXAMPLES = [
|
|
|
464
728
|
"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",
|
|
465
729
|
"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.'
|
|
466
730
|
},
|
|
731
|
+
{
|
|
732
|
+
"slug": "flowchart-prisma-systematic-review",
|
|
733
|
+
"diagram": "flowchart",
|
|
734
|
+
"title": "PRISMA 2020 systematic review flow",
|
|
735
|
+
"description": "Canonical PRISMA 2020 flow diagram for a systematic review \u2014 records identified across databases, screened, assessed for eligibility, and included in synthesis.",
|
|
736
|
+
"standard": "PRISMA 2020 (Page et al., BMJ 2021)",
|
|
737
|
+
"tags": [
|
|
738
|
+
"flowchart",
|
|
739
|
+
"prisma",
|
|
740
|
+
"systematic-review",
|
|
741
|
+
"meta-analysis",
|
|
742
|
+
"research",
|
|
743
|
+
"evidence-synthesis"
|
|
744
|
+
],
|
|
745
|
+
"complexity": 3,
|
|
746
|
+
"featured": true,
|
|
747
|
+
"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',
|
|
748
|
+
"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).'
|
|
749
|
+
},
|
|
467
750
|
{
|
|
468
751
|
"slug": "genogram-brca-cancer",
|
|
469
752
|
"diagram": "genogram",
|
|
@@ -609,6 +892,26 @@ var EXAMPLES = [
|
|
|
609
892
|
"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)',
|
|
610
893
|
"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."
|
|
611
894
|
},
|
|
895
|
+
{
|
|
896
|
+
"slug": "matrix-9-box-talent",
|
|
897
|
+
"diagram": "matrix",
|
|
898
|
+
"title": "9-box talent grid",
|
|
899
|
+
"description": "3\xD73 performance \xD7 potential talent grid \u2014 the GE/McKinsey HR review tool used to plan promotions, succession, and performance management.",
|
|
900
|
+
"standard": "9-Box Talent Grid (GE / McKinsey)",
|
|
901
|
+
"tags": [
|
|
902
|
+
"matrix",
|
|
903
|
+
"9-box",
|
|
904
|
+
"talent",
|
|
905
|
+
"hr",
|
|
906
|
+
"succession",
|
|
907
|
+
"performance",
|
|
908
|
+
"table"
|
|
909
|
+
],
|
|
910
|
+
"complexity": 2,
|
|
911
|
+
"featured": false,
|
|
912
|
+
"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)"',
|
|
913
|
+
"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."
|
|
914
|
+
},
|
|
612
915
|
{
|
|
613
916
|
"slug": "matrix-bcg-portfolio",
|
|
614
917
|
"diagram": "matrix",
|
|
@@ -631,19 +934,58 @@ var EXAMPLES = [
|
|
|
631
934
|
"slug": "matrix-eisenhower-week",
|
|
632
935
|
"diagram": "matrix",
|
|
633
936
|
"title": "Eisenhower week prioritization",
|
|
634
|
-
"description": "2\xD72 Eisenhower
|
|
937
|
+
"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.",
|
|
635
938
|
"standard": "Eisenhower (1954)",
|
|
636
939
|
"tags": [
|
|
637
940
|
"matrix",
|
|
638
941
|
"eisenhower",
|
|
639
942
|
"prioritization",
|
|
640
943
|
"productivity",
|
|
641
|
-
"planning"
|
|
944
|
+
"planning",
|
|
945
|
+
"table"
|
|
642
946
|
],
|
|
643
|
-
"complexity":
|
|
947
|
+
"complexity": 1,
|
|
644
948
|
"featured": true,
|
|
645
|
-
"dsl": 'matrix eisenhower "This Week"\
|
|
646
|
-
"notes": '## Scenario\n\nAn engineering manager
|
|
949
|
+
"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"',
|
|
950
|
+
"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.'
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
"slug": "matrix-impact-effort",
|
|
954
|
+
"diagram": "matrix",
|
|
955
|
+
"title": "Impact-effort feature prioritization",
|
|
956
|
+
"description": "2\xD72 impact \xD7 effort table sorting a backlog into Quick Wins / Major Projects / Fill-ins / Thankless \u2014 the classic PM prioritization grid.",
|
|
957
|
+
"standard": "Impact\u2013Effort (Sondhi 1999)",
|
|
958
|
+
"tags": [
|
|
959
|
+
"matrix",
|
|
960
|
+
"impact",
|
|
961
|
+
"effort",
|
|
962
|
+
"prioritization",
|
|
963
|
+
"product",
|
|
964
|
+
"table"
|
|
965
|
+
],
|
|
966
|
+
"complexity": 1,
|
|
967
|
+
"featured": false,
|
|
968
|
+
"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"',
|
|
969
|
+
"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."
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
"slug": "matrix-johari-window",
|
|
973
|
+
"diagram": "matrix",
|
|
974
|
+
"title": "Johari window \u2014 manager self-assessment",
|
|
975
|
+
"description": "2\xD72 Johari window placing self-traits across Open / Blind / Hidden / Unknown \u2014 the classic coaching exercise rendered as a four-cell table.",
|
|
976
|
+
"standard": "Johari window (Luft & Ingham 1955)",
|
|
977
|
+
"tags": [
|
|
978
|
+
"matrix",
|
|
979
|
+
"johari",
|
|
980
|
+
"coaching",
|
|
981
|
+
"self-awareness",
|
|
982
|
+
"hr",
|
|
983
|
+
"table"
|
|
984
|
+
],
|
|
985
|
+
"complexity": 1,
|
|
986
|
+
"featured": false,
|
|
987
|
+
"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"',
|
|
988
|
+
"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."
|
|
647
989
|
},
|
|
648
990
|
{
|
|
649
991
|
"slug": "mindmap-product-launch",
|
|
@@ -788,6 +1130,62 @@ var EXAMPLES = [
|
|
|
788
1130
|
"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"',
|
|
789
1131
|
"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.'
|
|
790
1132
|
},
|
|
1133
|
+
{
|
|
1134
|
+
"slug": "sfc-bake-cool-concurrent",
|
|
1135
|
+
"diagram": "sfc",
|
|
1136
|
+
"title": "Bake & cool concurrent batch (SFC)",
|
|
1137
|
+
"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.",
|
|
1138
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1139
|
+
"tags": [
|
|
1140
|
+
"sfc",
|
|
1141
|
+
"plc",
|
|
1142
|
+
"simultaneous-branch",
|
|
1143
|
+
"time-qualified",
|
|
1144
|
+
"batch-reactor",
|
|
1145
|
+
"oven"
|
|
1146
|
+
],
|
|
1147
|
+
"complexity": 3,
|
|
1148
|
+
"featured": true,
|
|
1149
|
+
"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',
|
|
1150
|
+
"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."
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
"slug": "sfc-bottle-filling",
|
|
1154
|
+
"diagram": "sfc",
|
|
1155
|
+
"title": "Bottle filling sequence (SFC)",
|
|
1156
|
+
"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.",
|
|
1157
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1158
|
+
"tags": [
|
|
1159
|
+
"sfc",
|
|
1160
|
+
"plc",
|
|
1161
|
+
"iec-61131-3",
|
|
1162
|
+
"sequential-control",
|
|
1163
|
+
"packaging"
|
|
1164
|
+
],
|
|
1165
|
+
"complexity": 1,
|
|
1166
|
+
"featured": true,
|
|
1167
|
+
"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',
|
|
1168
|
+
"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."
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
"slug": "sfc-order-routing-alt",
|
|
1172
|
+
"diagram": "sfc",
|
|
1173
|
+
"title": "Order routing \u2014 express vs standard shipping (SFC)",
|
|
1174
|
+
"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.",
|
|
1175
|
+
"standard": "IEC 61131-3:2013 \xA76.5",
|
|
1176
|
+
"tags": [
|
|
1177
|
+
"sfc",
|
|
1178
|
+
"plc",
|
|
1179
|
+
"alternative-branch",
|
|
1180
|
+
"priority",
|
|
1181
|
+
"routing",
|
|
1182
|
+
"e-commerce"
|
|
1183
|
+
],
|
|
1184
|
+
"complexity": 2,
|
|
1185
|
+
"featured": false,
|
|
1186
|
+
"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',
|
|
1187
|
+
"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."
|
|
1188
|
+
},
|
|
791
1189
|
{
|
|
792
1190
|
"slug": "sld-generator-ats",
|
|
793
1191
|
"diagram": "sld",
|
|
@@ -1021,7 +1419,7 @@ var SYNTAX = {
|
|
|
1021
1419
|
},
|
|
1022
1420
|
"matrix": {
|
|
1023
1421
|
"title": "Matrix / Quadrant diagram",
|
|
1024
|
-
"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---'
|
|
1422
|
+
"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---'
|
|
1025
1423
|
},
|
|
1026
1424
|
"orgchart": {
|
|
1027
1425
|
"title": "Org chart",
|
|
@@ -1042,6 +1440,26 @@ var SYNTAX = {
|
|
|
1042
1440
|
"pid": {
|
|
1043
1441
|
"title": "P&ID (Piping & Instrumentation Diagram)",
|
|
1044
1442
|
"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---'
|
|
1443
|
+
},
|
|
1444
|
+
"erd": {
|
|
1445
|
+
"title": "ERD (Entity-Relationship Diagram)",
|
|
1446
|
+
"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`.'
|
|
1447
|
+
},
|
|
1448
|
+
"breadboard": {
|
|
1449
|
+
"title": "Breadboard / Physical Wiring",
|
|
1450
|
+
"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)."
|
|
1451
|
+
},
|
|
1452
|
+
"bpmn": {
|
|
1453
|
+
"title": "BPMN / Business Process",
|
|
1454
|
+
"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.'
|
|
1455
|
+
},
|
|
1456
|
+
"fbd": {
|
|
1457
|
+
"title": "Function Block Diagram (FBD)",
|
|
1458
|
+
"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.'
|
|
1459
|
+
},
|
|
1460
|
+
"sfc": {
|
|
1461
|
+
"title": "Sequential Function Chart (SFC)",
|
|
1462
|
+
"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.'
|
|
1045
1463
|
}
|
|
1046
1464
|
};
|
|
1047
1465
|
|
|
@@ -1154,5 +1572,5 @@ function resolveTypeFromText(text) {
|
|
|
1154
1572
|
}
|
|
1155
1573
|
|
|
1156
1574
|
export { DIAGRAM_REGISTRY, getAllDiagramTypes, getDiagramMeta, getExamples, getSyntax, listDiagrams, renderDsl, validateDsl };
|
|
1157
|
-
//# sourceMappingURL=chunk-
|
|
1158
|
-
//# sourceMappingURL=chunk-
|
|
1575
|
+
//# sourceMappingURL=chunk-3ADSXODY.js.map
|
|
1576
|
+
//# sourceMappingURL=chunk-3ADSXODY.js.map
|