schematex 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +24 -3
  2. package/dist/ai/ai-sdk.cjs +9 -9
  3. package/dist/ai/ai-sdk.d.cts +2 -2
  4. package/dist/ai/ai-sdk.d.ts +2 -2
  5. package/dist/ai/ai-sdk.js +4 -4
  6. package/dist/ai/index.cjs +12 -12
  7. package/dist/ai/index.d.cts +3 -3
  8. package/dist/ai/index.d.ts +3 -3
  9. package/dist/ai/index.js +4 -4
  10. package/dist/{api-BIj9t4Oc.d.cts → api-C5UcmT7n.d.cts} +1 -1
  11. package/dist/{api-BIj9t4Oc.d.ts → api-C5UcmT7n.d.ts} +1 -1
  12. package/dist/browser.cjs +6 -6
  13. package/dist/browser.d.cts +2 -2
  14. package/dist/browser.d.ts +2 -2
  15. package/dist/browser.js +4 -4
  16. package/dist/{chunk-SMXU3KYA.cjs → chunk-3YUUC6RN.cjs} +5115 -282
  17. package/dist/chunk-3YUUC6RN.cjs.map +1 -0
  18. package/dist/{chunk-KWQTF6ZL.js → chunk-GTDQAN2Z.js} +5110 -280
  19. package/dist/chunk-GTDQAN2Z.js.map +1 -0
  20. package/dist/{chunk-J7JWMQD5.js → chunk-HUPDIRBX.js} +119 -4
  21. package/dist/chunk-HUPDIRBX.js.map +1 -0
  22. package/dist/{chunk-UBTKM2TB.js → chunk-IM4RCUHA.js} +210 -22
  23. package/dist/chunk-IM4RCUHA.js.map +1 -0
  24. package/dist/{chunk-N3SLYVNW.cjs → chunk-NWPCY65Z.cjs} +212 -24
  25. package/dist/{chunk-UBTKM2TB.js.map → chunk-NWPCY65Z.cjs.map} +1 -1
  26. package/dist/{chunk-VITE3MZQ.cjs → chunk-QTNPMIO2.cjs} +99 -5
  27. package/dist/chunk-QTNPMIO2.cjs.map +1 -0
  28. package/dist/{chunk-6IGSKU6D.js → chunk-UFTYX73U.js} +99 -5
  29. package/dist/chunk-UFTYX73U.js.map +1 -0
  30. package/dist/{chunk-2Z543TC3.cjs → chunk-XRCY75UV.cjs} +119 -4
  31. package/dist/chunk-XRCY75UV.cjs.map +1 -0
  32. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  33. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  34. package/dist/diagrams/circuit/index.cjs +7 -7
  35. package/dist/diagrams/circuit/index.d.cts +1 -1
  36. package/dist/diagrams/circuit/index.d.ts +1 -1
  37. package/dist/diagrams/circuit/index.js +1 -1
  38. package/dist/diagrams/ecomap/index.d.cts +1 -1
  39. package/dist/diagrams/ecomap/index.d.ts +1 -1
  40. package/dist/diagrams/entity/index.d.cts +1 -1
  41. package/dist/diagrams/entity/index.d.ts +1 -1
  42. package/dist/diagrams/fishbone/index.d.cts +1 -1
  43. package/dist/diagrams/fishbone/index.d.ts +1 -1
  44. package/dist/diagrams/flowchart/index.cjs +7 -7
  45. package/dist/diagrams/flowchart/index.d.cts +2 -2
  46. package/dist/diagrams/flowchart/index.d.ts +2 -2
  47. package/dist/diagrams/flowchart/index.js +1 -1
  48. package/dist/diagrams/genogram/index.d.cts +1 -1
  49. package/dist/diagrams/genogram/index.d.ts +1 -1
  50. package/dist/diagrams/ladder/index.d.cts +1 -1
  51. package/dist/diagrams/ladder/index.d.ts +1 -1
  52. package/dist/diagrams/logic/index.d.cts +1 -1
  53. package/dist/diagrams/logic/index.d.ts +1 -1
  54. package/dist/diagrams/orgchart/index.d.cts +1 -1
  55. package/dist/diagrams/orgchart/index.d.ts +1 -1
  56. package/dist/diagrams/pedigree/index.d.cts +1 -1
  57. package/dist/diagrams/pedigree/index.d.ts +1 -1
  58. package/dist/diagrams/phylo/index.d.cts +1 -1
  59. package/dist/diagrams/phylo/index.d.ts +1 -1
  60. package/dist/diagrams/sld/index.d.cts +1 -1
  61. package/dist/diagrams/sld/index.d.ts +1 -1
  62. package/dist/diagrams/sociogram/index.d.cts +1 -1
  63. package/dist/diagrams/sociogram/index.d.ts +1 -1
  64. package/dist/diagrams/timing/index.d.cts +1 -1
  65. package/dist/diagrams/timing/index.d.ts +1 -1
  66. package/dist/diagrams/venn/index.d.cts +1 -1
  67. package/dist/diagrams/venn/index.d.ts +1 -1
  68. package/dist/{index-DYpJXJcy.d.cts → index-C9A0h-CB.d.cts} +1 -1
  69. package/dist/{index-BeUVaQiD.d.ts → index-CJai_TEZ.d.ts} +1 -1
  70. package/dist/index.cjs +23 -11
  71. package/dist/index.d.cts +10 -4
  72. package/dist/index.d.ts +10 -4
  73. package/dist/index.js +3 -3
  74. package/dist/react.cjs +4 -4
  75. package/dist/react.d.cts +1 -1
  76. package/dist/react.d.ts +1 -1
  77. package/dist/react.js +3 -3
  78. package/dist/{types-DKdo-Ua_.d.cts → types-BOAsqHoU.d.cts} +2 -2
  79. package/dist/{types-DKdo-Ua_.d.ts → types-BOAsqHoU.d.ts} +2 -2
  80. package/package.json +2 -2
  81. package/dist/chunk-2Z543TC3.cjs.map +0 -1
  82. package/dist/chunk-6IGSKU6D.js.map +0 -1
  83. package/dist/chunk-J7JWMQD5.js.map +0 -1
  84. package/dist/chunk-KWQTF6ZL.js.map +0 -1
  85. package/dist/chunk-N3SLYVNW.cjs.map +0 -1
  86. package/dist/chunk-SMXU3KYA.cjs.map +0 -1
  87. package/dist/chunk-VITE3MZQ.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkSMXU3KYA_cjs = require('./chunk-SMXU3KYA.cjs');
3
+ var chunk3YUUC6RN_cjs = require('./chunk-3YUUC6RN.cjs');
4
4
 
5
5
  // src/ai/registry.ts
