schematex 0.4.1 → 0.4.3
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/dist/ai/ai-sdk.cjs +16 -14
- package/dist/ai/ai-sdk.cjs.map +1 -1
- package/dist/ai/ai-sdk.d.cts +1 -1
- package/dist/ai/ai-sdk.d.ts +1 -1
- package/dist/ai/ai-sdk.js +11 -9
- package/dist/ai/ai-sdk.js.map +1 -1
- package/dist/ai/index.cjs +19 -17
- package/dist/ai/index.d.cts +1 -1
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.js +11 -9
- package/dist/browser.cjs +13 -11
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +11 -9
- package/dist/browser.js.map +1 -1
- package/dist/chunk-2KTQ75LN.js +67 -0
- package/dist/chunk-2KTQ75LN.js.map +1 -0
- package/dist/chunk-3KRL2EGN.cjs +70 -0
- package/dist/chunk-3KRL2EGN.cjs.map +1 -0
- package/dist/{chunk-YWDODCW2.js → chunk-3M6T7KB4.js} +60 -14
- package/dist/chunk-3M6T7KB4.js.map +1 -0
- package/dist/{chunk-OIZ4MYSF.cjs → chunk-3M6WB62Y.cjs} +43 -9
- package/dist/chunk-3M6WB62Y.cjs.map +1 -0
- package/dist/{chunk-KVP7AORH.js → chunk-6IGSKU6D.js} +61 -12
- package/dist/chunk-6IGSKU6D.js.map +1 -0
- package/dist/{chunk-JDBG5DU2.js → chunk-6OSUNBZY.js} +43 -9
- package/dist/chunk-6OSUNBZY.js.map +1 -0
- package/dist/{chunk-O5POCPXZ.cjs → chunk-EGSUMHCS.cjs} +21 -10
- package/dist/chunk-EGSUMHCS.cjs.map +1 -0
- package/dist/{chunk-5FF2IT3C.js → chunk-IBRW3UOA.js} +51 -10
- package/dist/chunk-IBRW3UOA.js.map +1 -0
- package/dist/{chunk-LPKVIRYT.js → chunk-JHDR56XO.js} +18 -9
- package/dist/chunk-JHDR56XO.js.map +1 -0
- package/dist/{chunk-Z5NGIM4Z.js → chunk-KWQTF6ZL.js} +30 -13
- package/dist/chunk-KWQTF6ZL.js.map +1 -0
- package/dist/{chunk-WCAADEXJ.cjs → chunk-N3SLYVNW.cjs} +83 -418
- package/dist/chunk-N3SLYVNW.cjs.map +1 -0
- package/dist/{chunk-GZY4CJ23.cjs → chunk-N7W5KZK7.cjs} +51 -10
- package/dist/chunk-N7W5KZK7.cjs.map +1 -0
- package/dist/chunk-PIV2A3HG.js +55 -0
- package/dist/chunk-PIV2A3HG.js.map +1 -0
- package/dist/chunk-SBB6C4OP.cjs +57 -0
- package/dist/chunk-SBB6C4OP.cjs.map +1 -0
- package/dist/{chunk-DHHVYSQX.cjs → chunk-SMXU3KYA.cjs} +38 -21
- package/dist/chunk-SMXU3KYA.cjs.map +1 -0
- package/dist/{chunk-K6RAUXRQ.cjs → chunk-TZTCIAYW.cjs} +7 -6
- package/dist/chunk-TZTCIAYW.cjs.map +1 -0
- package/dist/{chunk-4SJSIJK2.js → chunk-UBTKM2TB.js} +81 -416
- package/dist/chunk-UBTKM2TB.js.map +1 -0
- package/dist/{chunk-6WORZSL3.cjs → chunk-VFZOPRQP.cjs} +60 -14
- package/dist/chunk-VFZOPRQP.cjs.map +1 -0
- package/dist/{chunk-E2EJRVWS.cjs → chunk-VITE3MZQ.cjs} +61 -12
- package/dist/chunk-VITE3MZQ.cjs.map +1 -0
- package/dist/{chunk-WHNIK4LK.js → chunk-VJGMEGMR.js} +7 -6
- package/dist/chunk-VJGMEGMR.js.map +1 -0
- package/dist/{chunk-3MJKJX27.cjs → chunk-VZ5LDNHK.cjs} +18 -9
- package/dist/chunk-VZ5LDNHK.cjs.map +1 -0
- package/dist/{chunk-6XGSEG3K.js → chunk-ZL5RB4UV.js} +21 -10
- package/dist/chunk-ZL5RB4UV.js.map +1 -0
- package/dist/diagrams/blockdiagram/index.d.cts +1 -1
- package/dist/diagrams/blockdiagram/index.d.ts +1 -1
- package/dist/diagrams/circuit/index.d.cts +1 -1
- package/dist/diagrams/circuit/index.d.ts +1 -1
- package/dist/diagrams/ecomap/index.cjs +7 -6
- package/dist/diagrams/ecomap/index.d.cts +1 -1
- package/dist/diagrams/ecomap/index.d.ts +1 -1
- package/dist/diagrams/ecomap/index.js +2 -1
- package/dist/diagrams/entity/index.d.cts +1 -1
- package/dist/diagrams/entity/index.d.ts +1 -1
- package/dist/diagrams/fishbone/index.cjs +8 -7
- package/dist/diagrams/fishbone/index.d.cts +1 -1
- package/dist/diagrams/fishbone/index.d.ts +1 -1
- package/dist/diagrams/fishbone/index.js +2 -1
- package/dist/diagrams/flowchart/index.cjs +8 -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 +2 -1
- package/dist/diagrams/genogram/index.cjs +9 -8
- package/dist/diagrams/genogram/index.d.cts +1 -1
- package/dist/diagrams/genogram/index.d.ts +1 -1
- package/dist/diagrams/genogram/index.js +2 -1
- package/dist/diagrams/ladder/index.cjs +7 -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 +3 -1
- package/dist/diagrams/logic/index.d.cts +1 -1
- package/dist/diagrams/logic/index.d.ts +1 -1
- package/dist/diagrams/orgchart/index.d.cts +1 -1
- package/dist/diagrams/orgchart/index.d.ts +1 -1
- package/dist/diagrams/pedigree/index.cjs +7 -6
- package/dist/diagrams/pedigree/index.d.cts +1 -1
- package/dist/diagrams/pedigree/index.d.ts +1 -1
- package/dist/diagrams/pedigree/index.js +2 -1
- package/dist/diagrams/phylo/index.d.cts +1 -1
- package/dist/diagrams/phylo/index.d.ts +1 -1
- package/dist/diagrams/sld/index.cjs +7 -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 +3 -1
- package/dist/diagrams/sociogram/index.d.cts +1 -1
- package/dist/diagrams/sociogram/index.d.ts +1 -1
- package/dist/diagrams/timing/index.d.cts +1 -1
- package/dist/diagrams/timing/index.d.ts +1 -1
- package/dist/diagrams/venn/index.d.cts +1 -1
- package/dist/diagrams/venn/index.d.ts +1 -1
- package/dist/{index-CGK0xVls.d.ts → index-BeUVaQiD.d.ts} +1 -2
- package/dist/{index-OW8eDrKj.d.cts → index-DYpJXJcy.d.cts} +1 -2
- package/dist/index.cjs +23 -21
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +10 -8
- package/dist/react.cjs +11 -9
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +10 -8
- package/dist/react.js.map +1 -1
- package/dist/{types-Gkyab1sL.d.ts → types-DKdo-Ua_.d.cts} +1 -1
- package/dist/{types-Gkyab1sL.d.cts → types-DKdo-Ua_.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3MJKJX27.cjs.map +0 -1
- package/dist/chunk-4SJSIJK2.js.map +0 -1
- package/dist/chunk-5FF2IT3C.js.map +0 -1
- package/dist/chunk-6WORZSL3.cjs.map +0 -1
- package/dist/chunk-6XGSEG3K.js.map +0 -1
- package/dist/chunk-DHHVYSQX.cjs.map +0 -1
- package/dist/chunk-E2EJRVWS.cjs.map +0 -1
- package/dist/chunk-GZY4CJ23.cjs.map +0 -1
- package/dist/chunk-JDBG5DU2.js.map +0 -1
- package/dist/chunk-K6RAUXRQ.cjs.map +0 -1
- package/dist/chunk-KVP7AORH.js.map +0 -1
- package/dist/chunk-LPKVIRYT.js.map +0 -1
- package/dist/chunk-O5POCPXZ.cjs.map +0 -1
- package/dist/chunk-OIZ4MYSF.cjs.map +0 -1
- package/dist/chunk-WCAADEXJ.cjs.map +0 -1
- package/dist/chunk-WHNIK4LK.js.map +0 -1
- package/dist/chunk-YWDODCW2.js.map +0 -1
- package/dist/chunk-Z5NGIM4Z.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parse, render } from './chunk-
|
|
1
|
+
import { parse, render } from './chunk-KWQTF6ZL.js';
|
|
2
2
|
|
|
3
3
|
// src/ai/registry.ts
|
|
4
4
|
var DIAGRAM_REGISTRY = [
|
|
@@ -263,19 +263,37 @@ function getAllDiagramTypes() {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
// src/ai/errors.ts
|
|
266
|
+
var ENGINE_BUG_NAMES = /* @__PURE__ */ new Set([
|
|
267
|
+
"ReferenceError",
|
|
268
|
+
"TypeError",
|
|
269
|
+
"RangeError"
|
|
270
|
+
]);
|
|
266
271
|
function extractError(err) {
|
|
267
272
|
if (err instanceof Error) {
|
|
268
273
|
const anyErr = err;
|
|
274
|
+
const hasParseFields = typeof anyErr.line === "number";
|
|
275
|
+
const isEngineBug = !hasParseFields && ENGINE_BUG_NAMES.has(err.name);
|
|
276
|
+
const sourceHint = isEngineBug ? firstStackFrame(err.stack) : typeof anyErr.source === "string" ? anyErr.source : void 0;
|
|
269
277
|
return {
|
|
270
278
|
line: typeof anyErr.line === "number" ? anyErr.line : void 0,
|
|
271
279
|
column: typeof anyErr.column === "number" ? anyErr.column : void 0,
|
|
272
|
-
source:
|
|
273
|
-
message: err.message,
|
|
274
|
-
hint: typeof anyErr.hint === "string" ? anyErr.hint : void 0
|
|
280
|
+
source: sourceHint,
|
|
281
|
+
message: isEngineBug ? `[engine bug: ${err.name}] ${err.message}` : err.message,
|
|
282
|
+
hint: typeof anyErr.hint === "string" ? anyErr.hint : isEngineBug ? "This looks like a Schematex internal error rather than a DSL syntax problem. Please file an issue with the failing DSL at https://github.com/SchemaTex/Schematex/issues." : void 0
|
|
275
283
|
};
|
|
276
284
|
}
|
|
277
285
|
return { message: String(err) };
|
|
278
286
|
}
|
|
287
|
+
function firstStackFrame(stack) {
|
|
288
|
+
if (!stack) return void 0;
|
|
289
|
+
for (const line of stack.split("\n")) {
|
|
290
|
+
const trimmed = line.trim();
|
|
291
|
+
if (trimmed.startsWith("at ")) {
|
|
292
|
+
return trimmed.replace(/\((?:.*\/)?([^/]+)\)/, "($1)");
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return void 0;
|
|
296
|
+
}
|
|
279
297
|
|
|
280
298
|
// src/ai/_generated.ts
|
|
281
299
|
var EXAMPLES = [
|
|
@@ -437,43 +455,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
437
455
|
"dsl": 'circuit "CE Amp (netlist)" netlist\nV1 vcc 0 9V\nRc vcc c 2.2k\nRb vcc b 100k\nQ1 c b e npn\nRe e 0 1k',
|
|
438
456
|
"notes": '## Scenario\n\nThe NPN common-emitter amplifier is the first transistor circuit every electronics student builds. Schematex renders it from a five-line SPICE netlist \u2014 the same format used in LTspice, ngspice, and Cadence \u2014 with automatic component placement and rail routing, so the diagram matches the hand-drawn textbook version without any manual layout.\n\n## Annotation key\n\n- `circuit "..." netlist` \u2014 enables netlist parsing mode (SPICE syntax)\n- `V1 vcc 0 9V` \u2014 voltage source named V1, positive terminal at node `vcc`, negative at `0` (ground), value 9V\n- `Rc vcc c 2.2k` \u2014 resistor Rc between nodes `vcc` and `c` with value 2.2 k\u03A9\n- `Rb vcc b 100k` \u2014 base bias resistor between `vcc` and node `b`\n- `Q1 c b e npn` \u2014 NPN BJT transistor: collector=c, base=b, emitter=e\n- `Re e 0 1k` \u2014 emitter degeneration resistor between node `e` and ground\n\n## How to read\n\nThe supply rail (Vcc = 9 V) connects to the top of both resistors. Rc is the collector load; the output signal is taken across it. Rb biases the base into the active region. Re provides emitter degeneration for stability. Q1 amplifies a small base current into a large collector-to-emitter current flow. The auto-layout positions Vcc at top, ground at bottom, and Q1 in the center.'
|
|
439
457
|
},
|
|
440
|
-
{
|
|
441
|
-
"slug": "decisiontree-buy-vs-lease-ev",
|
|
442
|
-
"diagram": "decisiontree",
|
|
443
|
-
"title": "Buy vs. lease an electric vehicle",
|
|
444
|
-
"description": "Howard-Raiffa expected-value tree for the buy/lease/used-EV decision \u2014 with resale probability and incentive chance nodes.",
|
|
445
|
-
"standard": "Raiffa & Schlaifer (1961)",
|
|
446
|
-
"tags": [
|
|
447
|
-
"decision-analysis",
|
|
448
|
-
"ev",
|
|
449
|
-
"buy-vs-lease",
|
|
450
|
-
"expected-value",
|
|
451
|
-
"consumer"
|
|
452
|
-
],
|
|
453
|
-
"complexity": 3,
|
|
454
|
-
"featured": false,
|
|
455
|
-
"dsl": 'decisiontree:decision "EV Acquisition Decision"\n\ndecision "Which acquisition path?"\n choice "Buy new EV"\n chance "Federal tax credit eligible?"\n prob 0.7 chance "Resale market in 5yr (w/ credit)"\n prob 0.55 end "Strong resale + credit" payoff=28500\n prob 0.45 end "Weak resale + credit" payoff=16000\n prob 0.3 chance "Resale market in 5yr (no credit)"\n prob 0.55 end "Strong resale, no credit" payoff=21000\n prob 0.45 end "Weak resale, no credit" payoff=8500\n choice "Lease EV 3yr"\n end "Predictable lease cost" payoff=14000\n choice "Buy used EV"\n chance "Battery health \u2265 80%?"\n prob 0.6 end "Good battery \u2014 low TCO" payoff=22000\n prob 0.4 end "Battery replacement needed" payoff=8000',
|
|
456
|
-
"notes": '## Scenario\n\nA household is choosing between three electric vehicle acquisition paths: buying new (eligible for a $7,500 federal tax credit with 70% probability, depending on income and vehicle MSRP cap), leasing for three years at a fixed all-in cost, or buying used. The buy-new path carries two sequential chance nodes \u2014 credit eligibility then a five-year resale market outcome \u2014 while used carries battery-health uncertainty. Payoffs represent net five-year economic value (savings versus equivalent ICE ownership, residual value, minus acquisition and maintenance costs).\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; actor chooses a branch\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; nature chooses; `prob N` on children must sum to 1\n- `end "\u2026" payoff=N` \u2014 terminal leaf with net five-year economic value in dollars\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nRoll back from leaves to root. Buy-new EV (with credit branch): 0.55 \xD7 28,500 + 0.45 \xD7 16,000 = **24,075**; without credit: 0.55 \xD7 21,000 + 0.45 \xD7 8,500 = **19,275**. Combined: 0.7 \xD7 24,075 + 0.3 \xD7 19,275 = **22,635**. Lease: flat **14,000**. Used EV: 0.6 \xD7 22,000 + 0.4 \xD7 8,000 = **16,400**. Under these assumptions *Buy new EV* dominates, largely because the 70% credit probability shifts the overall EV substantially upward. Sensitivity analysis on credit eligibility probability and the five-year resale spread is where the real MBA discussion lives.'
|
|
457
|
-
},
|
|
458
|
-
{
|
|
459
|
-
"slug": "decisiontree-go-nogo-product",
|
|
460
|
-
"diagram": "decisiontree",
|
|
461
|
-
"title": "Product launch go/no-go decision",
|
|
462
|
-
"description": "Stage-gate launch decision with market-size chance node, competitor-response chance, and NPV terminal values for a PM strategy review.",
|
|
463
|
-
"standard": "Raiffa & Schlaifer (1961)",
|
|
464
|
-
"tags": [
|
|
465
|
-
"launch",
|
|
466
|
-
"go-nogo",
|
|
467
|
-
"npv",
|
|
468
|
-
"strategy",
|
|
469
|
-
"product",
|
|
470
|
-
"chance"
|
|
471
|
-
],
|
|
472
|
-
"complexity": 3,
|
|
473
|
-
"featured": false,
|
|
474
|
-
"dsl": 'decisiontree:decision "Product Launch Strategy"\n\ndecision "Launch strategy?"\n choice "Launch Q1 (full)"\n chance "Market reception"\n prob 0.4 chance "Competitor copies within 6mo? (strong)"\n prob 0.5 end "Strong + copied" payoff=3200000\n prob 0.5 end "Strong + defended" payoff=5800000\n prob 0.35 chance "Competitor copies within 6mo? (moderate)"\n prob 0.5 end "Moderate + copied" payoff=1400000\n prob 0.5 end "Moderate + defended" payoff=2600000\n prob 0.25 end "Weak reception" payoff=400000\n choice "Launch Q3 (scoped)"\n chance "Market reception (scoped)"\n prob 0.45 end "Strong scoped" payoff=3100000\n prob 0.35 end "Moderate scoped" payoff=1800000\n prob 0.20 end "Weak scoped" payoff=600000\n choice "No launch"\n end "Saved development cost" payoff=900000',
|
|
475
|
-
"notes": '## Scenario\n\nA PM team is evaluating three paths ahead of an annual planning cycle: a full Q1 launch with the complete feature set, a scoped Q3 launch targeting the highest-confidence segments, and a no-launch option that recovers the estimated development spend. The Q1 full-launch path carries two sequential chance nodes \u2014 market reception (strong/moderate/weak) followed, for the non-weak outcomes, by a competitor-response chance (copies vs. defends). Payoffs are five-year NPV estimates in dollars, net of launch and ongoing operating costs.\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; PM team chooses a branch\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; market or competitor behavior; `prob N` sums to 1 per node\n- `end "\u2026" payoff=N` \u2014 terminal leaf with five-year NPV in dollars\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nFor Q1 full launch: strong-reception EV = 0.5 \xD7 3,200,000 + 0.5 \xD7 5,800,000 = **4,500,000**; moderate EV = 0.5 \xD7 1,400,000 + 0.5 \xD7 2,600,000 = **2,000,000**. Full-launch EV = 0.40 \xD7 4,500,000 + 0.35 \xD7 2,000,000 + 0.25 \xD7 400,000 = **2,600,000**. Scoped-Q3 EV = 0.45 \xD7 3,100,000 + 0.35 \xD7 1,800,000 + 0.20 \xD7 600,000 = **2,118,000**. No launch: **900,000**. Q1 full launch produces the highest EV, but the moderate-reception + copied scenario at $1.4M is a painful downside worth stress-testing \u2014 reducing competitor copy probability from 0.5 to 0.3 in that branch raises the EV meaningfully and may justify a launch accelerator investment.'
|
|
476
|
-
},
|
|
477
458
|
{
|
|
478
459
|
"slug": "decisiontree-investment-analysis",
|
|
479
460
|
"diagram": "decisiontree",
|
|
@@ -492,44 +473,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
492
473
|
"dsl": 'decisiontree:decision "Platform Vendor Choice"\n\ndecision "Which vendor?"\n choice "Build in-house"\n chance "Project outcome"\n prob 0.6 end "On-time delivery" payoff=900000\n prob 0.4 end "Over budget / delayed" payoff=150000\n choice "Managed SaaS vendor"\n end "Predictable cost" payoff=500000\n choice "Hybrid approach"\n chance "Integration complexity"\n prob 0.5 end "Smooth integration" payoff=700000\n prob 0.5 end "Integration rework" payoff=300000',
|
|
493
474
|
"notes": '## Scenario\n\nA CTO is deciding how to stand up a new data-platform layer: build internally, buy managed SaaS, or take a hybrid. Each path has outcomes with probabilities and net-value estimates. The decision-analysis tree rolls the expected value back to the decision node so the optimal branch is identified automatically.\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 actor chooses a branch\n- `chance "\u2026"` \u2014 nature chooses; `prob N` on each child (must sum to 1)\n- `end "\u2026" payoff=N` \u2014 terminal payoff\n- `choice "label"` \u2014 label on an outgoing decision branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV\n\n## How to read\n\nEvaluate each branch\'s expected value. Build in-house: 0.6 \xD7 900k + 0.4 \xD7 150k = **600k**. Managed SaaS: flat **500k**. Hybrid: 0.5 \xD7 700k + 0.5 \xD7 300k = **500k**. Under these estimates the optimal branch is *Build in-house* \u2014 the parser flags it on render. The chart\'s real value is in forcing stakeholders to state probabilities explicitly; sensitivity to them is where the interesting argument happens.'
|
|
494
475
|
},
|
|
495
|
-
{
|
|
496
|
-
"slug": "decisiontree-iris-sklearn",
|
|
497
|
-
"diagram": "decisiontree",
|
|
498
|
-
"title": "Iris species classifier (scikit-learn CART)",
|
|
499
|
-
"description": "The classic sklearn Iris CART decision tree \u2014 three species, two splits on petal length and width, rendered from a functional ML-tree description.",
|
|
500
|
-
"standard": "Breiman CART (1984)",
|
|
501
|
-
"tags": [
|
|
502
|
-
"cart",
|
|
503
|
-
"sklearn",
|
|
504
|
-
"iris",
|
|
505
|
-
"classification",
|
|
506
|
-
"ml",
|
|
507
|
-
"decision-tree"
|
|
508
|
-
],
|
|
509
|
-
"complexity": 2,
|
|
510
|
-
"featured": false,
|
|
511
|
-
"dsl": 'decisiontree:ml "Iris Classifier"\n\nsplit "petal length (cm) \u2264 2.45"\n true leaf "Setosa" [support=50, impurity=0.0, class=setosa]\n false split "petal width (cm) \u2264 1.75"\n true leaf "Versicolor" [support=47, impurity=0.168, class=versicolor]\n false leaf "Virginica" [support=45, impurity=0.043, class=virginica]',
|
|
512
|
-
"notes": '## Scenario\n\nThe Iris dataset \u2014 150 samples of three species (Iris setosa, versicolor, and virginica) measured across four features \u2014 is the canonical teaching example for classification. A CART tree trained with scikit-learn `DecisionTreeClassifier(max_depth=2)` produces exactly this two-level tree. Setosa is perfectly linearly separable on petal length alone; versicolor and virginica require a second split on petal width. The resulting tree achieves ~96% cross-validated accuracy.\n\n## Annotation key\n\n- `split "condition"` \u2014 internal node; routes left (`true`) when condition holds, right (`false`) when it does not\n- `true` / `false` \u2014 branch direction prefix indicating which child is reached when the split condition evaluates to that boolean\n- `leaf "label"` \u2014 terminal classification node\n- `[support=N]` \u2014 number of training samples reaching this leaf\n- `[impurity=N]` \u2014 Gini impurity at the node (0 = pure, 0.5 = maximally impure for binary)\n- `[class=\u2026]` \u2014 majority class label at the leaf\n\n## How to read\n\nStart at the root split. If petal length \u2264 2.45 cm, the sample is classified as **Setosa** immediately (Gini = 0, perfectly pure \u2014 all 50 setosa training samples land here). Otherwise, evaluate petal width: \u2264 1.75 cm predicts **Versicolor** (47 samples, Gini = 0.168 \u2014 a small number of virginica blur this boundary); > 1.75 cm predicts **Virginica** (45 samples, Gini = 0.043 \u2014 nearly pure). This tree is shallow enough to fit on an index card and remains the first model every ML course deploys.'
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
"slug": "decisiontree-litigation-settle",
|
|
516
|
-
"diagram": "decisiontree",
|
|
517
|
-
"title": "Litigation vs. settlement analysis",
|
|
518
|
-
"description": "Expected-value analysis of settling a $2M breach-of-contract claim vs. going to trial \u2014 with verdict probability and appeal chance nodes.",
|
|
519
|
-
"standard": "Raiffa & Schlaifer (1961)",
|
|
520
|
-
"tags": [
|
|
521
|
-
"litigation",
|
|
522
|
-
"settlement",
|
|
523
|
-
"legal",
|
|
524
|
-
"expected-value",
|
|
525
|
-
"trial",
|
|
526
|
-
"appeal"
|
|
527
|
-
],
|
|
528
|
-
"complexity": 3,
|
|
529
|
-
"featured": false,
|
|
530
|
-
"dsl": 'decisiontree:decision "Litigation Strategy"\n\ndecision "Litigation strategy?"\n choice "Settle now"\n end "Settlement payment" payoff=-350000\n choice "Proceed to trial"\n chance "Verdict"\n prob 0.55 chance "Plaintiff appeals? (defense wins)"\n prob 0.3 chance "Appeal outcome"\n prob 0.4 end "Reversed on appeal" payoff=0\n prob 0.6 end "Upheld on appeal" payoff=-2200000\n prob 0.7 end "No appeal \u2014 defense prevails" payoff=0\n prob 0.45 end "Plaintiff verdict \u2014 damages + fees" payoff=-2000000',
|
|
531
|
-
"notes": '## Scenario\n\nA corporate defendant faces a $2 million breach-of-contract claim. Outside counsel has assessed a 55% probability of a defense verdict at trial and a 45% probability of a plaintiff verdict (full damages plus attorney fees). If the defense wins, there is a 30% chance the plaintiff appeals; an appeal resolves with a 40% probability of reversal (cost: zero) and a 60% probability of affirmance, which adds appellate costs bringing total exposure to $2.2M. The client can alternatively settle immediately for $350,000. All payoffs are expressed as costs to the defendant (negative = outflow).\n\n## Annotation key\n\n- `decision "\u2026"` \u2014 decision node; counsel and client choose the path\n- `choice "\u2026"` \u2014 label on a decision branch\n- `chance "\u2026"` \u2014 chance node; court or opposing party behavior; `prob N` sums to 1\n- `end "\u2026" payoff=N` \u2014 terminal leaf; negative values represent costs to defendant\n- `prob N` \u2014 probability (0\u20131) on a chance branch\n- EV rollback: chance = probability-weighted sum; decision = max child EV (least negative)\n\n## How to read\n\nRoll back from leaves. Appeal-outcome EV: 0.4 \xD7 0 + 0.6 \xD7 \u22122,200,000 = **\u22121,320,000**. Defense-wins-verdict branch EV: 0.3 \xD7 \u22121,320,000 + 0.7 \xD7 0 = **\u2212396,000**. Trial EV: 0.55 \xD7 \u2212396,000 + 0.45 \xD7 \u22122,000,000 = **\u22121,117,800**. Settlement: **\u2212350,000**. Under these probability estimates, settling for $350,000 is the rational choice \u2014 it avoids the \u2212$1.12M expected cost of going to trial. The key sensitivity is the defense-verdict probability: if counsel is more than ~75% confident of winning at trial, the EV of proceeding drops below \u2212350,000 and trial becomes preferred.'
|
|
532
|
-
},
|
|
533
476
|
{
|
|
534
477
|
"slug": "decisiontree-support-triage",
|
|
535
478
|
"diagram": "decisiontree",
|
|
@@ -548,45 +491,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
548
491
|
"dsl": 'decisiontree "Customer Support Triage"\ndirection: top-down\n\nquestion "Is the service completely down?"\n yes: question "Outage confirmed on status page?"\n yes: answer "Follow incident protocol \u2014 page on-call"\n no: answer "Check monitoring \u2014 open severity-1 ticket"\n no: question "Is the issue affecting billing?"\n yes: answer "Escalate to billing team \u2014 SLA breach risk"\n no: question "Can user reproduce consistently?"\n yes: answer "Collect HAR trace \u2014 file bug report"\n no: answer "Ask for screenshot \u2014 watch for recurrence"',
|
|
549
492
|
"notes": '## Scenario\n\nThe support lead bakes this tree into the agent runbook so new hires can triage in week one without a buddy. Three gates \u2014 outage, billing, reproducibility \u2014 route 90% of tickets deterministically. The remaining 10% (edge cases, multi-category) get flagged for human escalation instead of guessed at.\n\n## Annotation key\n\n- `question "text"` \u2014 internal decision node\n- `answer "text"` \u2014 terminal outcome\n- `yes:` / `no:` \u2014 branch label\n- Indentation (2 spaces) \u2014 parent-child nesting\n\n## How to read\n\nStart at the root. At each `question` node the agent answers yes or no and follows the matching branch. Every path terminates in an `answer` \u2014 a concrete next action, not another decision. The tree is deliberately shallow (max depth 3) so agents can hold it in their head; deeper branches would push into a runbook rather than a decision tree.'
|
|
550
493
|
},
|
|
551
|
-
{
|
|
552
|
-
"slug": "decisiontree-triage-chest-pain",
|
|
553
|
-
"diagram": "decisiontree",
|
|
554
|
-
"title": "ED chest pain triage",
|
|
555
|
-
"description": "Emergency department chest-pain triage algorithm \u2014 HEART score pathway, STEMI/NSTEMI rule-out, and disposition decision for the ED physician.",
|
|
556
|
-
"standard": "AHA/ACC 2021 Chest Pain Guidelines",
|
|
557
|
-
"tags": [
|
|
558
|
-
"triage",
|
|
559
|
-
"chest-pain",
|
|
560
|
-
"ed",
|
|
561
|
-
"stemi",
|
|
562
|
-
"heart-score",
|
|
563
|
-
"clinical",
|
|
564
|
-
"aha"
|
|
565
|
-
],
|
|
566
|
-
"complexity": 4,
|
|
567
|
-
"featured": false,
|
|
568
|
-
"dsl": 'decisiontree:taxonomy "ED Chest Pain Triage"\n\nquestion "ECG: ST elevation present?"\n yes: answer "Activate cath lab \u2014 STEMI protocol"\n no: question "Troponin elevated at 0h or 3h?"\n yes: question "Dynamic troponin rise (\u2265 3 ng/L delta)?"\n yes: answer "NSTEMI confirmed \u2014 cardiology consult, anticoagulate"\n no: answer "Possible NSTEMI \u2014 repeat troponin at 6h"\n no: question "HEART score \u2265 4?"\n yes: answer "High risk \u2014 observation unit + stress test or CTA"\n no: question "All low-risk features present?"\n yes: answer "Discharge \u2014 outpatient follow-up within 72h"\n no: answer "Observation \u2014 shared decision making with patient"',
|
|
569
|
-
"notes": '## Scenario\n\nChest pain accounts for roughly 8 million ED visits per year in the United States. The AHA/ACC 2021 Chest Pain Guidelines provide a tiered rule-out pathway: first exclude STEMI via ECG, then use high-sensitivity troponin at 0h and 3h to distinguish NSTEMI from unstable angina or non-cardiac causes, and finally apply the HEART score (History, ECG, Age, Risk factors, Troponin) to stratify remaining patients into high-risk observation vs. safe discharge. This tree encodes the core algorithmic structure for a busy ED attending.\n\n## Annotation key\n\n- `question "\u2026"` \u2014 internal clinical decision node; physician evaluates the criterion\n- `answer "\u2026"` \u2014 terminal disposition or action\n- `yes:` / `no:` \u2014 branch label indicating the clinical finding\n- HEART score: 0\u20133 low risk, 4\u20136 moderate, 7\u201310 high risk\n- Dynamic troponin: delta \u2265 3 ng/L between 0h and 3h draws meets ESC high-sensitivity criterion\n\n## How to read\n\nEntry is the 12-lead ECG. ST elevation routes directly to cath-lab activation \u2014 time is myocardium and no further branching is needed. Absence of ST elevation triggers the troponin pathway: a positive draw at either time point prompts delta assessment to distinguish true NSTEMI from a chronic elevation; a negative troponin advances to HEART score stratification. A score of 4 or higher mandates observation-unit admission with functional testing; a score below 4 with all low-risk clinical features present supports discharge with prompt outpatient follow-up. The final branch \u2014 observation with shared decision making \u2014 captures the borderline-HEART-score patient where physician judgment, patient preference, and social circumstances all contribute to disposition.'
|
|
570
|
-
},
|
|
571
|
-
{
|
|
572
|
-
"slug": "decisiontree-xgboost-churn",
|
|
573
|
-
"diagram": "decisiontree",
|
|
574
|
-
"title": "Customer churn prediction tree (XGBoost)",
|
|
575
|
-
"description": "One tree from an XGBoost churn model \u2014 days since last login, MRR tier, support tickets \u2014 showing how gradient boosting splits differ from CART.",
|
|
576
|
-
"standard": "Chen & Guestrin XGBoost (2016)",
|
|
577
|
-
"tags": [
|
|
578
|
-
"xgboost",
|
|
579
|
-
"churn",
|
|
580
|
-
"ml",
|
|
581
|
-
"gradient-boosting",
|
|
582
|
-
"saas",
|
|
583
|
-
"prediction"
|
|
584
|
-
],
|
|
585
|
-
"complexity": 3,
|
|
586
|
-
"featured": false,
|
|
587
|
-
"dsl": 'decisiontree:ml "Churn Prediction Tree (XGBoost)"\n\nsplit "days_since_login > 21"\n true split "mrr_tier < 2"\n true leaf "High churn risk" [score=0.72, class=churn]\n false leaf "Medium risk \u2014 monitor" [score=0.41, class=churn]\n false split "support_tickets_30d > 3"\n true leaf "Medium risk \u2014 support-driven" [score=0.38, class=churn]\n false leaf "Low churn risk" [score=0.09, class=retain]',
|
|
588
|
-
"notes": '## Scenario\n\nA SaaS company trains an XGBoost churn model on 90 days of product usage data. This is one representative tree from the ensemble, illustrating the three strongest churn signals in the dataset: recency of login (days since last login > 21 is the dominant split), MRR tier (lower-tier accounts churn faster when disengaged), and recent support ticket volume (elevated tickets correlate with frustration even among recently active users). Unlike a standalone CART tree, XGBoost trees output raw scores (log-odds contributions) that are summed across the ensemble before sigmoid transformation \u2014 the `score` values shown are per-tree contributions, not final probabilities.\n\n## Annotation key\n\n- `split "condition"` \u2014 internal split node; `true` branch when condition holds\n- `true` / `false` \u2014 branch direction prefix\n- `leaf "label"` \u2014 terminal node with a descriptive risk label\n- `[score=N]` \u2014 raw XGBoost leaf score (log-odds contribution from this tree)\n- `[class=\u2026]` \u2014 dominant class assignment at this leaf\n- XGBoost does not use Gini/entropy impurity; splits are chosen to maximize second-order gradient gain\n\n## How to read\n\nStart at the root. Accounts with more than 21 days since last login are immediately flagged: if they are also on MRR tier 0 or 1 (lowest-value tiers), the leaf score is 0.72 \u2014 the highest churn signal in this tree. High-tier disengaged accounts score 0.41, indicating meaningful but lower risk, consistent with higher switching costs. For recently active accounts (login \u2264 21 days), elevated support tickets (> 3 in 30 days) push score to 0.38 \u2014 a product-experience alert \u2014 while accounts that are both active and support-quiet score 0.09, the healthiest segment. In production, this tree\'s scores are summed with hundreds of sibling trees and passed through a sigmoid to yield a final churn probability between 0 and 1.'
|
|
589
|
-
},
|
|
590
494
|
{
|
|
591
495
|
"slug": "ecomap-refugee-resettlement",
|
|
592
496
|
"diagram": "ecomap",
|
|
@@ -806,63 +710,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
806
710
|
"dsl": 'fishbone "Fishbone diagram \u2014 Website traffic drop"\n\neffect "Traffic decline"\n\ncategory content "Content"\ncategory tech "Technical"\ncategory links "Backlinks"\ncategory ux "UX"\ncategory competition "Competition"\ncategory algo "Algorithm"\n\ncontent : "Publishing frequency down"\ncontent : "Content too generic"\ncontent : "Keyword gaps"\ncontent : "Low-quality AI content"\n\ntech : "Core Web Vitals failing"\ntech : "Crawl coverage drop"\ntech : "Crawler blocked by WAF"\ntech : "Missing structured data"\n\nlinks : "High-quality backlinks lost"\nlinks : "High ratio of low-quality links"\nlinks : "Referring domain growth stalled"\nlinks : "Low anchor text diversity"\n\nux : "Bounce rate rising"\nux : "Poor mobile experience"\nux : "Slow above-fold load"\nux : "Excessive popup ads"\n\ncompetition : "New competitors entering"\ncompetition : "AI tools replacing search"\ncompetition : "Weakening brand recall"\ncompetition : "Competitors publishing faster"\n\nalgo : "Core Update penalty"\nalgo : "Weak E-E-A-T signals"\nalgo : "AI Overviews / SGE cutoff"\nalgo : "Search intent drift"',
|
|
807
711
|
"notes": '## Scenario\n\nAn ops lead runs a growth post-mortem after a 30% organic traffic drop. The Ishikawa (fishbone) diagram structures the team\'s brainstorm into six standard causal categories, preventing the meeting from fixating on the most vocal hypothesis while ignoring systemic causes. The completed diagram becomes the project brief for the remediation sprint.\n\n## Annotation key\n\n- `effect "..."` \u2014 the problem statement, placed at the fish\'s head (right side)\n- `category id "Label"` \u2014 defines a major causal branch (a "bone"); use a short `id` to assign causes\n- `id : "cause text"` \u2014 assigns a cause string to the named category branch\n- Each category renders as a diagonal rib pointing toward the effect\n- Sub-causes (second-order) can be added by nesting if the DSL supports it\n\n## How to read\n\nThe effect (traffic decline) sits at the right. Six causal ribs branch from the spine: Content, Technical, Backlinks, UX, Competition, and Algorithm. Each rib lists four specific hypotheses. In a workshop, the team votes on each cause, color-codes high-confidence ones, and converts the highest-priority items into action items. The diagram serves as both a brainstorming artifact and a living post-mortem document.'
|
|
808
712
|
},
|
|
809
|
-
{
|
|
810
|
-
"slug": "flowchart-algo-binary-search",
|
|
811
|
-
"diagram": "flowchart",
|
|
812
|
-
"title": "Binary search algorithm",
|
|
813
|
-
"description": "Iterative binary search over a sorted array \u2014 the classic CS teaching flowchart, from array + target input to found/not-found output.",
|
|
814
|
-
"standard": "ISO 5807:1985",
|
|
815
|
-
"tags": [
|
|
816
|
-
"algorithm",
|
|
817
|
-
"binary-search",
|
|
818
|
-
"teaching",
|
|
819
|
-
"cs",
|
|
820
|
-
"sorted-array",
|
|
821
|
-
"iterative"
|
|
822
|
-
],
|
|
823
|
-
"complexity": 2,
|
|
824
|
-
"featured": false,
|
|
825
|
-
"dsl": "flowchart TD\n input([Input: sorted array A, target T]) --> init[low = 0, high = n \u2212 1]\n init --> loopcheck{low \u2264 high?}\n loopcheck -->|No| notfound([Return \u22121 \u2014 target not found])\n loopcheck -->|Yes| mid[mid = floor((low + high) / 2)]\n mid --> eqcheck{A[mid] == T?}\n eqcheck -->|Yes| found([Return mid \u2014 target found at index mid])\n eqcheck -->|No| ltcheck{A[mid] < T?}\n ltcheck -->|Yes \u2014 search right half| newlow[low = mid + 1]\n newlow --> loopcheck\n ltcheck -->|No \u2014 search left half| newhigh[high = mid \u2212 1]\n newhigh --> loopcheck",
|
|
826
|
-
"notes": "## Scenario\n\nA CS teacher is preparing lecture slides on divide-and-conquer algorithms and wants a textbook-quality flowchart students can annotate alongside the pseudocode. The iterative formulation makes the loop invariant \u2014 the search space halving each iteration \u2014 visually explicit, and the two boundary-update branches give students a concrete mental model for why the algorithm runs in O(log n) time.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; algorithm entry with inputs and terminal return values\n- `{\u2026}` \u2014 diamond; loop-continuation test and value-comparison decisions\n- `[\u2026]` \u2014 rectangle; variable initialization and index update assignments\n- `-->|label|` \u2014 branch labels stating the condition outcome and which half is selected\n- Back edges from `newlow` and `newhigh` to `loopcheck` form the iterative loop body\n\n## How to read\n\nThe algorithm initializes two index pointers \u2014 `low` at zero and `high` at the last index \u2014 then enters the main loop gate. If `low` exceeds `high` the search space is exhausted and \u22121 is returned. Otherwise `mid` is computed as the floor average of the two pointers and the element at that index is compared to the target. An exact match terminates with the index; a mismatch routes to the less-than check, which moves `low` one past `mid` to discard the left half, or moves `high` one below `mid` to discard the right half. Either update sends control back to the loop gate, halving the remaining search space on every iteration."
|
|
827
|
-
},
|
|
828
|
-
{
|
|
829
|
-
"slug": "flowchart-approval-bpmn",
|
|
830
|
-
"diagram": "flowchart",
|
|
831
|
-
"title": "Purchase order approval",
|
|
832
|
-
"description": "Employee submits PO \u2192 manager review \u2192 finance approval \u2192 payment \u2014 BPMN gateway shapes for a business approval workflow.",
|
|
833
|
-
"standard": "ISO 5807:1985",
|
|
834
|
-
"tags": [
|
|
835
|
-
"approval",
|
|
836
|
-
"bpmn",
|
|
837
|
-
"purchase-order",
|
|
838
|
-
"workflow",
|
|
839
|
-
"finance",
|
|
840
|
-
"gateway"
|
|
841
|
-
],
|
|
842
|
-
"complexity": 2,
|
|
843
|
-
"featured": false,
|
|
844
|
-
"dsl": "flowchart TD\n submit([Employee submits purchase order]) --> amtcheck{Amount > $10,000?}\n amtcheck -->|Yes \u2014 CFO track| cfo[CFO review queue]\n amtcheck -->|No \u2014 standard track| mgr[Department manager review]\n mgr --> mapproved{Manager approved?}\n mapproved -->|No| revise[Request revision from employee]\n revise --> submit\n mapproved -->|Yes| cfo\n cfo --> capproved{CFO approved?}\n capproved -->|No| reject([Reject PO \u2014 notify employee with reason])\n capproved -->|Yes| finance[Finance processes payment]\n finance --> vendor[Send payment confirmation to vendor]\n vendor --> done([PO closed \u2014 archived to ERP])",
|
|
845
|
-
"notes": "## Scenario\n\nA business analyst is documenting a company's purchase order workflow to support an ERP implementation and audit readiness review. The diagram makes explicit the dollar-amount threshold that gates which approval track a PO enters, the revision loop that keeps rejected items in flight rather than discarding them, and the two possible terminal outcomes \u2014 closed PO or formal rejection with written rationale.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; employee-initiated event and terminal closure or rejection nodes\n- `{\u2026}` \u2014 diamond; BPMN-style exclusive gateways branching on amount threshold or approval decision\n- `[\u2026]` \u2014 rectangle; human review steps and system actions (payment, notification, archival)\n- `-->|label|` \u2014 branch label showing threshold condition or approval outcome\n- Loop from `revise` back to `submit` keeps the PO in flight through the standard track after revision\n\n## How to read\n\nEvery PO enters the amount-check gateway immediately after submission. Orders above ten thousand dollars skip manager review and go directly to the CFO queue; orders at or below the threshold must first receive manager approval. A manager rejection sends the PO back to the employee for revision, which re-enters the same gateway \u2014 the amount does not change, so revised orders under the threshold loop through manager review again. Once the CFO approves (either from the high-value track or an escalated standard-track PO), finance executes payment and notifies the vendor, closing the PO in the ERP. A CFO rejection terminates the flow with a formal notice to the employee."
|
|
846
|
-
},
|
|
847
|
-
{
|
|
848
|
-
"slug": "flowchart-auth-flow",
|
|
849
|
-
"diagram": "flowchart",
|
|
850
|
-
"title": "OAuth 2.0 authorization code + PKCE",
|
|
851
|
-
"description": "OAuth 2.0 authorization code flow with PKCE \u2014 the recommended grant for SPAs and mobile apps, per RFC 7636.",
|
|
852
|
-
"standard": "ISO 5807:1985",
|
|
853
|
-
"tags": [
|
|
854
|
-
"oauth",
|
|
855
|
-
"pkce",
|
|
856
|
-
"authorization-code",
|
|
857
|
-
"security",
|
|
858
|
-
"spa",
|
|
859
|
-
"rfc7636"
|
|
860
|
-
],
|
|
861
|
-
"complexity": 4,
|
|
862
|
-
"featured": false,
|
|
863
|
-
"dsl": 'flowchart LR\n subgraph "Client App"\n start([User initiates login]) --> gen[Generate code verifier + SHA-256 challenge]\n gen --> redirect[Redirect to authorization endpoint with challenge + state]\n callback[Receive authorization code] --> exchange[POST /token \u2014 code + code verifier]\n tokens[Store access + refresh tokens] --> bearer[Attach Bearer token to API request]\n end\n subgraph "Authorization Server"\n redirect --> login[Present login + consent UI]\n login --> consent{User consents?}\n consent -->|No| deny([Authorization denied \u2014 redirect with error])\n consent -->|Yes| issue[Issue authorization code \u2014 redirect to callback]\n issue --> callback\n exchange --> verify{code_challenge matches verifier hash?}\n verify -->|No| err([400 Bad Request \u2014 PKCE mismatch])\n verify -->|Yes| mint[Mint access token + refresh token]\n mint --> tokens\n end\n subgraph "Resource Server"\n bearer --> validate{Bearer token valid + not expired?}\n validate -->|No| unauth([401 Unauthorized])\n validate -->|Yes| data([Return protected resource])\n end',
|
|
864
|
-
"notes": '## Scenario\n\nA security engineer is reviewing a team\'s SPA authentication implementation against RFC 7636 to verify that the implicit grant has been fully removed in favor of authorization code with PKCE. The diagram makes the cryptographic handshake \u2014 code verifier generated client-side, challenge sent to the authorization server, verifier submitted at token exchange \u2014 visible alongside the three distinct server boundaries, helping reviewers confirm that no secret is ever stored in browser memory.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; user-initiated events and terminal success/error responses\n- `{\u2026}` \u2014 diamond; server-side validation gates (consent, PKCE hash match, token validity)\n- `[\u2026]` \u2014 rectangle; client or server processing steps\n- `subgraph "\u2026"` \u2014 trust boundary lanes for Client App, Authorization Server, and Resource Server\n- `-->|label|` \u2014 branch labels showing consent outcome or validation result\n\n## How to read\n\nThe flow starts in the Client App lane where the application generates a random code verifier and derives its SHA-256 challenge before redirecting the user. In the Authorization Server lane the user authenticates and consents; the server returns an authorization code bound to the challenge. The client then submits the original verifier in the token exchange request \u2014 the Authorization Server hashes it and compares it to the stored challenge, rejecting mismatches with a 400. Valid exchanges produce short-lived access and refresh tokens. The Resource Server lane shows the final step: every API call presents the Bearer token and the server validates its signature and expiry before returning data, enforcing a clean separation between authorization and resource access.'
|
|
865
|
-
},
|
|
866
713
|
{
|
|
867
714
|
"slug": "flowchart-cicd-pipeline",
|
|
868
715
|
"diagram": "flowchart",
|
|
@@ -881,62 +728,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
881
728
|
"dsl": "flowchart TD\n commit([Push to main]) --> build[Build artifact]\n build --> unit{Unit tests pass?}\n unit -->|No| fail([Fail build])\n unit -->|Yes| scan[Security scan]\n scan --> vuln{High-severity CVEs?}\n vuln -->|Yes| fail\n vuln -->|No| stage[Deploy to staging]\n stage --> smoke{Smoke tests green?}\n smoke -->|No| fail\n smoke -->|Yes| approve{Manual approval?}\n approve -->|No| wait([Await approver])\n approve -->|Yes| prod[Deploy to production]\n prod --> health{Post-deploy health check?}\n health -->|Yes| done([Release complete])\n health -->|No| rollback[Automatic rollback]\n rollback --> done",
|
|
882
729
|
"notes": "## Scenario\n\nA platform engineer is documenting the team's trunk-based pipeline for a new-hire runbook. The diagram makes the four automated gates (tests \u2192 scan \u2192 smoke \u2192 post-deploy health) and the single human gate (manual approval) obvious at a glance, and shows that every failure path terminates the pipeline rather than silently continuing.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; start and terminal nodes\n- `{\u2026}` \u2014 diamond; automated or manual gate\n- `[\u2026]` \u2014 rectangle; build / deploy / scan step\n- `-->|Yes/No|` \u2014 branch labels on each gate\n\n## How to read\n\nStart at *Push to main*. Every diamond is a gate \u2014 a *No* on any of unit tests, CVE scan, or smoke tests terminates at *Fail build*. Manual approval is the only human gate; it can park the pipeline at *Await approver* without failing. The post-deploy health check guards production: a failure triggers automatic rollback, which still completes at *Release complete* because the rollback itself is a successful outcome."
|
|
883
730
|
},
|
|
884
|
-
{
|
|
885
|
-
"slug": "flowchart-etl-pipeline",
|
|
886
|
-
"diagram": "flowchart",
|
|
887
|
-
"title": "ETL data pipeline",
|
|
888
|
-
"description": "Source extraction through transform, validation, load, and warehouse notification \u2014 the standard data-engineering pipeline diagram.",
|
|
889
|
-
"standard": "ISO 5807:1985",
|
|
890
|
-
"tags": [
|
|
891
|
-
"etl",
|
|
892
|
-
"pipeline",
|
|
893
|
-
"data",
|
|
894
|
-
"warehouse",
|
|
895
|
-
"validation",
|
|
896
|
-
"transform"
|
|
897
|
-
],
|
|
898
|
-
"complexity": 3,
|
|
899
|
-
"featured": false,
|
|
900
|
-
"dsl": 'flowchart LR\n subgraph "Sources"\n pg[(PostgreSQL)] --> extract\n s3[(S3 bucket)] --> extract\n api[REST API] --> extract\n end\n extract[Extract to raw staging] --> clean[Clean \u2014 strip nulls, deduplicate]\n clean --> normalize[Normalize \u2014 cast types, unify schemas]\n normalize --> enrich[Enrich \u2014 join lookup tables]\n enrich --> validate{Error rate > 1%?}\n validate -->|Yes| quarantine[Quarantine bad rows]\n quarantine --> notify[Alert data-quality Slack channel]\n notify --> retry{Retry batch?}\n retry -->|Yes| extract\n retry -->|No| abort([Abort run \u2014 log to incident tracker])\n validate -->|No| load[Load to data warehouse]\n load --> qcheck[Run row-count and sum reconciliation]\n qcheck --> passed{Reconciliation passed?}\n passed -->|No| rollback[Rollback warehouse load]\n rollback --> abort\n passed -->|Yes| publish[Publish partition metadata]\n publish --> downstream([Notify downstream consumers \u2014 dbt, BI, ML])',
|
|
901
|
-
"notes": '## Scenario\n\nA data engineer is documenting a nightly batch ETL job that ingests transactional records from three heterogeneous sources into a central warehouse. The diagram serves as both a runbook and a stakeholder communication artifact, showing data-quality enforcement points that prevent silent corruption from propagating to reporting dashboards and machine-learning feature stores.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; terminal run outcomes (abort, notify consumers)\n- `{\u2026}` \u2014 diamond; quality gates with quantitative thresholds\n- `[\u2026]` \u2014 rectangle; processing steps or system actions\n- `[(\u2026)]` \u2014 cylinder; external data stores\n- `subgraph "Sources"` \u2014 groups the three ingestion connectors into one tier\n- Loop from `retry -->|Yes|` back to `extract` models full-batch reprocessing after quarantine\n\n## How to read\n\nThe pipeline fans in from three source connectors into a single extract step that writes to raw staging. The transform chain \u2014 clean, normalize, enrich \u2014 runs sequentially; each step narrows and standardizes the data before passing it forward. The validation gate measures the bad-row error rate: if it exceeds one percent, bad rows are quarantined, an alert fires, and the operator decides whether to retry or abort the run. Rows that pass validation are loaded to the warehouse, then verified with a row-count and sum reconciliation; a failed reconciliation triggers a rollback and abort rather than leaving inconsistent data in place. A successful reconciliation publishes partition metadata and fans out notifications to downstream consumers.'
|
|
902
|
-
},
|
|
903
|
-
{
|
|
904
|
-
"slug": "flowchart-incident-response",
|
|
905
|
-
"diagram": "flowchart",
|
|
906
|
-
"title": "On-call incident response",
|
|
907
|
-
"description": "SRE on-call decision tree from alert page through triage, escalation, mitigation, and post-mortem \u2014 BPMN-shaped TD flow.",
|
|
908
|
-
"standard": "ISO 5807:1985",
|
|
909
|
-
"tags": [
|
|
910
|
-
"incident",
|
|
911
|
-
"sre",
|
|
912
|
-
"on-call",
|
|
913
|
-
"escalation",
|
|
914
|
-
"mitigation",
|
|
915
|
-
"postmortem"
|
|
916
|
-
],
|
|
917
|
-
"complexity": 3,
|
|
918
|
-
"featured": false,
|
|
919
|
-
"dsl": "flowchart TD\n page([Alert fires \u2014 on-call paged]) --> ack{Acknowledged within 5 min?}\n ack -->|No| escalate[Escalate to secondary on-call]\n escalate --> sev\n ack -->|Yes| sev{Severity assessment}\n sev -->|SEV1 \u2014 customer-facing outage| sev1[Wake CTO + open war room bridge]\n sev -->|SEV2 \u2014 degraded service| sev2[Notify team lead + Slack channel]\n sev -->|SEV3 \u2014 internal only| sev3[Self-resolve within shift]\n sev1 --> mitigate[Apply mitigation \u2014 rollback or hotfix]\n sev2 --> mitigate\n sev3 --> mitigate\n mitigate --> health{Service health restored?}\n health -->|No| mitigate\n health -->|Yes| resolved([Incident resolved \u2014 close bridge])\n resolved --> postmortem{SEV1 or SEV2?}\n postmortem -->|Yes| pm[Write post-mortem within 48 h]\n postmortem -->|No| log[Log in incident tracker]\n pm --> done([Done])\n log --> done",
|
|
920
|
-
"notes": "## Scenario\n\nAn SRE team uses this flowchart as the canonical on-call runbook embedded in their incident-management wiki. When an alert fires at 3 AM the responder can follow the diagram top to bottom without improvising, ensuring that acknowledgment, severity triage, escalation paths, and post-mortem obligations are never skipped regardless of who is on duty.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; trigger events and terminal closure nodes\n- `{\u2026}` \u2014 diamond; time-boxed decisions and severity gates\n- `[\u2026]` \u2014 rectangle; prescribed human actions (escalate, notify, mitigate, document)\n- `-->|label|` \u2014 branch label showing condition or severity band\n- Loop back from `health -->|No|` to `mitigate` represents the retry-until-resolved mitigation cycle\n\n## How to read\n\nThe flow begins the moment an alert fires. The first gate enforces the five-minute acknowledgment SLA; a miss immediately escalates to the secondary responder who then re-enters the severity triage diamond. Severity determines the escalation audience \u2014 SEV1 wakes executive leadership, SEV2 notifies the team lead, SEV3 is self-contained. All three paths converge on the mitigation loop, which repeats until health is restored. The final diamond routes only SEV1 and SEV2 incidents to a formal post-mortem; SEV3 incidents close with a tracker log entry."
|
|
921
|
-
},
|
|
922
|
-
{
|
|
923
|
-
"slug": "flowchart-microservices-request",
|
|
924
|
-
"diagram": "flowchart",
|
|
925
|
-
"title": "Microservices request flow",
|
|
926
|
-
"description": "API gateway routing a request through auth, rate-limit, and three backend services to a shared DB \u2014 LR subgraph layout.",
|
|
927
|
-
"standard": "ISO 5807:1985",
|
|
928
|
-
"tags": [
|
|
929
|
-
"microservices",
|
|
930
|
-
"api-gateway",
|
|
931
|
-
"request-flow",
|
|
932
|
-
"backend",
|
|
933
|
-
"subgraph"
|
|
934
|
-
],
|
|
935
|
-
"complexity": 3,
|
|
936
|
-
"featured": false,
|
|
937
|
-
"dsl": 'flowchart LR\n subgraph "API Layer"\n client([Client request]) --> gateway[API Gateway]\n gateway --> auth{Auth valid?}\n auth -->|No| reject([401 Unauthorized])\n auth -->|Yes| rate{Rate limit ok?}\n rate -->|No| throttle([429 Too Many Requests])\n end\n subgraph "Services"\n rate -->|Yes| route{Route by path}\n route -->|/users| user[User Service]\n route -->|/orders| order[Order Service]\n order --> notify[Notification Service]\n end\n subgraph "Data"\n user --> db[(PostgreSQL)]\n order --> db\n end\n user -->|200 response| client\n order -->|200 response| client\n db -->|query error| dberr([500 DB Error])',
|
|
938
|
-
"notes": '## Scenario\n\nA backend engineer is documenting the runtime topology of a decomposed e-commerce platform so that new team members can trace a request end to end without reading source code. The diagram exposes the two pre-routing gates (authentication and rate limiting) and the downstream fan-out to specialized services, making it clear why a client might receive a 401, 429, or 500 before any business logic executes.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; entry points and terminal error/success nodes\n- `{\u2026}` \u2014 diamond; routing and policy decision gates\n- `[\u2026]` \u2014 rectangle; service or infrastructure processing step\n- `[(\u2026)]` \u2014 cylinder; persistent data store\n- `-->|label|` \u2014 labeled directed edge showing condition or path name\n- `subgraph "name"` \u2014 swimlane grouping API, service, and data tiers\n\n## How to read\n\nStart at *Client request* and follow the arrow into the API Layer subgraph. The request must clear two sequential gates \u2014 authentication then rate limiting \u2014 before reaching the route diamond. The route diamond dispatches to *User Service* or *Order Service* based on the URL path; an order request additionally triggers the *Notification Service* asynchronously. Both services share the same *PostgreSQL* store; a database error at that layer surfaces as a 500 terminal node independent of which service triggered the query.'
|
|
939
|
-
},
|
|
940
731
|
{
|
|
941
732
|
"slug": "flowchart-order-fulfillment",
|
|
942
733
|
"diagram": "flowchart",
|
|
@@ -974,25 +765,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
974
765
|
"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',
|
|
975
766
|
"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).'
|
|
976
767
|
},
|
|
977
|
-
{
|
|
978
|
-
"slug": "flowchart-user-onboarding",
|
|
979
|
-
"diagram": "flowchart",
|
|
980
|
-
"title": "User onboarding flow",
|
|
981
|
-
"description": "Signup through email verification, profile setup, first-action tutorial, and activation milestone \u2014 a product manager's north-star flow.",
|
|
982
|
-
"standard": "ISO 5807:1985",
|
|
983
|
-
"tags": [
|
|
984
|
-
"onboarding",
|
|
985
|
-
"activation",
|
|
986
|
-
"signup",
|
|
987
|
-
"tutorial",
|
|
988
|
-
"user-flow",
|
|
989
|
-
"product"
|
|
990
|
-
],
|
|
991
|
-
"complexity": 2,
|
|
992
|
-
"featured": false,
|
|
993
|
-
"dsl": "flowchart TD\n signup([User submits signup form]) --> email[Send verification email]\n email --> verified{Email verified?}\n verified -->|No \u2014 after 24 h| resend[Resend verification email]\n resend --> verified\n verified -->|Yes| profile[Profile setup wizard]\n profile --> skipped{Wizard completed?}\n skipped -->|Skip| tour[Feature tour \u2014 3 tooltip steps]\n skipped -->|Complete| tour\n tour --> action{First core action taken?}\n action -->|No \u2014 after 48 h| nudge[Send nudge email with shortcut link]\n nudge --> action\n action -->|Yes| activate[Record activation event]\n activate --> welcome([Welcome milestone reached])",
|
|
994
|
-
"notes": '## Scenario\n\nA product manager is mapping the critical path from sign-up to activation to align engineering, growth, and design on what "activated user" means. The diagram makes every drop-off risk visible \u2014 email verification friction, wizard abandonment, and first-action hesitation \u2014 so each team can own the metric that corresponds to their part of the funnel.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; user-triggered entry and milestone terminal nodes\n- `{\u2026}` \u2014 diamond; binary or conditional state checks\n- `[\u2026]` \u2014 rectangle; system or product actions (send email, show wizard, record event)\n- `-->|label|` \u2014 branch labels showing condition, time trigger, or user choice\n- Loop edges from `resend` and `nudge` model retry cycles that resolve when the user acts\n\n## How to read\n\nThe flow starts at form submission and immediately hits the email verification gate. Users who do not verify within 24 hours loop through a resend step; this loop continues until verification succeeds. Once verified, all users \u2014 whether they complete the profile wizard or skip it \u2014 enter the three-step feature tour. The first-action gate determines activation: users who have not acted within 48 hours receive a nudge email that links directly to the core feature, shortening the path back into the loop. Activation fires a single analytics event that marks the user as "activated" and terminates the onboarding sequence.'
|
|
995
|
-
},
|
|
996
768
|
{
|
|
997
769
|
"slug": "genogram-brca-cancer",
|
|
998
770
|
"diagram": "genogram",
|
|
@@ -1269,83 +1041,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1269
1041
|
"dsl": "mindmap\n\n# Q4 Company OKRs\n\n## Grow ARR 30%\n### Expand enterprise pipeline\n- 10 new qualified logos\n- Win rate \u2265 25%\n### Increase expansion\n- Net revenue retention \u2265 120%\n- Seat adoption +40%\n\n## Ship Platform v2\n### Core migration\n- 100% API coverage\n- Zero-downtime cutover\n### Developer experience\n- Sub-5-min quickstart\n- 95% doc satisfaction\n\n## Strengthen team\n### Hiring\n- 8 senior engineers\n- 2 staff PMs\n### Retention\n- Voluntary attrition < 5%\n- eNPS \u2265 40",
|
|
1270
1042
|
"notes": "## Scenario\n\nThe chief of staff projects this during the Q4 all-hands. Three objectives radiate from the centre; every key result is a leaf with a specific number. The mindmap format reads fast \u2014 every person in the company can find their team's objective within three seconds \u2014 and it tolerates mid-quarter edits without disturbing other branches.\n\n## Annotation key\n\n- `#` \u2014 root; company-level frame\n- `##` \u2014 objective (qualitative direction)\n- `###` \u2014 key-result cluster\n- `-` bullets \u2014 specific measurable KRs\n\n## How to read\n\nThe root names the quarter. The three `##` branches are the objectives \u2014 the things that will be judged at the end of the quarter. Each `###` groups key results by theme; the bullets are the actual measurable targets. If a KR can't be reduced to a number, it probably belongs in a planning doc rather than on this mindmap."
|
|
1271
1043
|
},
|
|
1272
|
-
{
|
|
1273
|
-
"slug": "orgchart-board-committees",
|
|
1274
|
-
"diagram": "orgchart",
|
|
1275
|
-
"title": "Corporate board and committee structure",
|
|
1276
|
-
"description": "Public-company board governance \u2014 full board with audit, compensation, nominating/governance, and risk subcommittees per SEC requirements.",
|
|
1277
|
-
"standard": "SEC / NYSE governance",
|
|
1278
|
-
"tags": [
|
|
1279
|
-
"orgchart",
|
|
1280
|
-
"board",
|
|
1281
|
-
"governance",
|
|
1282
|
-
"audit",
|
|
1283
|
-
"compensation",
|
|
1284
|
-
"sec",
|
|
1285
|
-
"committee"
|
|
1286
|
-
],
|
|
1287
|
-
"complexity": 3,
|
|
1288
|
-
"featured": false,
|
|
1289
|
-
"dsl": 'orgchart "Acme Corp \u2014 Board & Committee Structure"\nchair: "Victoria Harmon" | Board Chair [role: advisor]\n audit_chair: "Ellen Frost, CPA" | Audit Committee Chair [role: finance]\n audit_m1: "James Liu" | Audit Committee Member [role: finance]\n audit_m2: "Priya Mehta" | Audit Committee Member [role: finance]\n comp_chair: "Thomas Osei" | Compensation Committee Chair [role: hr]\n comp_m1: "Sarah Nakamura" | Compensation Committee Member [role: hr]\n comp_m2: "Rafael Dominguez" | Compensation Committee Member [role: hr]\n nom_chair: "Linda Abramowitz" | Nom. & Governance Chair [role: legal]\n nom_m1: "Derek Abubakar" | Nom. & Governance Member [role: legal]\n nom_m2: "Yuki Fernandez" | Nom. & Governance Member [role: legal]\n risk_chair: "Raj Mehta" | Risk Committee Chair [role: ops]\n risk_m1: "Cynthia Okonkwo" | Risk Committee Member [role: ops]\n risk_m2: "Simon Park" | Risk Committee Member [role: ops]\nboard_ceo: "David Park" | CEO (Management) [role: ceo]\n mgmt_cfo: "Angela Torres" | CFO [role: finance]\n mgmt_clo: "Marcus Reyes" | Chief Legal Officer [role: legal]\nboard_ceo -.-> audit_chair\nboard_ceo -.-> comp_chair\nboard_ceo -.-> nom_chair\nboard_ceo -.-> risk_chair',
|
|
1290
|
-
"notes": '## Scenario\n\nThe corporate secretary is preparing the annual proxy statement and needs to document the board\'s committee structure as required by SEC Regulation S-K Item 407 and NYSE Listed Company Rules. The four standing committees \u2014 Audit, Compensation, Nominating & Governance, and Risk \u2014 each consist entirely of independent directors. The CEO and CFO participate in committee meetings by invitation and report to the relevant committees, but are not members. The dotted lines from the CEO to each committee chair represent this management reporting relationship for operational matters.\n\n## Annotation key\n\n- `chair: "Victoria Harmon" | Board Chair [role: advisor]` \u2014 independent chair; non-executive\n- Committee chairs and members use `[role: finance]`, `[role: hr]`, `[role: legal]`, `[role: ops]` to visually distinguish oversight focus\n- `board_ceo: "David Park" | CEO (Management)` \u2014 management side; inside-the-box CEO distinct from the independent board\n- `board_ceo -.-> audit_chair` \u2014 dotted lines represent management\'s accountability to each committee, not reporting hierarchy\n- All committee members must be independent directors under SEC Rule 10A-3 (Audit) and NYSE Section 303A\n\n## How to read\n\nThe board chart has two distinct clusters. The upper cluster \u2014 Board Chair and the four committees \u2014 is the governance structure: independent directors exercising fiduciary oversight. The lower cluster \u2014 CEO and management \u2014 represents the executive team that is accountable to the board. Dotted lines from the CEO to each committee chair indicate that management attends and reports to committees without being members or having voting rights. The Audit Committee chair (Ellen Frost, CPA) satisfies the SEC\'s financial expert disclosure requirement. NYSE rules require that Compensation and Nom/Gov committees be composed solely of independent directors; the Risk Committee follows the same practice here but is not legally mandated to be fully independent.'
|
|
1291
|
-
},
|
|
1292
|
-
{
|
|
1293
|
-
"slug": "orgchart-engineering-dept",
|
|
1294
|
-
"diagram": "orgchart",
|
|
1295
|
-
"title": "Engineering department \u2014 platform, product, infra squads",
|
|
1296
|
-
"description": "Engineering org with three squad leads under a VP Eng \u2014 platform, product, and infrastructure, with open headcount flagged.",
|
|
1297
|
-
"standard": "HR convention",
|
|
1298
|
-
"tags": [
|
|
1299
|
-
"orgchart",
|
|
1300
|
-
"engineering",
|
|
1301
|
-
"squad",
|
|
1302
|
-
"platform",
|
|
1303
|
-
"infra",
|
|
1304
|
-
"product"
|
|
1305
|
-
],
|
|
1306
|
-
"complexity": 3,
|
|
1307
|
-
"featured": false,
|
|
1308
|
-
"dsl": 'orgchart "Engineering Department \u2014 Q3 Headcount Plan"\nstaff_pe: "Diana Okonkwo" | Staff Principal Engineer [role: engineer]\nvp_eng: "Sarah Chen" | VP Engineering [role: cto]\n platform_lead: "Marco Rossi" | Platform Lead [role: engineer]\n pe1: "Kenji Watanabe" | Senior Engineer | Platform [role: engineer]\n pe2: "Aaliya Hassan" | Engineer | Platform [role: engineer]\n pe3: "Lucas Ferreira" | Engineer | Platform [role: engineer]\n open_sr: open "TBH" | Senior Engineer | Platform [role: engineer]\n product_lead: "Aisha Okafor" | Product Eng Lead [role: engineer]\n pe4: "Rohan Mehta" | Senior Engineer | Product [role: engineer]\n pe5: "Chloe Martin" | Engineer | Product [role: engineer]\n pe6: "Jae-won Oh" | Engineer | Product [role: engineer]\n pe7: "Fatima Al-Rashid" | Engineer | Product [role: engineer]\n draft_staff: draft "TBH" | Staff Engineer | Product [role: engineer]\n infra_lead: "Dev Patel" | Infra Lead [role: engineer]\n ie1: "Nadia Kowalski" | Senior SRE [role: engineer]\n ie2: "Emre Yilmaz" | SRE [role: engineer]\n open_sre: open "TBH" | Site Reliability Engineer [role: engineer]\nstaff_pe -.-> platform_lead\nstaff_pe -.-> product_lead\nstaff_pe -.-> infra_lead',
|
|
1309
|
-
"notes": '## Scenario\n\nThe engineering director is presenting the Q3 headcount plan to the CFO. The chart shows three squads \u2014 platform, product engineering, and infrastructure \u2014 each under a dedicated lead reporting to the VP of Engineering. A Staff Principal Engineer provides technical oversight across all three squads via dotted-line relationships. Two open reqs are actively being recruited (Platform Senior Engineer, SRE), and one Staff Engineer seat in the product squad is planned for Q4 but not yet approved.\n\n## Annotation key\n\n- `vp_eng: "Sarah Chen" | VP Engineering [role: cto]` \u2014 VP-level node coloured with the cto role style\n- Indentation (2 spaces) \u2014 solid-line reporting hierarchy\n- `open "TBH"` \u2014 approved open requisition, currently recruiting\n- `draft "TBH"` \u2014 planned headcount, not yet approved or posted\n- `staff_pe -.-> platform_lead` \u2014 dotted line; technical authority without HR reporting chain\n\n## How to read\n\nThe tree root is the VP of Engineering. The three squad leads sit at the second level \u2014 equal peers in the org, differentiated only by domain. Headcount marked `open` (Platform Senior Eng, SRE) represents approved budget the director is actively spending; `draft` (Product Staff) is the ask for the next planning cycle. The staff principal at the top of the chart is neither the VP\'s direct report nor a squad lead: the dotted lines to all three leads signal that she sets technical standards and does architecture review across squads without owning any head count.'
|
|
1310
|
-
},
|
|
1311
|
-
{
|
|
1312
|
-
"slug": "orgchart-hospital-dept",
|
|
1313
|
-
"diagram": "orgchart",
|
|
1314
|
-
"title": "Hospital clinical department hierarchy",
|
|
1315
|
-
"description": "Hospital clinical org \u2014 Chief Medical Officer, department heads, attendings, residents, and nursing leads for a teaching hospital.",
|
|
1316
|
-
"standard": "JCAHO / hospital convention",
|
|
1317
|
-
"tags": [
|
|
1318
|
-
"orgchart",
|
|
1319
|
-
"hospital",
|
|
1320
|
-
"clinical",
|
|
1321
|
-
"physician",
|
|
1322
|
-
"nursing",
|
|
1323
|
-
"hierarchy"
|
|
1324
|
-
],
|
|
1325
|
-
"complexity": 4,
|
|
1326
|
-
"featured": false,
|
|
1327
|
-
"dsl": 'orgchart "General Hospital \u2014 Clinical Leadership"\ncmo: "Dr. Patricia Williams" | Chief Medical Officer [role: medical]\n chief_med: "Dr. James Park" | Chief of Medicine [role: medical]\n cardio_head: "Dr. Amara Nwosu" | Division Chief | Cardiology [role: medical]\n att_card1: "Dr. Elena Sousa" | Attending Physician [role: medical]\n att_card2: "Dr. Ravi Gupta" | Attending Physician [role: medical]\n res_card1: "Dr. Yuki Tanaka" | PGY-3 Resident [role: medical]\n res_card2: "Dr. Malik Johnson" | PGY-2 Resident [role: medical]\n neuro_head: "Dr. Ingrid Larsen" | Division Chief | Neurology [role: medical]\n att_neuro1: "Dr. Omar Sharif" | Attending Physician [role: medical]\n att_neuro2: "Dr. Priya Krishnan" | Attending Physician [role: medical]\n res_neuro1: "Dr. Tom\xE1s Rivera" | PGY-3 Resident [role: medical]\n res_neuro2: "Dr. Aisha Conteh" | PGY-2 Resident [role: medical]\n chief_surg: "Dr. Amara Diallo" | Chief of Surgery [role: medical]\n gen_surg_head: "Dr. Wei Zhang" | Division Chief | General Surgery [role: medical]\n att_gs1: "Dr. Sofia Reyes" | Attending Surgeon [role: medical]\n att_gs2: "Dr. Kwame Mensah" | Attending Surgeon [role: medical]\n ortho_head: "Dr. Henrik Svensson" | Division Chief | Orthopedics [role: medical]\n att_orth1: "Dr. Nalini Patel" | Attending Surgeon [role: medical]\n att_orth2: "Dr. Seun Adeyemi" | Attending Surgeon [role: medical]\n cno: "Maria Gonzalez, RN, MSN" | Chief Nursing Officer [role: medical]\n med_surg_mgr: "Lisa Park, RN" | Nurse Manager | Med-Surg [role: medical]\n icu_mgr: "Robert Osei, RN" | ICU Nurse Manager [role: medical]',
|
|
1328
|
-
"notes": "## Scenario\n\nA hospital administrator is preparing a JCAHO accreditation submission and needs to document the clinical governance structure. The chart shows the three-pillar model common to teaching hospitals: Medicine and Surgery under the CMO handle physician credentialing and clinical protocols, while Nursing reports separately to ensure independent oversight of nursing practice standards. Attendings supervise residents directly; residents rotate between divisions but report to their division chief.\n\n## Annotation key\n\n- `[role: medical]` \u2014 all clinical staff rendered with the medical colour coding\n- Indentation \u2014 solid-line administrative and clinical reporting chain\n- `PGY-2 / PGY-3` \u2014 Post-Graduate Year, the standard US resident designation (PGY-1 = intern)\n- `RN, MSN` \u2014 inline credentials appended to the name field, common in nursing leadership notation\n- Division Chiefs sit between the department Chief and individual attendings \u2014 the standard academic medical centre layer\n\n## How to read\n\nThe CMO owns clinical quality across all departments. Medicine and Surgery are equal pillars \u2014 each Chief has autonomous credentialing authority within their specialty. Within Medicine, Cardiology and Neurology each run their own attending\u2013resident teaching structure: attendings carry clinical responsibility; residents operate under supervision with authority expanding by PGY year. Nursing reports up through the CNO rather than through either clinical chief \u2014 a deliberate governance separation required by Magnet hospital standards. The two nurse managers (Med-Surg floor, ICU) translate CNO policy to unit-level staffing and care protocols."
|
|
1329
|
-
},
|
|
1330
|
-
{
|
|
1331
|
-
"slug": "orgchart-law-firm-partnership",
|
|
1332
|
-
"diagram": "orgchart",
|
|
1333
|
-
"title": "Law firm partnership structure",
|
|
1334
|
-
"description": "AmLaw 100-style law firm org \u2014 equity and non-equity partners, counsel, associates, and professional staff by practice group.",
|
|
1335
|
-
"standard": "NALP convention",
|
|
1336
|
-
"tags": [
|
|
1337
|
-
"orgchart",
|
|
1338
|
-
"law-firm",
|
|
1339
|
-
"partnership",
|
|
1340
|
-
"counsel",
|
|
1341
|
-
"associate",
|
|
1342
|
-
"legal"
|
|
1343
|
-
],
|
|
1344
|
-
"complexity": 3,
|
|
1345
|
-
"featured": false,
|
|
1346
|
-
"dsl": 'orgchart "Chen & Associates LLP \u2014 Partnership Structure"\nmanaging_partner: "Robert Chen" | Managing Partner [role: ceo]\n corp_chair: "Jennifer Wu" | Corporate Practice Chair [role: coo]\n corp_ep1: "David Okafor" | Equity Partner | M&A [role: legal]\n corp_ep1_sa1: "Mei-Ling Torres" | Senior Associate [role: legal]\n corp_ep1_a1: "Brendan Nwosu" | Associate [role: legal]\n corp_ep1_a2: "Priya Sharma" | Associate [role: legal]\n corp_ep2: "Simone Beaumont" | Equity Partner | Securities [role: legal]\n corp_ep2_sa1: "Aleksei Volkov" | Senior Associate [role: legal]\n corp_ep2_a1: "Fatou Diallo" | Associate [role: legal]\n corp_nep: "Marcus Tran" | Non-Equity Partner | Corporate [role: legal]\n corp_nep_a1: "Yuna Kim" | Associate [role: legal]\n corp_para1: "Sandra Lopez" | Paralegal [role: ops]\n lit_chair: "Marcus Johnson" | Litigation Practice Chair [role: coo]\n lit_ep1: "Amara Osei" | Equity Partner | Commercial Lit [role: legal]\n lit_ep1_sa1: "Tobias Gruber" | Senior Associate [role: legal]\n lit_ep1_a1: "Chimamanda Eze" | Associate [role: legal]\n lit_ep2: "Hiroshi Nakamura" | Equity Partner | White Collar [role: legal]\n lit_ep2_sa1: "Valentina Cruz" | Senior Associate [role: legal]\n lit_ep2_a1: "Daniel Abioye" | Associate [role: legal]\n lit_counsel: "Rachel Goldstein" | Counsel | Litigation [role: legal]\n cfo: "Dana Kim" | COO / CFO [role: finance]\n mkt: "Alex Torres" | Chief Marketing Officer [role: ops]',
|
|
1347
|
-
"notes": "## Scenario\n\nThe managing partner is preparing materials for the annual partnership meeting, including the governance deck and lateral-hire pitch collateral. The chart shows the two-track attorney structure common to AmLaw 100 firms: equity partners share in firm profits and have capital accounts; non-equity partners are on fixed compensation; counsel are senior attorneys on a permanent non-partnership track. Associates are levelled as first-through-fifth-year and senior (sixth-plus). Professional staff \u2014 COO/CFO and CMO \u2014 sit as firm-level directs to the managing partner.\n\n## Annotation key\n\n- `[role: legal]` \u2014 attorney nodes; `[role: finance]` and `[role: ops]` \u2014 professional staff\n- Equity Partner \u2014 profit-sharing, voting interest in firm governance\n- Non-Equity Partner \u2014 title parity without capital account; typically earns a fixed bonus-eligible salary\n- Counsel \u2014 senior non-partner track: often former partners, domain specialists, or attorneys who opted out of the equity track\n- Senior Associate \u2014 sixth year or above; on the partnership evaluation clock\n- `corp_chair` / `lit_chair` \u2014 practice group chairs own lateral hiring, billing rate setting, and matter assignment within their group\n\n## How to read\n\nRobert Chen, as managing partner, chairs the firm's executive committee and carries final governance authority. The two practice chairs report to him and run their groups as semi-autonomous profit centres. Within each group, equity partners own client relationships and sign off on fee arrangements; associates bill under partner supervision. The non-equity partner in Corporate adds capacity without diluting the equity pool \u2014 a common structure when a client relationship is stable but not large enough to justify a new equity slot. Counsel in Litigation handles specialized motions work that would otherwise require lateral-hiring a lateral partner. The COO/CFO and CMO report directly to the managing partner rather than through a practice chair \u2014 they serve the whole firm, not a single group."
|
|
1348
|
-
},
|
|
1349
1044
|
{
|
|
1350
1045
|
"slug": "orgchart-matrix-reporting",
|
|
1351
1046
|
"diagram": "orgchart",
|
|
@@ -1527,6 +1222,56 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1527
1222
|
"dsl": 'sld "Utility + Generator Backup"\nUTIL = utility [voltage: "480V", label: "Utility"]\nGEN = generator [rating: "500 kW", voltage: "480V", label: "Emergency Gen"]\nATS1 = ats [rating: "800A", label: "ATS-1"]\nBUS1 = bus [voltage: "480V", label: "Critical Load Bus"]\nCB1 = breaker [rating: "200A"]\nCB2 = breaker [rating: "200A"]\nL1 = load [rating: "100A", label: "Critical Load 1"]\nL2 = load [rating: "100A", label: "Critical Load 2"]\nUTIL -> ATS1\nGEN -> ATS1\nATS1 -> BUS1\nBUS1 -> CB1\nBUS1 -> CB2\nCB1 -> L1\nCB2 -> L2',
|
|
1528
1223
|
"notes": "## Scenario\n\nA facility engineer draws this one-line during the design review of a data-center UPS bypass or hospital emergency power system. The single-line diagram (SLD) is the first document a utility inspector or commissioning engineer asks for \u2014 it must show every source, switching device, bus, and load path in a single horizontal view without wiring details.\n\n## Annotation key\n\n- `utility` \u2014 mains supply; drawn as the IEEE 315 utility symbol (three-line source)\n- `generator` \u2014 diesel or gas genset; drawn as rotating-machine circle with winding symbol\n- `ats` \u2014 Automatic Transfer Switch; drawn as the NEMA/IEEE transfer-switch symbol\n- `bus` \u2014 horizontal bus bar; all connected devices share the same voltage rail\n- `breaker` \u2014 molded-case or air circuit breaker; drawn as the IEEE 315 breaker symbol\n- `load` \u2014 end-consumer device or feeder\n- `UTIL -> ATS1` \u2014 directed line representing the power path from source to device\n\n## How to read\n\nTwo sources (utility and generator) feed into the ATS. The ATS selects the live source and connects it to the 480 V critical load bus. From the bus, two independently-fused circuit breakers (CB1, CB2) feed their respective critical loads. If utility power fails, the ATS senses the loss, the generator starts, and the ATS transfers within seconds \u2014 all without interrupting the bus downstream."
|
|
1529
1224
|
},
|
|
1225
|
+
{
|
|
1226
|
+
"slug": "sld-residential-iec-60364-consumer-unit",
|
|
1227
|
+
"diagram": "sld",
|
|
1228
|
+
"title": "Residential consumer unit \u2014 generic IEC 60364",
|
|
1229
|
+
"description": "Generic European residential consumer unit per IEC 60364 / EN 61439-3 \u2014 service head, isolator, type-AC main RCD, and per-circuit MCBs for lighting, sockets, kitchen, water heater, EV charger (with type-B RCBO), and outdoor circuit.",
|
|
1230
|
+
"standard": "IEC 60364 / EN 61439-3",
|
|
1231
|
+
"tags": [
|
|
1232
|
+
"sld",
|
|
1233
|
+
"residential",
|
|
1234
|
+
"iec-60364",
|
|
1235
|
+
"en-61439",
|
|
1236
|
+
"europe",
|
|
1237
|
+
"consumer-unit",
|
|
1238
|
+
"rcd",
|
|
1239
|
+
"rcbo",
|
|
1240
|
+
"mcb",
|
|
1241
|
+
"isolator",
|
|
1242
|
+
"ev-charger"
|
|
1243
|
+
],
|
|
1244
|
+
"complexity": 2,
|
|
1245
|
+
"featured": true,
|
|
1246
|
+
"dsl": 'sld "Residential Consumer Unit \u2014 IEC 60364"\nSERVICE = utility [voltage: "230V", label: "Service head 230V/63A"]\nKWHM = watthour_meter [label: "kWh meter"]\nISO = breaker [rating: "63A 6kA", label: "Main isolator"]\nRCD = ground_fault [rating: "63A / 30mA Type AC", label: "Main RCD"]\nCU = bus [voltage: "230V", label: "Consumer-unit busbar"]\nMCB1 = breaker [rating: "6A B-curve", label: "MCB lighting"]\nMCB2 = breaker [rating: "16A B-curve", label: "MCB sockets ground floor"]\nMCB3 = breaker [rating: "16A B-curve", label: "MCB sockets first floor"]\nMCB4 = breaker [rating: "20A C-curve", label: "MCB kitchen ring"]\nMCB5 = breaker [rating: "20A C-curve", label: "MCB water heater"]\nRCBO_EV = ground_fault [rating: "32A / 30mA Type B", label: "RCBO EV charger"]\nMCB6 = breaker [rating: "10A B-curve", label: "MCB outdoor"]\nL1 = load [label: "Lighting circuit"]\nL2 = load [label: "Sockets \u2014 ground floor"]\nL3 = load [label: "Sockets \u2014 first floor"]\nL4 = load [label: "Kitchen ring final"]\nL5 = load [label: "Water heater 4.5 kW"]\nEV = load [label: "EV charger 7.4 kW Mode 3"]\nL6 = load [label: "Outdoor / garden"]\nSERVICE -> KWHM\nKWHM -> ISO\nISO -> RCD\nRCD -> CU\nCU -> MCB1\nMCB1 -> L1 [cable: "1.5 mm\xB2 Cu PVC"]\nCU -> MCB2\nMCB2 -> L2 [cable: "2.5 mm\xB2 Cu PVC"]\nCU -> MCB3\nMCB3 -> L3 [cable: "2.5 mm\xB2 Cu PVC"]\nCU -> MCB4\nMCB4 -> L4 [cable: "4 mm\xB2 Cu PVC"]\nCU -> MCB5\nMCB5 -> L5 [cable: "4 mm\xB2 Cu PVC"]\nCU -> RCBO_EV\nRCBO_EV -> EV [cable: "6 mm\xB2 Cu XLPE"]\nCU -> MCB6\nMCB6 -> L6 [cable: "2.5 mm\xB2 Cu XLPE"]',
|
|
1247
|
+
"notes": '## Scenario\n\nA domestic electrical installer in any IEC 60364 jurisdiction \u2014 France (NF C 15-100), Germany (DIN VDE 0100), the United Kingdom (BS 7671), Italy (CEI 64-8), Australia / New Zealand (AS/NZS 3000), and most of the rest of the world outside the NEC \u2014 files this single-line as part of the *Certificat de Conformit\xE9* / *Elektroinstallationsattest* / *Electrical Installation Condition Report* required after a new installation or major alteration. EN 61439-3 is the European harmonized standard for *Distribution Boards intended to be operated by Ordinary persons* (DBO), and IEC 60364-4-41 governs the protection-against-shock chain (isolation \u2192 30 mA RCD \u2192 branch protection). Unlike NEC residential practice where the *panel* lives as a leaf on the SLD with internals on a separate panel schedule, the IEC 60364 single-line is expected to expand the consumer unit\'s internal protection chain.\n\n## Annotation key\n\n- `utility [voltage:..., label: "Service head\u2026"]` \u2014 the cut-out / service-fuse head where the distribution network terminates and the customer installation begins\n- `watthour_meter` \u2014 utility-owned kWh meter (smart meter in most modern installations)\n- `breaker [label: "Main isolator"]` \u2014 main switch / isolator that disconnects the entire installation, sized at or above the cut-out fuse rating\n- `ground_fault [rating: "\u2026A / 30mA Type AC", label: "Main RCD"]` \u2014 whole-installation residual-current device, 30 mA sensitivity, Type AC (the IEC 60364 default for circuits without significant DC residual content)\n- `bus [voltage: "230V", label: "Consumer-unit busbar"]` \u2014 the internal busbar of the consumer unit, rendered as a horizontal rail to which every branch device connects\n- `breaker [rating: "\u2026A B-curve" or "\u2026A C-curve", label: "MCB \u2026"]` \u2014 branch *miniature circuit breaker*: B-curve (3\u20135 \xD7 In) for resistive / lighting / general-sockets circuits, C-curve (5\u201310 \xD7 In) for inductive loads (kitchen ring, immersion heater) \u2014 per IEC 60898-1\n- `ground_fault [rating: "32A / 30mA Type B", label: "RCBO EV charger"]` \u2014 Type B RCBO is mandatory on EV charging circuits per IEC 60364-7-722 / HD 60364-7-722 because Mode-3 chargers can leak DC residual currents that blind a Type AC RCD\n- `load` \u2014 the final circuit served by each MCB / RCBO\n- `[cable: "\u2026 mm\xB2 Cu PVC|XLPE"]` \u2014 conductor cross-sectional area, copper, with PVC insulation for indoor cables and XLPE for outdoor / EV runs\n\n## How to read\n\nThe service head delivers single-phase 230 V at the cut-out fuse rating (63 A here). The kWh meter records consumption, then the main isolator gives a single-action means of disconnecting the entire installation for maintenance. Downstream of the isolator the main RCD provides shock protection at 30 mA Type AC for the bulk of branch circuits; from the consumer-unit busbar, six MCBs feed lighting, two socket circuits, a kitchen ring, a water heater, and an outdoor circuit. The EV charger does not share the main RCD \u2014 IEC 60364-7-722 requires a Type B RCBO on the charger circuit because the Mode-3 charge controller can produce smooth DC residual currents that a Type AC RCD cannot detect, leaving people unprotected against shock during a DC fault. Cable sizes scale with the MCB rating per the relevant national reference method (1.5 mm\xB2 for 6 A lighting, 2.5 mm\xB2 for 16 A sockets, 4 mm\xB2 for 20 A kitchen / heater, 6 mm\xB2 for the 32 A EV charger). An inspector reads the diagram top-down to verify the protection chain and the discrimination between the main RCD and the EV-circuit RCBO.'
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
"slug": "sld-residential-rebt-cgmp",
|
|
1251
|
+
"diagram": "sld",
|
|
1252
|
+
"title": "Residential CGMP \u2014 Spanish REBT vivienda",
|
|
1253
|
+
"description": "Cuadro General de Mando y Protecci\xF3n for a Spanish residence per REBT ITC-BT-17 \u2014 acometida, contador/ICP, IGA, diferencial Tipo A 30 mA, and per-circuit PIAs (MCBs) feeding lighting, sockets, kitchen, washer, bathroom, and HVAC circuits with H07V-K cables.",
|
|
1254
|
+
"standard": "REBT ITC-BT-17",
|
|
1255
|
+
"tags": [
|
|
1256
|
+
"sld",
|
|
1257
|
+
"residential",
|
|
1258
|
+
"rebt",
|
|
1259
|
+
"spain",
|
|
1260
|
+
"latam",
|
|
1261
|
+
"cgmp",
|
|
1262
|
+
"iga",
|
|
1263
|
+
"diferencial",
|
|
1264
|
+
"pia",
|
|
1265
|
+
"mcb",
|
|
1266
|
+
"iec-60364",
|
|
1267
|
+
"h07v-k",
|
|
1268
|
+
"esquema-unifilar"
|
|
1269
|
+
],
|
|
1270
|
+
"complexity": 2,
|
|
1271
|
+
"featured": true,
|
|
1272
|
+
"dsl": 'sld "Vivienda \u2014 CGMP REBT ITC-BT-17"\nACOM = utility [voltage: "230V", label: "Acometida 230V mono"]\nICP = watthour_meter [label: "Contador + ICP 25A"]\nIGA = breaker [rating: "40A curva C, 6kA", label: "IGA"]\nID = ground_fault [rating: "40A / 30mA Tipo A", label: "Diferencial general"]\nBUS = bus [voltage: "230V", label: "Embarrado CGMP"]\nC1 = breaker [rating: "10A curva C", label: "PIA C1"]\nC2 = breaker [rating: "16A curva C", label: "PIA C2"]\nC3 = breaker [rating: "25A curva C", label: "PIA C3"]\nC4 = breaker [rating: "20A curva C", label: "PIA C4"]\nC5 = breaker [rating: "16A curva C", label: "PIA C5"]\nC6 = breaker [rating: "25A curva C", label: "PIA C6"]\nL1 = load [label: "C1 Iluminaci\xF3n"]\nL2 = load [label: "C2 Tomas uso general"]\nL3 = load [label: "C3 Cocina + horno"]\nL4 = load [label: "C4 Lavadora / lavavajillas"]\nL5 = load [label: "C5 Tomas ba\xF1o y cocina"]\nL6 = load [label: "C6 Aerotermia / climatizaci\xF3n"]\nACOM -> ICP\nICP -> IGA\nIGA -> ID\nID -> BUS\nBUS -> C1\nC1 -> L1 [cable: "1.5 mm\xB2 Cu H07V-K"]\nBUS -> C2\nC2 -> L2 [cable: "2.5 mm\xB2 Cu H07V-K"]\nBUS -> C3\nC3 -> L3 [cable: "6 mm\xB2 Cu H07V-K"]\nBUS -> C4\nC4 -> L4 [cable: "4 mm\xB2 Cu H07V-K"]\nBUS -> C5\nC5 -> L5 [cable: "2.5 mm\xB2 Cu H07V-K"]\nBUS -> C6\nC6 -> L6 [cable: "6 mm\xB2 Cu H07V-K"]',
|
|
1273
|
+
"notes": '## Scenario\n\nA Spanish electrician (or an electrical-engineering student preparing the *Esquema Unifilar* for a course or permit) documents the *Cuadro General de Mando y Protecci\xF3n* (CGMP) of a single-family home. Spain\'s *Reglamento Electrot\xE9cnico para Baja Tensi\xF3n* (REBT) \xA7ITC-BT-17 is explicit about what the residential single-line must show: the incoming *acometida*, the utility-owned *Interruptor de Control de Potencia* (ICP) inside the meter cabinet, the consumer-owned *Interruptor General Autom\xE1tico* (IGA), one or more residual-current devices (*Diferenciales*), and a per-circuit *Peque\xF1o Interruptor Autom\xE1tico* (PIA / MCB) for every final circuit \u2014 typically C1 through C6 in a basic *grado de electrificaci\xF3n b\xE1sica* dwelling. The same pattern applies across Latin America (ABNT NBR 5410 in Brazil, NMX-J-098 in Mexico) and to most IEC-60364 jurisdictions, in contrast to NEC residential practice where the panel internals would normally live on a separate panel schedule.\n\n## Annotation key\n\n- `utility [voltage:..., label:...]` \u2014 *Acometida*: the 230 V single-phase service drop from the distribution network up to the meter cabinet\n- `watthour_meter [label:...]` \u2014 *Contador + ICP*: revenue meter and the utility\'s tamper-sealed power-limiter breaker (25 A here, contracted at 5.75 kW)\n- `breaker [rating:"\u2026A curva C, \u2026kA", label: "IGA"]` \u2014 *Interruptor General Autom\xE1tico*: customer-owned main breaker; REBT requires curve C and \u2265 6 kA breaking capacity for residential\n- `ground_fault [rating: "\u2026A / 30mA Tipo A", label: "Diferencial general"]` \u2014 Type-A residual-current device tripping at 30 mA per ITC-BT-17 \xA71.2 (Tipo A covers AC + pulsating DC residual currents from electronics and inverter loads)\n- `bus [voltage: "230V", label: "Embarrado CGMP"]` \u2014 common busbar inside the consumer unit; every PIA taps off this rail\n- `breaker [rating:"\u2026A curva C", label: "PIA Cn"]` \u2014 branch-circuit *PIA*: one MCB per final circuit, sized per ITC-BT-25 Table 1 (10 A lighting, 16 A general sockets, 20\u201325 A kitchen / washer / HVAC)\n- `load [label: "Cn \u2026"]` \u2014 the final circuit\'s loads grouped under their REBT circuit designation (C1\u2013C6)\n- `[cable: "\u2026 mm\xB2 Cu H07V-K"]` \u2014 conductor cross-sectional area, copper, single-core insulated H07V-K \u2014 the canonical cable type for residential indoor wiring per UNE-EN 50525\n\n## How to read\n\nPower enters at the *acometida* and reaches the meter cabinet, where the utility\'s ICP enforces the contracted 5.75 kW power limit. Past the meter, the customer\'s CGMP begins: the IGA isolates the whole installation; the *Diferencial general* (40 A, 30 mA, Type A) trips on any earth-leakage fault to protect against electric shock per ITC-BT-24 \xA74.1; downstream of the differential, the busbar fans out to six branch circuits \u2014 lighting (1.5 mm\xB2), general sockets (2.5 mm\xB2), kitchen and oven (6 mm\xB2), high-current appliances such as washer or dishwasher (4 mm\xB2), bathroom and kitchen sockets (2.5 mm\xB2), and the heat-pump / aerotermia (6 mm\xB2). Each branch passes through its own PIA (curve C, sized per ITC-BT-25) before reaching the final circuit, so a fault in any one circuit drops only that circuit, not the whole dwelling. An REBT inspector reads this diagram top-down to verify selectivity (PIA < differential < IGA < ICP) and that conductor sizing matches PIA rating per the \xA7ITC-BT-19 ampacity table.'
|
|
1274
|
+
},
|
|
1530
1275
|
{
|
|
1531
1276
|
"slug": "sld-substation-13kv",
|
|
1532
1277
|
"diagram": "sld",
|
|
@@ -1638,27 +1383,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1638
1383
|
"dsl": 'timing "SPI Transaction"\nCLK: pppppppp\nCS_N: 10000001\nMOSI: x======= data: ["0xAB","0xCD","0xEF","0x01","0x02","0x03","0x04","0x05"]\nMISO: zzzz==== data: ["","","","","0xFF","0x12","0x34","0x56"]',
|
|
1639
1384
|
"notes": "## Scenario\n\nA firmware engineer or hardware designer documents an 8-byte SPI master-to-slave transaction for a device driver review or datasheet. The WaveDrom-compatible syntax means the same DSL can be pasted directly into WaveDrom's online editor or embedded in documentation pipelines.\n\n## Annotation key\n\n- `p` \u2014 clock pulse (high period followed by low); each `p` is one clock cycle\n- `1` / `0` \u2014 logic high / logic low\n- `=` \u2014 data bus: stable data (value unchanged from previous cycle)\n- `x` \u2014 don't-care or undefined state (transition state)\n- `z` \u2014 high-impedance (floating / tri-state)\n- `data: [...]` \u2014 optional data labels for each stable segment, rendered inside the bus bar\n- `CS_N` \u2014 active-low chip select; `1` = deselected, `0` = selected\n\n## How to read\n\nThe clock runs for 8 cycles. CS_N goes low at cycle 1 and returns high at cycle 8, framing the transaction. MOSI (master out) sends 8 bytes starting at cycle 1. MISO (slave in) is high-Z for the first 4 cycles (slave preparing the response) then transitions to stable data bytes 5\u20138. The transaction completes when CS_N de-asserts."
|
|
1640
1385
|
},
|
|
1641
|
-
{
|
|
1642
|
-
"slug": "venn-audience-overlap-marketing",
|
|
1643
|
-
"diagram": "venn",
|
|
1644
|
-
"title": "Paid audience overlap \u2014 Meta \xD7 Google \xD7 TikTok",
|
|
1645
|
-
"description": "Three ad-platform audience overlap for performance marketing \u2014 Meta, Google, and TikTok intersection counts to guide budget allocation.",
|
|
1646
|
-
"standard": "Venn (1880)",
|
|
1647
|
-
"tags": [
|
|
1648
|
-
"venn",
|
|
1649
|
-
"audience",
|
|
1650
|
-
"meta",
|
|
1651
|
-
"google",
|
|
1652
|
-
"tiktok",
|
|
1653
|
-
"marketing",
|
|
1654
|
-
"overlap",
|
|
1655
|
-
"paid"
|
|
1656
|
-
],
|
|
1657
|
-
"complexity": 2,
|
|
1658
|
-
"featured": false,
|
|
1659
|
-
"dsl": 'venn "Q4 Holiday Campaign \u2014 Paid Audience Overlap"\nset meta "Meta (FB + IG)" [color: "#1877F2"]\nset google "Google Ads" [color: "#EA4335"]\nset tiktok "TikTok" [color: "#010101"]\nmeta & google : 18400\nmeta & tiktok : 24700\ngoogle & tiktok : 9200\nmeta & google & tiktok : 5100\nmeta only : 61000\ngoogle only : 38500\ntiktok only : 42300',
|
|
1660
|
-
"notes": '## Scenario\n\nA performance marketing manager is finalising the Q4 holiday campaign budget across three platforms. The Venn reveals that a meaningful audience of 5,100 users is targetable on all three channels simultaneously \u2014 this cohort will see the brand multiple times, so frequency capping is critical. The 61k Meta-exclusive pool is the largest single-platform opportunity, while TikTok\'s 42k exclusive reach justifies keeping it in the mix even at a higher CPM.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 one ad platform per circle\n- `A & B : n` \u2014 users reachable on both platforms (multi-touch risk)\n- `A only : n` \u2014 users reachable exclusively on one platform\n\n## How to read\n\nEach circle represents the targetable audience on one platform. Intersection counts show users reachable across multiple channels \u2014 useful for setting frequency caps and coordinating creative sequencing. The triple intersection (5,100) is the most saturated segment and should receive unified messaging. Exclusive regions show where each platform provides unique incremental reach that the others cannot access.'
|
|
1661
|
-
},
|
|
1662
1386
|
{
|
|
1663
1387
|
"slug": "venn-customer-segments",
|
|
1664
1388
|
"diagram": "venn",
|
|
@@ -1677,65 +1401,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1677
1401
|
"dsl": 'venn "Customer Segments \u2014 Q3 2025"\nset email "Email subscribers" [color: "#1E88E5"]\nset paid "Paid users" [color: "#E53935"]\nset mobile "Mobile app users" [color: "#43A047"]\nemail & paid : 1840\nemail & mobile : 920\npaid & mobile : 2100\nemail & paid & mobile : 650\nemail only : 12400\npaid only : 3200\nmobile only : 8700',
|
|
1678
1402
|
"notes": '## Scenario\n\nA lifecycle marketer is planning Q4 campaigns and needs to see which audiences overlap before deciding where to spend budget. The 650-strong triple intersection is the highest-LTV segment; the 12.4k email-only group is the biggest conversion opportunity. Putting the numbers on one Venn makes the gaps and overlaps argue for themselves in a 30-second leadership review.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 declare a circle\n- `A & B : n` \u2014 count in the intersection of A and B\n- `A only : n` \u2014 count exclusive to A\n\n## How to read\n\nEach circle is a total audience; each overlap is people who belong to multiple audiences. The triple intersection (email \u2229 paid \u2229 mobile, 650 users) is your most engaged cohort \u2014 the obvious group to upsell. The *email only* and *mobile only* exclusive regions are your largest activation opportunities because each represents users who have not yet crossed into the other channels.'
|
|
1679
1403
|
},
|
|
1680
|
-
{
|
|
1681
|
-
"slug": "venn-euler-taxonomy",
|
|
1682
|
-
"diagram": "venn",
|
|
1683
|
-
"title": "Euler diagram \u2014 animal kingdom containment",
|
|
1684
|
-
"description": "Euler containment diagram showing Animals \u2283 Vertebrates \u2283 Mammals \u2283 Primates \u2014 a nested subset visualization for biology class.",
|
|
1685
|
-
"standard": "Euler (1768)",
|
|
1686
|
-
"tags": [
|
|
1687
|
-
"euler",
|
|
1688
|
-
"venn",
|
|
1689
|
-
"taxonomy",
|
|
1690
|
-
"mammals",
|
|
1691
|
-
"vertebrates",
|
|
1692
|
-
"biology",
|
|
1693
|
-
"containment"
|
|
1694
|
-
],
|
|
1695
|
-
"complexity": 1,
|
|
1696
|
-
"featured": false,
|
|
1697
|
-
"dsl": 'venn "Animal Kingdom \u2014 Nested Containment"\nmode: euler\nset animals "Animals" [color: "#43A047"]\nset vertebrates "Vertebrates" [subset-of: animals, color: "#1E88E5"]\nset mammals "Mammals" [subset-of: vertebrates, color: "#FB8C00"]\nset primates "Primates" [subset-of: mammals, color: "#E53935"]',
|
|
1698
|
-
"notes": "## Scenario\n\nA biology teacher uses this Euler diagram to introduce taxonomic hierarchy on the first day of a classification unit. Unlike a Venn diagram \u2014 which implies partial overlap between circles \u2014 an Euler diagram shows true containment: every primate is a mammal, every mammal is a vertebrate, and every vertebrate is an animal. Students can immediately see that the sets are nested, not intersecting.\n\n## Annotation key\n\n- `mode: euler` \u2014 enables containment (subset) layout instead of partial overlap\n- `subset-of: ID` \u2014 declares that this set is fully enclosed within another\n- Nested rings from outermost to innermost: Animals \u2192 Vertebrates \u2192 Mammals \u2192 Primates\n\n## How to read\n\nRead from the outside in. The outermost ring (Animals) contains all others. Each inner ring is a strict subset of the ring enclosing it \u2014 no element can be in Primates without also being in Mammals, Vertebrates, and Animals. The space between Vertebrates and Mammals represents vertebrates that are not mammals (fish, amphibians, reptiles, birds). The space between Mammals and Primates represents mammals that are not primates (dogs, cats, whales, bats)."
|
|
1699
|
-
},
|
|
1700
|
-
{
|
|
1701
|
-
"slug": "venn-feature-comparison-tools",
|
|
1702
|
-
"diagram": "venn",
|
|
1703
|
-
"title": "Feature comparison \u2014 Notion vs. Obsidian vs. Roam",
|
|
1704
|
-
"description": "Three-way Venn of knowledge-management features across Notion, Obsidian, and Roam Research \u2014 for product teams benchmarking a new tool.",
|
|
1705
|
-
"standard": "Venn (1880)",
|
|
1706
|
-
"tags": [
|
|
1707
|
-
"venn",
|
|
1708
|
-
"feature-comparison",
|
|
1709
|
-
"notion",
|
|
1710
|
-
"obsidian",
|
|
1711
|
-
"roam",
|
|
1712
|
-
"product",
|
|
1713
|
-
"competitive"
|
|
1714
|
-
],
|
|
1715
|
-
"complexity": 2,
|
|
1716
|
-
"featured": false,
|
|
1717
|
-
"dsl": 'venn "Knowledge Management Tools \u2014 Feature Overlap"\nset notion "Notion" [color: "#000000"]\nset obsidian "Obsidian" [color: "#7C3AED"]\nset roam "Roam Research" [color: "#3B82F6"]\nnotion & obsidian : 3\nnotion & roam : 2\nobsidian & roam : 2\nnotion & obsidian & roam : 3\nnotion only : 8\nobsidian only : 6\nroam only : 4',
|
|
1718
|
-
"notes": "## Scenario\n\nA product manager is building a competitive teardown before a roadmap review. Rather than a spreadsheet of checkboxes, the Venn communicates at a glance which features are table stakes (the triple intersection), which are differentiators (exclusive regions), and which signal partnership opportunities or feature gaps. The counts here represent clusters of related capabilities, not raw feature counts.\n\n## Annotation key\n\n- `set ID \"Label\"` \u2014 one tool per circle\n- `A & B : n` \u2014 number of feature clusters shared by both tools\n- `A only : n` \u2014 feature clusters unique to one tool\n\n## How to read\n\nEach circle represents one tool's total feature set grouped into capability clusters. The triple intersection (3 clusters: block-based editing, bidirectional links, tagging) represents the baseline every modern knowledge tool must ship. Notion's exclusive region (8 clusters) reflects its broader collaboration and database surface area. Obsidian's exclusive region (6) reflects its plugin ecosystem and local-first architecture. Roam's exclusive region (4) reflects its outliner-first and daily-notes conventions."
|
|
1719
|
-
},
|
|
1720
|
-
{
|
|
1721
|
-
"slug": "venn-prisma-screening",
|
|
1722
|
-
"diagram": "venn",
|
|
1723
|
-
"title": "PRISMA systematic review \u2014 database screening",
|
|
1724
|
-
"description": "Three-database PRISMA deduplication Venn showing PubMed, Embase, and Cochrane overlap counts for a systematic literature review.",
|
|
1725
|
-
"standard": "PRISMA 2020",
|
|
1726
|
-
"tags": [
|
|
1727
|
-
"venn",
|
|
1728
|
-
"prisma",
|
|
1729
|
-
"systematic-review",
|
|
1730
|
-
"literature",
|
|
1731
|
-
"pubmed",
|
|
1732
|
-
"embase"
|
|
1733
|
-
],
|
|
1734
|
-
"complexity": 2,
|
|
1735
|
-
"featured": false,
|
|
1736
|
-
"dsl": 'venn "Database Screening \u2014 PRISMA Deduplication"\nset pubmed "PubMed" [color: "#1E88E5"]\nset embase "Embase" [color: "#E53935"]\nset cochrane "Cochrane" [color: "#43A047"]\npubmed & embase : 1240\npubmed & cochrane : 340\nembase & cochrane : 280\npubmed & embase & cochrane : 180\npubmed only : 4200\nembase only : 2800\ncochrane only : 620',
|
|
1737
|
-
"notes": '## Scenario\n\nA systematic reviewer searches PubMed, Embase, and Cochrane before title/abstract screening. Before any reading begins, duplicates must be removed \u2014 the same paper indexed in multiple databases would inflate the apparent evidence base. This Venn shows where the three databases overlap so the reviewer can report the PRISMA 2020 deduplication step with exact counts and transparently justify why 2,040 records were removed before screening began.\n\n## Annotation key\n\n- `set ID "Label"` \u2014 one database per circle\n- `A & B : n` \u2014 records indexed in both databases (potential duplicates)\n- `A only : n` \u2014 records unique to a single database\n\n## How to read\n\nEach circle represents one database\'s raw retrieval. Overlapping regions are records that appear in more than one source and are the primary deduplication targets. The triple intersection (180) means those papers were found in all three databases simultaneously. After removing all intersections as duplicates, the unique record count is 4 200 + 2 800 + 620 = 7 620 \u2014 the number that proceeds to title/abstract screening and is recorded in the PRISMA flow diagram.'
|
|
1738
|
-
},
|
|
1739
1404
|
{
|
|
1740
1405
|
"slug": "venn-programming-paradigms",
|
|
1741
1406
|
"diagram": "venn",
|
|
@@ -1758,15 +1423,15 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1758
1423
|
var SYNTAX = {
|
|
1759
1424
|
"genogram": {
|
|
1760
1425
|
"title": "Genogram",
|
|
1761
|
-
"content": '## 1. Your first genogram\n\nThe smallest clinically useful genogram: two parents, one child.\n\n```\ngenogram\n alice [female, 1980]\n bob [male, 1978]\n alice -- bob "m. 2005"\n carol [female, 2008]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `genogram`, optionally followed by a quoted title.\n2. Declare each person on their own line: `id [attributes]`. Attributes go in square brackets, comma-separated.\n3. Connect two people with a **couple operator** \u2014 `--` (marriage) here; see \xA74.1 for all six. A trailing quoted string is the relationship label.\n4. **Indent under the couple line** to add their children.\n\n> Comments must be on their own line, starting with `#`. Trailing inline comments (`bob [male, 1978] # ...`) are not supported and will break the parser \u2014 see \xA78.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `other` | Shape: square, circle, diamond, diamond |\n| Status | `deceased`, `stillborn`, `miscarriage`, `abortion` | Visual modifier (X-out, scaled shape, etc.) |\n| Birth year | 4-digit number, e.g. `1980` | First 4-digit token = birth year |\n| Death year | 4-digit number after birth, e.g. `1980, 2055` | Second 4-digit token = death year |\n| `index` | flag | Concentric shape = identified patient |\n| `unknown-siblings` | flag | Diamond with `?` \u2014 placeholder for \u22651 siblings of unknown count |\n| `age:N` | e.g. `age:42` | Age shown inside shape |\n| `death:YYYY` | e.g. `death:2020` | Explicit death year |\n| `label:"\u2026"` | e.g. `label:"Dr. Smith"` | Display label override |\n| `sibling-of:<id>` | e.g. `sibling-of:monica` | Pins same generation as the referenced sibling, draws a dashed bracket \u2014 for known relatives with unknown ancestry. |\n| `conditions:\u2026` | see \xA75 | Medical/psychological conditions |\n| `key:value` | any custom | Stored as metadata |\n\n```\ngenogram\n grandma [female, 1920, 2002, deceased]\n dad [male, 1950, age:74]\n me [male, 1985, index]\n daughter [female, 2012, label:"Em"]\n```\n\n---\n\n## 3. Shapes\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` | Male |\n| \u25CB Circle | `female` | Female |\n| \u25C7 Diamond | `unknown`, `other`, *or* attribute omitted | Unknown / unspecified |\n\nStatus modifiers layer on top of the base shape:\n\n```\ngenogram\n alive [male, 1960]\n passed [male, 1930, 2010, deceased]\n stillborn_child [unknown, stillborn]\n lost [unknown, miscarriage]\n```\n\n---\n\n## 4. Connections\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first one that matches wins \u2014 so `-x-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-x-` | divorced | `a -x- b` | Divorce |\n| `-/-` | separated | `a -/- b` | Separation (married) |\n| `-//` | separated | `a -// b` | Separation (alias for `-/-`) |\n| `-o-` | engaged | `a -o- b` | Engagement |\n| `==` | consanguineous | `a == b` | Blood-related couple |\n| `--` | married | `a -- b` | Marriage |\n| `~` | cohabiting | `a ~ b` | Cohabiting / LTR (current) |\n| `~/~` | cohabiting-ended | `a ~/~ b` | Cohabitation has ended (never-married). Common in LATAM child-protection caseloads where biological parents lived together unmarried and the relationship has since broken \u2014 distinct from `-x-` divorce (no marriage) and `-/-` separation (still married). |\n\nA trailing quoted string becomes the relationship label (`a -- b "m. 2005"`).\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand person hasn\'t been declared yet, you can declare them in-place:\n\n```\ngenogram\n ann [female, 1970]\n ann -- ben [male, 1968] "m. 1995"\n kim [female, 1997]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; by convention use 2 more spaces. Children are rendered in order of declaration (render also sorts by birth year when present).\n\n```\ngenogram\n dad [male, 1950]\n mom [female, 1952]\n dad -- mom\n eldest [male, 1975]\n middle [female, 1978, adopted]\n twin_a [male, 1985, twin-identical]\n twin_b [male, 1985, twin-identical]\n```\n\n**Special child attributes:**\n\n| Attribute | Effect |\n|---|---|\n| `adopted` | Adoption line style |\n| `foster` | Foster relationship |\n| `guardian` | Guardianship by a non-parent relative (e.g. grandparent custody). Same primitive as `foster` \u2014 drawn as a secondary "current caregiver" link when biological parents are also declared. |\n| `twin-identical` | Grouped with other `twin-identical` children of the same couple |\n| `twin-fraternal` | Grouped with other `twin-fraternal` children |\n| `unknown-siblings` | Single diamond with `?` glyph \u2014 "\u22651 siblings, count and identities unknown" (pedigree convention). |\n\n### 4.3.1 Dual-parent families (foster, adoption, guardianship)\n\nChildren placed with a non-biological caregiver while biological parents are still part of the case can be declared under both couples. **Declare the child with full attributes the first time** (under the biological couple), then **redeclare with just `[foster]` / `[adopted]` / `[guardian]`** under the current caregiver. The first declaration wins layout; the second is drawn as a secondary dotted "current caregiver" link that does not pull the child away from their biological position.\n\n```\ngenogram "Foster placement"\n bp1 [male, label: "Bio dad"]\n bp2 [female, label: "Bio mom"]\n bp1 ~/~ bp2\n child [male, 2018, index]\n fp1 [male, label: "Foster dad"]\n fp2 [female, label: "Foster mom"]\n fp1 -- fp2\n own [male, 2010]\n child [foster]\n```\n\nThe same primitive serves adoption (closed/open), foster placement, and guardianship by a relative \u2014 only the keyword differs. Re-declaration **merges** non-conflicting attributes (sex, birth year, label, `index` marker) into the original; declaring a conflicting `male` vs `female` raises a parse error rather than silently overwriting.\n\n### 4.3.2 Unknown-count siblings\n\nWhen a case file mentions "the child has siblings" without naming them, use either the `?` shorthand on its own line, or `[unknown-siblings]` on a regular id. Both render as a single diamond with a "?" glyph \u2014 the standard pedigree marker for "one or more siblings, identities unknown."\n\n```\ngenogram\n dad [male]\n mom [female]\n dad -- mom\n ?\n known_kid [male, 2018]\n```\n\n### 4.3.3 Sibling-of (known relative, unknown ancestry)\n\nTo express "X is a sibling of Y" without inventing parents, use the `sibling-of: <id>` property. The renderer pins X to Y\'s generation and draws a dashed bracket above the two \u2014 the standard pedigree convention for a known relative whose ancestry is not part of the case.\n\n```\ngenogram\n monica [female, 1990]\n uncle [male, label: "T\xEDo materno", sibling-of: monica]\n```\n\n### 4.4 Emotional relationships\n\nSeparate line, parser pattern `A -TYPE- B` (non-directional) or `A -TYPE-> B` (directional). An optional quoted label goes at the end. **Both individuals must already be declared** before the emotional line.\n\n```\nharry -cutoff- petunia # non-directional\nharry -hostile- dudley "since 1991"\nuncle -abuse-> nephew # directional (arrow)\n```\n\nAll 32 types the parser accepts today:\n\n| Category | Types |\n|---|---|\n| Positive / close | `harmony`, `close`, `bestfriends`, `love`, `inlove`, `friendship` |\n| Negative / hostile | `hostile`, `conflict`, `enmity`, `distant-hostile`, `cutoff` |\n| Ambivalent | `close-hostile`, `fused`, `fused-hostile` |\n| Distance | `distant`, `normal`, `nevermet` |\n| Abuse *(directional)* | `abuse`, `physical-abuse`, `emotional-abuse`, `sexual-abuse`, `neglect` |\n| Control *(directional)* | `manipulative`, `controlling`, `jealous` |\n| Special | `focused`, `focused-neg`, `distrust`, `admirer`, `limerence` |\n\n```\ngenogram\n dad [male, 1950]\n son [male, 1985]\n daughter [female, 1988]\n dad -close- daughter\n dad -conflict- son\n son -cutoff- dad "since 2010"\n```\n\n---\n\n## 5. Medical conditions\n\nSyntax: `conditions: name(fill) [+ name(fill, #color)]\u2026`\n\n```\nfather [male, 1945, conditions: heart(full, #E53935)]\nmother [female, 1948, conditions: diabetes(half-left) + anxiety(half-right, #26A69A)]\n```\n\n- **`name`** \u2014 any identifier you choose (displayed in legend/tooltip).\n- **`fill`** \u2014 required, controls which region of the shape is colored. See table below.\n- **`color`** \u2014 optional hex. Default depends on the renderer theme.\n- Multiple conditions are joined with `+`. Each needs its own `(fill)`.\n\n**Fill positions:**\n\n| `fill` value | Region |\n|---|---|\n| `full` | Entire shape |\n| `half-left` / `half-right` | Left / right half |\n| `half-top` / `half-bottom` | Top / bottom half |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | One quadrant |\n| `striped` | Diagonal stripe pattern (asymptomatic carrier) |\n| `dotted` | Dot pattern |\n\n```\ngenogram\n dad [male, 1950, conditions: heart(full, #E53935)]\n mom [female, 1952, conditions: diabetes(half-left) + depression(half-right, #5C6BC0)]\n dad -- mom\n son [male, 1980, conditions: carrier(striped)]\n```\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `genogram "Smith Family"` \u2014 first line only.\n- **Person label override:** `alice [female, label:"Dr. Alice Smith"]`.\n- **Relationship label:** trailing quoted string on a couple or emotional line \u2014 `alice -- bob "m. 2005"`.\n- **Comments:** `#` at the start of a line (after leading whitespace). Inline comments are **not** supported.\n\n```\ngenogram "Smith Family"\n # this line is a comment \u2014 fine\n alice [female, 1980] # \u2190 THIS trailing comment breaks the parser\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `genogram` (header keyword).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `~`, `~/~`, `==`, `-x-`, `-/-`, `-//`, `-o-`, and any `-<type>-` / `-<type>->` matching an emotional-relationship type.\n\n**Reserved id `?`** \u2014 bare `?` on a child line auto-generates a synthetic placeholder with the `unknown-siblings` marker. Do not use `?` as a real id.\n\n**Strings with spaces** must be double-quoted: titles, labels, `label:"\u2026"`. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `alex [nonbinary, 1995]` | `Unknown property \'nonbinary\'` | Use `unknown` or `other` (nonbinary is \xA713 Roadmap) |\n| `alice [female, transgender]` | `Unknown property \'transgender\'` | Not yet parseable (\xA713 Roadmap) |\n| `dad -- mom` \u2190 followed by `child [male, 2010]` at the **same indent** | Child parsed as a new top-level individual, not as their child | Indent the child line deeper than the couple line (2 spaces is enough) |\n| `A -- B` where `A` was never declared | `Unknown individual \'A\'` | Declare `A [sex, year]` on a line above |\n| `father -- mother "married"` on line 1 (no `genogram` header) | `Expected "genogram" header` | Start the file with `genogram` or `genogram "Title"` |\n| `conditions: diabetes + cancer` (no parens) | `Invalid condition format \'diabetes\'` | Add fill: `conditions: diabetes(half-left) + cancer(half-right)` |\n| `[triplet-identical]` | `Unknown property \'triplet-identical\'` | Triplets not yet parseable (\xA713 Roadmap) |\n| `dad -- mom # first marriage` | Trailing inline `#` comment is treated as part of the label / errors | Move the comment to its own line |\n| Same id declared twice with different sex (`x [male]` then `x [female]`) | `Conflicting sex for \'x\': previously \'male\', now \'female\'` | Pick one or rename one of the ids |\n| `child [foster]` redeclared but biological parents never declared | `child` becomes the foster couple\'s regular child (no secondary link drawn) | This is intentional \u2014 secondary links require an existing primary parent-child rel from a prior declaration |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | individual | couple-block | emotional)*\n\nheader = "genogram" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side ( WS quoted-string )? NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\n | INDENT "?" NEWLINE // unknown-count sibling shorthand\nright-side = id ( "[" attrs "]" )?\n\nemotional = INDENT id WS "-" type "-" id ( WS quoted-string )? NEWLINE\n | INDENT id WS "-" type "->" id ( WS quoted-string )? NEWLINE\n\ncoupleOp = "~/~" | "-//" | "-x-" | "-/-" | "-o-" | "==" | "--" | "~"\ntype = "harmony" | "close" | "bestfriends" | "love" | "inlove"\n | "friendship" | "hostile" | "conflict" | "enmity"\n | "distant-hostile" | "cutoff" | "close-hostile" | "fused"\n | "fused-hostile" | "distant" | "normal" | "nevermet"\n | "abuse" | "physical-abuse" | "emotional-abuse"\n | "sexual-abuse" | "neglect" | "manipulative" | "controlling"\n | "jealous" | "focused" | "focused-neg" | "distrust"\n | "admirer" | "limerence"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = "male" | "female" | "unknown" | "other"\n | "deceased" | "stillborn" | "miscarriage" | "abortion"\n | "adopted" | "foster" | "guardian"\n | "twin-identical" | "twin-fraternal"\n | "index" | "unknown-siblings"\n | digit digit digit digit // year\n | "age" ":" digits\n | "death" ":" digit digit digit digit\n | "label" ":" quoted-string\n | "sibling-of" ":" id\n | "conditions" ":" condition ("+" condition)*\n | key ":" value // custom\ncondition = name "(" fill ("," "#" hex)? ")"\nfill = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n | "striped" | "dotted"\n\ncomment = INDENT "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/genogram/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1426
|
+
"content": '## 1. Your first genogram\n\nThe smallest clinically useful genogram: two parents, one child.\n\n```\ngenogram\n alice [female, 1980]\n bob [male, 1978]\n alice -- bob "m. 2005"\n carol [female, 2008]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `genogram`, optionally followed by a quoted title.\n2. Declare each person on their own line: `id [attributes]`. Attributes go in square brackets, comma-separated.\n3. Connect two people with a **couple operator** \u2014 `--` (marriage) here; see \xA74.1 for all six. A trailing quoted string is the relationship label.\n4. **Indent under the couple line** to add their children.\n\n> Comments must be on their own line, starting with `#`, `//`, or Mermaid-style `%%`. Trailing inline comments (`bob [male, 1978] # ...`) are not supported and will break the parser \u2014 see \xA78.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `other` | Shape: square, circle, diamond, diamond |\n| Status | `deceased`, `stillborn`, `miscarriage`, `abortion` | Visual modifier (X-out, scaled shape, etc.) |\n| Birth year | 4-digit number, e.g. `1980` | First 4-digit token = birth year |\n| Death year | 4-digit number after birth, e.g. `1980, 2055` | Second 4-digit token = death year |\n| `index` | flag | Concentric shape = identified patient |\n| `unknown-siblings` | flag | Diamond with `?` \u2014 placeholder for \u22651 siblings of unknown count |\n| `age:N` | e.g. `age:42` | Age shown inside shape |\n| `death:YYYY` | e.g. `death:2020` | Explicit death year |\n| `label:"\u2026"` | e.g. `label:"Dr. Smith"` | Display label override |\n| `sibling-of:<id>` | e.g. `sibling-of:monica` | Pins same generation as the referenced sibling, draws a dashed bracket \u2014 for known relatives with unknown ancestry. |\n| `conditions:\u2026` | see \xA75 | Medical/psychological conditions |\n| `key:value` | any custom | Stored as metadata |\n\n```\ngenogram\n grandma [female, 1920, 2002, deceased]\n dad [male, 1950, age:74]\n me [male, 1985, index]\n daughter [female, 2012, label:"Em"]\n```\n\n---\n\n## 3. Shapes\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` | Male |\n| \u25CB Circle | `female` | Female |\n| \u25C7 Diamond | `unknown`, `other`, *or* attribute omitted | Unknown / unspecified |\n\nStatus modifiers layer on top of the base shape:\n\n```\ngenogram\n alive [male, 1960]\n passed [male, 1930, 2010, deceased]\n stillborn_child [unknown, stillborn]\n lost [unknown, miscarriage]\n```\n\n---\n\n## 4. Connections\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first one that matches wins \u2014 so `-x-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-x-` | divorced | `a -x- b` | Divorce |\n| `-/-` | separated | `a -/- b` | Separation (married) |\n| `-//` | separated | `a -// b` | Separation (alias for `-/-`) |\n| `-o-` | engaged | `a -o- b` | Engagement |\n| `==` | consanguineous | `a == b` | Blood-related couple |\n| `--` | married | `a -- b` | Marriage |\n| `~` | cohabiting | `a ~ b` | Cohabiting / LTR (current) |\n| `~/~` | cohabiting-ended | `a ~/~ b` | Cohabitation has ended (never-married). Common in LATAM child-protection caseloads where biological parents lived together unmarried and the relationship has since broken \u2014 distinct from `-x-` divorce (no marriage) and `-/-` separation (still married). |\n\nA trailing quoted string becomes the relationship label (`a -- b "m. 2005"`).\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand person hasn\'t been declared yet, you can declare them in-place:\n\n```\ngenogram\n ann [female, 1970]\n ann -- ben [male, 1968] "m. 1995"\n kim [female, 1997]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; by convention use 2 more spaces. Children are rendered in order of declaration (render also sorts by birth year when present).\n\n```\ngenogram\n dad [male, 1950]\n mom [female, 1952]\n dad -- mom\n eldest [male, 1975]\n middle [female, 1978, adopted]\n twin_a [male, 1985, twin-identical]\n twin_b [male, 1985, twin-identical]\n```\n\n**Special child attributes:**\n\n| Attribute | Effect |\n|---|---|\n| `adopted` | Adoption line style |\n| `foster` | Foster relationship |\n| `guardian` | Guardianship by a non-parent relative (e.g. grandparent custody). Same primitive as `foster` \u2014 drawn as a secondary "current caregiver" link when biological parents are also declared. |\n| `twin-identical` | Grouped with other `twin-identical` children of the same couple |\n| `twin-fraternal` | Grouped with other `twin-fraternal` children |\n| `unknown-siblings` | Single diamond with `?` glyph \u2014 "\u22651 siblings, count and identities unknown" (pedigree convention). |\n\n### 4.3.1 Dual-parent families (foster, adoption, guardianship)\n\nChildren placed with a non-biological caregiver while biological parents are still part of the case can be declared under both couples. **Declare the child with full attributes the first time** (under the biological couple), then **redeclare with just `[foster]` / `[adopted]` / `[guardian]`** under the current caregiver. The first declaration wins layout; the second is drawn as a secondary dotted "current caregiver" link that does not pull the child away from their biological position.\n\n```\ngenogram "Foster placement"\n bp1 [male, label: "Bio dad"]\n bp2 [female, label: "Bio mom"]\n bp1 ~/~ bp2\n child [male, 2018, index]\n fp1 [male, label: "Foster dad"]\n fp2 [female, label: "Foster mom"]\n fp1 -- fp2\n own [male, 2010]\n child [foster]\n```\n\nThe same primitive serves adoption (closed/open), foster placement, and guardianship by a relative \u2014 only the keyword differs. Re-declaration **merges** non-conflicting attributes (sex, birth year, label, `index` marker) into the original; declaring a conflicting `male` vs `female` raises a parse error rather than silently overwriting.\n\n### 4.3.2 Unknown-count siblings\n\nWhen a case file mentions "the child has siblings" without naming them, use either the `?` shorthand on its own line, or `[unknown-siblings]` on a regular id. Both render as a single diamond with a "?" glyph \u2014 the standard pedigree marker for "one or more siblings, identities unknown."\n\n```\ngenogram\n dad [male]\n mom [female]\n dad -- mom\n ?\n known_kid [male, 2018]\n```\n\n### 4.3.3 Sibling-of (known relative, unknown ancestry)\n\nTo express "X is a sibling of Y" without inventing parents, use the `sibling-of: <id>` property. The renderer pins X to Y\'s generation and draws a dashed bracket above the two \u2014 the standard pedigree convention for a known relative whose ancestry is not part of the case.\n\n```\ngenogram\n monica [female, 1990]\n uncle [male, label: "T\xEDo materno", sibling-of: monica]\n```\n\n### 4.4 Emotional relationships\n\nSeparate line, parser pattern `A -TYPE- B` (non-directional) or `A -TYPE-> B` (directional). An optional quoted label goes at the end. **Both individuals must already be declared** before the emotional line.\n\n```\nharry -cutoff- petunia # non-directional\nharry -hostile- dudley "since 1991"\nuncle -abuse-> nephew # directional (arrow)\n```\n\nAll 32 types the parser accepts today:\n\n| Category | Types |\n|---|---|\n| Positive / close | `harmony`, `close`, `bestfriends`, `love`, `inlove`, `friendship` |\n| Negative / hostile | `hostile`, `conflict`, `enmity`, `distant-hostile`, `cutoff` |\n| Ambivalent | `close-hostile`, `fused`, `fused-hostile` |\n| Distance | `distant`, `normal`, `nevermet` |\n| Abuse *(directional)* | `abuse`, `physical-abuse`, `emotional-abuse`, `sexual-abuse`, `neglect` |\n| Control *(directional)* | `manipulative`, `controlling`, `jealous` |\n| Special | `focused`, `focused-neg`, `distrust`, `admirer`, `limerence` |\n\n```\ngenogram\n dad [male, 1950]\n son [male, 1985]\n daughter [female, 1988]\n dad -close- daughter\n dad -conflict- son\n son -cutoff- dad "since 2010"\n```\n\n---\n\n## 5. Medical conditions\n\nSyntax: `conditions: name(fill) [+ name(fill, #color)]\u2026`\n\n```\nfather [male, 1945, conditions: heart(full, #E53935)]\nmother [female, 1948, conditions: diabetes(half-left) + anxiety(half-right, #26A69A)]\n```\n\n- **`name`** \u2014 any identifier you choose (displayed in legend/tooltip).\n- **`fill`** \u2014 required, controls which region of the shape is colored. See table below.\n- **`color`** \u2014 optional hex. Default depends on the renderer theme.\n- Multiple conditions are joined with `+`. Each needs its own `(fill)`.\n\n**Fill positions:**\n\n| `fill` value | Region |\n|---|---|\n| `full` | Entire shape |\n| `half-left` / `half-right` | Left / right half |\n| `half-top` / `half-bottom` | Top / bottom half |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | One quadrant |\n| `striped` | Diagonal stripe pattern (asymptomatic carrier) |\n| `dotted` | Dot pattern |\n\n```\ngenogram\n dad [male, 1950, conditions: heart(full, #E53935)]\n mom [female, 1952, conditions: diabetes(half-left) + depression(half-right, #5C6BC0)]\n dad -- mom\n son [male, 1980, conditions: carrier(striped)]\n```\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `genogram "Smith Family"` \u2014 first line only.\n- **Person label override:** `alice [female, label:"Dr. Alice Smith"]`.\n- **Relationship label:** trailing quoted string on a couple or emotional line \u2014 `alice -- bob "m. 2005"`.\n- **Comments:** `#`, `//`, or `%%` at the start of a line (after leading whitespace). Inline comments are **not** supported.\n\n```\ngenogram "Smith Family"\n # this line is a comment \u2014 fine\n %% Mermaid-style comment \u2014 also fine\n alice [female, 1980] # \u2190 THIS trailing comment breaks the parser\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `genogram` (header keyword).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `~`, `~/~`, `==`, `-x-`, `-/-`, `-//`, `-o-`, and any `-<type>-` / `-<type>->` matching an emotional-relationship type.\n\n**Reserved id `?`** \u2014 bare `?` on a child line auto-generates a synthetic placeholder with the `unknown-siblings` marker. Do not use `?` as a real id.\n\n**Strings with spaces** must be double-quoted: titles, labels, `label:"\u2026"`. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `alex [nonbinary, 1995]` | `Unknown property \'nonbinary\'` | Use `unknown` or `other` (nonbinary is \xA713 Roadmap) |\n| `alice [female, transgender]` | `Unknown property \'transgender\'` | Not yet parseable (\xA713 Roadmap) |\n| `dad -- mom` \u2190 followed by `child [male, 2010]` at the **same indent** | Child parsed as a new top-level individual, not as their child | Indent the child line deeper than the couple line (2 spaces is enough) |\n| `A -- B` where `A` was never declared | `Unknown individual \'A\'` | Declare `A [sex, year]` on a line above |\n| `father -- mother "married"` on line 1 (no `genogram` header) | `Expected "genogram" header` | Start the file with `genogram` or `genogram "Title"` |\n| `conditions: diabetes + cancer` (no parens) | `Invalid condition format \'diabetes\'` | Add fill: `conditions: diabetes(half-left) + cancer(half-right)` |\n| `[triplet-identical]` | `Unknown property \'triplet-identical\'` | Triplets not yet parseable (\xA713 Roadmap) |\n| `dad -- mom # first marriage` | Trailing inline `#` comment is treated as part of the label / errors | Move the comment to its own line |\n| Same id declared twice with different sex (`x [male]` then `x [female]`) | `Conflicting sex for \'x\': previously \'male\', now \'female\'` | Pick one or rename one of the ids |\n| `child [foster]` redeclared but biological parents never declared | `child` becomes the foster couple\'s regular child (no secondary link drawn) | This is intentional \u2014 secondary links require an existing primary parent-child rel from a prior declaration |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | individual | couple-block | emotional)*\n\nheader = "genogram" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side ( WS quoted-string )? NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\n | INDENT "?" NEWLINE // unknown-count sibling shorthand\nright-side = id ( "[" attrs "]" )?\n\nemotional = INDENT id WS "-" type "-" id ( WS quoted-string )? NEWLINE\n | INDENT id WS "-" type "->" id ( WS quoted-string )? NEWLINE\n\ncoupleOp = "~/~" | "-//" | "-x-" | "-/-" | "-o-" | "==" | "--" | "~"\ntype = "harmony" | "close" | "bestfriends" | "love" | "inlove"\n | "friendship" | "hostile" | "conflict" | "enmity"\n | "distant-hostile" | "cutoff" | "close-hostile" | "fused"\n | "fused-hostile" | "distant" | "normal" | "nevermet"\n | "abuse" | "physical-abuse" | "emotional-abuse"\n | "sexual-abuse" | "neglect" | "manipulative" | "controlling"\n | "jealous" | "focused" | "focused-neg" | "distrust"\n | "admirer" | "limerence"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = "male" | "female" | "unknown" | "other"\n | "deceased" | "stillborn" | "miscarriage" | "abortion"\n | "adopted" | "foster" | "guardian"\n | "twin-identical" | "twin-fraternal"\n | "index" | "unknown-siblings"\n | digit digit digit digit // year\n | "age" ":" digits\n | "death" ":" digit digit digit digit\n | "label" ":" quoted-string\n | "sibling-of" ":" id\n | "conditions" ":" condition ("+" condition)*\n | key ":" value // custom\ncondition = name "(" fill ("," "#" hex)? ")"\nfill = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n | "striped" | "dotted"\n\ncomment = INDENT ( "#" | "//" | "%%" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/genogram/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1762
1427
|
},
|
|
1763
1428
|
"ecomap": {
|
|
1764
1429
|
"title": "Ecomap",
|
|
1765
|
-
"content": '## 1. Your first ecomap\n\nThe smallest useful ecomap: one center and three outside systems.\n\n```\necomap\n center: client [label: "Maria"]\n mom [label: "Mother", category: family]\n work [label: "Tech Corp", category: work]\n therapist [label: "Dr. Patel", category: mental-health]\n mom === client\n work --- client\n therapist <-> client [label: "weekly"]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `ecomap`, optionally followed by a quoted title.\n2. Declare the center on its own line: `center: id [label: "\u2026"]`. Exactly one center per diagram.\n3. Declare each outside system on its own line: `id [label: "\u2026", category: \u2026]`.\n4. Connect any two declared IDs with a **connection operator** \u2014 `===` (strong), `---` (normal), `<->` (reciprocal), etc. See \xA73 for the full table. A trailing `[label: "\u2026"]` adds an edge label.\n\n> Comments must be on their own line, starting with
|
|
1430
|
+
"content": '## 1. Your first ecomap\n\nThe smallest useful ecomap: one center and three outside systems.\n\n```\necomap\n center: client [label: "Maria"]\n mom [label: "Mother", category: family]\n work [label: "Tech Corp", category: work]\n therapist [label: "Dr. Patel", category: mental-health]\n mom === client\n work --- client\n therapist <-> client [label: "weekly"]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `ecomap`, optionally followed by a quoted title.\n2. Declare the center on its own line: `center: id [label: "\u2026"]`. Exactly one center per diagram.\n3. Declare each outside system on its own line: `id [label: "\u2026", category: \u2026]`.\n4. Connect any two declared IDs with a **connection operator** \u2014 `===` (strong), `---` (normal), `<->` (reciprocal), etc. See \xA73 for the full table. A trailing `[label: "\u2026"]` adds an edge label.\n\n> Comments must be on their own line, starting with `#`, `//`, or Mermaid-style `%%`. Inline trailing comments will break the parser.\n\n---\n\n## 2. Center and outside systems\n\nEvery ecomap has one **center** and any number of **outside systems**. Both use the same `id [attrs]` syntax; the only difference is the `center:` prefix.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive; the original token is kept as the default label.\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| `label:"\u2026"` | any quoted string | Display label override |\n| `category:\u2026` | see \xA72.1 | Color / grouping of a system node |\n| `size:\u2026` | `small`, `medium`, `large` | Node size |\n| `importance:\u2026` | `major`, `moderate`, `minor` | Visual weight |\n| `sector:\u2026` | `top`, `right`, `bottom`, `left` | Hint for which side of the center the system sits on |\n| `age:N` | e.g. `age:34` | Age shown inside a person-typed center |\n| `male` / `female` / `unknown` | flag | Sex for a person-typed center |\n\n### 2.1 System categories\n\nCategories color-code outside systems by the life domain they belong to. The parser accepts any string \u2014 these are the values the renderer has themed palettes for:\n\n| Category | Typical examples |\n|---|---|\n| `family` | Extended family, in-laws, cousins |\n| `friends` | Friends, neighbors |\n| `work` | Employer, coworkers |\n| `education` | School, college, training program |\n| `health` | Primary care, specialist, hospital |\n| `mental-health` | Therapist, psychiatrist, support group |\n| `religion` | Church, temple, spiritual community |\n| `recreation` | Sports, hobbies, clubs |\n| `legal` | Lawyer, probation, court |\n| `government` | Social services, housing, immigration |\n| `financial` | Bank, benefits, financial aid |\n| `community` | Neighborhood groups, sponsors |\n| `cultural` | Cultural/ethnic organizations |\n| `substance` | Recovery programs or, if negative, active-use sources |\n| `technology` | Online community, support forum |\n| `pet` | Pets, service animals |\n\n```\necomap\n center: client [label: "Marcus, age 15"]\n mom [label: "Mother", category: family]\n dad [label: "Father (divorced)", category: family]\n school [label: "East High School", category: education]\n coach [label: "Soccer Coach", category: community]\n therapist [label: "Ms. Chen", category: mental-health]\n mom === client\n dad --- client [label: "EOW weekends"]\n school === client\n coach --> client [label: "mentor"]\n therapist <-> client [label: "weekly"]\n```\n\n---\n\n## 3. Connections\n\nA connection is one line: `fromId OP toId` optionally followed by `[label: "\u2026"]`. Both IDs must already be declared (center counts).\n\n### 3.1 Relationship-quality operators\n\n| Operator | Type | Meaning |\n|---|---|---|\n| `===` | strong | Close, supportive, high-frequency |\n| `==` | moderate | Positive, moderate involvement |\n| `---` | normal | Neutral / average |\n| `- -` | weak | Tenuous, fragile, early-stage |\n| `~~~` | stressful | Stressful relationship |\n| `~=~` | stressful-strong | Close *and* stressful |\n| `~x~` | conflictual | Active conflict |\n| `-/-` | broken | Severed, estranged, cutoff |\n\n### 3.2 Energy-flow operators\n\nLayer arrow direction onto strong or normal lines:\n\n| Operator | Meaning |\n|---|---|\n| `-->` | One-way: energy flows from center to system |\n| `<--` | One-way: energy flows from system to center |\n| `<->` | Reciprocal / bidirectional |\n| `===>` | Strong one-way outflow (draining) |\n| `<===` | Strong one-way inflow (nourishing) |\n| `<=>` | Strong reciprocal |\n| `==>` | Moderate one-way outflow |\n| `<==` | Moderate one-way inflow |\n\nThe parser normalizes direction so arrows read relative to the center. Writing `family === resettlement` and `resettlement === family` produces the same diagram; writing `clinic --> family` vs `family <-- clinic` likewise produces the same arrow pointing *from* the clinic *to* the family.\n\n```\necomap\n center: client [label: "Rosa"]\n mom [category: family]\n ex [category: family]\n aa [label: "AA Group", category: substance]\n job [label: "Warehouse", category: work]\n mom === client [label: "daily calls"]\n ex ~x~ client [label: "custody disputes"]\n aa <== client [label: "sponsor support"]\n job - - client [label: "unstable hours"]\n```\n\n### 3.3 Edge labels\n\nA trailing `[label: "\u2026"]` is the only attribute a connection line accepts. Put schedule, nature, or a short note here:\n\n```\nfamily === temple [label: "weekly service"]\nclinic --> family [label: "vaccinations"]\ncaseworker <-> family [label: "every Tuesday"]\n```\n\n---\n\n## 4. Labels & comments\n\n- **Title:** `ecomap "Nguyen Family"` \u2014 first line only.\n- **Node label override:** `family [label: "The Nguyens"]`.\n- **Edge label:** trailing `[label: "\u2026"]` on a connection line.\n- **Mode suffix:** `ecomap:strengths "Smith family"` is accepted. The suffix is stored as `metadata.mode`; current renderers ignore it.\n- **Comments:** `#`, `//`, or `%%` at the start of a line (after leading whitespace). Inline trailing comments are **not** supported.\n\n```\necomap "Marcus Intake"\n # caseworker\'s notes \u2014 fine\n // also fine\n %% Mermaid-style comments are fine\n mom [category: family] # \u2190 THIS trailing comment breaks the parser\n```\n\n---\n\n## 5. Reserved words & escaping\n\n**Reserved at line start:** `ecomap`, `center:`.\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`===`, `==`, `---`, `- -`, `~~~`, `~=~`, `~x~`, `-/-`, and the directional variants listed in \xA73.2.\n\n**Strings with spaces** must be double-quoted: titles and any label. Single quotes and backticks are not recognized.\n\n---\n\n## 6. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `family -- school` | `Unexpected: family -- school` | Ecomap uses `===`/`---`/`<->` etc. `--` is a genogram/pedigree operator |\n| `family === school` where `school` was never declared | Silently creates an empty `school` node with no label/category | Declare systems above their connection lines |\n| No `center:` anywhere | Renders but with no visual center anchor | Every ecomap needs exactly one `center:` line |\n| Two `center:` lines | Only the first is treated as center; the second becomes a regular system | Pick one |\n| `family==school` (no spaces) | `Unexpected: family==school` | Operators require a space on each side |\n| `family === school [weekly]` | Bare token `weekly` is parsed as a property flag, no label shown | Use `[label: "weekly"]` |\n| `family === school # daily` | Trailing `#` is consumed as part of the line | Move the comment above |\n\n---\n\n## 7. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | center | system | connection)*\n\nheader = "ecomap" ( ":" mode )? ( WS quoted-string )? NEWLINE\nmode = [A-Za-z] [A-Za-z0-9_-]*\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\ncenter = "center:" WS id ( "[" attrs "]" )? NEWLINE\nsystem = id ( "[" attrs "]" )? NEWLINE\nconnection = id WS op WS id ( WS "[" "label:" quoted-string "]" )? NEWLINE\n\nop = "===" | "==" | "---" | "- -" | "~~~" | "~=~" | "~x~" | "-/-"\n | "===>" | "<===" | "<=>" | "==>" | "<=="\n | "-->" | "<--" | "<->"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = "label" ":" quoted-string\n | "category" ":" category\n | "size" ":" ("small" | "medium" | "large")\n | "importance" ":" ("major" | "moderate" | "minor")\n | "sector" ":" ("top" | "right" | "bottom" | "left")\n | "age" ":" digits\n | "male" | "female" | "unknown"\n | key ":" value // custom, stored as metadata\n\ncategory = "family" | "friends" | "work" | "education" | "health"\n | "mental-health" | "religion" | "recreation" | "legal"\n | "government" | "financial" | "community" | "cultural"\n | "substance" | "technology" | "pet" | "other"\n\ncomment = ( "#" | "//" | "%%" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/ecomap/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1766
1431
|
},
|
|
1767
1432
|
"pedigree": {
|
|
1768
1433
|
"title": "Pedigree",
|
|
1769
|
-
"content": '## 1. Your first pedigree\n\nThe smallest clinically useful pedigree: two parents and their affected child.\n\n```\npedigree\n I-1 [male, carrier]\n I-2 [female, carrier]\n I-1 -- I-2\n II-1 [male, affected, proband]\n II-2 [female, unaffected]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `pedigree`, optionally followed by a quoted title.\n2. Declare each individual on their own line: `id [attributes]`. Conventionally IDs are `I-1`, `II-3`, etc. \u2014 Roman-numeral generation, dash, position within the generation.\n3. Connect two individuals with a **couple operator** \u2014 `--` (mated), `==` (consanguineous), `-/-` (separated), `~` (no offspring). See \xA74.\n4. **Indent under the couple line** to add their children. Any deeper indent works; two spaces is conventional.\n\n> Comments must be on their own line, starting with `#`. Inline trailing comments will break the parser.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `amab`, `afab`, `uaab` | Shape: square, circle, diamond (see \xA73) |\n| Genetic status | `unaffected`, `affected`, `carrier`, `carrier-x`, `obligate-carrier`, `presymptomatic` | Fill / inner marker (see \xA73) |\n| Marker | `proband`, `consultand`, `evaluated` | Arrow + letter annotation (see \xA73.3) |\n| Life status | `deceased`, `stillborn`, `pregnancy`, `sab`, `tab`, `ectopic` | Visual modifier |\n| Birth year | 4-digit number, e.g. `1958` | Shown below shape |\n| `label:"\u2026"` | any quoted string | Display label override |\n| `affected: trait1+trait2` | see \xA75 | Multi-trait quadrant fill |\n\n```\npedigree\n I-1 [male, 1942, deceased]\n I-2 [female, 1945, affected, deceased]\n II-1 [female, affected, proband, label: "Jane (42)"]\n II-2 [male, evaluated]\n II-3 [female, presymptomatic]\n```\n\n---\n\n## 3. Shapes, status, markers\n\n### 3.1 Shapes (Bennett 2022)\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` or `amab` | Assigned male at birth |\n| \u25CB Circle | `female` or `afab` | Assigned female at birth |\n| \u25C7 Diamond | `unknown`, `uaab`, or omitted | Unknown / DSD / not disclosed / in utero |\n\nBennett 2022 formalized that square and circle represent **assigned sex at birth**, not gender identity. If gender identity differs, record it in the label (`[female, label: "Trans man (AFAB)"]`) \u2014 do not change the shape.\n\n### 3.2 Genetic status (fill)\n\n| Status | Meaning |\n|---|---|\n| (default, no status token) | Unaffected \u2014 empty shape |\n| `unaffected` | Explicit unaffected |\n| `affected` | Fully filled shape |\n| `carrier` | Half-filled \u2014 autosomal carrier |\n| `carrier-x` | Center dot \u2014 X-linked carrier female |\n| `obligate-carrier` | Center dot \u2014 inferred from pedigree structure |\n| `presymptomatic` | Vertical line through shape \u2014 tested positive, no clinical signs yet |\n\n```\npedigree\n I-1 [male, unaffected]\n I-2 [female, affected]\n I-3 [female, carrier]\n I-4 [female, carrier-x]\n I-5 [male, obligate-carrier]\n I-6 [female, presymptomatic]\n```\n\n### 3.3 Markers\n\n| Marker | Meaning |\n|---|---|\n| `proband` | Arrow + "P" \u2014 the index case who triggered the referral |\n| `consultand` | Arrow + "C" \u2014 the person who sought genetic counseling |\n| `evaluated` | "E" \u2014 evaluated but no positive finding recorded |\n\n### 3.4 Life status\n\n| Value | Meaning |\n|---|---|\n| `deceased` | Diagonal slash across the shape |\n| `stillborn` | Small shape + "SB" label |\n| `pregnancy` | Shape + "P" label, or diamond if sex unknown |\n| `sab` | Small triangle \u2014 spontaneous abortion |\n| `tab` | Small triangle with bar \u2014 terminated pregnancy |\n| `ectopic` | Small triangle + "ECT" label |\n\nMultiple tokens combine: `[female, affected, deceased]`, `[male, sab]`, `[unknown, pregnancy, presymptomatic]`.\n\n---\n\n## 4. Couples and children\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first match wins \u2014 so `-/-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-/-` | separated | `a -/- b` | Mated pair, no longer together |\n| `==` | consanguineous | `a == b` | Blood-related union (clinically critical) |\n| `--` | married | `a -- b` | Mated pair with offspring |\n| `~` | cohabiting | `a ~ b` | Partners without offspring |\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand individual has not been declared yet, declare them in place:\n\n```\npedigree\n I-1 [female, carrier]\n I-1 -- I-2 [male, unaffected]\n II-1 [female, affected, proband]\n II-2 [male, carrier]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; two spaces is conventional.\n\n```\npedigree "Cystic Fibrosis \u2014 autosomal recessive"\n I-1 [male, carrier]\n I-2 [female, carrier]\n I-1 -- I-2\n II-1 [male, affected, proband]\n II-2 [female, carrier]\n II-3 [male, unaffected]\n```\n\n### 4.4 Consanguineous unions\n\nConsanguinity is rendered as a double line and must be made visible \u2014 it is the single most load-bearing piece of information on many pedigrees.\n\n```\npedigree "Consanguineous union"\n I-1 [male, carrier]\n I-2 [female, unaffected]\n I-1 -- I-2\n II-1 [male, carrier]\n I-3 [male, unaffected]\n I-4 [female, carrier]\n I-3 -- I-4\n II-3 [female, carrier]\n II-1 == II-3\n III-1 [male, affected, proband]\n```\n\n---\n\n## 5. Multi-trait pedigrees\n\nFor families that carry more than one heritable condition, use `legend:` lines to define which quadrant of the shape represents which trait, then tag individuals with `affected: trait1+trait2`.\n\n```\npedigree "Cancer Family Syndrome"\n legend: breast = "Breast cancer" (fill: quad-tl)\n legend: ovarian = "Ovarian cancer" (fill: quad-tr)\n legend: prostate = "Prostate cancer" (fill: quad-bl)\n legend: colon = "Colon cancer" (fill: quad-br)\n\n I-1 [male, affected: prostate, deceased]\n I-2 [female, affected: breast, deceased]\n I-1 -- I-2\n II-1 [female, affected: breast+ovarian]\n II-2 [male, unaffected]\n```\n\n**Legend syntax:** `legend: id = "Human label" (fill: POSITION)`.\n\n| `fill` position | Region |\n|---|---|\n| `full` | Entire shape (default if `(fill: \u2026)` omitted) |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | Top-left / top-right / bottom-left / bottom-right quadrant |\n| `half-left` / `half-right` / `half-top` / `half-bottom` | A half of the shape |\n\nIndividuals use the legend trait IDs: `[affected: breast]`, `[affected: breast+ovarian]`. The `+` joins traits; quadrants fill cumulatively.\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `pedigree "BRCA1 Family"` \u2014 first line only.\n- **Individual label override:** `II-1 [female, affected, label: "Jane Smith (42)"]`.\n- **Legend entry:** `legend: id = "Label" (fill: POSITION)` \u2014 see \xA75.\n- **Comments:** `#` or `//` at the start of a line (after leading whitespace). Inline trailing comments are **not** supported.\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `pedigree` (header), `legend:` (legend entry).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `==`, `-/-`, `~`.\n\n**Reserved attribute tokens** inside `[\u2026]` \u2014 the parser will interpret these regardless of position: sex tokens (`male`, `female`, `unknown`, `amab`, `afab`, `uaab`), genetic statuses (`affected`, `carrier`, `carrier-x`, `obligate-carrier`, `presymptomatic`, `unaffected`), markers (`proband`, `consultand`, `evaluated`), and life statuses (`deceased`, `stillborn`, `pregnancy`, `sab`, `tab`, `ectopic`).\n\n**Strings with spaces** must be double-quoted. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `II-1 -- II-4` where `II-4` was never declared | `Unknown individual \'II-4\'` | Declare `II-4` above, or use inline form: `II-1 -- II-4 [male, unaffected]` |\n| `II-1 [nonbinary]` | Silently stored as a custom property; shape stays diamond | Bennett 2022 distinguishes assigned sex from gender \u2014 use `amab`/`afab`/`uaab` and record identity in `label:` |\n| `II-3 [twin-mz]` | Stored as a custom property; no twin line rendered | Twin notation is \xA710 Roadmap |\n| `I-1 -- I-2` followed by `II-1 [male]` at the **same indent** | Child parsed as a new top-level individual, not as offspring | Indent the child line deeper than the couple line |\n| `I-1 [affected: breast]` with no matching `legend:` | Trait ID stored but no legend-keyed fill is rendered | Add `legend: breast = "\u2026" (fill: quad-tl)` above |\n| `II-1[affected]` (no space, no attrs split) | Works for a single token; breaks when a second attribute is added | Always separate `id` and `[\u2026]` with a space |\n| Line 1 is `I-1 [male]` with no `pedigree` header | `Expected "pedigree" header` | Start with `pedigree` or `pedigree "Title"` |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | legend | individual | couple-block)*\n\nheader = "pedigree" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nlegend = INDENT "legend:" WS id WS "=" WS quoted-string\n ( WS "(" "fill:" fill-value ")" )? NEWLINE\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\nright-side = id ( "[" attrs "]" )?\n\ncoupleOp = "-/-" | "==" | "--" | "~"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = sex\n | genetic-status\n | marker\n | life-status\n | digit digit digit digit // birth year\n | "label" ":" quoted-string\n | "affected" ":" trait-id ( "+" trait-id )*\n | key ":" value // custom\n\nsex = "male" | "female" | "unknown" | "amab" | "afab" | "uaab"\ngenetic-status = "unaffected" | "affected" | "carrier" | "carrier-x"\n | "obligate-carrier" | "presymptomatic"\nmarker = "proband" | "consultand" | "evaluated"\nlife-status = "deceased" | "stillborn" | "pregnancy"\n | "sab" | "tab" | "ectopic"\nfill-value = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n\ncomment = INDENT ( "#" | "//" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/pedigree/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1434
|
+
"content": '## 1. Your first pedigree\n\nThe smallest clinically useful pedigree: two parents and their affected child.\n\n```\npedigree\n I-1 [male, carrier]\n I-2 [female, carrier]\n I-1 -- I-2\n II-1 [male, affected, proband]\n II-2 [female, unaffected]\n```\n\nFour rules cover 80% of usage:\n\n1. Start with the keyword `pedigree`, optionally followed by a quoted title.\n2. Declare each individual on their own line: `id [attributes]`. Conventionally IDs are `I-1`, `II-3`, etc. \u2014 Roman-numeral generation, dash, position within the generation.\n3. Connect two individuals with a **couple operator** \u2014 `--` (mated), `==` (consanguineous), `-/-` (separated), `~` (no offspring). See \xA74.\n4. **Indent under the couple line** to add their children. Any deeper indent works; two spaces is conventional.\n\n> Comments must be on their own line, starting with `#`, `//`, or Mermaid-style `%%`. Inline trailing comments will break the parser.\n\n---\n\n## 2. Individuals\n\nAn individual line is `id [attr1, attr2, \u2026]`. Attributes are comma-separated, order-independent, all optional.\n\n**ID rules.** Must match `[a-zA-Z][a-zA-Z0-9_-]*`. IDs are case-insensitive internally but preserve their original casing as the display label (override with `label:"\u2026"`).\n\n**Attributes accepted by the parser today:**\n\n| Attribute | Values | Effect |\n|---|---|---|\n| Sex | `male`, `female`, `unknown`, `amab`, `afab`, `uaab` | Shape: square, circle, diamond (see \xA73) |\n| Genetic status | `unaffected`, `affected`, `carrier`, `carrier-x`, `obligate-carrier`, `presymptomatic` | Fill / inner marker (see \xA73) |\n| Marker | `proband`, `consultand`, `evaluated` | Arrow + letter annotation (see \xA73.3) |\n| Life status | `deceased`, `stillborn`, `pregnancy`, `sab`, `tab`, `ectopic` | Visual modifier |\n| Birth year | 4-digit number, e.g. `1958` | Shown below shape |\n| `label:"\u2026"` | any quoted string | Display label override |\n| `affected: trait1+trait2` | see \xA75 | Multi-trait quadrant fill |\n\n```\npedigree\n I-1 [male, 1942, deceased]\n I-2 [female, 1945, affected, deceased]\n II-1 [female, affected, proband, label: "Jane (42)"]\n II-2 [male, evaluated]\n II-3 [female, presymptomatic]\n```\n\n---\n\n## 3. Shapes, status, markers\n\n### 3.1 Shapes (Bennett 2022)\n\n| Visual | Sex value | Meaning |\n|---|---|---|\n| \u2610 Square | `male` or `amab` | Assigned male at birth |\n| \u25CB Circle | `female` or `afab` | Assigned female at birth |\n| \u25C7 Diamond | `unknown`, `uaab`, or omitted | Unknown / DSD / not disclosed / in utero |\n\nBennett 2022 formalized that square and circle represent **assigned sex at birth**, not gender identity. If gender identity differs, record it in the label (`[female, label: "Trans man (AFAB)"]`) \u2014 do not change the shape.\n\n### 3.2 Genetic status (fill)\n\n| Status | Meaning |\n|---|---|\n| (default, no status token) | Unaffected \u2014 empty shape |\n| `unaffected` | Explicit unaffected |\n| `affected` | Fully filled shape |\n| `carrier` | Half-filled \u2014 autosomal carrier |\n| `carrier-x` | Center dot \u2014 X-linked carrier female |\n| `obligate-carrier` | Center dot \u2014 inferred from pedigree structure |\n| `presymptomatic` | Vertical line through shape \u2014 tested positive, no clinical signs yet |\n\n```\npedigree\n I-1 [male, unaffected]\n I-2 [female, affected]\n I-3 [female, carrier]\n I-4 [female, carrier-x]\n I-5 [male, obligate-carrier]\n I-6 [female, presymptomatic]\n```\n\n### 3.3 Markers\n\n| Marker | Meaning |\n|---|---|\n| `proband` | Arrow + "P" \u2014 the index case who triggered the referral |\n| `consultand` | Arrow + "C" \u2014 the person who sought genetic counseling |\n| `evaluated` | "E" \u2014 evaluated but no positive finding recorded |\n\n### 3.4 Life status\n\n| Value | Meaning |\n|---|---|\n| `deceased` | Diagonal slash across the shape |\n| `stillborn` | Small shape + "SB" label |\n| `pregnancy` | Shape + "P" label, or diamond if sex unknown |\n| `sab` | Small triangle \u2014 spontaneous abortion |\n| `tab` | Small triangle with bar \u2014 terminated pregnancy |\n| `ectopic` | Small triangle + "ECT" label |\n\nMultiple tokens combine: `[female, affected, deceased]`, `[male, sab]`, `[unknown, pregnancy, presymptomatic]`.\n\n---\n\n## 4. Couples and children\n\n### 4.1 Couple operators\n\nThe parser tries these in order. The first match wins \u2014 so `-/-` beats `--`.\n\n| Operator | Type | Example | Meaning |\n|---|---|---|---|\n| `-/-` | separated | `a -/- b` | Mated pair, no longer together |\n| `==` | consanguineous | `a == b` | Blood-related union (clinically critical) |\n| `--` | married | `a -- b` | Mated pair with offspring |\n| `~` | cohabiting | `a ~ b` | Partners without offspring |\n\n### 4.2 Inline individual on the right side\n\nIf the right-hand individual has not been declared yet, declare them in place:\n\n```\npedigree\n I-1 [female, carrier]\n I-1 -- I-2 [male, unaffected]\n II-1 [female, affected, proband]\n II-2 [male, carrier]\n```\n\n### 4.3 Children (indented under a couple)\n\nIndentation under a couple line = "these are the children of this couple." Any indent greater than the couple\'s indent works; two spaces is conventional.\n\n```\npedigree "Cystic Fibrosis \u2014 autosomal recessive"\n I-1 [male, carrier]\n I-2 [female, carrier]\n I-1 -- I-2\n II-1 [male, affected, proband]\n II-2 [female, carrier]\n II-3 [male, unaffected]\n```\n\n### 4.4 Consanguineous unions\n\nConsanguinity is rendered as a double line and must be made visible \u2014 it is the single most load-bearing piece of information on many pedigrees.\n\n```\npedigree "Consanguineous union"\n I-1 [male, carrier]\n I-2 [female, unaffected]\n I-1 -- I-2\n II-1 [male, carrier]\n I-3 [male, unaffected]\n I-4 [female, carrier]\n I-3 -- I-4\n II-3 [female, carrier]\n II-1 == II-3\n III-1 [male, affected, proband]\n```\n\n---\n\n## 5. Multi-trait pedigrees\n\nFor families that carry more than one heritable condition, use `legend:` lines to define which quadrant of the shape represents which trait, then tag individuals with `affected: trait1+trait2`.\n\n```\npedigree "Cancer Family Syndrome"\n legend: breast = "Breast cancer" (fill: quad-tl)\n legend: ovarian = "Ovarian cancer" (fill: quad-tr)\n legend: prostate = "Prostate cancer" (fill: quad-bl)\n legend: colon = "Colon cancer" (fill: quad-br)\n\n I-1 [male, affected: prostate, deceased]\n I-2 [female, affected: breast, deceased]\n I-1 -- I-2\n II-1 [female, affected: breast+ovarian]\n II-2 [male, unaffected]\n```\n\n**Legend syntax:** `legend: id = "Human label" (fill: POSITION)`.\n\n| `fill` position | Region |\n|---|---|\n| `full` | Entire shape (default if `(fill: \u2026)` omitted) |\n| `quad-tl` / `quad-tr` / `quad-bl` / `quad-br` | Top-left / top-right / bottom-left / bottom-right quadrant |\n| `half-left` / `half-right` / `half-top` / `half-bottom` | A half of the shape |\n\nIndividuals use the legend trait IDs: `[affected: breast]`, `[affected: breast+ovarian]`. The `+` joins traits; quadrants fill cumulatively.\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `pedigree "BRCA1 Family"` \u2014 first line only.\n- **Individual label override:** `II-1 [female, affected, label: "Jane Smith (42)"]`.\n- **Legend entry:** `legend: id = "Label" (fill: POSITION)` \u2014 see \xA75.\n- **Mode suffix:** `pedigree:autosomal-dominant "Family X"` is accepted. The suffix is stored as `metadata.mode`; current renderers ignore it.\n- **Comments:** `#`, `//`, or `%%` at the start of a line (after leading whitespace). Inline trailing comments are **not** supported.\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `pedigree` (header), `legend:` (legend entry).\n\n**Reserved operator tokens** inside a line \u2014 avoid using these sequences in IDs:\n`--`, `==`, `-/-`, `~`.\n\n**Reserved attribute tokens** inside `[\u2026]` \u2014 the parser will interpret these regardless of position: sex tokens (`male`, `female`, `unknown`, `amab`, `afab`, `uaab`), genetic statuses (`affected`, `carrier`, `carrier-x`, `obligate-carrier`, `presymptomatic`, `unaffected`), markers (`proband`, `consultand`, `evaluated`), and life statuses (`deceased`, `stillborn`, `pregnancy`, `sab`, `tab`, `ectopic`).\n\n**Strings with spaces** must be double-quoted. Single quotes and backticks are not recognized.\n\n---\n\n## 8. Common mistakes\n\nReal parser errors, what triggers them, and how to fix.\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `II-1 -- II-4` where `II-4` was never declared | `Unknown individual \'II-4\'` | Declare `II-4` above, or use inline form: `II-1 -- II-4 [male, unaffected]` |\n| `II-1 [nonbinary]` | Silently stored as a custom property; shape stays diamond | Bennett 2022 distinguishes assigned sex from gender \u2014 use `amab`/`afab`/`uaab` and record identity in `label:` |\n| `II-3 [twin-mz]` | Stored as a custom property; no twin line rendered | Twin notation is \xA710 Roadmap |\n| `I-1 -- I-2` followed by `II-1 [male]` at the **same indent** | Child parsed as a new top-level individual, not as offspring | Indent the child line deeper than the couple line |\n| `I-1 [affected: breast]` with no matching `legend:` | Trait ID stored but no legend-keyed fill is rendered | Add `legend: breast = "\u2026" (fill: quad-tl)` above |\n| `II-1[affected]` (no space, no attrs split) | Works for a single token; breaks when a second attribute is added | Always separate `id` and `[\u2026]` with a space |\n| Line 1 is `I-1 [male]` with no `pedigree` header | `Expected "pedigree" header` | Start with `pedigree` or `pedigree "Title"` |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | legend | individual | couple-block)*\n\nheader = "pedigree" ( ":" mode )? ( WS quoted-string )? NEWLINE\nmode = [A-Za-z] [A-Za-z0-9_-]*\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nlegend = INDENT "legend:" WS id WS "=" WS quoted-string\n ( WS "(" "fill:" fill-value ")" )? NEWLINE\n\nindividual = INDENT id ( "[" attrs "]" )? NEWLINE\ncouple-block = INDENT id WS coupleOp WS right-side NEWLINE\n ( deeper-indent child )*\nchild = INDENT id ( "[" attrs "]" )? NEWLINE\nright-side = id ( "[" attrs "]" )?\n\ncoupleOp = "-/-" | "==" | "--" | "~"\n\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nattrs = attr ("," attr)*\nattr = sex\n | genetic-status\n | marker\n | life-status\n | digit digit digit digit // birth year\n | "label" ":" quoted-string\n | "affected" ":" trait-id ( "+" trait-id )*\n | key ":" value // custom\n\nsex = "male" | "female" | "unknown" | "amab" | "afab" | "uaab"\ngenetic-status = "unaffected" | "affected" | "carrier" | "carrier-x"\n | "obligate-carrier" | "presymptomatic"\nmarker = "proband" | "consultand" | "evaluated"\nlife-status = "deceased" | "stillborn" | "pregnancy"\n | "sab" | "tab" | "ectopic"\nfill-value = "full" | "half-left" | "half-right" | "half-top" | "half-bottom"\n | "quad-tl" | "quad-tr" | "quad-bl" | "quad-br"\n\ncomment = INDENT ( "#" | "//" | "%%" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/pedigree/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1770
1435
|
},
|
|
1771
1436
|
"phylo": {
|
|
1772
1437
|
"title": "Phylogenetic tree",
|
|
@@ -1794,11 +1459,11 @@ var SYNTAX = {
|
|
|
1794
1459
|
},
|
|
1795
1460
|
"ladder": {
|
|
1796
1461
|
"title": "Ladder logic",
|
|
1797
|
-
"content": '## 1. Your first ladder diagram\n\nThe smallest useful ladder program: one rung, two contacts, one coil.\n\n```\nladder "First Rung"\nrung 1 "Start when button pressed, stop on fault":\n XIC(START_PB)\n XIO(FAULT)\n OTE(MOTOR_RUN)\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `ladder`, optionally followed by a quoted title.\n2. Each **rung** begins with `rung N "optional comment":` on its own line.\n3. Elements are listed one per line, indented under the rung \u2014 left to right means series (AND logic).\n4. A `parallel:` / `branch:` block introduces OR logic. Every branch holds its own element list.\n\n> Comments
|
|
1462
|
+
"content": '## 1. Your first ladder diagram\n\nThe smallest useful ladder program: one rung, two contacts, one coil.\n\n```\nladder "First Rung"\nrung 1 "Start when button pressed, stop on fault":\n XIC(START_PB)\n XIO(FAULT)\n OTE(MOTOR_RUN)\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `ladder`, optionally followed by a quoted title.\n2. Each **rung** begins with `rung N "optional comment":` on its own line. The trailing colon is optional.\n3. Elements are listed one per line, indented under the rung \u2014 left to right means series (AND logic).\n4. A `parallel:` / `branch:` block introduces OR logic. Every branch holds its own element list.\n\n> Comments may start with `#`, `//`, or Mermaid-style `%%` on their own line.\n\n---\n\n## 2. Contacts\n\nContacts represent input conditions \u2014 they pass power when the associated bit matches the contact type.\n\n| Type | Name | Passes power when\u2026 |\n|---|---|---|\n| `XIC` | Examine If Closed | Tag bit = 1 (normally open) |\n| `XIO` | Examine If Open | Tag bit = 0 (normally closed) |\n| `ONS` | One-Shot Rising | Tag transitions 0 \u2192 1 (rising edge, one scan) |\n| `OSF` | One-Shot Falling | Tag transitions 1 \u2192 0 (falling edge, one scan) |\n\n**Syntax:**\n\n```\nXIC(tag)\nXIC(tag, "address")\nXIC(tag, "address", name="Description")\nXIC(tag, address="address", name="Description")\n```\n\n- `tag` \u2014 required. The PLC tag name (displayed below the contact symbol).\n- `"address"` \u2014 optional positional second argument. The I/O address (e.g. `"IN 1.0"`, `"BIT 3.1"`).\n- `name="\u2026"` \u2014 optional key-value. Human-readable description (displayed above the symbol).\n\n```\nladder "Contact types"\nrung 1 "All four contact types":\n XIC(START_PB, "IN 1.0", name="Start Button")\n XIO(E_STOP, "IN 1.5", name="Emergency Stop NC")\n ONS(PULSE_IN, "BIT 5.0", name="One-Shot Rising")\n OSF(RESET_SIG, "BIT 5.1", name="One-Shot Falling")\n OTE(OUT_RLY, "OUT 2.0", name="Output Relay")\n```\n\n---\n\n## 3. Coils\n\nCoils represent output actions \u2014 they act on a tag bit when the rung has power flow.\n\n| Type | Name | Effect on tag bit |\n|---|---|---|\n| `OTE` | Output Energize | Sets bit = 1 while rung is true; clears to 0 when rung is false |\n| `OTL` | Output Latch | Sets bit = 1; **retains** even after rung goes false (latches) |\n| `OTU` | Output Unlatch | Clears bit = 0; retains even after rung goes false |\n| `OTN` | Output Negate | Sets bit = 0 while rung is true; sets to 1 when rung is false |\n| `RES` | Reset | Rockwell / Allen-Bradley counter or timer reset coil |\n\n**Syntax:** identical to contacts \u2014 `OTE(tag)`, `OTE(tag, "address")`, `OTE(tag, "address", name="\u2026")`.\n\n`OTL` and `OTU` are used in pairs to build Set/Reset flip-flops. The last rung to write wins.\n\n```\nladder "Set-Reset latch"\nrung 1 "Set on start":\n XIC(START_PB, "IN 1.0", name="Start")\n OTL(MOTOR_ON, "BIT 3.0", name="Motor Latch")\nrung 2 "Reset on stop or fault":\n parallel:\n branch:\n XIC(STOP_PB, "IN 1.1", name="Stop")\n branch:\n XIC(E_STOP, "IN 1.5", name="E-Stop")\n OTU(MOTOR_ON, "BIT 3.0", name="Motor Latch")\n```\n\n---\n\n## 4. Function blocks\n\nFunction blocks perform timer, counter, math, and comparison operations. They appear inline in a rung and have keyword parameters after the mandatory tag argument.\n\n### 4.1 Timers\n\n| Type | Name | Key parameters |\n|---|---|---|\n| `TON` | Timer On-Delay | `PT=` preset time in milliseconds |\n| `TOFF` | Timer Off-Delay | `PT=` preset time in milliseconds |\n| `TP` | Timer Pulse | `PT=` preset time in milliseconds |\n\n```\nTON(timer_tag, PT=5000)\n```\n\nThe timer tag stores elapsed time. The timer\'s `Q` bit (done output) is accessed by tag name in downstream contacts.\n\n### 4.2 Counters\n\n| Type | Name | Key parameters |\n|---|---|---|\n| `CTU` | Count Up | `PV=` preset value (integer) |\n| `CTD` | Count Down | `PV=` preset value |\n| `CTUD` | Count Up/Down | `PV=` preset value |\n\n```\nCTU(cycle_counter, PV=100)\n```\n\n### 4.3 Math\n\n| Type | Operation |\n|---|---|\n| `ADD` | Add |\n| `SUB` | Subtract |\n| `MUL` | Multiply |\n| `DIV` | Divide |\n| `MOV` | Move (copy) |\n\n```\nADD(result_tag, IN1=setpoint, IN2=offset)\nMOV(dest_tag, IN1=source_tag)\n```\n\n### 4.4 Comparisons\n\n| Type | Meaning |\n|---|---|\n| `EQU` | Equal |\n| `NEQ` | Not equal |\n| `GRT` | Greater than |\n| `LES` | Less than |\n| `GEQ` | Greater than or equal |\n| `LEQ` | Less than or equal |\n\n```\nEQU(compare_tag, IN1=speed_actual, IN2=speed_setpoint)\n```\n\n```\nladder "Timer and counter"\nrung 1 "Start run timer":\n XIC(MOTOR_CMD, "BIT 3.0", name="Motor Running")\n TON(RUN_TIMER, PT=10000)\nrung 2 "Count completed cycles":\n XIC(CYCLE_SENSOR, "IN 2.0", name="Cycle Sensor")\n CTU(PART_COUNT, PV=500)\nrung 3 "Alarm when batch complete":\n XIC(PART_COUNT, name="Count Done")\n OTE(BATCH_ALARM, "OUT 3.0", name="Batch Complete Alarm")\n```\n\n---\n\n## 5. Parallel branches\n\nA `parallel:` block introduces OR logic \u2014 the rung has power if **any** branch conducts. Each branch is a `branch:` sub-block with its elements indented below it.\n\n```\nparallel:\n branch:\n XIC(LOCAL_START)\n branch:\n XIC(REMOTE_START)\n```\n\nBranches in a `parallel:` are evaluated simultaneously. The block closes when indentation returns to the level before `parallel:`.\n\n**Rules:**\n- `parallel:` must appear inside a rung.\n- `branch:` must appear inside a `parallel:` \u2014 using it alone throws `LadderParseError`.\n- Each branch holds one or more elements.\n- Elements after the `parallel:` block are series with it (AND logic).\n\n```\nladder "Parallel OR logic"\nrung 1 "Start from either local or remote":\n parallel:\n branch:\n XIC(LOCAL_START, "IN 1.0", name="Local Start")\n branch:\n XIC(REMOTE_START, "BIT 5.2", name="Remote Start")\n XIO(STOP_ALL, "IN 1.5", name="Stop All")\n OTE(CONVEYOR, "OUT 2.0", name="Conveyor Run")\n```\n\n---\n\n## 6. Labels & comments\n\n- **Title:** `ladder "Motor Control"` \u2014 first line only, quoted string.\n- **Rung number:** required integer after `rung`.\n- **Rung comment:** optional quoted string after the rung number, before the optional colon: `rung 3 "Run indicator":` or `rung 3 "Run indicator"`.\n- **Tag:** first argument inside the parentheses \u2014 displayed below the symbol.\n- **Address:** second positional argument (quoted): `XIC(START_PB, "IN 1.0")`.\n- **Name:** `name="\u2026"` keyword argument \u2014 human-readable description displayed above the symbol.\n- **Line comments:** `#`, `//`, or `%%` at the start of a line (after leading whitespace). The same markers also start trailing comments.\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start (case-insensitive):** `ladder`, `rung`, `parallel:`, `branch:`.\n\n**Element names** are all uppercase ASCII: `XIC`, `XIO`, `ONS`, `OSF`, `OTE`, `OTL`, `OTU`, `OTN`, `TON`, `TOFF`, `TP`, `CTU`, `CTD`, `CTUD`, `ADD`, `SUB`, `MUL`, `DIV`, `MOV`, `EQU`, `NEQ`, `GRT`, `LES`, `GEQ`, `LEQ`.\n\n**Tag IDs** \u2014 must match `[A-Z][A-Z0-9_]*` (the parser matches `[A-Z][A-Z0-9_]*` for the element name prefix). Lowercase tags are accepted inside the parentheses.\n\n**Quoted strings** in address or name arguments must use double quotes `"\u2026"`.\n\n---\n\n## 8. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `rung 1` (no colon) | Parsed correctly | The trailing colon is optional |\n| `ONF(TAG)` | `LadderParseError: unknown element type "ONF"` | Falling-edge contact is `OSF`, not `ONF` |\n| `parallel:` without `branch:` | Empty parallel block \u2014 rung has no element | Add at least one `branch:` inside the `parallel:` |\n| `branch:` before `parallel:` | `LadderParseError: branch: without parallel:` | Always open `parallel:` first |\n| `OTE()` \u2014 no tag | `LadderParseError: element missing tag` | Tag is required: `OTE(MY_TAG)` |\n| `var StartBtn: bool` (variable declaration) | `LadderParseError: invalid element syntax` | No variable declarations \u2014 tags are used directly |\n| Empty rung (no elements after `rung N:`) | `LadderParseError: Rung N: empty rung` | Add at least one element to each rung |\n| `TON(T1, T#5s)` | `LadderParseError: invalid element syntax` (T# not a valid number) | Use milliseconds integer: `TON(T1, PT=5000)` |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header NEWLINE rung+\n\nheader = "ladder" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nrung = "rung" WS integer ( WS quoted-string )? ":"? NEWLINE\n element+\n\nelement = contact-line\n | coil-line\n | fb-line\n | parallel-block\n\ncontact-line = contact-type "(" tag ( "," arg )* ")" NEWLINE\ncontact-type = "XIC" | "XIO" | "ONS" | "OSF"\n\ncoil-line = coil-type "(" tag ( "," arg )* ")" NEWLINE\ncoil-type = "OTE" | "OTL" | "OTU" | "OTN" | "RES"\n\nfb-line = fb-type "(" tag ( "," arg )* ")" NEWLINE\nfb-type = "TON" | "TOFF" | "TP"\n | "CTU" | "CTD" | "CTUD"\n | "ADD" | "SUB" | "MUL" | "DIV" | "MOV"\n | "EQU" | "NEQ" | "GRT" | "LES" | "GEQ" | "LEQ"\n\narg = quoted-string // positional (address)\n | key "=" quoted-string // keyword (e.g. name="\u2026")\n | key "=" number // keyword (e.g. PT=5000)\n\nparallel-block = INDENT\u22652 "parallel:" NEWLINE\n ( INDENT branch-block )+\n\nbranch-block = "branch:" NEWLINE\n ( INDENT element )+\n\ntag = [A-Za-z][A-Za-z0-9_]*\nkey = [A-Za-z][A-Za-z0-9_]*\ninteger = [0-9]+\nnumber = [0-9]+ ( "." [0-9]+ )?\ncomment = ( "#" | "//" | "%%" ) any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/ladder/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1798
1463
|
},
|
|
1799
1464
|
"sld": {
|
|
1800
1465
|
"title": "Single-line diagram (SLD)",
|
|
1801
|
-
"content": '## 1. Your first single-line diagram\n\nThe simplest SLD: a utility source, a transformer, a breaker, and a load.\n\n```\nsld "Simple feeder"\nutil = utility [label: "Utility 13.8kV"]\nxfmr = transformer [rating: "500 kVA", voltage: "13.8kV/480V"]\nbus1 = bus [voltage: "480V", label: "480V Bus"]\ncb1 = breaker [rating: "200A"]\nload1 = load [label: "Panel LP-1"]\nutil -> xfmr\nxfmr -> bus1\nbus1 -> cb1\ncb1 -> load1\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `sld`, optionally followed by a quoted title.\n2. Declare each equipment item as `id = nodeType [attributes]` \u2014 one per line.\n3. Connect items with `from -> to`, optionally adding `[cable: "\u2026", label: "\u2026"]`.\n4. IDs may contain letters, digits, underscores, and hyphens \u2014 but must start with a letter.\n\n> Comments must start with `#` on their own line.\n\n---\n\n## 2. Node types\n\nA node line is `id = nodeType [attr: value, \u2026]`. The node type determines the symbol drawn.\n\n### 2.1 Sources\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `utility` | Utility source arrow | Infinite bus / grid connection |\n| `generator` | Circle with `G` | Diesel, gas, or hydro genset |\n| `solar` | PV panel symbol | Photovoltaic array |\n| `wind` | Turbine symbol | Wind turbine |\n| `ups` | Block with battery | Uninterruptible power supply |\n\n```\nsld "Generation sources"\nutil = utility [label: "Grid 115 kV"]\ngen = generator [rating: "2 MW", label: "Diesel Gen"]\nsol = solar [rating: "500 kW", label: "PV Array"]\nwnd = wind [rating: "1 MW", label: "Wind Turbine"]\nups = ups [rating: "100 kVA", label: "UPS System"]\nutil -> gen\nutil -> sol\nutil -> wnd\nutil -> ups\n```\n\n### 2.2 Transformers\n\n| Type | Winding configuration | Notes |\n|---|---|---|\n| `transformer` | Generic two-winding | No winding spec |\n| `transformer_dy` | Delta \u2192 Wye grounded (\u0394-Yg) | Most common distribution |\n| `transformer_yd` | Wye grounded \u2192 Delta (Yg-\u0394) | |\n| `transformer_yy` | Wye-Wye (both grounded) | |\n| `transformer_dd` | Delta-Delta | |\n| `autotransformer` | Single-winding with tap | Zigzag coil symbol |\n| `transformer_3winding` | Three-winding | HV / MV / LV taps |\n\n```\nsld "Transformer configurations"\nsrc = utility [label: "138kV Grid"]\nt_dy = transformer_dy [rating: "30 MVA", voltage: "138kV/13.8kV", label: "\u0394-Yg (most common)"]\nt_yy = transformer_yy [rating: "10 MVA", voltage: "138kV/13.8kV", label: "Yg-Yg"]\nt_auto = autotransformer [rating: "50 MVA", voltage: "138kV/69kV", label: "Autotransformer"]\nt_3w = transformer_3winding [rating: "40 MVA", voltage: "138/13.8/4.16kV", label: "3-Winding"]\nsrc -> t_dy\nsrc -> t_yy\nsrc -> t_auto\nsrc -> t_3w\n```\n\n### 2.3 Buses and nodes\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `bus` | Thick horizontal line | Main voltage bus bar |\n| `bus_tie` | Bus-tie breaker | Links two parallel buses at the same voltage |\n| `hub` | Wide rectangle | Multi-feeder combining point |\n\n### 2.4 Switching and protection\n\n| Type | Symbol | Device number |\n|---|---|---|\n| `breaker` | Diagonal + arc | 52 (AC circuit breaker) |\n| `breaker_vacuum` | Diagonal + V-oval | 52 vacuum type |\n| `switch` | Diagonal (no arc) | 89 (disconnect / isolator) |\n| `switch_load` | Load interrupter switch | \u2014 |\n| `ground_switch` | Diagonal + ground symbol | Grounding disconnect |\n| `ats` | Transfer switch symbol | Automatic transfer switch |\n| `recloser` | Diagonal + arc + arrow | Auto-reclosing breaker |\n| `sectionalizer` | Diagonal + S | Distribution sectionalizer |\n| `fuse` | Oval with diagonal | Expulsion fuse cutout |\n| `fuse_cl` | Rectangle with diagonal | Current-limiting fuse |\n\n```\nsld "Switching and protection"\nsrc = utility [label: "Source"]\nrclsr = recloser [label: "Recloser"]\nsect = sectionalizer [label: "Sectionalizer"]\nfuse1 = fuse [label: "Fuse"]\nsw = switch [label: "Disconnect"]\ngnd_sw = ground_switch [label: "Ground SW"]\nsrc -> rclsr\nrclsr -> sect\nsect -> fuse1\nsect -> sw\nsw -> gnd_sw\n```\n\n### 2.5 Protection and monitoring\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `ct` | Small circle with line through | Current transformer |\n| `pt` | Small circle | Potential / voltage transformer |\n| `relay` | Small circle with device number | Protection relay (ANSI number via `device:`) |\n| `surge_arrester` | Arrow + ground | Lightning arrester |\n| `ground_fault` | GFI symbol | Ground-fault detector |\n\n### 2.6 Loads and equipment\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `motor` | Circle with `M` | Three-phase motor |\n| `load` | Rectangle | Generic load or feeder |\n| `capacitor_bank` | Two plates + switch | Power factor correction |\n| `harmonic_filter` | LC symbol | Passive harmonic filter |\n| `vfd` | Rectangle with VFD | Variable-frequency drive |\n\n### 2.7 Metering\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `watthour_meter` | Circle with `Wh` | Energy meter |\n| `demand_meter` | Circle with `D` | Demand meter |\n\n```\nsld "Equipment types"\nsrc = utility [label: "Grid 13.8kV"]\ntx = transformer_dy [rating: "1000 kVA", voltage: "13.8kV/480V", label: "Main TX"]\nbk = breaker [rating: "2000A", label: "Main Breaker"]\nbus = bus [voltage: "480V", label: "480V MV Bus"]\nct1 = ct [label: "CT-1"]\nrly = relay [device: "51", label: "Overcurrent Relay"]\ncap = capacitor_bank [rating: "150 kVAR", label: "PF Cap"]\nmtr = motor [rating: "100HP", label: "Pump Motor"]\ngen = generator [rating: "500kW", label: "Emergency Gen"]\nats = ats [rating: "800A", label: "ATS-1"]\nsrc -> tx\ntx -> bk\nbk -> bus\nbus -> ct1\nct1 -> rly\nbus -> cap\nbus -> mtr\ngen -> ats\nats -> bus\n```\n\n---\n\n## 3. Node attributes\n\nAttributes are written inside `[\u2026]` after the node type, comma-separated.\n\n| Attribute | Values | Effect |\n|---|---|---|\n| `label: "\u2026"` | quoted string | Display name on the diagram |\n| `voltage: "\u2026"` | quoted string, e.g. `"13.8kV"`, `"480V"` | Voltage level annotation |\n| `rating: "\u2026"` | quoted string, e.g. `"1000 kVA"`, `"200A"` | Equipment rating annotation |\n| `device: "\u2026"` | ANSI device number, e.g. `"51"`, `"87"` | Used with `relay` nodes |\n| any other key | quoted string | Stored as nameplate data (transformer kVA, %Z, etc.) |\n\n**Example with all common attributes:**\n\n```\nxfmr = transformer_dy [\n label: "Main Transformer",\n voltage: "13.8kV/480V",\n rating: "1000 kVA",\n impedance: "5.75%Z"\n]\n```\n\nThe attribute block may span multiple lines \u2014 the parser joins lines until the `]` is balanced.\n\n---\n\n## 4. Connections\n\nA connection line is `fromId -> toId`, optionally followed by `[cable: "\u2026", label: "\u2026"]`.\n\n```\nbus1 -> cb1\nbus1 -> cb1 [cable: "3#2/0 AWG"]\nbus1 -> cb1 [cable: "3#2/0 AWG", label: "Feeder A"]\n```\n\n**Rules:**\n- Both IDs must be declared before or after the connection \u2014 all connections are validated at end of parse.\n- Only `->` (directed, source-to-load) is accepted. The connection direction is used for layout.\n- An unknown node ID throws `SLDParseError: Connection references unknown node "\u2026"`.\n\n```\nsld "ATS backup with cable labels"\nUTIL = utility [label: "Utility 480V"]\nGEN = generator [rating: "500 kW", label: "Emergency Gen"]\nATS1 = ats [rating: "800A", label: "ATS-1"]\nBUS1 = bus [voltage: "480V", label: "Critical Bus"]\nCB1 = breaker [rating: "200A", label: "CB-1"]\nCB2 = breaker [rating: "200A", label: "CB-2"]\nL1 = load [label: "Server Room"]\nL2 = load [label: "Life Safety"]\nUTIL -> ATS1 [label: "Normal source"]\nGEN -> ATS1 [label: "Emergency source"]\nATS1 -> BUS1 [cable: "3#2/0 AWG"]\nBUS1 -> CB1\nBUS1 -> CB2\nCB1 -> L1 [cable: "3#4 AWG"]\nCB2 -> L2 [cable: "3#4 AWG"]\n```\n\n---\n\n## 5. Labels & comments\n\n- **Title:** `sld "Substation One-Line"` \u2014 first line only.\n- **Node label:** `id = type [label: "\u2026"]` \u2014 the display name.\n- **Connection label:** `A -> B [label: "\u2026"]` \u2014 appears alongside the connecting line.\n- **Cable annotation:** `A -> B [cable: "3#2/0 AWG, 200ft"]` \u2014 conductor specification.\n- **Comments:** `#` at the start of a line. Inline `#` on the same line as a node or connection is also stripped.\n\n---\n\n## 6. Reserved words & escaping\n\n**Reserved at line start:** `sld` (header).\n\n**Operator token** \u2014 avoid `->` inside node IDs. IDs may contain `[A-Za-z][A-Za-z0-9_-]*` \u2014 hyphens are valid (e.g. `CB-101` is a legal ID).\n\n**Attribute block** \u2014 `[\u2026]` brackets may span multiple physical lines. The parser joins continuation lines until the bracket depth reaches zero.\n\n**Duplicate IDs** throw `SLDParseError: Duplicate node id "\u2026"`.\n\n---\n\n## 7. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `xfmr1 [type: transformer]` | `SLDParseError: Cannot parse line` | Use `=` assignment: `xfmr1 = transformer [...]` |\n| `id = battery [...]` | `SLDParseError: Unknown node type "battery"` | No `battery` type \u2014 use `ups` or `generator` |\n| `A -- B` (bidirectional) | `SLDParseError: Cannot parse line` | Only `->` is accepted; use two `->` lines if needed |\n| `A -> B -> C` (chained) | `SLDParseError: Cannot parse line` | Each connection is one `->` per line |\n| `relay [label: "OC"]` (no device number) | Relay renders with blank number | Add `device: "51"` for the ANSI device number |\n| `voltage: 480V` (unquoted) | Attribute value not recognized | Quote all values: `voltage: "480V"` |\n| Node ID starting with digit: `2BUS` | `SLDParseError: Cannot parse line` | IDs must start with a letter: `BUS2` |\n| Connection before node declared | `SLDParseError: Connection references unknown node "\u2026"` | Declare nodes before or after connections \u2014 validated at end of parse, so order is flexible |\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = header NEWLINE ( blank | comment | node-def | connection )*\n\nheader = "sld" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nnode-def = id WS "=" WS node-type ( WS "[" attr-list "]" )? NEWLINE\nnode-type = "utility" | "generator" | "solar" | "wind" | "ups"\n | "transformer" | "transformer_dy" | "transformer_yd"\n | "transformer_yy" | "transformer_dd"\n | "autotransformer" | "transformer_3winding"\n | "bus" | "bus_tie" | "hub"\n | "breaker" | "breaker_vacuum" | "switch" | "switch_load"\n | "ground_switch" | "ats" | "recloser" | "sectionalizer"\n | "fuse" | "fuse_cl"\n | "ct" | "pt" | "relay" | "surge_arrester" | "ground_fault"\n | "motor" | "load" | "capacitor_bank" | "harmonic_filter" | "vfd"\n | "watthour_meter" | "demand_meter"\n\nattr-list = attr ( "," attr )*\nattr = key ":" WS quoted-string\n\nconnection = id WS "->" WS id ( WS "[" conn-attrs "]" )? NEWLINE\nconn-attrs = conn-attr ( "," conn-attr )*\nconn-attr = "cable" ":" WS quoted-string\n | "label" ":" WS quoted-string\n\nid = [A-Za-z] [A-Za-z0-9_-]*\nkey = [A-Za-z] [A-Za-z0-9_]*\ncomment = "#" any NEWLINE\n```\n\nThe attribute block `[\u2026]` may span multiple physical lines \u2014 the parser joins continuation lines until the bracket depth returns to zero.\n\nAuthoritative source: `src/diagrams/sld/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1466
|
+
"content": '## 1. Your first single-line diagram\n\nThe simplest SLD: a utility source, a transformer, a breaker, and a load.\n\n```\nsld "Simple feeder"\nutil = utility [label: "Utility 13.8kV"]\nxfmr = transformer [rating: "500 kVA", voltage: "13.8kV/480V"]\nbus1 = bus [voltage: "480V", label: "480V Bus"]\ncb1 = breaker [rating: "200A"]\nload1 = load [label: "Panel LP-1"]\nutil -> xfmr\nxfmr -> bus1\nbus1 -> cb1\ncb1 -> load1\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `sld`, optionally followed by a quoted title.\n2. Declare each equipment item as `id = nodeType [attributes]` \u2014 one per line.\n3. Connect items with `from -> to`, optionally adding `[cable: "\u2026", label: "\u2026"]`.\n4. IDs may contain letters, digits, underscores, and hyphens \u2014 but must start with a letter.\n\n> Comments may start with `#`, `//`, or Mermaid-style `%%` on their own line.\n\n---\n\n## 2. Node types\n\nA node line is `id = nodeType [attr: value, \u2026]`. The node type determines the symbol drawn.\n\n### 2.1 Sources\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `utility` | Utility source arrow | Infinite bus / grid connection |\n| `generator` | Circle with `G` | Diesel, gas, or hydro genset |\n| `solar` | PV panel symbol | Photovoltaic array |\n| `wind` | Turbine symbol | Wind turbine |\n| `ups` | Block with battery | Uninterruptible power supply |\n\n```\nsld "Generation sources"\nutil = utility [label: "Grid 115 kV"]\ngen = generator [rating: "2 MW", label: "Diesel Gen"]\nsol = solar [rating: "500 kW", label: "PV Array"]\nwnd = wind [rating: "1 MW", label: "Wind Turbine"]\nups = ups [rating: "100 kVA", label: "UPS System"]\nutil -> gen\nutil -> sol\nutil -> wnd\nutil -> ups\n```\n\n### 2.2 Transformers\n\n| Type | Winding configuration | Notes |\n|---|---|---|\n| `transformer` | Generic two-winding | No winding spec |\n| `transformer_dy` | Delta \u2192 Wye grounded (\u0394-Yg) | Most common distribution |\n| `transformer_yd` | Wye grounded \u2192 Delta (Yg-\u0394) | |\n| `transformer_yy` | Wye-Wye (both grounded) | |\n| `transformer_dd` | Delta-Delta | |\n| `autotransformer` | Single-winding with tap | Zigzag coil symbol |\n| `transformer_3winding` | Three-winding | HV / MV / LV taps |\n\n```\nsld "Transformer configurations"\nsrc = utility [label: "138kV Grid"]\nt_dy = transformer_dy [rating: "30 MVA", voltage: "138kV/13.8kV", label: "\u0394-Yg (most common)"]\nt_yy = transformer_yy [rating: "10 MVA", voltage: "138kV/13.8kV", label: "Yg-Yg"]\nt_auto = autotransformer [rating: "50 MVA", voltage: "138kV/69kV", label: "Autotransformer"]\nt_3w = transformer_3winding [rating: "40 MVA", voltage: "138/13.8/4.16kV", label: "3-Winding"]\nsrc -> t_dy\nsrc -> t_yy\nsrc -> t_auto\nsrc -> t_3w\n```\n\n### 2.3 Buses and nodes\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `bus` | Thick horizontal line | Main voltage bus bar |\n| `bus_tie` | Bus-tie breaker | Links two parallel buses at the same voltage |\n| `hub` | Wide rectangle | Multi-feeder combining point |\n\n### 2.4 Switching and protection\n\n| Type | Symbol | Device number |\n|---|---|---|\n| `breaker` | Diagonal + arc | 52 (AC circuit breaker) |\n| `breaker_vacuum` | Diagonal + V-oval | 52 vacuum type |\n| `switch` | Diagonal (no arc) | 89 (disconnect / isolator) |\n| `switch_load` | Load interrupter switch | \u2014 |\n| `ground_switch` | Diagonal + ground symbol | Grounding disconnect |\n| `ats` | Transfer switch symbol | Automatic transfer switch |\n| `recloser` | Diagonal + arc + arrow | Auto-reclosing breaker |\n| `sectionalizer` | Diagonal + S | Distribution sectionalizer |\n| `fuse` | Oval with diagonal | Expulsion fuse cutout |\n| `fuse_cl` | Rectangle with diagonal | Current-limiting fuse |\n\n```\nsld "Switching and protection"\nsrc = utility [label: "Source"]\nrclsr = recloser [label: "Recloser"]\nsect = sectionalizer [label: "Sectionalizer"]\nfuse1 = fuse [label: "Fuse"]\nsw = switch [label: "Disconnect"]\ngnd_sw = ground_switch [label: "Ground SW"]\nsrc -> rclsr\nrclsr -> sect\nsect -> fuse1\nsect -> sw\nsw -> gnd_sw\n```\n\n### 2.5 Protection and monitoring\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `ct` | Small circle with line through | Current transformer |\n| `pt` | Small circle | Potential / voltage transformer |\n| `relay` | Small circle with device number | Protection relay (ANSI number via `device:`) |\n| `surge_arrester` | Arrow + ground | Lightning arrester |\n| `ground_fault` | GFI symbol | Ground-fault detector |\n\n### 2.6 Loads and equipment\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `motor` | Circle with `M` | Three-phase motor |\n| `load` | Rectangle | Generic load or feeder |\n| `capacitor_bank` | Two plates + switch | Power factor correction |\n| `harmonic_filter` | LC symbol | Passive harmonic filter |\n| `vfd` | Rectangle with VFD | Variable-frequency drive |\n\n### 2.7 Metering\n\n| Type | Symbol | Typical use |\n|---|---|---|\n| `watthour_meter` | Circle with `Wh` | Energy meter |\n| `demand_meter` | Circle with `D` | Demand meter |\n\n```\nsld "Equipment types"\nsrc = utility [label: "Grid 13.8kV"]\ntx = transformer_dy [rating: "1000 kVA", voltage: "13.8kV/480V", label: "Main TX"]\nbk = breaker [rating: "2000A", label: "Main Breaker"]\nbus = bus [voltage: "480V", label: "480V MV Bus"]\nct1 = ct [label: "CT-1"]\nrly = relay [device: "51", label: "Overcurrent Relay"]\ncap = capacitor_bank [rating: "150 kVAR", label: "PF Cap"]\nmtr = motor [rating: "100HP", label: "Pump Motor"]\ngen = generator [rating: "500kW", label: "Emergency Gen"]\nats = ats [rating: "800A", label: "ATS-1"]\nsrc -> tx\ntx -> bk\nbk -> bus\nbus -> ct1\nct1 -> rly\nbus -> cap\nbus -> mtr\ngen -> ats\nats -> bus\n```\n\n---\n\n## 3. Node attributes\n\nAttributes are written inside `[\u2026]` after the node type, comma-separated.\n\n| Attribute | Values | Effect |\n|---|---|---|\n| `label: "\u2026"` | quoted string | Display name on the diagram |\n| `voltage: "\u2026"` | quoted string, e.g. `"13.8kV"`, `"480V"` | Voltage level annotation |\n| `rating: "\u2026"` | quoted string, e.g. `"1000 kVA"`, `"200A"` | Equipment rating annotation |\n| `device: "\u2026"` | ANSI device number, e.g. `"51"`, `"87"` | Used with `relay` nodes |\n| any other key | quoted string | Stored as nameplate data (transformer kVA, %Z, etc.) |\n\n**Example with all common attributes:**\n\n```\nxfmr = transformer_dy [\n label: "Main Transformer",\n voltage: "13.8kV/480V",\n rating: "1000 kVA",\n impedance: "5.75%Z"\n]\n```\n\nThe attribute block may span multiple lines \u2014 the parser joins lines until the `]` is balanced.\n\n---\n\n## 4. Connections\n\nA connection line is `fromId -> toId`, optionally followed by `[cable: "\u2026", label: "\u2026"]`.\n\n```\nbus1 -> cb1\nbus1 -> cb1 [cable: "3#2/0 AWG"]\nbus1 -> cb1 [cable: "3#2/0 AWG", label: "Feeder A"]\n```\n\n**Rules:**\n- Both IDs must be declared before or after the connection \u2014 all connections are validated at end of parse.\n- Only `->` (directed, source-to-load) is accepted. The connection direction is used for layout.\n- An unknown node ID throws `SLDParseError: Connection references unknown node "\u2026"`.\n\n```\nsld "ATS backup with cable labels"\nUTIL = utility [label: "Utility 480V"]\nGEN = generator [rating: "500 kW", label: "Emergency Gen"]\nATS1 = ats [rating: "800A", label: "ATS-1"]\nBUS1 = bus [voltage: "480V", label: "Critical Bus"]\nCB1 = breaker [rating: "200A", label: "CB-1"]\nCB2 = breaker [rating: "200A", label: "CB-2"]\nL1 = load [label: "Server Room"]\nL2 = load [label: "Life Safety"]\nUTIL -> ATS1 [label: "Normal source"]\nGEN -> ATS1 [label: "Emergency source"]\nATS1 -> BUS1 [cable: "3#2/0 AWG"]\nBUS1 -> CB1\nBUS1 -> CB2\nCB1 -> L1 [cable: "3#4 AWG"]\nCB2 -> L2 [cable: "3#4 AWG"]\n```\n\n---\n\n## 5. Labels & comments\n\n- **Title:** `sld "Substation One-Line"` \u2014 first line only.\n- **Node label:** `id = type [label: "\u2026"]` \u2014 the display name.\n- **Connection label:** `A -> B [label: "\u2026"]` \u2014 appears alongside the connecting line.\n- **Cable annotation:** `A -> B [cable: "3#2/0 AWG, 200ft"]` \u2014 conductor specification.\n- **Comments:** `#` at the start of a line. Inline `#` on the same line as a node or connection is also stripped.\n- **Residential aliases:** IEC / REBT vocabulary such as `mcb`, `rcd`, `rcbo`, `rccb`, `pia`, `iga`, `main_switch`, `consumer_unit`, `distribution_board`, `panel`, and `panelboard` is accepted as input and mapped to existing SLD primitives.\n\n---\n\n## 6. Reserved words & escaping\n\n**Reserved at line start:** `sld` (header).\n\n**Operator token** \u2014 avoid `->` inside node IDs. IDs may contain `[A-Za-z][A-Za-z0-9_-]*` \u2014 hyphens are valid (e.g. `CB-101` is a legal ID).\n\n**Attribute block** \u2014 `[\u2026]` brackets may span multiple physical lines. The parser joins continuation lines until the bracket depth reaches zero.\n\n**Duplicate IDs** throw `SLDParseError: Duplicate node id "\u2026"`.\n\n---\n\n## 7. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `xfmr1 [type: transformer]` | `SLDParseError: Cannot parse line` | Use `=` assignment: `xfmr1 = transformer [...]` |\n| `id = battery [...]` | `SLDParseError: Unknown node type "battery"` | No `battery` type \u2014 use `ups` or `generator` |\n| `id = breakerz` | `SLDParseError: Unknown node type ... (did you mean \'breaker\'?)` | Use the suggested canonical type or alias |\n| `A -- B` (bidirectional) | `SLDParseError: Cannot parse line` | Only `->` is accepted; use two `->` lines if needed |\n| `A -> B -> C` (chained) | `SLDParseError: Cannot parse line` | Each connection is one `->` per line |\n| `relay [label: "OC"]` (no device number) | Relay renders with blank number | Add `device: "51"` for the ANSI device number |\n| `voltage: 480V` (unquoted) | Attribute value not recognized | Quote all values: `voltage: "480V"` |\n| Node ID starting with digit: `2BUS` | `SLDParseError: Cannot parse line` | IDs must start with a letter: `BUS2` |\n| Connection before node declared | `SLDParseError: Connection references unknown node "\u2026"` | Declare nodes before or after connections \u2014 validated at end of parse, so order is flexible |\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = header NEWLINE ( blank | comment | node-def | connection )*\n\nheader = "sld" ( WS quoted-string )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\nnode-def = id WS "=" WS node-type ( WS "[" attr-list "]" )? NEWLINE\nnode-type = "utility" | "generator" | "solar" | "wind" | "ups"\n | "transformer" | "transformer_dy" | "transformer_yd"\n | "transformer_yy" | "transformer_dd"\n | "autotransformer" | "transformer_3winding"\n | "bus" | "bus_tie" | "hub"\n | "breaker" | "breaker_vacuum" | "switch" | "switch_load"\n | "ground_switch" | "ats" | "recloser" | "sectionalizer"\n | "fuse" | "fuse_cl"\n | "ct" | "pt" | "relay" | "surge_arrester" | "ground_fault"\n | "motor" | "load" | "capacitor_bank" | "harmonic_filter" | "vfd"\n | "watthour_meter" | "demand_meter"\n | residential-alias\n\nresidential-alias\n = "mcb" | "mccb" | "rcd" | "rcbo" | "rccb"\n | "differential" | "diferencial" | "pia" | "iga"\n | "main_switch" | "isolator" | "disconnector"\n | "consumer_unit" | "distribution_board" | "panel" | "panelboard"\n\nattr-list = attr ( "," attr )*\nattr = key ":" WS quoted-string\n\nconnection = id WS "->" WS id ( WS "[" conn-attrs "]" )? NEWLINE\nconn-attrs = conn-attr ( "," conn-attr )*\nconn-attr = "cable" ":" WS quoted-string\n | "label" ":" WS quoted-string\n\nid = [A-Za-z] [A-Za-z0-9_-]*\nkey = [A-Za-z] [A-Za-z0-9_]*\ncomment = ( "#" | "//" | "%%" ) any NEWLINE\n```\n\nThe attribute block `[\u2026]` may span multiple physical lines \u2014 the parser joins continuation lines until the bracket depth returns to zero.\n\nAuthoritative source: `src/diagrams/sld/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1802
1467
|
},
|
|
1803
1468
|
"entity": {
|
|
1804
1469
|
"title": "Entity structure diagram",
|
|
@@ -1806,7 +1471,7 @@ var SYNTAX = {
|
|
|
1806
1471
|
},
|
|
1807
1472
|
"fishbone": {
|
|
1808
1473
|
"title": "Fishbone diagram",
|
|
1809
|
-
"content": '## 1. Your first fishbone\n\nThe smallest useful fishbone: three categories, one cause each, one with a sub-cause.\n\n```\nfishbone "API latency spike"\neffect "P99 > 2 s after deploy"\ncategory code "Code"\ncategory infra "Infra"\ncategory data "Data"\ncode : "N+1 query in new endpoint"\n - "Missing eager-load on orders"\ninfra : "DB connection pool exhausted"\ndata : "Index missing on accounts table"\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `fishbone`, optionally followed by a quoted title.\n2. Declare each branch with `category id "Label"` \u2014 the `id` is a short internal key, `"Label"` is what prints on the diagram.\n3. Add causes with `id : "cause text"` on their own lines.\n4. Indent a line by at least 2 spaces and start it with `-` to create a sub-cause (second-order branch) under the preceding cause.\n\n> Comments
|
|
1474
|
+
"content": '## 1. Your first fishbone\n\nThe smallest useful fishbone: three categories, one cause each, one with a sub-cause.\n\n```\nfishbone "API latency spike"\neffect "P99 > 2 s after deploy"\ncategory code "Code"\ncategory infra "Infra"\ncategory data "Data"\ncode : "N+1 query in new endpoint"\n - "Missing eager-load on orders"\ninfra : "DB connection pool exhausted"\ndata : "Index missing on accounts table"\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `fishbone`, optionally followed by a quoted title.\n2. Declare each branch with `category id "Label"` \u2014 the `id` is a short internal key, `"Label"` is what prints on the diagram.\n3. Add causes with `id : "cause text"` on their own lines.\n4. Indent a line by at least 2 spaces and start it with `-` to create a sub-cause (second-order branch) under the preceding cause.\n\n> Comments may start with `#`, `//`, or Mermaid-style `%%` on their own line.\n\n---\n\n## 2. Building blocks\n\n### The spine and effect\n\n`effect "Problem statement"` places text in the fish\'s head. If `effect` is omitted the parser falls back to the diagram title.\n\n```\nfishbone "Title"\neffect "Specific problem statement"\n```\n\nThe head sits on the right by default (`config direction = right`). Use `config direction = left` to flip it.\n\n### Categories (major bones)\n\n`category id "Label"` declares a branch. The `id` is used internally to assign causes; the quoted `"Label"` appears on the diagram.\n\nCategories also accept optional properties in `[\u2026]`:\n\n| Property | Values | Effect |\n|---|---|---|\n| `color: "#hex"` | hex color string | Branch and label color |\n| `side: top` / `side: bottom` | `top`, `bottom` | Forces this branch to the top or bottom rail (default: alternating) |\n| `order: N` | integer | Position within its rail \u2014 lower numbers sit closer to the tail |\n\n```\ncategory rework "Rework" [color: "#E53935", side: top, order: 1]\n```\n\n### Causes (minor bones)\n\nTwo styles are accepted and can be mixed in one diagram:\n\n**Style A \u2014 structured.** Declare categories first, then assign causes with `id : "text"`:\n\n```\ncategory code "Code"\ncategory infra "Infra"\ncode : "N+1 query in endpoint"\ncode : "Missing cache layer"\ninfra : "Auto-scaling lag"\n```\n\n**Style B \u2014 compact.** Category label and causes in one line, separated by `;` or `,`:\n\n```\ncategory Code: N+1 query; Missing cache; Synchronous call\ncategory Infra: Auto-scaling lag; CDN misconfigured\n```\n\nIn compact style the `id` is auto-derived from the label text (lowercased, spaces \u2192 hyphens). Quotes are optional for cause text.\n\n```\nfishbone "Conversion rate drop"\neffect "Checkout conversion -12% MoM"\n# Style A \u2014 structured\ncategory ux "UX"\ncategory trust "Trust"\nux : "Confusing multi-step form"\nux : "Slow page on mobile"\ntrust : "No payment security badge"\n# Style B \u2014 compact\ncategory Pricing: Price-anchoring missing; No annual discount shown; Coupon field too prominent\n```\n\n**Style C \u2014 Mermaid-mindmap shorthand.** A top-level bare line becomes a category,\nand indented `-` items become sibling Level-1 causes under that category:\n\n```txt\nfishbone "Why is the site slow?"\neffect "Page LCP > 4s"\nContent\n - heavy hero image\n - too much above-the-fold text\nTech\n - JS bundle too large\n - render-blocking CSS\n```\n\n---\n\n## 3. Sub-causes (second-order branches)\n\nIndent a `-` line by at least 2 spaces after a Level-1 cause to attach a sub-cause to it. The `-` dash is part of the syntax; the text follows it.\n\n```\nmethod : "Stencil aperture undersized"\n - "Tolerance spec from 2018 board revision"\n - "No re-validation after material change"\nmethod : "Pick-and-place speed too high"\n - "Speed limit lifted during overtime run"\n```\n\nSub-causes appear as shorter, narrower twigs branching off their parent rib.\n\n```\nfishbone "Medication error increase"\neffect "Errors up 18% in Q3"\ncategory process "Process"\ncategory people "People"\nprocess : "CPOE alert fatigue"\n - "47 non-critical alerts per shift"\n - "Override too easy \u2014 one click"\nprocess : "5-Rights verification skipped"\n - "No barcode scanner at bedside"\npeople : "Float staff unfamiliar with unit"\n - "No unit-specific orientation checklist"\npeople : "Handoff communication gaps"\n```\n\n---\n\n## 4. Config options\n\n`config key = value` lines can appear anywhere after the header. Unknown keys and values are silently ignored.\n\n| Config key | Values | Default | Effect |\n|---|---|---|---|\n| `direction` | `right` / `left` (also `ltr` / `rtl`) | `right` | Which side the effect head appears on |\n| `sides` | `both`, `top`, `bottom` | `both` | Which half of the spine hosts branches |\n| `density` | `compact`, `normal`, `spacious` | `normal` | Spacing between ribs \u2014 affects how many branches fit before overlap |\n| `slope` (or `ribslope`) | `gentle`, `normal`, `steep`, or a number (0\u20133) | `normal` (0.6) | Rib angle \u2014 shallow vs. steep diagonal |\n| `causeside` (or `cause-side`) | `head`, `tail`, `both` | `head` | Which side of a rib sub-causes branch off from |\n| `width` | integer px | auto | Override canvas width |\n| `height` | integer px | auto | Override canvas height |\n\n```\nconfig direction = left\nconfig density = compact\nconfig slope = gentle\nconfig sides = top\n```\n\n---\n\n## 5. Labels & comments\n\n- **Diagram title:** `fishbone "Website Traffic Drop"` \u2014 first line, optional.\n- **Effect label:** `effect "30% organic traffic decline"` \u2014 the problem at the fish\'s head.\n- **Category label:** `category id "Human-readable name"` \u2014 printed on the branch.\n- **Cause text:** quoted `"like this"` or unquoted (spaces allowed in compact style).\n- **Sub-cause text:** after the leading `-`, quoted or unquoted.\n- **Comments:** `#`, `//`, or `%%` at the start of a line (after optional leading whitespace). The same markers also start trailing comments outside double-quoted strings.\n\n---\n\n## 6. Reserved words & escaping\n\n**Reserved at line start:** `fishbone` (header), `effect`, `category`, `config`.\n\n**The `-` prefix** on an indented line is reserved as the sub-cause marker. To include a literal hyphen-dash at the start of cause text, quote it: `code : "- old deprecated path"`.\n\n**Strings with spaces** in structured-style cause text should be double-quoted: `code : "N+1 query"`. In compact style (`category Label: ...`) the text runs to the `;` or `,` separator and quoting is optional.\n\n**Comment markers** (`#`, `//`, `%%`) start a comment unless inside a double-quoted string.\n\n| Reserved sequence | Context | Alternative |\n|---|---|---|\n| `#` at line start | Comment marker | Quote the text if `#` is part of content |\n| `-` at start after \u22652-space indent | Sub-cause marker | Quote: `- "- text with dash"` |\n| `category`, `effect`, `config`, `fishbone` | Line-start keywords | Cannot be used as category IDs |\n\n---\n\n## 7. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `cause1 : "text"` with no prior `category cause1` | `FishboneParseError: Unknown category "cause1"` | Declare `category cause1 "Label"` before assigning causes |\n| `- "sub-cause"` at the start of the file (no preceding Level-1 cause) | `FishboneParseError: Sub-cause \u2026 has no preceding Level-1 cause` | Place the sub-cause line immediately after a `id : "cause"` line |\n| `- "sub-cause"` with only 1-space indent | Treated as a cause line, not a sub-cause | Indent with at least 2 spaces |\n| `category Code: cause one, cause two` | Parsed as compact style \u2014 `,` and `;` are both separators | Intended behavior; both separators work |\n| `config direction = center` | Unknown value \u2014 silently ignored, stays `right` | Use `right` or `left` |\n| `config slope = 45` | Out of range (must be 0\u20133 exclusive); silently ignored | Use a preset (`gentle`, `normal`, `steep`) or a value like `0.5` |\n| `fishbone: "Title"` | Parsed correctly \u2014 colon after keyword is optional | Both `fishbone "Title"` and `fishbone: "Title"` work |\n| Mermaid mindmap-style bare category | Parsed as an implicit category | `Content` followed by indented `- item` lines works without `category` |\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | effect | category | config | cause | sub-cause | implicit-category)*\n\nheader = "fishbone" ":"? ( WS quoted-string )? NEWLINE\neffect = "effect" ":"? WS quoted-string NEWLINE\nconfig = "config" WS config-key WS "=" WS config-value NEWLINE\nconfig-key = "direction" | "width" | "height" | "sides"\n | "slope" | "ribslope" | "density" | "causeside" | "cause-side"\nconfig-value = bare-word | number | quoted-string\n\ncategory = "category" WS id WS label-or-compact ( "[" category-attrs "]" )? NEWLINE\nimplicit-category\n = bare-text NEWLINE # top-level, no ":"\n\nlabel-or-compact\n = quoted-string # structured form: category id "Label"\n | id WS ":" WS compact-causes # compact form: category Label: cause; cause\n\ncategory-attrs = category-attr ("," category-attr)*\ncategory-attr = "color:" quoted-string\n | "side:" ( "top" | "bottom" )\n | "order:" integer\n\ncause = id WS ":" WS cause-text NEWLINE # structured form\ncause-text = quoted-string | bare-text\n\nsub-cause = INDENT\u22652 "-" WS cause-text NEWLINE\n\ncompact-causes = compact-cause ( (";" | ",") compact-cause )*\ncompact-cause = quoted-string | bare-text\n\ncomment = ( "#" | "//" | "%%" ) any NEWLINE\nid = [a-zA-Z] [a-zA-Z0-9_-]*\nquoted-string = \'"\' any-char-but-unescaped-quote* \'"\'\n```\n\nAuthoritative source: `src/diagrams/fishbone/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1810
1475
|
},
|
|
1811
1476
|
"venn": {
|
|
1812
1477
|
"title": "Venn / Euler diagram",
|
|
@@ -1818,7 +1483,7 @@ var SYNTAX = {
|
|
|
1818
1483
|
},
|
|
1819
1484
|
"flowchart": {
|
|
1820
1485
|
"title": "Flowchart",
|
|
1821
|
-
"content": '## 1. Your first flowchart\n\nThe smallest useful flowchart: a decision with two outcomes.\n\n```\nflowchart TD\n A([Start]) --> B{File exists?}\n B -->|Yes| C[Read file]\n B -->|No| D[Return error]\n C --> E([Done])\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `flowchart` followed by a direction: `TD`, `LR`, `BT`, or `RL`.\n2. Each node is `ID[Label]` \u2014 the shape brackets determine the node type (see \xA72).\n3. Connect nodes with `-->`. Add a label between pipe characters: `-->|Yes|`.\n4. Nodes are created automatically when first referenced in an edge \u2014 but explicit declarations let you set shapes and labels independently.\n\n> Comments start with `%%` on their own line.\n\n---\n\n## 2. Node shapes\n\nEach node shape is written as `ID<brackets>Label<brackets>`. The ID must start with a letter and may contain letters, digits, `_`, and `-`.\n\n| Syntax | Shape | Typical use |\n|---|---|---|\n| `A[Label]` | Rectangle | Process step, operation |\n| `A(Label)` | Rounded rectangle | Subprocess, soft step |\n| `A([Label])` | Stadium (pill) | Start / end terminal |\n| `A{Label}` | Diamond | Decision / condition |\n| `A{{Label}}` | Hexagon | Preparation, configuration |\n| `A[[Label]]` | Subroutine | Predefined process |\n| `A[(Label)]` | Cylinder | Database, storage |\n| `A((Label))` | Circle | Connector, junction |\n| `A(((Label)))` | Double circle | End state |\n| `A[/Label/]` | Parallelogram | Input / output |\n| `A[\\Label\\]` | Parallelogram (alt) | Manual operation |\n| `A[/Label\\]` | Trapezoid | Manual input |\n| `A[\\Label/]` | Trapezoid (alt) | Off-page connector |\n| `A>Label]` | Asymmetric | Tag, annotation |\n\n```\nflowchart TD\n t([Terminal / stadium])\n r[Rectangle process]\n d{Diamond decision}\n p[/Parallelogram input/]\n db[(Cylinder database)]\n sub[[Subroutine]]\n t --> r --> d\n d -->|branch A| p\n d -->|branch B| db\n p --> sub\n db --> sub\n```\n\n---\n\n## 3. Edges\n\nAn edge connects two nodes. The connector symbol determines the visual style and whether a label or arrowhead is present.\n\n### 3.1 Edge types\n\n```\nflowchart TD\n A --> B\n C --- D\n E -.-> F\n G ==> H\n I <--> J\n K --x L\n M --o N\n```\n\n| Syntax | Style | Arrow | Typical use |\n|---|---|---|---|\n| `A --> B` | Solid | Arrow | Normal flow |\n| `A --- B` | Solid | None | Association, undirected link |\n| `A -.-> B` | Dotted | Arrow | Optional / async path |\n| `A ==> B` | Thick | Arrow | Critical / primary path |\n| `A <--> B` | Solid | Both ends | Bidirectional flow |\n| `A --x B` | Solid | Cross | Blocked / rejected path |\n| `A --o B` | Solid | Circle | Aggregation / composition |\n\n### 3.2 Edge labels\n\nTwo syntaxes attach a label to an edge:\n\n**Pipe label** \u2014 placed between `|` characters directly after the arrow:\n```\nA -->|Yes| B\nA -.->|optional| B\nA ==>|critical| B\n```\n\n**Inline label** \u2014 text placed between the dashes, before the arrow character:\n```\nA -- success --> B\nA -- error --x C\n```\n\nBoth produce identical results. Pipe label is more common when sharing a diagram with Mermaid tools.\n\n```\nflowchart TD\n req[Request received]\n req -->|valid| proc[Process]\n req -->|invalid| err[Return 400]\n proc -- success --> ok([Done])\n proc -.->|timeout| retry[Retry queue]\n retry ==>|max retries| dead[(Dead letter)]\n```\n\n### 3.3 Chains\n\nConnect three or more nodes in a single line:\n\n```\nA --> B --> C --> D\n```\n\nThis is equivalent to three separate edge statements.\n\n### 3.4 Fan-out with `&`\n\nUse `&` to include multiple nodes on either side of an arrow. The parser generates the full cross-product of edges:\n\n```\nA & B --> C %% A\u2192C and B\u2192C\nA --> B & C %% A\u2192B and A\u2192C\nA & B --> C & D %% four edges: A\u2192C, A\u2192D, B\u2192C, B\u2192D\n```\n\n```\nflowchart LR\n deploy[Deploy service]\n smoke[Smoke test]\n health[Health check]\n notify_slack[Slack alert]\n notify_email[Email alert]\n deploy --> smoke & health\n smoke & health -->|fail| notify_slack & notify_email\n```\n\n---\n\n## 4. Subgraphs\n\nA `subgraph` groups related nodes into a labeled cluster with a visible border.\n\n```\nsubgraph "Title"\n A --> B\nend\n```\n\nThree subgraph header forms are accepted:\n\n| Form | ID | Label |\n|---|---|---|\n| `subgraph "My Group"` | auto-generated | `My Group` |\n| `subgraph sg1 "My Group"` | `sg1` | `My Group` |\n| `subgraph sg1 [My Group]` | `sg1` | `My Group` |\n\nSubgraphs can have their own `direction` override:\n\n```\nsubgraph sg1 "Frontend"\n direction LR\n ui[React App] --> api[API Client]\nend\n```\n\n```\nflowchart TB\n subgraph ingestion [Ingestion]\n raw[/Raw events/] --> parse[Parse & validate]\n parse --> enrich[Enrich]\n end\n subgraph storage [Storage]\n dw[(Data warehouse)]\n cache[(Redis cache)]\n end\n enrich --> dw\n enrich --> cache\n dw --> report[Generate report]\n```\n\n---\n\n## 5. Styling\n\n### 5.1 Semantic classes\n\nAssign CSS class names to nodes for theme-level visual grouping. Classes are defined with `classDef` and applied with `class`.\n\n```\nclassDef danger fill:#f9c,stroke:#c00\nclassDef safe fill:#cfc,stroke:#090\nclass errorNode danger\nclass successNode safe\n```\n\n### 5.2 Per-node style overrides\n\n```\nstyle nodeId fill:#f9f,stroke:#333,stroke-width:4px\n```\n\nAccepts standard CSS property names. Multiple properties are comma-separated.\n\n### 5.3 Per-edge style overrides\n\n`linkStyle` targets edges by their **declaration index** (0-based, in the order they appear in the source). Multiple comma-separated indices apply the same props to several edges:\n\n```\nflowchart TD\n A --> B\n B ==> C\n B -.-> D\n C --> E\n D --> E\n linkStyle 1 stroke:#d32f2f,stroke-width:4px\n linkStyle 2,4 stroke:#f57c00,stroke-dasharray:5 5\n```\n\nUse this to highlight a critical path or distinguish an alternate flow.\n\n### 5.4 Inline label formatting\n\nNode labels accept three inline formatting tags:\n\n| Tag | Effect |\n|---|---|\n| `<br/>` or `<br>` | Line break |\n| `<b>\u2026</b>` | Bold |\n| `<i>\u2026</i>` | Italic |\n\n```\nflowchart TD\n M1["0 \\| 0<br/><b>START</b>"]\n M2["4 \\| 4<br/><b>Phase 1</b><br/><i>est. 4h</i>"]\n M1 --> M2\n```\n\nTags can be nested and mixed mid-line (`Hello <b>world</b>!`). Edge labels are single-line and do not currently support these tags.\n\n---\n\n## 6. Labels & comments\n\n- **Direction:** `flowchart TD` \u2014 first token after `flowchart` or `graph`. `TD` and `TB` are equivalent.\n- **Title:** `flowchart LR "My diagram"` \u2014 optional quoted string after the direction.\n- **Edge labels:** pipe syntax `-->|label|` or inline `-- label -->`.\n- **Comments:** `%%` at the start of a line (after leading whitespace).\n\n```\nflowchart LR\n%% This is a comment \u2014 ignored by the parser\nA[Step 1] --> B[Step 2] %% inline %% is NOT supported \u2014 only line-start %%\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `flowchart`, `graph` (header), `subgraph`, `end`, `direction`, `class`, `classDef`, `style`, `linkStyle`.\n\n**Reserved ID characters:** IDs match `[A-Za-z0-9_-]` starting with a letter. Do not use spaces or operator characters in node IDs.\n\n**Operator tokens to avoid inside IDs:** `-->`, `---`, `-.->`, `==>`, `<-->`, `--x`, `--o`, `|`, `&`.\n\n**Labels with special characters:** The label is everything inside the shape brackets. Special characters are supported inside labels as-is \u2014 brackets/braces that would be ambiguous are closed by the matching closing token.\n\n---\n\n## 8. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `flowchart` with no direction | Direction defaults to `TB` | Add a direction: `flowchart TD` |\n| `A --> B` before declaring shapes | Works \u2014 nodes created as rectangles with the ID as label | Declare explicitly when you need a non-rect shape: `A([Start])` |\n| `A[Label with [brackets]]` | Inner `]` closes the shape early | Avoid nested brackets in labels |\n| `subgraph My Group` (unquoted, with space) | Parser takes `My` as subgraph id, `Group` as unknown token | Quote: `subgraph "My Group"` |\n| `%% comment` mid-line after code | Inline comments are not supported; `%%` must be at line start | Move comments to their own line |\n| `A --> B --> C` mixed with `A --> B` | Chains are additive \u2014 duplicate edges may appear | Use chains OR separate lines, not both for the same pair |\n| `direction LR` outside a subgraph | Silently ignored \u2014 `direction` override only applies inside `subgraph \u2026 end` | Set direction on the `flowchart` header line |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | subgraph-block | direction-stmt\n | class-stmt | classdef-stmt | style-stmt\n | linkstyle-stmt | chain-stmt)*\n\nheader = ("flowchart" | "graph") ( WS direction )? ( WS title )? NEWLINE\ndirection = "TD" | "TB" | "BT" | "LR" | "RL"\ntitle = \'"\' any-char-but-quote* \'"\' | bare-word\n\nsubgraph-block = "subgraph" ( WS subgraph-header )? NEWLINE\n ( WS? "direction" WS direction NEWLINE )?\n statement*\n "end" NEWLINE\nsubgraph-header = id WS "[" label "]"\n | id WS quoted-string\n | quoted-string\n | id\n\nchain-stmt = node-group ( WS edge-op WS pipe-label? WS node-group )* NEWLINE\nnode-group = node-ref ( WS "&" WS node-ref )*\nnode-ref = id shape-suffix?\nshape-suffix = "[" label "]" %% rect\n | "(" label ")" %% round\n | "([" label "])" %% stadium\n | "{" label "}" %% diamond\n | "{{" label "}}" %% hexagon\n | "[[" label "]]" %% subroutine\n | "[(" label ")]" %% cylinder\n | "((" label "))" %% circle\n | "(((" label ")))" %% double-circle\n | "[/" label "/]" %% parallelogram\n | "[\\" label "\\]" %% parallelogram-alt\n | "[/" label "\\]" %% trapezoid\n | "[\\" label "/]" %% trapezoid-alt\n | ">" label "]" %% asymmetric\n\nedge-op = "-->" | "---" | "-."-".->" | "==>" | "<-->" | "--x" | "--o"\n | inline-label variants of the above\npipe-label = "|" text "|"\n\nclass-stmt = "class" WS id-list WS class-name NEWLINE\nclassdef-stmt = "classDef" WS class-name WS css-props NEWLINE\nstyle-stmt = "style" WS id WS css-props NEWLINE\nlinkstyle-stmt = "linkStyle" WS index-list WS css-props NEWLINE\nindex-list = NUMBER ( "," NUMBER )* | "default"\n\ncomment = "%%" any NEWLINE\nid = [A-Za-z] [A-Za-z0-9_-]*\n```\n\nAuthoritative source: `src/diagrams/flowchart/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1486
|
+
"content": '## 1. Your first flowchart\n\nThe smallest useful flowchart: a decision with two outcomes.\n\n```\nflowchart TD\n A([Start]) --> B{File exists?}\n B -->|Yes| C[Read file]\n B -->|No| D[Return error]\n C --> E([Done])\n```\n\nFour rules cover 80% of usage:\n\n1. Start with `flowchart` followed by a direction: `TD`, `LR`, `BT`, or `RL`.\n2. Each node is `ID[Label]` \u2014 the shape brackets determine the node type (see \xA72).\n3. Connect nodes with `-->`. Add a label between pipe characters: `-->|Yes|`.\n4. Nodes are created automatically when first referenced in an edge \u2014 but explicit declarations let you set shapes and labels independently.\n\n> Comments start with `%%` on their own line.\n\n---\n\n## 2. Node shapes\n\nEach node shape is written as `ID<brackets>Label<brackets>`. The ID must start with a letter and may contain letters, digits, `_`, and `-`.\n\n| Syntax | Shape | Typical use |\n|---|---|---|\n| `A[Label]` | Rectangle | Process step, operation |\n| `A(Label)` | Rounded rectangle | Subprocess, soft step |\n| `A([Label])` | Stadium (pill) | Start / end terminal |\n| `A{Label}` | Diamond | Decision / condition |\n| `A{{Label}}` | Hexagon | Preparation, configuration |\n| `A[[Label]]` | Subroutine | Predefined process |\n| `A[(Label)]` | Cylinder | Database, storage |\n| `A((Label))` | Circle | Connector, junction |\n| `A(((Label)))` | Double circle | End state |\n| `A[/Label/]` | Parallelogram | Input / output |\n| `A[\\Label\\]` | Parallelogram (alt) | Manual operation |\n| `A[/Label\\]` | Trapezoid | Manual input |\n| `A[\\Label/]` | Trapezoid (alt) | Off-page connector |\n| `A>Label]` | Asymmetric | Tag, annotation |\n\n```\nflowchart TD\n t([Terminal / stadium])\n r[Rectangle process]\n d{Diamond decision}\n p[/Parallelogram input/]\n db[(Cylinder database)]\n sub[[Subroutine]]\n t --> r --> d\n d -->|branch A| p\n d -->|branch B| db\n p --> sub\n db --> sub\n```\n\n---\n\n## 3. Edges\n\nAn edge connects two nodes. The connector symbol determines the visual style and whether a label or arrowhead is present.\n\n### 3.1 Edge types\n\n```\nflowchart TD\n A --> B\n C --- D\n E -.-> F\n G ==> H\n I <--> J\n K --x L\n M --o N\n```\n\n| Syntax | Style | Arrow | Typical use |\n|---|---|---|---|\n| `A --> B` | Solid | Arrow | Normal flow |\n| `A --- B` | Solid | None | Association, undirected link |\n| `A -.-> B` | Dotted | Arrow | Optional / async path |\n| `A ==> B` | Thick | Arrow | Critical / primary path |\n| `A <--> B` | Solid | Both ends | Bidirectional flow |\n| `A --x B` | Solid | Cross | Blocked / rejected path |\n| `A --o B` | Solid | Circle | Aggregation / composition |\n\n### 3.2 Edge labels\n\nTwo syntaxes attach a label to an edge:\n\n**Pipe label** \u2014 placed between `|` characters directly after the arrow:\n```\nA -->|Yes| B\nA -.->|optional| B\nA ==>|critical| B\n```\n\n**Inline label** \u2014 text placed between the dashes, before the arrow character:\n```\nA -- success --> B\nA -- error --x C\n```\n\nBoth produce identical results. Pipe label is more common when sharing a diagram with Mermaid tools.\n\n```\nflowchart TD\n req[Request received]\n req -->|valid| proc[Process]\n req -->|invalid| err[Return 400]\n proc -- success --> ok([Done])\n proc -.->|timeout| retry[Retry queue]\n retry ==>|max retries| dead[(Dead letter)]\n```\n\n### 3.3 Chains\n\nConnect three or more nodes in a single line:\n\n```\nA --> B --> C --> D\n```\n\nThis is equivalent to three separate edge statements.\n\n### 3.4 Fan-out with `&`\n\nUse `&` to include multiple nodes on either side of an arrow. The parser generates the full cross-product of edges:\n\n```\nA & B --> C %% A\u2192C and B\u2192C\nA --> B & C %% A\u2192B and A\u2192C\nA & B --> C & D %% four edges: A\u2192C, A\u2192D, B\u2192C, B\u2192D\n```\n\n```\nflowchart LR\n deploy[Deploy service]\n smoke[Smoke test]\n health[Health check]\n notify_slack[Slack alert]\n notify_email[Email alert]\n deploy --> smoke & health\n smoke & health -->|fail| notify_slack & notify_email\n```\n\n---\n\n## 4. Subgraphs\n\nA `subgraph` groups related nodes into a labeled cluster with a visible border.\n\n```\nsubgraph "Title"\n A --> B\nend\n```\n\nThree subgraph header forms are accepted:\n\n| Form | ID | Label |\n|---|---|---|\n| `subgraph "My Group"` | auto-generated | `My Group` |\n| `subgraph sg1 "My Group"` | `sg1` | `My Group` |\n| `subgraph sg1 [My Group]` | `sg1` | `My Group` |\n\nSubgraphs can have their own `direction` override:\n\n```\nsubgraph sg1 "Frontend"\n direction LR\n ui[React App] --> api[API Client]\nend\n```\n\n```\nflowchart TB\n subgraph ingestion [Ingestion]\n raw[/Raw events/] --> parse[Parse & validate]\n parse --> enrich[Enrich]\n end\n subgraph storage [Storage]\n dw[(Data warehouse)]\n cache[(Redis cache)]\n end\n enrich --> dw\n enrich --> cache\n dw --> report[Generate report]\n```\n\n---\n\n## 5. Styling\n\n### 5.1 Semantic classes\n\nAssign CSS class names to nodes for theme-level visual grouping. Classes are defined with `classDef` and applied with `class`. Mermaid inline class syntax is also accepted: `A[Start]:::critical`.\n\n```\nclassDef danger fill:#f9c,stroke:#c00\nclassDef safe fill:#cfc,stroke:#090\nclass errorNode danger\nclass successNode safe\nB[Review]:::danger\n```\n\n### 5.2 Per-node style overrides\n\n```\nstyle nodeId fill:#f9f,stroke:#333,stroke-width:4px\n```\n\nAccepts standard CSS property names. Multiple properties are comma-separated.\n\n### 5.3 Per-edge style overrides\n\n`linkStyle` targets edges by their **declaration index** (0-based, in the order they appear in the source). Multiple comma-separated indices apply the same props to several edges:\n\n```\nflowchart TD\n A --> B\n B ==> C\n B -.-> D\n C --> E\n D --> E\n linkStyle 1 stroke:#d32f2f,stroke-width:4px\n linkStyle 2,4 stroke:#f57c00,stroke-dasharray:5 5\n```\n\nUse this to highlight a critical path or distinguish an alternate flow.\n\n### 5.4 Inline label formatting\n\nNode labels accept three inline formatting tags:\n\n| Tag | Effect |\n|---|---|\n| `<br/>` or `<br>` | Line break |\n| `<b>\u2026</b>` | Bold |\n| `<i>\u2026</i>` | Italic |\n\n```\nflowchart TD\n M1["0 \\| 0<br/><b>START</b>"]\n M2["4 \\| 4<br/><b>Phase 1</b><br/><i>est. 4h</i>"]\n M1 --> M2\n```\n\nTags can be nested and mixed mid-line (`Hello <b>world</b>!`). Edge labels are single-line and do not currently support these tags.\n\n---\n\n## 6. Labels & comments\n\n- **Direction:** `flowchart TD` \u2014 first token after `flowchart` or `graph`. `TD` and `TB` are equivalent.\n- **Title:** `flowchart LR "My diagram"` \u2014 optional quoted string after the direction.\n- **Edge labels:** pipe syntax `-->|label|` or inline `-- label -->`.\n- **Comments:** `%%` at the start of a line (after leading whitespace).\n\n```\nflowchart LR\n%% This is a comment \u2014 ignored by the parser\nA[Step 1] --> B[Step 2] %% inline %% is NOT supported \u2014 only line-start %%\n```\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start:** `flowchart`, `graph` (header), `subgraph`, `end`, `direction`, `class`, `classDef`, `style`, `linkStyle`.\n\n**Reserved ID characters:** IDs match `[A-Za-z0-9_-]` starting with a letter. Do not use spaces or operator characters in node IDs.\n\n**Operator tokens to avoid inside IDs:** `-->`, `---`, `-.->`, `==>`, `<-->`, `--x`, `--o`, `|`, `&`.\n\n**Labels with special characters:** The label is everything inside the shape brackets. Special characters are supported inside labels as-is \u2014 brackets/braces that would be ambiguous are closed by the matching closing token.\n\n---\n\n## 8. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `flowchart` with no direction | Direction defaults to `TB` | Add a direction: `flowchart TD` |\n| `A --> B` before declaring shapes | Works \u2014 nodes created as rectangles with the ID as label | Declare explicitly when you need a non-rect shape: `A([Start])` |\n| `A[Label with [brackets]]` | Inner `]` closes the shape early | Avoid nested brackets in labels |\n| `subgraph My Group` (unquoted, with space) | Parser takes `My` as subgraph id, `Group` as unknown token | Quote: `subgraph "My Group"` |\n| `%% comment` mid-line after code | Inline comments are not supported; `%%` must be at line start | Move comments to their own line |\n| `A --> B --> C` mixed with `A --> B` | Chains are additive \u2014 duplicate edges may appear | Use chains OR separate lines, not both for the same pair |\n| `direction LR` outside a subgraph | Silently ignored \u2014 `direction` override only applies inside `subgraph \u2026 end` | Set direction on the `flowchart` header line |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | subgraph-block | direction-stmt\n | class-stmt | classdef-stmt | style-stmt\n | linkstyle-stmt | chain-stmt)*\n\nheader = ("flowchart" | "graph") ( WS direction )? ( WS title )? NEWLINE\ndirection = "TD" | "TB" | "BT" | "LR" | "RL"\ntitle = \'"\' any-char-but-quote* \'"\' | bare-word\n\nsubgraph-block = "subgraph" ( WS subgraph-header )? NEWLINE\n ( WS? "direction" WS direction NEWLINE )?\n statement*\n "end" NEWLINE\nsubgraph-header = id WS "[" label "]"\n | id WS quoted-string\n | quoted-string\n | id\n\nchain-stmt = node-group ( WS edge-op WS pipe-label? WS node-group )* NEWLINE\nnode-group = node-ref ( WS "&" WS node-ref )*\nnode-ref = id shape-suffix?\nshape-suffix = "[" label "]" %% rect\n | "(" label ")" %% round\n | "([" label "])" %% stadium\n | "{" label "}" %% diamond\n | "{{" label "}}" %% hexagon\n | "[[" label "]]" %% subroutine\n | "[(" label ")]" %% cylinder\n | "((" label "))" %% circle\n | "(((" label ")))" %% double-circle\n | "[/" label "/]" %% parallelogram\n | "[\\" label "\\]" %% parallelogram-alt\n | "[/" label "\\]" %% trapezoid\n | "[\\" label "/]" %% trapezoid-alt\n | ">" label "]" %% asymmetric\n\nedge-op = "-->" | "---" | "-."-".->" | "==>" | "<-->" | "--x" | "--o"\n | inline-label variants of the above\npipe-label = "|" text "|"\n\nclass-stmt = "class" WS id-list WS class-name NEWLINE\n | node-ref ":::" class-name NEWLINE # Mermaid inline form\nclassdef-stmt = "classDef" WS class-name WS css-props NEWLINE\nstyle-stmt = "style" WS id WS css-props NEWLINE\nlinkstyle-stmt = "linkStyle" WS index-list WS css-props NEWLINE\nindex-list = NUMBER ( "," NUMBER )* | "default"\n\ncomment = "%%" any NEWLINE\nid = [A-Za-z] [A-Za-z0-9_-]*\n```\n\nAuthoritative source: `src/diagrams/flowchart/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
1822
1487
|
},
|
|
1823
1488
|
"matrix": {
|
|
1824
1489
|
"title": "Matrix / Quadrant diagram",
|
|
@@ -1975,5 +1640,5 @@ function resolveTypeFromText(text) {
|
|
|
1975
1640
|
}
|
|
1976
1641
|
|
|
1977
1642
|
export { DIAGRAM_REGISTRY, getAllDiagramTypes, getDiagramMeta, getExamples, getSyntax, listDiagrams, renderDsl, validateDsl };
|
|
1978
|
-
//# sourceMappingURL=chunk-
|
|
1979
|
-
//# sourceMappingURL=chunk-
|
|
1643
|
+
//# sourceMappingURL=chunk-UBTKM2TB.js.map
|
|
1644
|
+
//# sourceMappingURL=chunk-UBTKM2TB.js.map
|