6
6
  var DIAGRAM_REGISTRY = [
@@ -208,6 +208,35 @@ var DIAGRAM_REGISTRY = [
208
208
  standard: "OMG BPMN 2.0.2 / ISO/IEC 19510:2013 visual subset; see 25-BPMN-STANDARD.md",
209
209
  syntaxKey: "bpmn"
210
210
  },
211
+ {
212
+ type: "usecase",
213
+ name: "UML use case diagram",
214
+ tagline: "UML 2.5 use case \u2014 actors, use cases, subject boundary, include/extend/generalization.",
215
+ useWhen: "Use for software-engineering requirements and scope diagrams \u2014 'what does this system do, and for whom'. Actors (stick figures, or `(external)` rectangles for other systems) sit outside a subject boundary; use cases are ellipses inside it. `--` association, `..>` \xABinclude\xBB (source includes target), `<..` \xABextend\xBB (left extends right, with optional `[condition]` and extension points), `--|>` generalization (hollow triangle to parent, between actors or between use cases). Accepts a PlantUML-style inline form (`:Actor:`, `(Use case)`, `as ID`). Distinct from `state` (intra-object behavior, not system scope), `flowchart` (no actor/subject/include-extend semantics), and `bpmn` (how a process executes, not what a system offers).",
216
+ cluster: "behavior-modeling",
217
+ standard: "OMG UML 2.5.1 \xA718 visual subset; see 29-USECASE-STANDARD.md",
218
+ syntaxKey: "usecase"
219
+ },
220
+ // ── Research / evidence synthesis ────────────────────────────
221
+ {
222
+ type: "prisma",
223
+ name: "PRISMA 2020 flow diagram",
224
+ tagline: "PRISMA 2020 \u2014 the mandatory four-row flow diagram for systematic reviews and meta-analyses.",
225
+ useWhen: "Use whenever the user mentions 'PRISMA', 'systematic review', 'meta-analysis flow', 'scoping review', 'evidence screening', or 'Cochrane review' \u2014 this is the dedicated, standards-correct engine (prefer it over a generic flowchart). The author writes record counts and exclusion reasons; the rigid four-row layout (Identification \u2192 Screening \u2192 Eligibility \u2192 Included) is correct by construction, with mandatory `n = \u2026` counts, parallel exclusion side-boxes, and an optional second 'other methods' column (`mode: 2020-dual`). Vocabulary swaps for scoping reviews (`kind: scoping-review`) and IPD (`kind: ipd`). Count arithmetic is validated (`validate-counts: warn|strict|off`). Distinct from `flowchart` (no mandatory stages/counts/exclusion-box convention).",
226
+ cluster: "research",
227
+ standard: "PRISMA 2020 (Page MJ et al., BMJ 2021;372:n71); see 28-PRISMA-STANDARD.md",
228
+ syntaxKey: "prisma"
229
+ },
230
+ // ── Project management / scheduling ──────────────────────────
231
+ {
232
+ type: "pert",
233
+ name: "PERT / CPM network",
234
+ tagline: "Activity-on-node project schedule that computes ES/EF/LS/LF, slack, and the critical path.",
235
+ useWhen: "Use whenever the user mentions 'PERT', 'CPM', 'critical path', 'project network', 'precedence diagram', or wants a project schedule from tasks + durations + dependencies. Unlike a flowchart, this engine *computes* the schedule: write `task <id> \"label\" duration: <n> after: <preds>` and it runs the forward/backward pass and returns Early/Late Start & Finish, total slack, project duration, and highlights the critical path in red. Supports PDM dependency types (FS/SS/FF/SF) with lag/lead (`after: A SS+2d`), three-point estimation (`duration: 4/6/10` \u2192 te + variance), milestones (`milestone`), swimlanes (`lane: \"Team\"`), a `layout: timescaled` mode (x \u221D ES, width \u221D duration) for a network-Gantt hybrid, and a legacy `layout: aoa` mode (activity-on-arrow: numbered event circles + arrow activities + dummy activities, FS-only). Distinct from `flowchart` (no scheduling), `timeline`/Gantt (no critical-path computation), and `bpmn` (organisational process, not a one-off schedule).",
236
+ cluster: "project-management",
237
+ standard: "PMI PMBOK 7 + Moder 1983 (AON/PDM); see 32-PERT-STANDARD.md",
238
+ syntaxKey: "pert"
239
+ },
211
240
  // ── Generic process / flow ───────────────────────────────────
212
241
  {
213
242
  type: "flowchart",
@@ -748,25 +777,6 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
748
777
  "dsl": "flowchart LR\n start([New order received])\n start --> validate{Inventory available?}\n validate -->|Yes| reserve[Reserve items]\n validate -->|No| notify[Notify customer]\n notify --> done([End])\n reserve --> payment{Payment authorized?}\n payment -->|Yes| ship[Ship order]\n payment -->|No| cancel[Cancel & release]\n ship --> confirm[Send confirmation email]\n confirm --> done\n cancel --> done",
749
778
  "notes": '## Scenario\n\nA product ops lead circulates this flowchart during an ops-review meeting to align engineering, customer support, and fulfillment on the single source of truth for what happens when a new order comes in. It surfaces the two decision gates (inventory, payment) and the three exception paths (out-of-stock notification, payment failure with released hold, successful ship with confirmation).\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium / terminal; used for Start and End\n- `{\u2026}` \u2014 diamond; decision node\n- `[\u2026]` \u2014 rectangle; process step\n- `-->|label|` \u2014 edge with a branch label (`Yes` / `No`)\n\n## How to read\n\nStart at the top-left terminal. Inventory check gates the first branch \u2014 a "No" routes straight to the End after notification. A "Yes" reserves stock then hits the payment gate. Payment failure releases the reservation and goes to End; success ships and emails the customer. Every path terminates at the same End node, so nothing dangles.'
750
779
  },
751
- {
752
- "slug": "flowchart-prisma-systematic-review",
753
- "diagram": "flowchart",
754
- "title": "PRISMA 2020 systematic review flow",
755
- "description": "Canonical PRISMA 2020 flow diagram for a systematic review \u2014 records identified across databases, screened, assessed for eligibility, and included in synthesis.",
756
- "standard": "PRISMA 2020 (Page et al., BMJ 2021)",
757
- "tags": [
758
- "flowchart",
759
- "prisma",
760
- "systematic-review",
761
- "meta-analysis",
762
- "research",
763
- "evidence-synthesis"
764
- ],
765
- "complexity": 3,
766
- "featured": true,
767
- "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',
768
- "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).'
769
- },
770
780
  {
771
781
  "slug": "genogram-brca-cancer",
772
782
  "diagram": "genogram",
@@ -1132,6 +1142,97 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
1132
1142
  "dsl": 'pedigree "Hemophilia A"\n I-1 [male, unaffected]\n I-2 [female, carrier-x]\n I-1 -- I-2\n II-1 [male, affected]\n II-2 [female, carrier-x]\n II-3 [male, unaffected]\n II-4 [female, unaffected]\n II-2 -- II-5 [male, unaffected]\n III-1 [male, affected]\n III-2 [female, carrier-x]\n III-3 [male, unaffected]',
1133
1143
  "notes": "## Scenario\n\nA genetic counselor documents a three-generation hemophilia A pedigree during a prenatal consultation. The X-linked recessive pattern \u2014 carrier females who show no symptoms but pass the mutated allele \u2014 must be clearly distinguished from affected males. NSGC standard notation is required for clinical records and insurance pre-authorization.\n\n## Annotation key\n\n- `carrier-x` \u2014 female carrier of an X-linked recessive allele; rendered as a circle with a centre dot per NSGC convention\n- `affected` \u2014 fully filled symbol; individual expresses the condition\n- `unaffected` \u2014 open (unfilled) symbol; no clinical presentation\n- `proband` \u2014 the index case who prompted clinical referral (not used here, but add `proband` to any individual)\n- `I-1 -- I-2` followed by indented children \u2014 defines a mating pair and their offspring\n\n## How to read\n\nGeneration I: unaffected father, carrier mother. Generation II: one affected son (II-1), one carrier daughter (II-2), two unaffected children. Generation III: carrier daughter II-2 married an unaffected man; they produced another affected son (III-1) and another carrier daughter (III-2) \u2014 demonstrating the classic X-linked skip-generation pattern where the trait disappears in daughters only to re-emerge in grandsons."
1134
1144
  },
1145
+ {
1146
+ "slug": "pert-aoa-software-project",
1147
+ "diagram": "pert",
1148
+ "title": "Activity-on-arrow (AOA) network",
1149
+ "description": "The classic textbook PERT notation \u2014 numbered event circles, activities as labelled arrows, and dotted dummy activities auto-inserted at multi-predecessor merges. Written in the same activity-on-node DSL; Schematex builds and numbers the event graph.",
1150
+ "standard": "PMI PMBOK 7 + Moder 1983 \u2014 Activity-on-Arrow (ADM, legacy)",
1151
+ "tags": [
1152
+ "pert",
1153
+ "aoa",
1154
+ "activity-on-arrow",
1155
+ "critical-path",
1156
+ "education"
1157
+ ],
1158
+ "complexity": 2,
1159
+ "featured": false,
1160
+ "dsl": 'pert\ntitle: "Software project (AOA)"\nlayout: aoa\nunit: days\n\ntask A "create schedule" duration: 10\ntask B "buy hardware" duration: 5\ntask C "programming" duration: 20 after: A\ntask D "installation" duration: 5 after: B\ntask E "conversion" duration: 15 after: D\ntask F "test code" duration: 20 after: C, E\ntask G "write manual" duration: 15 after: E\ntask H "test system" duration: 10 after: F\ntask I "training" duration: 5 after: G\ntask J "user test" duration: 10 after: H, I',
1161
+ "notes": "Before activity-on-node won, project networks were drawn **activity-on-arrow** (AOA / ADM): the *arrows* are the work and the *nodes* are events \u2014 the instants when activities start and finish. It's the form on Investopedia and in older textbooks, and it's what `layout: aoa` produces.\n\n**You still write activity-on-node.** The DSL is identical to every other PERT example \u2014 tasks, durations, `after:` dependencies. Schematex converts it: each activity gets a head event, and the events are numbered so every arrow runs from a lower id to a higher one (the classic *i-j* rule).\n\n**Dummy activities.** AOA can't show two activities merging into one without help, so wherever an activity has multiple predecessors a **dummy** (dotted, zero-duration arrow) is inserted. Here `test code` depends on both `programming` and `conversion`, and `user test` on both `test system` and `training` \u2014 each merge gets dummies that carry the dependency without representing real work.\n\n**The critical path is still computed.** The forward/backward pass runs on the event graph and the critical activities are drawn as bold red arrows: `create schedule \u2192 programming \u2192 test code \u2192 test system \u2192 user test` (70 days).\n\n**One caveat.** AOA can only express finish-to-start logic \u2014 there's no way to draw a start-to-start or finish-to-finish relationship as an arrow-between-events. If your network uses SS/FF/SF or lag, those are flattened to FS with a warning. For real scheduling, prefer the default `network` (AON) layout; reach for `aoa` when you need to match a textbook figure."
1162
+ },
1163
+ {
1164
+ "slug": "pert-migration-timescaled",
1165
+ "diagram": "pert",
1166
+ "title": "Time-scaled migration plan (network-Gantt)",
1167
+ "description": "A data-centre migration in the time-scaled layout \u2014 x-position proportional to Early Start, width proportional to duration, with a unit time axis. Exercises start-to-start and finish-to-finish dependencies, lag/lead, a milestone, and lane packing.",
1168
+ "standard": "PMI PMBOK 7 + Moder 1983 (AON/PDM)",
1169
+ "tags": [
1170
+ "pert",
1171
+ "cpm",
1172
+ "timescaled",
1173
+ "gantt",
1174
+ "dependencies",
1175
+ "milestone"
1176
+ ],
1177
+ "complexity": 3,
1178
+ "featured": false,
1179
+ "dsl": 'pert\ntitle: "Data-centre migration"\nunit: days\nlayout: timescaled\n\ntask A "Inventory systems" duration: 5\ntask B "Stakeholder review" duration: 6 after: A SS+1\ntask C "Vendor selection" duration: 8 after: A, B\ntask D "Architecture" duration: 10 after: C\ntask E "Procurement" duration: 12 after: C+2\ntask F "Code refactor" duration: 15 after: D\ntask G "Pilot env" duration: 5 after: E, F FF\ntask H "Pilot run" duration: 7 after: G\ntask I "Cutover" milestone after: H\ntask J "Hypercare" duration: 5 after: I',
1180
+ "notes": "`layout: timescaled` is the bridge between the network view and a Gantt chart. Each activity's **x-position is proportional to its Early Start** and its **width is proportional to its duration**, with a unit time axis along the bottom \u2014 so distance reads as time.\n\n**Full PDM dependencies.** This network uses every relationship type beyond the default finish-to-start. `B after: A SS+1` is start-to-start with a 1-day lag (stakeholder review begins a day into the inventory). `E after: C+2` is FS with a 2-day lag (procurement waits two days after vendor selection finishes). `G after: ... F FF` is finish-to-finish (the pilot environment must be ready *when* the code refactor finishes, not after it). Each non-FS edge is labelled on the connector (`SS+1d`, `FS+2d`, `FF`).\n\n**Milestones and lane packing.** `Cutover` is declared with the `milestone` flag \u2014 a zero-duration checkpoint drawn as a diamond at its scheduled date. To avoid overlaps, activities are greedily packed into horizontal lanes by start time, and task names sit above their bars (Gantt convention) so long labels never overflow a short bar.\n\n**Still computed, still critical-aware.** Even in the time-scaled view the critical path is highlighted in red and slack is shown on each bar. `Procurement` (E) carries 6 days of slack and renders in blue, visibly off the critical chain `A \u2192 C \u2192 D \u2192 F \u2192 G \u2192 H \u2192 I \u2192 J`."
1181
+ },
1182
+ {
1183
+ "slug": "pert-product-launch",
1184
+ "diagram": "pert",
1185
+ "title": "Q3 product launch PERT/CPM network",
1186
+ "description": "A seven-task product-launch schedule where the engine computes every Early/Late Start & Finish, total slack, and the critical path (A \u2192 C \u2192 D \u2192 E \u2192 G) automatically \u2014 the canonical activity-on-node network with the six-field box.",
1187
+ "standard": "PMI PMBOK 7 + Moder 1983 (AON/PDM)",
1188
+ "tags": [
1189
+ "pert",
1190
+ "cpm",
1191
+ "critical-path",
1192
+ "schedule",
1193
+ "project-management"
1194
+ ],
1195
+ "complexity": 2,
1196
+ "featured": true,
1197
+ "dsl": 'pert\ntitle: "Q3 Product Launch"\nunit: days\n\ntask A "Market research" duration: 5\ntask B "Design mockups" duration: 8 after: A\ntask C "Backend API" duration: 15 after: A\ntask D "Frontend build" duration: 10 after: B, C\ntask E "QA / testing" duration: 5 after: D\ntask F "Marketing collateral" duration: 7 after: B\ntask G "Launch event" duration: 2 after: E, F',
1198
+ "notes": 'This is what separates Schematex\'s `pert` engine from a drag-and-drop "PERT chart maker": you write only the tasks, durations, and dependencies \u2014 the schedule is *computed*.\n\n**The six-field box.** Each activity renders as the canonical 3\xD72 PERT/CPM rectangle: Early Start / Duration / Early Finish on top, the task name and id in the middle, and Late Start / Slack / Late Finish on the bottom. Those four schedule fields are never typed by hand \u2014 a forward pass walks the network to find ES/EF, a backward pass finds LS/LF, and total slack is `LS \u2212 ES`.\n\n**The critical path falls out of the math.** Any activity with zero slack is on the critical path and is drawn in red: `A \u2192 C \u2192 D \u2192 E \u2192 G`. Here `C` (Backend API, 15 days) is the long pole \u2014 it dominates `B` (Design mockups, 8 days) at the `D` merge, so the schedule pivots on the backend, not the design. Change `C` to 6 days and the critical path shifts to run through `B` instead; the render updates because the computation does.\n\n**Parallel work, one merge.** `B` and `C` both start once research finishes, run concurrently, and re-converge at `D` (Frontend build). `F` (Marketing collateral) branches off `B` and carries slack \u2014 it can slip several days without moving the launch. The project duration, 37 days, is the maximum Early Finish over the terminal tasks, not simply the last task you declared.'
1199
+ },
1200
+ {
1201
+ "slug": "pert-swimlane-online-shop",
1202
+ "diagram": "pert",
1203
+ "title": "PERT swimlanes grouped by team",
1204
+ "description": "The same computed activity-on-node schedule, re-grouped into horizontal swimlanes by responsible team (Customer Account, Shopping Site, Shopping Cart, Testing) \u2014 the way Visual Paradigm and PMO templates present a project network.",
1205
+ "standard": "PMI PMBOK 7 + Moder 1983 (AON/PDM)",
1206
+ "tags": [
1207
+ "pert",
1208
+ "cpm",
1209
+ "swimlane",
1210
+ "critical-path",
1211
+ "project-management"
1212
+ ],
1213
+ "complexity": 2,
1214
+ "featured": false,
1215
+ "dsl": 'pert\ntitle: "Online Shop Project"\nunit: days\n\ntask T1 "Support Account Deletion" duration: 3 lane: "Customer Account"\ntask T2 "Design a New Theme" duration: 8 lane: "Shopping Site"\ntask T3 "Apply New Theme to the Site" duration: 15 after: T2 lane: "Shopping Site"\ntask T4 "Improve Searching" duration: 7 after: T3 lane: "Shopping Site"\ntask T5 "Enhance Shopping Cart Functionality" duration: 8 after: T2 lane: "Shopping Cart"\ntask T6 "Enhance Shopping Cart Checkout" duration: 6 after: T5 lane: "Shopping Cart"\ntask T7 "Ready Testing Environment" duration: 2 after: T1, T4, T6 lane: "Testing"\ntask T8 "Test Online Shop" duration: 8 after: T7 lane: "Testing"',
1216
+ "notes": 'A flat network answers "what\'s the critical path?"; a swimlane network also answers "who owns what?". Add `lane: "\u2026"` to any task and the diagram re-groups into horizontal bands \u2014 by team, phase, or owner \u2014 without changing a single number in the schedule.\n\n**Same engine, different presentation.** This is still pure activity-on-node: the forward/backward pass runs exactly as it would without lanes, so the critical path `T2 \u2192 T3 \u2192 T4 \u2192 T7 \u2192 T8` and every slack value are identical to the ungrouped layout. Lanes are a *view*, not a computation \u2014 they activate automatically the moment any task declares one.\n\n**Reading the bands.** Lanes appear in first-declared order, each as a banded row with a label gutter on the left. A task sits in the column for its dependency depth but the row for its team, so you can trace both the time order (left to right) and the ownership (top to bottom) at a glance. Dependencies that cross teams \u2014 `T1` (Customer Account) and `T4` (Shopping Site) and `T6` (Shopping Cart) all feeding `T7` (Testing) \u2014 render as orthogonal connectors hopping between bands, making hand-off points obvious.\n\n**Where this helps.** This is the format PMO templates and tools like Visual Paradigm use for status reviews, because a stakeholder can find their team\'s row instantly and see what it\'s waiting on and what\'s waiting on it.'
1217
+ },
1218
+ {
1219
+ "slug": "pert-three-point-estimation",
1220
+ "diagram": "pert",
1221
+ "title": "Three-point (PERT) estimation with variance",
1222
+ "description": "Durations written as optimistic/most-likely/pessimistic (O/M/P). The engine computes the beta-distribution expected duration te = (O+4M+P)/6 per activity, the per-task variance, and the project-level standard deviation along the critical path.",
1223
+ "standard": "PMI PMBOK 7 \u2014 three-point (beta-PERT) estimation",
1224
+ "tags": [
1225
+ "pert",
1226
+ "three-point",
1227
+ "estimation",
1228
+ "variance",
1229
+ "critical-path"
1230
+ ],
1231
+ "complexity": 2,
1232
+ "featured": false,
1233
+ "dsl": 'pert\ntitle: "Three-point project"\nunit: days\ncritical-tolerance: 0.01\n\ntask A "Spec" duration: 2/3/5\ntask B "Build" duration: 5/8/14 after: A\ntask C "Test" duration: 3/4/6 after: B\ntask D "Deploy" duration: 1/2/3 after: C',
1234
+ "notes": "PERT's original 1959 contribution wasn't the box \u2014 it was handling *uncertainty* in durations. Write a duration as `O/M/P` (optimistic / most-likely / pessimistic) and the engine treats it as a beta-PERT estimate.\n\n**Expected duration.** Each three-point activity collapses to its beta-distribution mean **te = (O + 4M + P) / 6**, which is what the Duration field shows. `Build` at `5/8/14` becomes `te = 8.5` \u2014 pulled above the most-likely 8 because the pessimistic tail (14) is fatter than the optimistic one (5). The whole forward/backward pass then runs on these `te` values, so the project duration here is \u2248 17.83 days, not an integer.\n\n**Variance and project risk.** Each activity also carries `\u03C3\xB2 = ((P \u2212 O) / 6)\xB2`, surfaced as a small `\u03C3=\u2026` annotation under the name and on a `data-pert-variance` attribute. Summed over the critical-path activities (under the classical independence assumption), the project standard deviation is \u2248 1.69 days \u2014 a one-line risk figure you can quote: \"\u224868% chance of finishing within \xB11.69 days of 17.83.\"\n\n**Why `critical-tolerance: 0.01`.** Once durations are fractional, accumulated floating-point error can give a truly-critical activity a slack of `0.0000001`. The tolerance treats anything within 0.01 of zero as critical, so the red path stays stable across runs. For all-integer projects you can leave it at the default of `0`."
1235
+ },
1135
1236
  {
1136
1237
  "slug": "phylo-bacterial-diversity",
1137
1238
  "diagram": "phylo",
@@ -1150,6 +1251,44 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
1150
1251
  "dsl": 'phylo "Bacterial Diversity"\n newick: "((((Ecoli:0.1,Salmonella:0.12):0.05[&&NHX:B=98],Vibrio:0.2):0.08[&&NHX:B=85],((Bacillus:0.15,Staph:0.18):0.06[&&NHX:B=92],Listeria:0.22):0.1):0.15,((Myco_tb:0.3,Myco_leprae:0.28):0.12[&&NHX:B=100],(Strepto:0.25,Lactobacillus:0.2):0.08[&&NHX:B=78]):0.2);"\n clade Gamma = (Ecoli, Salmonella, Vibrio) [color: "#1E88E5", label: "\u03B3-Proteobacteria"]\n clade Firmi = (Bacillus, Staph, Listeria, Strepto, Lactobacillus) [color: "#E53935", label: "Firmicutes"]\n clade Actino = (Myco_tb, Myco_leprae) [color: "#43A047", label: "Actinobacteria"]\n scale "substitutions/site"',
1151
1252
  "notes": '## Scenario\n\nA microbiologist or bioinformatician pastes a Newick tree string exported from RAxML, IQ-TREE, or MEGA and immediately gets a publication-ready SVG with clade highlights and a branch-length scale bar \u2014 no manual layout required.\n\n## Annotation key\n\n- `newick: "..."` \u2014 standard Newick format tree string; branch lengths follow `:` after each taxon name\n- `[&&NHX:B=98]` \u2014 NHX annotation; `B=` is the bootstrap support value (0\u2013100), rendered on internal nodes\n- `clade id = (taxon, ...)` \u2014 defines a named clade by listing its leaf members\n- `[color: "#hex", label: "..."]` \u2014 colors the clade\'s subtree and adds a labeled arc\n- `scale "..."` \u2014 draws a calibrated scale bar with the given unit label\n\n## How to read\n\nThe tree shows three major bacterial clades. Blue (\u03B3-Proteobacteria): *E. coli*, *Salmonella*, and *Vibrio* cluster with 98% bootstrap support. Red (Firmicutes): *Bacillus*, *Staph*, *Listeria*, *Streptococcus*, and *Lactobacillus*. Green (Actinobacteria): the two *Mycobacterium* species form a highly supported clade (bootstrap 100). Branch lengths represent substitutions per site \u2014 longer branches indicate faster evolutionary rates.'
1152
1253
  },
1254
+ {
1255
+ "slug": "prisma-dual-pipeline",
1256
+ "diagram": "prisma",
1257
+ "title": "PRISMA 2020 dual pipeline (databases + other methods)",
1258
+ "description": "PRISMA 2020 flow diagram in dual-pipeline mode \u2014 identification via databases and registers plus a second column for other methods (citation searching, hand searches, expert recommendations), merged into screening via a Y-junction.",
1259
+ "standard": "PRISMA 2020 (Page et al., BMJ 2021;372:n71)",
1260
+ "tags": [
1261
+ "prisma",
1262
+ "systematic-review",
1263
+ "dual-pipeline",
1264
+ "citation-search",
1265
+ "evidence-synthesis",
1266
+ "meta-analysis"
1267
+ ],
1268
+ "complexity": 3,
1269
+ "featured": false,
1270
+ "dsl": "prisma\nmode: 2020-dual\ntitle: Effect of yoga on chronic back pain \u2014 SR\n\nidentification:\n databases:\n n: 1234\n sources: PubMed=600, Embase=450, Cochrane=184\n duplicates-removed: 254\n other:\n n: 56\n sources: citation-search=30, hand-search=20, expert-recommendation=6\n\nscreening:\n records-screened: 1036\n excluded:\n n: 810\n reasons: duplicate=120, irrelevant title=560, non-English=130\n reports-sought: 226\n reports-not-retrieved: 12\n\neligibility:\n full-text-assessed: 214\n excluded:\n n: 191\n reasons: wrong population=80, wrong intervention=60, wrong outcome=51\n\nincluded:\n studies: 23\n reports: 25",
1271
+ "notes": '## Scenario\n\nThe 2020 update to PRISMA added a **second identification pathway** for studies found outside formal database searches \u2014 citation chasing, hand-searching reference lists, and expert recommendations. Reviewers must report these separately and show both streams merging into a single screening process. The `prisma` engine renders the two columns side by side with a Y-junction merge.\n\n## Annotation key\n\n- **`mode: 2020-dual`** \u2014 adds the right-hand "Identification via other methods" column. The engine auto-detects dual mode whenever an `other:` block is present, so the explicit `mode` line is optional here.\n- **`identification.other`** \u2014 its own `n:` total and `sources:` breakdown (citation search, hand search, expert recommendation).\n- **`reports-sought:` / `reports-not-retrieved:`** \u2014 optional Screening detail lines for the retrieval step.\n- **Y-junction merge** \u2014 the databases stream is the trunk; the other-methods stream drops and runs left to join it just above Screening.\n\n## Standard reference\n\nPage MJ, McKenzie JE, Bossuyt PM, et al. *The PRISMA 2020 statement.* BMJ 2021;372:n71, Figure 2 (dual-source variant).'
1272
+ },
1273
+ {
1274
+ "slug": "prisma-systematic-review",
1275
+ "diagram": "prisma",
1276
+ "title": "PRISMA 2020 systematic review (single pipeline)",
1277
+ "description": "Canonical PRISMA 2020 flow diagram for a systematic review using the dedicated prisma engine \u2014 records identified across four databases, deduplicated, screened, assessed for eligibility, and included, with exclusion side-boxes and mandatory n = counts.",
1278
+ "standard": "PRISMA 2020 (Page et al., BMJ 2021;372:n71)",
1279
+ "tags": [
1280
+ "prisma",
1281
+ "systematic-review",
1282
+ "meta-analysis",
1283
+ "research",
1284
+ "evidence-synthesis",
1285
+ "cochrane"
1286
+ ],
1287
+ "complexity": 2,
1288
+ "featured": true,
1289
+ "dsl": "prisma\nmode: 2020-single\ntitle: Effect of exercise on chronic low-back pain \u2014 SR\n\nidentification:\n databases:\n n: 1418\n sources: PubMed=600, Embase=450, Cochrane=184, Web of Science=184\n duplicates-removed: 318\n\nscreening:\n records-screened: 1100\n excluded:\n n: 870\n reasons: irrelevant title=750, non-English=120\n\neligibility:\n full-text-assessed: 230\n excluded:\n n: 195\n reasons: wrong population=80, wrong intervention=60, wrong outcome=55\n\nincluded:\n studies: 35\n reports: 38",
1290
+ "notes": '## Scenario\n\nA research librarian produces the PRISMA 2020 flow diagram for a Cochrane review submission. The journal **requires** the diagram in the exact four-row structure \u2014 Identification \u2192 Screening \u2192 Eligibility \u2192 Included \u2014 with the count `(n = \u2026)` shown in every box and the excluded boxes itemizing reasons. With the dedicated `prisma` engine the librarian writes only counts and reasons; the rigid layout, the "Records removed before screening" side-box, and the exclusion side-boxes are produced automatically and are correct by construction.\n\n## Annotation key\n\n- **`mode: 2020-single`** \u2014 one Identification column (databases & registers). Use `mode: 2020-dual` to add the "other methods" column.\n- **`identification.databases`** \u2014 `n:` is the mandatory total; `sources:` renders the per-database breakdown; `duplicates-removed:` splits out into the right-column "Records removed before screening" box automatically.\n- **`screening` / `eligibility` `excluded:` blocks** \u2014 each has its own `n:` total and an optional `reasons:` breakdown rendered in a side-box to the right, connected by a horizontal arrow.\n- **`included.studies` / `reports`** \u2014 one study can yield several reports, so both counts render.\n\n## How to read\n\nTop to bottom mirrors the PRISMA 2020 template exactly. The left capsule bands label the three canonical stages; the orange bar spans the Identification column group. Counts reconcile across stages (1418 \u2212 318 = 1100 screened; 1100 \u2212 870 = 230 assessed; 230 \u2212 195 = 35 included) \u2014 the engine warns if they don\'t.\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. Template: [prisma-statement.org/prisma-2020-flow-diagram](https://www.prisma-statement.org/prisma-2020-flow-diagram).'
1291
+ },
1153
1292
  {
1154
1293
  "slug": "sfc-bake-cool-concurrent",
1155
1294
  "diagram": "sfc",
@@ -1385,6 +1524,43 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
1385
1524
  "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"]',
1386
1525
  "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."
1387
1526
  },
1527
+ {
1528
+ "slug": "usecase-atm",
1529
+ "diagram": "usecase",
1530
+ "title": "ATM use case diagram (UML)",
1531
+ "description": "The canonical software-engineering use case diagram \u2014 a Customer and an external Bank system around an ATM, with four withdraw/deposit/balance/transfer use cases. Exercises stick-figure actors, the external-system rectangle, subject sizing, and primary/supporting actor flanking.",
1532
+ "standard": "OMG UML 2.5.1 \xA718",
1533
+ "tags": [
1534
+ "usecase",
1535
+ "uml",
1536
+ "requirements",
1537
+ "actor",
1538
+ "subject"
1539
+ ],
1540
+ "complexity": 1,
1541
+ "featured": true,
1542
+ "dsl": 'usecase\ntitle: "ATM"\nsystem: "ATM System"\n\nactor: Customer\nactor: Bank (external)\n\nusecase: "Withdraw Cash" as Withdraw\nusecase: "Deposit Funds" as Deposit\nusecase: "Check Balance" as Check\nusecase: "Transfer Funds" as Transfer\n\nCustomer -- Withdraw\nCustomer -- Deposit\nCustomer -- Check\nCustomer -- Transfer\n\nWithdraw -- Bank\nDeposit -- Bank\nCheck -- Bank\nTransfer -- Bank',
1543
+ "notes": 'The ATM is the hello-world of UML use case diagrams \u2014 it appears in nearly every software-engineering textbook because it shows the whole notation with no clutter. The diagram answers "what can you do at an ATM, and who does the work behind the scenes?"\n\n**Two actors, two roles.** `Customer` is the **primary actor** \u2014 the human who initiates the interaction \u2014 so Schematex places the stick figure on the **left**. `Bank` is declared `(external)`, marking it as another software system rather than a person; it renders as a rectangle carrying the `\xABactor\xBB` stereotype and is placed on the **right** as a supporting actor. This left-primary / right-supporting convention comes from the Bittner & Spence style guide and matches what reviewers expect to see.\n\n**Four use cases, one subject.** Each `usecase:` becomes an ellipse, and the `system: "ATM System"` header wraps them in a rounded **subject** rectangle with the system name at the top. The subject is sized *after* the use cases are placed, so it always hugs its contents.\n\n**Plain associations.** Every `--` line is an undirected association \u2014 a solid line from the actor to the use-case ellipse perimeter. The Customer triggers all four operations; each operation in turn talks to the Bank to settle the transaction. There are no `\xABinclude\xBB` or `\xABextend\xBB` relationships here \u2014 that\'s deliberate. The ATM diagram\'s job is to establish *scope*, and at this level of detail plain associations are exactly right. Reach for include/extend only when use cases genuinely compose.'
1544
+ },
1545
+ {
1546
+ "slug": "usecase-online-bookstore",
1547
+ "diagram": "usecase",
1548
+ "title": "Online bookstore use case diagram (include + extend)",
1549
+ "description": "An e-commerce checkout use case diagram showing \xABinclude\xBB chains, an \xABextend\xBB relationship with a condition and extension point, and the extension-point compartment inside the base ellipse. A primary customer, an external payment gateway, and a supporting warehouse actor.",
1550
+ "standard": "OMG UML 2.5.1 \xA718",
1551
+ "tags": [
1552
+ "usecase",
1553
+ "uml",
1554
+ "include",
1555
+ "extend",
1556
+ "extension-point",
1557
+ "requirements"
1558
+ ],
1559
+ "complexity": 2,
1560
+ "featured": true,
1561
+ "dsl": 'usecase\ntitle: "Online Bookstore \u2014 Checkout"\nsystem: "Bookstore System"\n\nactor: Customer\nactor: "Payment Gateway" as PG (external)\nactor: "Warehouse Staff" as WH\n\nusecase: "Browse Catalog" as Browse\nusecase: "Add to Cart" as AddCart\nusecase: "Checkout" as Checkout {\n extension point: payment failed\n extension point: stock depleted\n}\nusecase: "Pay" as Pay\nusecase: "Validate Card" as ValidateCard\nusecase: "Cancel Order" as Cancel\nusecase: "Ship Order" as Ship\n\nCustomer -- Browse\nCustomer -- AddCart\nCustomer -- Checkout\nCheckout ..> Pay : \xABinclude\xBB\nPay ..> ValidateCard : \xABinclude\xBB\nPay -- PG\nCancel <.. Checkout : \xABextend\xBB [payment failed] (extension point: payment failed)\nShip -- WH\nCheckout ..> Ship : \xABinclude\xBB',
1562
+ "notes": "This is the diagram a business analyst hands to engineering when an online store is being scoped. It uses every relationship in the use case vocabulary, and each one means something precise.\n\n**Three actors on two sides.** `Customer` is the primary actor (left). `Payment Gateway` is `(external)` \u2014 a third-party system, drawn as an `\xABactor\xBB` rectangle on the right. `Warehouse Staff` is a supporting human actor, also on the right. Schematex flanks the subject automatically.\n\n**`\xABinclude\xBB` \u2014 mandatory composition.** `Checkout ..> Pay` reads \"Checkout *includes* Pay\": every checkout always runs the payment sub-flow, so the arrow points from the base toward the included use case. The chain continues \u2014 `Pay ..> ValidateCard` \u2014 so payment always validates the card. Include is the right tool when a step *always* happens and you want to factor it out for reuse. The dashed line, open arrowhead, and `\xABinclude\xBB` pill are all UML-standard.\n\n**`\xABextend\xBB` \u2014 optional, conditional behavior.** `Cancel <.. Checkout` reads \"Cancel Order *extends* Checkout\": cancellation is *optional* behavior that only kicks in under a condition. The `[payment failed]` clause is that condition, and `(extension point: payment failed)` ties it to the named extension point declared inside the Checkout ellipse. Note the arrow still points at the base (Checkout) even though Cancel is written first \u2014 that's the UML rule, and Schematex normalises it for you. Extend lines are drawn in the accent color because they're the rarer, more surprising relationship.\n\n**Extension points live in the ellipse.** Because `Checkout` declares `extension point: payment failed` and `stock depleted`, those appear in a compartment below the name, separated by a divider. They're the hooks an `\xABextend\xBB` relationship can attach to.\n\nThe result reads top-to-bottom as a flow: browse \u2192 add to cart \u2192 checkout, with checkout fanning out into pay (\u2192 validate card, \u2192 payment gateway), ship (\u2192 warehouse), and an optional cancel path. That's exactly the scope picture a stakeholder review needs."
1563
+ },
1388
1564
  {
1389
1565
  "slug": "venn-customer-segments",
1390
1566
  "diagram": "venn",
@@ -1530,6 +1706,18 @@ var SYNTAX = {
1530
1706
  "sfc": {
1531
1707
  "title": "Sequential Function Chart (SFC)",
1532
1708
  "content": '## 1. Your first chart\n\nTwo steps, one transition, an initial marker:\n\n```\nsfc\nstep S0 [initial]\nstep S1\ntransition from: S0 to: S1: Trigger\n```\n\n`S0` renders as a **double-bordered rectangle** (the IEC initial-step convention); `S1` as a single-border rectangle. Between them is a horizontal **transition bar** with the condition text `Trigger` to its right.\n\nIf you forget `[initial]`, the first declared step is auto-promoted to initial.\n\n---\n\n## 2. Steps\n\n```\nstep S_Filling [label: "Filling tank"]\n N FillValve_Open\n D Mixer_Run T#30s\n P StartChime\n```\n\nA step has:\n\n- An **id** (unique across the chart) \u2014 used in transitions and jumps.\n- An optional `[label: "..."]` for display.\n- An optional `[initial]` (one allowed) or `[final]` (vendor stop step, three borders).\n- Zero or more **action blocks**, indented one level, each with a qualifier letter.\n\n---\n\n## 3. Transitions\n\nA **transition** declares a directed link between two steps with a boolean condition:\n\n```\ntransition from: S0 to: S1: StartBtn\ntransition from: S1 to: S2: TankLevel >= 80.0 AND NOT EmergencyStop\ntransition T_Reset from: S5 to: S0: ResetBtn\n```\n\nThe condition text is opaque \u2014 Schematex stores it verbatim and renders it next to the bar. Every transition must have a non-empty condition; use `TRUE` for unconditional links.\n\nTransitions whose `from` and `to` are linearly adjacent in the body render as inline bars between the steps. Transitions whose pair is *not* linearly adjacent (e.g. a jump back to an earlier step) render as **margin arrows** on the left or right side of the chart.\n\n---\n\n## 4. Action qualifiers\n\nActions attach to the right side of a step and run according to their qualifier letter:\n\n| Qualifier | Behavior |\n|---|---|\n| `N` | Active while step is active (most common) |\n| `S` | Stored \u2014 set true on entry, stays until matching `R` |\n| `R` | Reset \u2014 clears a previously-stored action |\n| `L` | Time-Limited \u2014 active up to T after step entry |\n| `D` | Time-Delayed \u2014 activates T after entry |\n| `P` | Pulse \u2014 true for one PLC scan only |\n| `P0` | Pulse on deactivate (Siemens) |\n| `P1` | Synonym for `P` (Siemens) |\n| `SD` | Stored & Delayed |\n| `DS` | Delayed & Stored |\n| `SL` | Stored & Time-Limited |\n\nTime-parameterized qualifiers (L, D, SD, DS, SL) take a duration literal:\n\n```\nstep S1\n L LimitedRun T#5s\n D DelayedRun T#2s\n```\n\n---\n\n## 5. Alternative branches (single bar \u2014 OR)\n\nOnly **one** branch fires per scan, picked by transition condition:\n\n```\nstep S0 [initial]\nstep S_Pick\n\nalt from: S_Pick:\n branch [priority: 1]:\n transition: IsExpressShipping\n step S_Express\n N PrepExpressBox\n transition: TRUE\n branch [priority: 2]:\n transition: IsStandardShipping\n step S_Standard\n N PrepStandardBox\n transition: TRUE\nmerge_to: S_Ship\n\nstep S_Ship\n\ntransition from: S0 to: S_Pick: ProductOrdered\ntransition from: S_Ship to: S0: Shipped\n```\n\nThe single horizontal lines above and below the branches are the divergence and convergence bars. Each branch starts with its **entry transition** (between div bar and first step) and ends with an **exit transition** (between last step and conv bar).\n\n---\n\n## 6. Simultaneous branches (double bar \u2014 AND)\n\n**All** branches run concurrently; the chart waits at the convergence until every branch finishes:\n\n```\nsim from: S_Heat: TRUE\n branch:\n step S_Bake\n D Oven_Run T#15m\n branch:\n step S_Cool\n L Cooler_On T#5m\nmerge_to: S_Done: Bake_Done AND Cool_Done\n```\n\nThe two parallel horizontal lines (gap 4px) above and below the branches are the simultaneous bars. The shared **transition above** (`TRUE` here) triggers the divergence; the shared **transition below** (`Bake_Done AND Cool_Done`) is checked before convergence fires.\n\n---\n\n## 7. Jumps (loops)\n\nA transition whose target is an earlier step renders as a margin arrow:\n\n```\nstep S0 [initial]\nstep S1\nstep S2\ntransition from: S0 to: S1: A\ntransition from: S1 to: S2: B\ntransition T_Reset from: S2 to: S0: ResetBtn\ntransition from: S2 to: S1: NOT ResetBtn\n```\n\nThe forward `S2 \u2192 S1` (back-edge) gets the margin arrow on the right; the `T_Reset` jump back to `S0` goes on the left. Each margin arrow shows its target id and condition.\n\n---\n\n## 8. Variables\n\nReused from `ladder` and `fbd`:\n\n```\nvar StartBtn: bool\nvar TankLevel: real\nvar BakeReady: bool\nvar Counter: counter\nvar T1: timer\n```\n\nVariables declared in conditions and actions are not validated \u2014 Schematex treats condition / action body text as opaque strings, matching how `state` handles guards and actions.\n\n---\n\n## 9. v0.1 limitations\n\n- **Nested branches** (alt-in-sim, sim-in-alt) parse but layout collapse heuristics are basic; deep nests may overlap.\n- **S/R action-pair dashed connectors** (visually link an `S` action with its matching `R` elsewhere) are deferred.\n- **Active-step runtime indicator** (yellow fill on the currently active step) is deferred \u2014 useful for debugging integrations that surface PLC runtime state.\n- **GRAFCET forcing orders** (out-of-scope per IEC 60848-only feature).\n- **Final step** parses with `[final]` but renders with the same double border as initial; the IEC triple-border convention is deferred.'
1709
+ },
1710
+ "usecase": {
1711
+ "title": "UML Use Case Diagram",
1712
+ "content": '## 1. Your first diagram\n\nEvery document starts with the `usecase` keyword, then a header, then declarations and relationships:\n\n```\nusecase\nsystem: "Library"\n\nactor: Member\nusecase: "Borrow Book" as Borrow\n\nMember -- Borrow\n```\n\n`actor:` declares an actor (a stick figure), `usecase:` declares a use case (an ellipse), and `Member -- Borrow` draws a plain association between them. `system:` wraps the use cases in a labelled **subject** rectangle. The primary actor is placed on the left; supporting actors on the right.\n\nThe header accepts:\n\n- `title: "\u2026"` \u2014 a heading drawn above the diagram.\n- `system: "\u2026"` \u2014 the subject (system boundary) name. Omit it to let the use cases float free (Schematex warns if you omit it with \u22653 use cases).\n- `direction: LR | TB` \u2014 default `LR` (actors flank the subject horizontally).\n- `generalization: tree | individual` \u2014 whether to merge sibling generalization arrows (default `tree`).\n\n---\n\n## 2. Actors\n\n```\nactor: Customer\nactor: "Payment Gateway" as PG (external)\nactor: "Warehouse Staff" as WH\nactor: Admin (left)\n```\n\n- A bare or `"quoted"` name becomes the label; `as ID` gives it a short identifier for relationships.\n- `(external)` (or `(system)`) renders the actor as a **rectangle with an `\xABactor\xBB` stereotype** instead of a stick figure \u2014 use it for other software systems (payment gateways, third-party APIs).\n- `(business)` adds the Bittner & Spence diagonal slash across the stick figure.\n- `(left)` / `(right)` pins the actor to a side. By default the first actor goes left and the rest go right.\n\nCustom stereotypes go in guillemets after the declaration: `actor: "Audit Service" as Audit (external) \xABsystem\xBB`. The parser also accepts ASCII `<<system>>` and normalises it to `\xABsystem\xBB`.\n\n---\n\n## 3. Use cases\n\n```\nusecase: "Checkout" as Checkout {\n extension point: payment failed\n extension point: stock depleted\n}\n```\n\nA use case is an ellipse sized to fit its text. The optional `{ \u2026 }` block lists **extension points** in a compartment below the name, separated by a divider line. Stereotypes work here too: `usecase: "Validate Card" as ValidateCard \xABsecured\xBB`.\n\n---\n\n## 4. Relationships\n\nFour line types connect actors and use cases:\n\n| DSL | Meaning | Rendering |\n|-----|---------|-----------|\n| `A -- B` | association | solid line, no arrow |\n| `A --> B` | directed association | solid line, open arrow at B |\n| `A ..> B` | `A` **includes** `B` | dashed line, open arrow \u2192 B, `\xABinclude\xBB` pill |\n| `A <.. B` | `A` **extends** `B` | dashed line, open arrow \u2192 B (the base), `\xABextend\xBB` pill |\n| `A --\\|> B` | `A` is a specialisation of `B` | solid line, hollow triangle \u2192 parent B |\n\n```\nCustomer -- Checkout\nCheckout ..> Pay : \xABinclude\xBB\nPay ..> ValidateCard : \xABinclude\xBB\nCancel <.. Checkout : \xABextend\xBB [payment failed] (extension point: payment failed)\n```\n\n- **`\xABinclude\xBB`** points *toward the included use case* \u2014 the reusable behavior `A` always runs. Source includes target.\n- **`\xABextend\xBB`** points *toward the base* \u2014 `A` is the optional behavior, `B` is the base it extends. You can attach a `[condition]` and reference one of the base\'s `(extension point: \u2026)` entries. (The arrowhead is always drawn toward the base regardless of how you order the endpoints.)\n- An `\xABextend\xBB` line is drawn in the theme **accent color** so the rarer, more surprising relationship stands out.\n\nThe parser rejects the high-confidence mistakes humans and LLMs both make, with the offending line number: association between two actors or two use cases, `include`/`extend` touching an actor, generalization across metaclasses (actor \u2192 use case), reused identifiers, and extension-point references that don\'t exist on the base.\n\n---\n\n## 5. Generalization\n\n`--|>` works between two actors **or** between two use cases (never across the two \u2014 that\'s a hard error):\n\n```\nactor: User as U\nactor: "Premium User" as PU\nPU --|> U\n\nusecase: "Pay by Card" as PayCard\nusecase: "Pay by PayPal" as PayPaypal\nusecase: "Pay" as Pay\nPayCard --|> Pay\nPayPaypal --|> Pay\n```\n\nThe arrow carries a **hollow triangle** pointing at the parent. When three or more siblings share one parent, the arrows merge into a single shared head (UML 2.5 Figure 18.5 convention); set `generalization: individual` in the header to keep them separate. Actor hierarchies route as a clean bus on the outer edge of the actor stack.\n\n---\n\n## 6. Multiplicity\n\nQuote a multiplicity string immediately beside the endpoint it belongs to:\n\n```\nCustomer "1" -- "*" Checkout\nCashier "1..*" -- "1" Register\n```\n\n---\n\n## 7. PlantUML-style inline form\n\nComing from PlantUML? The inline declaration form works and mixes freely with the declarative form:\n\n```\nusecase\n:Customer: as C\n(Browse Catalog) as Browse\n(Add to Cart) as AddCart\n\nC -- Browse\nC -- AddCart\nBrowse ..> AddCart : \xABinclude\xBB\n```\n\n`:Name:` declares an actor, `(Name)` declares a use case, and `as ID` aliases either. Schematex is *inspired by* PlantUML, not a 1:1 transpiler \u2014 multiplicity and relationship syntax differ slightly.\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = "usecase" NEWLINE header_prop* statement*\nheader_prop = ("title:" | "system:") quoted_string\n | "direction:" ("LR" | "TB")\n | "generalization:" ("tree" | "individual")\n\nstatement = actor_decl | usecase_decl | plantuml_inline | relation | note\n\nactor_decl = "actor" ":" name ("as" IDENT)? actor_kind? stereotype?\nactor_kind = "(" ("external" | "system" | "business" | "left" | "right") ")"\nusecase_decl = "usecase" ":" quoted ("as" IDENT)? stereotype? extpoints?\nextpoints = "{" ("extension point:" TEXT)+ "}"\nplantuml_inline = ":" name ":" ("as" IDENT)? ; actor\n | "(" name ")" ("as" IDENT)? ; use case\n\nrelation = endpoint relop endpoint label_clause?\nendpoint = (IDENT | quoted) multiplicity? | multiplicity? (IDENT | quoted)\nrelop = "--" | "-->" | "..>" | "<.." | "--|>"\nlabel_clause = ":" stereotype? condition? extpoint_ref?\nstereotype = "\xAB" TEXT "\xBB" | "<<" TEXT ">>"\ncondition = "[" TEXT "]"\nextpoint_ref = "(extension point:" TEXT ")"\nmultiplicity = quoted_string ; "1", "*", "0..1", "1..*"\n```\n\n---'
1713
+ },
1714
+ "prisma": {
1715
+ "title": "PRISMA 2020 flow diagram",
1716
+ "content": '## 1. Your first diagram\n\nThe minimum is the four stage blocks. Counts are mandatory; the parser refuses to lay out a diagram with a missing total.\n\n```\nprisma\n\nidentification:\n databases:\n n: 1000\n\nscreening:\n records-screened: 900\n excluded:\n n: 600\n\neligibility:\n full-text-assessed: 300\n excluded:\n n: 250\n\nincluded:\n studies: 50\n```\n\nIndentation is significant \u2014 **two spaces per level**, like genogram and SLD. The first non-blank line must be `prisma`. Comments use `#` or `//`.\n\n---\n\n## 2. Meta lines\n\nTop-level `key: value` lines, written before the stage blocks:\n\n```\nprisma\nmode: 2020-single\nkind: systematic-review\ntitle: My review\nvalidate-counts: warn\n```\n\n| Key | Values | Default | Meaning |\n|---|---|---|---|\n| `mode` | `2020-single` \xB7 `2020-dual` \xB7 `2009` | `2020-single` | Single column, or dual ("other methods") column. |\n| `kind` | `systematic-review` \xB7 `scoping-review` \xB7 `ipd` \xB7 `nma` | `systematic-review` | Swaps stage vocabulary (see \xA76). |\n| `title` | string | \u2014 | Rendered above the diagram. |\n| `validate-counts` | `warn` \xB7 `strict` \xB7 `off` | `warn` | Arithmetic checking (see \xA77). |\n| `direction` | `TB` / `TD` | `TB` | PRISMA is vertical by standard; horizontal is rejected. |\n\n---\n\n## 3. Identification\n\nThe `identification:` block holds a `databases:` sub-block (always) and an optional `other:` sub-block (dual mode).\n\n```\nidentification:\n databases:\n n: 1418\n sources: PubMed=600, Embase=450, Cochrane=184\n duplicates-removed: 318\n ineligible-automation: 0\n other-removed: 0\n```\n\n- `n:` \u2014 total records identified (**mandatory**).\n- `sources:` \u2014 `name=count` pairs, comma-separated. Rendered as an indented breakdown. Names with spaces or punctuation can be quoted: `"Web of Science"=184`.\n- `duplicates-removed:`, `ineligible-automation:`, `other-removed:` \u2014 optional removal counts. When any are present they render as a separate **"Records removed before screening"** box in the right column, connected by a horizontal arrow.\n\nLarge numbers may use commas: `n: 1,418` is the same as `n: 1418`.\n\n---\n\n## 4. Screening & Eligibility\n\nBoth stages carry a main count plus an `excluded:` block. The excluded block has its own `n:` and an optional `reasons:` breakdown.\n\n```\nscreening:\n records-screened: 1100\n excluded:\n n: 870\n reasons: irrelevant title=750, non-English=120\n reports-sought: 226 # optional\n reports-not-retrieved: 12 # optional\n\neligibility:\n full-text-assessed: 230\n excluded:\n n: 195\n reasons: wrong population=80, wrong intervention=60, wrong outcome=55\n```\n\n`reasons:` are `name=count` pairs. If you list more than 8, the renderer sorts them descending and aggregates the tail as `Other (n = \u2026)` so the side-box stays readable.\n\n---\n\n## 5. Included\n\n```\nincluded:\n studies: 35\n reports: 38 # one study may yield several reports\n participants: 28741 # PRISMA-IPD only\n```\n\n`studies:` is mandatory. `reports:` and `participants:` are optional extra count lines.\n\n---\n\n## 6. Dual pipeline & review kinds\n\n**Dual pipeline** \u2014 the PRISMA 2020 update added a second "Identification via other methods" column (citation searching, hand searches, expert recommendations). Add an `other:` block; the two columns merge into Screening via a Y-junction.\n\n```\nprisma\nmode: 2020-dual\n\nidentification:\n databases:\n n: 1234\n duplicates-removed: 254\n other:\n n: 56\n sources: citation-search=30, hand-search=20, expert-recommendation=6\n\nscreening:\n records-screened: 1036\n excluded:\n n: 810\n\neligibility:\n full-text-assessed: 226\n excluded:\n n: 195\n\nincluded:\n studies: 31\n```\n\n**Scoping review** \u2014 `kind: scoping-review` swaps "studies" \u2192 "sources of evidence" and re-labels the stages per Tricco et al. 2018, without changing geometry.\n\n**Updated review** \u2014 an optional `previous-studies:` block draws a dashed box on top that feeds into the identification section:\n\n```\nprevious-studies:\n n: 19\n sources: previous review=19\n```\n\n---\n\n## 7. Count arithmetic validation\n\nWith `validate-counts: warn` (default) the engine checks that the counts reconcile across stages \u2014 e.g. `databases.n + other.n \u2212 duplicates-removed = records-screened`, and that source/reason breakdowns sum to their totals. Mismatches render a small warning under the diagram (also surfaced in the SVG `<desc>` for screen readers).\n\n`validate-counts: strict` turns a mismatch into a parse error with an "off by N" message. `off` skips checking entirely.\n\n---\n\n## 8. Grammar (EBNF)\n\n```\nprisma-document = "prisma", { meta-line }, stage-block, { stage-block } ;\nmeta-line = ("mode:" | "kind:" | "title:" | "review-id:" | "validate-counts:" | "direction:") value ;\n\nstage-block = previous-block | identification-block | screening-block | eligibility-block | included-block ;\n\nprevious-block = "previous-studies:" , indent, "n:" int, [ "reports:" int ], { "sources:" pairs } ;\nidentification-block = "identification:" , indent,\n "databases:" , indent, "n:" int, { "sources:" pairs },\n [ "duplicates-removed:" int ], [ "ineligible-automation:" int ], [ "other-removed:" int ],\n [ "other:" , indent, "n:" int, { "sources:" pairs } ] ;\nscreening-block = "screening:" , indent, "records-screened:" int,\n "excluded:" , indent, "n:" int, { "reasons:" pairs },\n [ "reports-sought:" int ], [ "reports-not-retrieved:" int ] ;\neligibility-block = "eligibility:" , indent, "full-text-assessed:" int,\n "excluded:" , indent, "n:" int, { "reasons:" pairs } ;\nincluded-block = "included:" , indent, "studies:" int, [ "reports:" int ], [ "participants:" int ] ;\n\npairs = pair, { "," pair } ;\npair = (string | quoted) "=" int ;\nint = digit, { digit | "," } ; (* commas stripped: 1,234 == 1234 *)\n```\n\nIndentation is two spaces per level. Unknown keys inside a stage block are a parse error, keeping each stage well-defined.\n\n---'
1717
+ },
1718
+ "pert": {
1719
+ "title": "PERT / CPM Network",
1720
+ "content": '## 1. Your first diagram\n\nEvery document starts with the `pert` keyword, an optional header, then one `task` line per activity:\n\n```\npert\nunit: days\n\ntask A "Market research" duration: 5\ntask B "Design mockups" duration: 8 after: A\ntask C "Backend API" duration: 15 after: A\ntask D "Frontend build" duration: 10 after: B, C\n```\n\nEach task carries an `<id>`, a quoted `<label>`, a `duration:`, and an optional `after:` list of predecessors. The engine adds an invisible Start and Finish, runs the schedule, and draws the six-field activity box for every task. You never type ES/EF/LS/LF \u2014 they are computed.\n\nThe header accepts:\n\n- `title: "\u2026"` \u2014 a heading drawn above the diagram.\n- `unit: days | weeks | hours | abstract` \u2014 the time unit (default `days`; purely a label, the engine is calendar-agnostic).\n- `direction: LR | TB` \u2014 left-to-right (default) or top-to-bottom.\n- `layout: network | timescaled` \u2014 the layered network (default) or a time-proportional view (\xA76).\n- `critical-tolerance: <n>` \u2014 slack \u2264 this counts as critical (default `0`; set `0.001` for three-point projects).\n- `show-sentinels: true` \u2014 draw the synthetic Start / Finish nodes (hidden by default).\n\n---\n\n## 2. The six-field activity box\n\nEvery task renders as the canonical 3\xD72 PERT/CPM rectangle:\n\n```\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ES \u2502 Duration \u2502 EF \u2502\n\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Task Name (ID) \u2502\n\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 LS \u2502 Slack \u2502 LF \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n- **ES / EF** \u2014 Early Start / Early Finish, from the forward pass.\n- **LS / LF** \u2014 Late Start / Late Finish, from the backward pass.\n- **Slack** (total float) = LS \u2212 ES = LF \u2212 EF. Zero slack means the activity is on the critical path.\n\nCritical activities get a **red border** and a bold `0` slack; the project\'s critical chain reads as an unbroken red line. Every field is also mirrored onto `data-*` attributes (`data-es`, `data-slack`, `data-critical`, \u2026) so you can query the SVG without re-running the math.\n\n**On the two-colour palette.** A PERT chart is deliberately drawn in just two colours. Red for the critical path is a genuine industry convention \u2014 MS Project, Oracle Primavera P6, and PMBOK figures all use it, because "critical vs. not" is the one distinction the diagram exists to surface. Everything else stays a neutral house-blue. Adding more colours would imply categories that PERT\'s semantics don\'t have; if you need to group by team or phase, use [swimlanes](#7-swimlanes-tags-classes-and-comments) (`lane:`) instead of colour.\n\n---\n\n## 3. Dependencies (FS / SS / FF / SF + lag/lead)\n\n`after:` takes a comma-separated list of predecessor references. The default relationship is **Finish-to-Start (FS)** \u2014 a task starts once its predecessor finishes:\n\n```\ntask D "Frontend build" duration: 10 after: B, C\n```\n\nModern scheduling needs the other three Precedence-Diagramming relationships and **lag** (delay) or **lead** (negative lag):\n\n```\ntask B "Stakeholder interviews" duration: 6 after: A SS+1 # start 1d after A starts\ntask I "Documentation" duration: 4 after: D+3 # FS with a 3-day lag\ntask J "Translation" duration: 3 after: I SS-1 # start 1d before I starts (lead)\ntask K "Sign-off" duration: 1 after: I FF # finishes when I finishes\ntask L "Press release" duration: 2 after: G SF+1 # start-to-finish (rare)\n```\n\n| Form | Meaning |\n|------|---------|\n| `after: A` | Finish-to-Start, no lag (the common case) |\n| `after: A+2` or `after: A+2d` | FS with a 2-unit lag |\n| `after: A SS` / `A FF` / `A SF` | Start-to-Start / Finish-to-Finish / Start-to-Finish |\n| `after: A SS+2d` / `A FF-1d` | any type with lag (`+`) or lead (`-`) |\n\nA lag unit suffix (`d` / `w` / `h`) must match the diagram\'s `unit:` or be omitted; mixed units are rejected. FS with zero lag is unlabelled; SS/FF/SF always show their type on the edge.\n\n---\n\n## 4. Three-point (PERT) estimation\n\nWrite a duration as `O/M/P` (optimistic / most-likely / pessimistic) and the engine computes the beta-distribution expected duration **te = (O + 4M + P) / 6** and the variance **\u03C3\xB2 = ((P \u2212 O)/6)\xB2**:\n\n```\npert\ncritical-tolerance: 0.01\ntask A "Spec" duration: 2/3/5 # te = 3.17, \u03C3\xB2 = 0.25\ntask B "Build" duration: 5/8/14 after: A # te = 8.50, \u03C3\xB2 = 2.25\ntask C "Test" duration: 3/4/6 after: B\ntask D "Deploy" duration: 1/2/3 after: C\n```\n\nThe Duration field shows `te`; a small `\u03C3=\u2026` annotation appears under the name; and the project-level standard deviation (\u221A of the summed critical-path variances) is reported in the footer. Use `critical-tolerance: 0.01` so floating-point `te` values don\'t displace the visible critical path.\n\n---\n\n## 5. Milestones\n\nA milestone is a zero-duration checkpoint, drawn as a diamond. Use the `milestone` flag or `duration: 0`:\n\n```\ntask P "Cutover weekend" milestone after: O\ntask Q "Go-live" duration: 0 after: P\n```\n\n---\n\n## 6. Time-scaled layout\n\n`layout: timescaled` switches from the layered network to a network-Gantt hybrid: each activity\'s **x-position is proportional to its ES** and its **width is proportional to its duration**, with a unit time axis along the bottom. Activities are packed into lanes so nothing overlaps.\n\n```\npert\nlayout: timescaled\nunit: days\n\ntask A "Inventory" duration: 5\ntask B "Interviews" duration: 6 after: A SS+1\ntask C "Design" duration: 10 after: A, B\ntask D "Build" duration: 15 after: C\ntask E "Pilot" duration: 7 after: D\n```\n\nThis is a bridge to a Gantt view, not a replacement: there\'s no calendar, working-time mask, or resource swimlane.\n\n### Activity-on-arrow (`layout: aoa`)\n\n`layout: aoa` renders the older **activity-on-arrow** (ADM) notation you\'ll find in textbooks and on Investopedia: numbered **event** circles, **activities as labelled arrows**, and dotted **dummy activities** auto-inserted wherever an activity has two or more predecessors. You write the same activity-on-node DSL \u2014 Schematex builds the event graph and numbers the events for you.\n\n```\npert\nlayout: aoa\nunit: days\n\ntask A "create schedule" duration: 10\ntask B "buy hardware" duration: 5\ntask C "programming" duration: 20 after: A\ntask D "installation" duration: 5 after: B\ntask E "conversion" duration: 15 after: D\ntask F "test code" duration: 20 after: C, E\ntask G "write manual" duration: 15 after: E\n```\n\nAOA is a **legacy** notation (PMBOK 7 dropped it; AON is the modern standard) and it can only express **finish-to-start** logic \u2014 SS/FF/SF and lag/lead are flattened to FS with a warning. Use it for teaching, exam prep, or matching an existing textbook figure; use the default `network` (AON) layout for real scheduling.\n\n---\n\n## 7. Swimlanes, tags, classes, and comments\n\nAdd `lane: "\u2026"` to any task and the network re-groups into horizontal swimlanes \u2014 by responsible team, phase, or owner \u2014 while still computing the schedule exactly as before:\n\n```\ntask T1 "Support Account Deletion" duration: 3 lane: "Customer Account"\ntask T2 "Design a New Theme" duration: 8 lane: "Shopping Site"\ntask T3 "Apply New Theme" duration: 15 after: T2 lane: "Shopping Site"\n```\n\nLanes appear in first-declared order, each as a banded row with a label gutter on the left. Swimlanes are a presentation of the same AON network, not a different layout mode \u2014 they activate automatically when any task declares a lane.\n\n```\ntask X "External vendor work" duration: 10 after: A tags: vendor, external class: secondary\n# this is a comment\n```\n\n`tags:` emit `data-tag="\u2026"` on the node group and `class:` adds a CSS class for downstream theming. `#` and `//` start a comment to end of line.\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = "pert" NEWLINE header* task+\nheader = "title:" quoted\n | "unit:" ("days" | "weeks" | "hours" | "abstract")\n | "direction:" ("LR" | "TB")\n | "layout:" ("network" | "timescaled" | "aoa")\n | "critical-tolerance:" number\n | "show-sentinels:" boolean\n\ntask = "task" IDENT quoted "duration:" duration ("after:" reflist)? "milestone"? attrs?\n | "task" IDENT quoted "milestone" ("after:" reflist)? attrs?\nduration = number | number "/" number "/" number ; deterministic or O/M/P\nreflist = ref ("," ref)*\nref = IDENT (WS deptype)? laglead?\n | IDENT "+" number unit? ; attached FS lag sugar\ndeptype = "FS" | "SS" | "FF" | "SF"\nlaglead = ("+" | "-") number unit?\nunit = "d" | "w" | "h"\nattrs = ("tags:" idlist)? ("class:" IDENT)? ("lane:" quoted)?\n```\n\n---'
1533
1721
  }
1534
1722
  };
1535
1723
 
@@ -1609,7 +1797,7 @@ function getExamples(type, opts = {}) {
1609
1797
  function validateDsl(type, dsl) {
1610
1798
  const config = type ? { type } : void 0;
1611
1799
  try {
1612
- chunkSMXU3KYA_cjs.parse(dsl, config);
1800
+ chunk3YUUC6RN_cjs.parse(dsl, config);
1613
1801
  return { ok: true, type: type ?? resolveTypeFromText(dsl) };
1614
1802
  } catch (err) {
1615
1803
  return {
@@ -1625,7 +1813,7 @@ function renderDsl(type, dsl, options = {}) {
1625
1813
  ...type ? { type } : {}
1626
1814
  };
1627
1815
  try {
1628
- const svg = chunkSMXU3KYA_cjs.render(dsl, config);
1816
+ const svg = chunk3YUUC6RN_cjs.render(dsl, config);
1629
1817
  return { ok: true, type: type ?? resolveTypeFromText(dsl), svg };
1630
1818
  } catch (err) {
1631
1819
  return {
@@ -1649,5 +1837,5 @@ exports.getSyntax = getSyntax;
1649
1837
  exports.listDiagrams = listDiagrams;
1650
1838
  exports.renderDsl = renderDsl;
1651
1839
  exports.validateDsl = validateDsl;
1652
- //# sourceMappingURL=chunk-N3SLYVNW.cjs.map
1653
- //# sourceMappingURL=chunk-N3SLYVNW.cjs.map
1840
+ //# sourceMappingURL=chunk-NWPCY65Z.cjs.map
1841
+ //# sourceMappingURL=chunk-NWPCY65Z.cjs.map