agentic-mermaid 0.4.1 → 0.5.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.
Files changed (253) hide show
  1. package/AGENT_NATIVE.md +94 -627
  2. package/CHANGELOG.md +651 -0
  3. package/Instructions_for_agents.md +44 -23
  4. package/LICENSES/Khroma-MIT.txt +21 -0
  5. package/LICENSES/Mermaid-MIT.txt +21 -0
  6. package/LICENSES/es-toolkit-MIT.txt +21 -0
  7. package/LICENSES/pele-MIT.txt +40 -0
  8. package/LICENSES/zenuml-core-MIT.txt +21 -0
  9. package/README.md +93 -50
  10. package/SECURITY.md +28 -12
  11. package/THIRD_PARTY_NOTICES.md +60 -0
  12. package/assets/hero.png +0 -0
  13. package/dist/agent-core.d.ts +478 -210
  14. package/dist/agent-core.js +1 -396
  15. package/dist/agent.d.ts +17 -8
  16. package/dist/agent.js +1 -408
  17. package/dist/agentic-mermaid-mcp.js +1 -11
  18. package/dist/am.js +1 -34562
  19. package/dist/browser-lazy/chunks/agentic-producer-core-CC6OOLDW.js +1 -0
  20. package/dist/browser-lazy/chunks/architecture-QUFVKYJR.js +13 -0
  21. package/dist/browser-lazy/chunks/block-6J3Q63BO.js +11 -0
  22. package/dist/browser-lazy/chunks/builtin-backends-7SOZZHPF.js +12 -0
  23. package/dist/browser-lazy/chunks/c4-SQVBZAKJ.js +10 -0
  24. package/dist/browser-lazy/chunks/chunk-2GPK4VFF.js +5 -0
  25. package/dist/browser-lazy/chunks/chunk-2I4UPL7Q.js +3 -0
  26. package/dist/browser-lazy/chunks/chunk-2SH76OTH.js +1 -0
  27. package/dist/browser-lazy/chunks/chunk-2UIA2IME.js +3 -0
  28. package/dist/browser-lazy/chunks/chunk-4LHYF3BS.js +1 -0
  29. package/dist/browser-lazy/chunks/chunk-5B2Z7575.js +1 -0
  30. package/dist/browser-lazy/chunks/chunk-5FQ534HP.js +1 -0
  31. package/dist/browser-lazy/chunks/chunk-5UVGUSD6.js +1 -0
  32. package/dist/browser-lazy/chunks/chunk-5X6MJX3H.js +1 -0
  33. package/dist/browser-lazy/chunks/chunk-AMJLVPUB.js +4 -0
  34. package/dist/browser-lazy/chunks/chunk-BU5LHXNJ.js +3 -0
  35. package/dist/browser-lazy/chunks/chunk-BY2CPG6B.js +1 -0
  36. package/dist/browser-lazy/chunks/chunk-CN7WTBWB.js +1 -0
  37. package/dist/browser-lazy/chunks/chunk-CQE4HQEW.js +1 -0
  38. package/dist/browser-lazy/chunks/chunk-CSFUKSU6.js +1 -0
  39. package/dist/browser-lazy/chunks/chunk-DF6765YX.js +17 -0
  40. package/dist/browser-lazy/chunks/chunk-E2WMJZNM.js +1 -0
  41. package/dist/browser-lazy/chunks/chunk-FAIMVOX5.js +6 -0
  42. package/dist/browser-lazy/chunks/chunk-GVOEAY52.js +1 -0
  43. package/dist/browser-lazy/chunks/chunk-HLWUNUCM.js +1 -0
  44. package/dist/browser-lazy/chunks/chunk-ICC7HBJX.js +1 -0
  45. package/dist/browser-lazy/chunks/chunk-J35HAQQF.js +20 -0
  46. package/dist/browser-lazy/chunks/chunk-J7FFAFQF.js +1 -0
  47. package/dist/browser-lazy/chunks/chunk-LH7HUDKW.js +1 -0
  48. package/dist/browser-lazy/chunks/chunk-N5ELX7LR.js +2 -0
  49. package/dist/browser-lazy/chunks/chunk-NMQQMRIR.js +1 -0
  50. package/dist/browser-lazy/chunks/chunk-NO7ZIVRU.js +1 -0
  51. package/dist/browser-lazy/chunks/chunk-OZ443IVJ.js +16 -0
  52. package/dist/browser-lazy/chunks/chunk-PQGPS2YV.js +7 -0
  53. package/dist/browser-lazy/chunks/chunk-QA6GJQ4X.js +1 -0
  54. package/dist/browser-lazy/chunks/chunk-RIVTHZAQ.js +1 -0
  55. package/dist/browser-lazy/chunks/chunk-SZELX2EJ.js +1 -0
  56. package/dist/browser-lazy/chunks/chunk-TYZOZXUJ.js +22 -0
  57. package/dist/browser-lazy/chunks/chunk-UL6NDWLL.js +1 -0
  58. package/dist/browser-lazy/chunks/chunk-VQYYGAXP.js +1 -0
  59. package/dist/browser-lazy/chunks/chunk-VWVZGQE2.js +1 -0
  60. package/dist/browser-lazy/chunks/chunk-X2UYKWKM.js +4 -0
  61. package/dist/browser-lazy/chunks/chunk-YCEICNM6.js +1 -0
  62. package/dist/browser-lazy/chunks/chunk-Z3FDIVLN.js +20 -0
  63. package/dist/browser-lazy/chunks/class-5QA4SCTS.js +13 -0
  64. package/dist/browser-lazy/chunks/decode-63UIZGD2.js +1 -0
  65. package/dist/browser-lazy/chunks/elk.bundled-L4CADV5W.js +24 -0
  66. package/dist/browser-lazy/chunks/er-7ZSKGN7Y.js +11 -0
  67. package/dist/browser-lazy/chunks/eventmodeling-2BPLHWRN.js +19 -0
  68. package/dist/browser-lazy/chunks/flowchart-NEIMZTB5.js +4 -0
  69. package/dist/browser-lazy/chunks/forest-implementation-AEP24AIP.js +1 -0
  70. package/dist/browser-lazy/chunks/gantt-RDPIFYAF.js +11 -0
  71. package/dist/browser-lazy/chunks/gitgraph-N4Y5RYB7.js +9 -0
  72. package/dist/browser-lazy/chunks/ishikawa-LD3YBDJN.js +6 -0
  73. package/dist/browser-lazy/chunks/journey-6YQR5DJX.js +16 -0
  74. package/dist/browser-lazy/chunks/kanban-PLMJ7NBW.js +20 -0
  75. package/dist/browser-lazy/chunks/mermaid-yaml-runtime-QVYX4EWK.js +136 -0
  76. package/dist/browser-lazy/chunks/mindmap-K2UBFO3Y.js +12 -0
  77. package/dist/browser-lazy/chunks/packet-CUW4QY6Y.js +7 -0
  78. package/dist/browser-lazy/chunks/pie-7F7UUCG3.js +15 -0
  79. package/dist/browser-lazy/chunks/quadrant-TOONO2WC.js +10 -0
  80. package/dist/browser-lazy/chunks/radar-J6JVWVAX.js +16 -0
  81. package/dist/browser-lazy/chunks/render-core-BZOM3K7D.js +3 -0
  82. package/dist/browser-lazy/chunks/requirement-CMAKDJPO.js +19 -0
  83. package/dist/browser-lazy/chunks/sankey-AWXQEP3F.js +13 -0
  84. package/dist/browser-lazy/chunks/sequence-Q2RJRB4L.js +5 -0
  85. package/dist/browser-lazy/chunks/state-WRBFQEDX.js +4 -0
  86. package/dist/browser-lazy/chunks/timeline-D2KILFXM.js +6 -0
  87. package/dist/browser-lazy/chunks/treemap-N3VYX5D4.js +6 -0
  88. package/dist/browser-lazy/chunks/xychart-G73OGK66.js +16 -0
  89. package/dist/browser-lazy/chunks/zenuml-H4BXNYXR.js +16 -0
  90. package/dist/browser-lazy/index.d.ts +544 -275
  91. package/dist/browser-lazy/index.js +1 -1
  92. package/dist/browser.global.js +802 -565
  93. package/dist/chunk-3LGLPG33.js +2 -0
  94. package/dist/chunk-7CRDX2QR.js +2 -0
  95. package/dist/chunk-7PPW2BMO.js +2 -0
  96. package/dist/chunk-DQDKA5ND.js +2 -0
  97. package/dist/chunk-EHCMJUMD.js +52 -0
  98. package/dist/chunk-GVCHLSHH.js +4 -0
  99. package/dist/chunk-H3NCS2XZ.js +19 -0
  100. package/dist/chunk-JZOJ4YGS.js +201 -0
  101. package/dist/chunk-MKE7GNYU.js +146 -0
  102. package/dist/chunk-NKNFOREZ.js +2 -0
  103. package/dist/chunk-O7H2UX5K.js +2 -0
  104. package/dist/chunk-OMY6NRQD.js +58 -0
  105. package/dist/chunk-UA234O4M.js +4 -0
  106. package/dist/chunk-VUFVLGTH.js +2 -0
  107. package/dist/chunk-XU5LPD2D.js +2 -0
  108. package/dist/cli-YGGTJZH7.js +226 -0
  109. package/dist/elk-constructor.js +2 -0
  110. package/dist/elk-constructor.node.js +11 -0
  111. package/dist/index-EeXqJXr5.d.ts +1223 -0
  112. package/dist/index.d.ts +4 -1
  113. package/dist/index.js +1 -334
  114. package/dist/jsonl-RPJY6YWO.js +2 -0
  115. package/dist/mcp-cli-63DYXTVD.js +2 -0
  116. package/dist/{index-BGA_-6LV.d.ts → paint-certification-6rwQjIv_.d.ts} +5283 -6173
  117. package/dist/server-5NEOHOFS.js +524 -0
  118. package/dist/svg-styles-BdnoM7AT.d.ts +724 -0
  119. package/dist/svg-styles.d.ts +1 -0
  120. package/dist/svg-styles.js +2 -0
  121. package/dist/svg.d.ts +13 -0
  122. package/dist/svg.js +2 -0
  123. package/dist/types-BcS52Mjt.d.ts +1360 -0
  124. package/dist/zenuml/chunks/appearance-UOQ5KA6O.js +1 -0
  125. package/dist/zenuml/chunks/builtin-backends-KDKE7YHO.js +12 -0
  126. package/dist/zenuml/chunks/chunk-42DXZ5C6.js +4 -0
  127. package/dist/zenuml/chunks/chunk-7TVYPTDW.js +1 -0
  128. package/dist/zenuml/chunks/chunk-EVPSMEKN.js +1 -0
  129. package/dist/zenuml/chunks/chunk-OXQWRSBM.js +20 -0
  130. package/dist/zenuml/chunks/chunk-QWX77U7G.js +2 -0
  131. package/dist/zenuml/chunks/chunk-RLJEI7YN.js +29 -0
  132. package/dist/zenuml/chunks/chunk-RZ6XK5CD.js +29 -0
  133. package/dist/zenuml/chunks/decode-BWERFDGK.js +1 -0
  134. package/dist/zenuml/chunks/mermaid-yaml-runtime-KZVU74WU.js +136 -0
  135. package/dist/zenuml/chunks/render-core-V5RQ737O.js +3 -0
  136. package/dist/zenuml/chunks/zenuml-EA2ZFRUX.js +20 -0
  137. package/dist/zenuml-frame.global.js +3626 -0
  138. package/dist/zenuml.d.ts +83 -0
  139. package/dist/zenuml.js +1 -0
  140. package/docs/MCP-DIRECTORY-LISTINGS.md +5 -1
  141. package/docs/README.md +59 -103
  142. package/docs/agent-api-cookbook.md +26 -16
  143. package/docs/agent-mutation-policy.md +86 -15
  144. package/docs/agent-workflow-examples.md +1 -1
  145. package/docs/api-advanced.md +385 -0
  146. package/docs/api.md +320 -366
  147. package/docs/ascii.md +40 -4
  148. package/docs/browser.md +46 -7
  149. package/docs/choosing-a-diagram.md +148 -0
  150. package/docs/code-mode-impact.md +1 -0
  151. package/docs/comparison.md +244 -28
  152. package/docs/computational-aesthetics-prototype-plan.md +10 -10
  153. package/docs/config.md +60 -2
  154. package/docs/custom-fonts.md +78 -21
  155. package/docs/diagram-families.md +160 -10
  156. package/docs/eventmodeling-and-zenuml.md +165 -0
  157. package/docs/features.md +21 -19
  158. package/docs/fork-differences.md +105 -32
  159. package/docs/getting-started.md +56 -51
  160. package/docs/layout-certification.md +126 -0
  161. package/docs/mcp-code-mode-rationale.md +20 -12
  162. package/docs/mcp-http-transport.md +14 -8
  163. package/docs/quality.md +145 -15
  164. package/docs/react.md +76 -31
  165. package/docs/style-authoring.md +23 -11
  166. package/docs/svg-semantic-contract.md +104 -4
  167. package/docs/testing-strategy.md +684 -126
  168. package/docs/theming.md +27 -8
  169. package/examples/styles/readme-hero.md +25 -0
  170. package/examples/styles/readme-hero.mmd +13 -0
  171. package/examples/styles/readme-hero.style.json +7 -0
  172. package/package.json +114 -57
  173. package/server.json +2 -2
  174. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +26 -8
  175. package/skills/agentic-mermaid-diagram-workflow/references/cli.md +13 -3
  176. package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +2 -1
  177. package/skills/agentic-mermaid-diagram-workflow/references/flowchart.md +9 -6
  178. package/skills/agentic-mermaid-diagram-workflow/references/hosted-mcp.md +1 -0
  179. package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +4 -3
  180. package/skills/agentic-mermaid-diagram-workflow/references/timeline.md +7 -6
  181. package/skills/agentic-mermaid-diagram-workflow/references/upstream/agentflow.md +574 -0
  182. package/skills/agentic-mermaid-diagram-workflow/references/upstream/architecture.md +10 -2
  183. package/skills/agentic-mermaid-diagram-workflow/references/upstream/c4.md +18 -0
  184. package/skills/agentic-mermaid-diagram-workflow/references/upstream/classDiagram.md +123 -0
  185. package/skills/agentic-mermaid-diagram-workflow/references/upstream/cynefin.md +6 -1
  186. package/skills/agentic-mermaid-diagram-workflow/references/upstream/entityRelationshipDiagram.md +129 -9
  187. package/skills/agentic-mermaid-diagram-workflow/references/upstream/eventmodeling.md +22 -0
  188. package/skills/agentic-mermaid-diagram-workflow/references/upstream/flowchart.md +188 -60
  189. package/skills/agentic-mermaid-diagram-workflow/references/upstream/gitgraph.md +13 -7
  190. package/skills/agentic-mermaid-diagram-workflow/references/upstream/mindmap.md +110 -1
  191. package/skills/agentic-mermaid-diagram-workflow/references/upstream/packet.md +38 -0
  192. package/skills/agentic-mermaid-diagram-workflow/references/upstream/requirementDiagram.md +115 -0
  193. package/skills/agentic-mermaid-diagram-workflow/references/upstream/sequenceDiagram.md +101 -0
  194. package/skills/agentic-mermaid-diagram-workflow/references/upstream/stateDiagram.md +87 -0
  195. package/skills/agentic-mermaid-diagram-workflow/references/upstream/swimlanes.md +105 -2
  196. package/skills/agentic-mermaid-diagram-workflow/references/upstream/timeline.md +12 -6
  197. package/skills/agentic-mermaid-diagram-workflow/references/upstream/usecase.md +953 -0
  198. package/skills/agentic-mermaid-diagram-workflow/references/upstream/venn.md +77 -0
  199. package/skills/agentic-mermaid-diagram-workflow/references/upstream/xyChart.md +1 -1
  200. package/dist/browser-lazy/chunks/architecture-KTHE2HX3.js +0 -31
  201. package/dist/browser-lazy/chunks/chunk-2XCPFAD5.js +0 -46
  202. package/dist/browser-lazy/chunks/chunk-3H4F7RBT.js +0 -1
  203. package/dist/browser-lazy/chunks/chunk-4EVLW2NJ.js +0 -1
  204. package/dist/browser-lazy/chunks/chunk-5Q4S74UO.js +0 -1
  205. package/dist/browser-lazy/chunks/chunk-6OAPWSDO.js +0 -1
  206. package/dist/browser-lazy/chunks/chunk-A7L4WWVW.js +0 -143
  207. package/dist/browser-lazy/chunks/chunk-C7FJO2I3.js +0 -4
  208. package/dist/browser-lazy/chunks/chunk-D3XXDKIO.js +0 -1
  209. package/dist/browser-lazy/chunks/chunk-DXA5WL7H.js +0 -4
  210. package/dist/browser-lazy/chunks/chunk-EPFMQPXX.js +0 -1
  211. package/dist/browser-lazy/chunks/chunk-FFOHLPDA.js +0 -2
  212. package/dist/browser-lazy/chunks/chunk-FLD63DXE.js +0 -2
  213. package/dist/browser-lazy/chunks/chunk-G6OLSHRG.js +0 -7
  214. package/dist/browser-lazy/chunks/chunk-GRXCKTHX.js +0 -0
  215. package/dist/browser-lazy/chunks/chunk-I6VE56S7.js +0 -1
  216. package/dist/browser-lazy/chunks/chunk-KJVNXJ5Y.js +0 -1
  217. package/dist/browser-lazy/chunks/chunk-L227EPFP.js +0 -11
  218. package/dist/browser-lazy/chunks/chunk-LNIHDJSF.js +0 -1
  219. package/dist/browser-lazy/chunks/chunk-M6BT2HIP.js +0 -1
  220. package/dist/browser-lazy/chunks/chunk-NZRUMODH.js +0 -1
  221. package/dist/browser-lazy/chunks/chunk-OFRMKQA6.js +0 -1
  222. package/dist/browser-lazy/chunks/chunk-P7HMSKHJ.js +0 -1
  223. package/dist/browser-lazy/chunks/chunk-PXKL3O6H.js +0 -1
  224. package/dist/browser-lazy/chunks/chunk-PZEWZT35.js +0 -1
  225. package/dist/browser-lazy/chunks/chunk-STQRDZ67.js +0 -1
  226. package/dist/browser-lazy/chunks/chunk-SUFMSWTX.js +0 -1
  227. package/dist/browser-lazy/chunks/chunk-T7IJ6V4B.js +0 -3
  228. package/dist/browser-lazy/chunks/chunk-UAEZO5VL.js +0 -1
  229. package/dist/browser-lazy/chunks/chunk-WEUWIFG3.js +0 -1
  230. package/dist/browser-lazy/chunks/chunk-X64T74C5.js +0 -24
  231. package/dist/browser-lazy/chunks/class-F7R6TJ73.js +0 -9
  232. package/dist/browser-lazy/chunks/er-BDK7CM5L.js +0 -9
  233. package/dist/browser-lazy/chunks/flowchart-KFU6XV7S.js +0 -4
  234. package/dist/browser-lazy/chunks/gantt-I64VVDSP.js +0 -28
  235. package/dist/browser-lazy/chunks/gitgraph-EDUVJ5IJ.js +0 -8
  236. package/dist/browser-lazy/chunks/journey-TLO2RNM3.js +0 -40
  237. package/dist/browser-lazy/chunks/mindmap-OJCNDYPM.js +0 -9
  238. package/dist/browser-lazy/chunks/pie-HVG6XO7K.js +0 -19
  239. package/dist/browser-lazy/chunks/quadrant-U6S2L4MJ.js +0 -24
  240. package/dist/browser-lazy/chunks/radar-ZDLOBTVG.js +0 -32
  241. package/dist/browser-lazy/chunks/render-core-Y2DFNMQG.js +0 -12
  242. package/dist/browser-lazy/chunks/sequence-Z4WFS3VB.js +0 -12
  243. package/dist/browser-lazy/chunks/state-2HV2YGN3.js +0 -4
  244. package/dist/browser-lazy/chunks/timeline-XM4UFPOC.js +0 -20
  245. package/dist/browser-lazy/chunks/xychart-7JDHWTQY.js +0 -36
  246. package/dist/chunk-GGXCNCNA.js +0 -4118
  247. package/dist/chunk-IVD4NXNE.js +0 -615
  248. package/dist/chunk-JDMRPUAG.js +0 -37
  249. package/dist/chunk-JWAAW3FH.js +0 -149
  250. package/dist/chunk-LCGBT32P.js +0 -62036
  251. package/dist/chunk-RWMZRUIC.js +0 -4715
  252. package/dist/mcp-cli-4MLKC3ZH.js +0 -17
  253. package/docs/mutation-testing.md +0 -285
@@ -0,0 +1,385 @@
1
+ # Advanced library API
2
+
3
+ Configure host rendering, inspect receipts, and extend AM.
4
+
5
+ Start with the ordinary workflows in the [library reference](./api.md).
6
+
7
+ This page describes the same source checkout as the library reference. Check its
8
+ [version information](./api.md#versions) before using a feature from an installed package.
9
+
10
+ ## Canonical requests and comparable receipts
11
+
12
+ Every first-party renderer enters through the same immutable internal request
13
+ boundary: source wrappers/config, the Style stack, colors, font, security, and
14
+ shared options are normalized once. Receipt-bearing variants make that boundary
15
+ observable without exporting its executable implementation types or changing
16
+ the existing convenience return types:
17
+
18
+ ```ts
19
+ import {
20
+ renderMermaidASCIIWithReceipt,
21
+ renderMermaidPNGWithReceipt,
22
+ renderMermaidSVGWithReceipt,
23
+ } from 'agentic-mermaid/agent'
24
+
25
+ const options = { style: 'hand-drawn', seed: 7, embedFontImport: false }
26
+ const svg = renderMermaidSVGWithReceipt(source, options)
27
+ const png = renderMermaidPNGWithReceipt(source, options)
28
+ const text = renderMermaidASCIIWithReceipt(source, { ...options, colorMode: 'none' })
29
+
30
+ console.assert(svg.receipt.sharedRequestDigest === png.receipt.sharedRequestDigest)
31
+ console.assert(svg.receipt.appearanceDigest === text.receipt.appearanceDigest)
32
+ ```
33
+
34
+ Each `RenderRequestReceipt` contains `version`, `output`,
35
+ `sharedRequestDigest`, output-specific `requestDigest`, and
36
+ `appearanceDigest`. Its `diagnostics` array records stable request-resolution,
37
+ compatibility, applicability, projection, and output-policy decisions. In
38
+ particular, `RENDER_OPTION_NOT_APPLICABLE` makes an authored family-scoped
39
+ option that the selected family does not consume observable instead of letting
40
+ it change request identity silently. CLI JSON results and local/hosted MCP
41
+ render results expose the same receipt. Use `validateSerializableRenderOptions(value)` and
42
+ `sharedRenderOptionsJsonSchema()` for untrusted advanced option objects, or
43
+ `styleInputJsonSchema()` for a standalone convenience `style` field; unknown
44
+ fields, `null`, functions, prototype keys, and non-finite values are rejected.
45
+ Graphical receipts name an explicitly selected pixel `textMeasurement` profile
46
+ (`id` and `version`). Trusted hosts can select custom metrics through the
47
+ renderer factories described below; their callback never enters a receipt.
48
+
49
+ ## PNG fonts, portability and rasterization
50
+
51
+ PNG rasterization uses offline `@resvg/resvg-js` with bundled fonts for
52
+ deterministic same-machine output: Inter (the default face — the same family
53
+ the SVG requests and the family `src/text-metrics.ts` is calibrated for, so
54
+ rasterized labels match their measured boxes), DejaVu Sans as a per-glyph
55
+ fallback for symbols Inter lacks, plus the faces the built-in styles
56
+ reference (Caveat, EB Garamond, Architects Daughter, Share Tech Mono — see
57
+ `assets/fonts/FONT-LICENSES.md`). A style whose `font` is neither bundled
58
+ nor supplied via `fontDirs` rasterizes with Inter. Characters no loaded font
59
+ covers (CJK, most emoji) draw as tofu boxes and raise a `PNG_FONT_COVERAGE`
60
+ warning naming the script and the escape hatches (`fontDirs` /
61
+ `loadSystemFonts`).
62
+
63
+ The raster-legibility gate measures literal absolute-pixel `font-size`
64
+ attributes on `text`, `tspan`, and `textPath` elements in the secured SVG.
65
+ This is exact for first-party built-in emitters. Extension SVG text is measured
66
+ only when the extension emits those literal attributes. The gate abstains when
67
+ CSS can override size or transforms, or when an SVG transform can change glyph
68
+ scale; translation and rotation are admitted because they preserve size. It
69
+ does not resolve extension-specific visibility, such as text templates under
70
+ `defs` or `display:none`, so such markup can conservatively over-report. The effective scale is
71
+ computed from the finalized integer raster height divided by the SVG `viewBox`
72
+ height, after projection rounding, because font sizes are expressed in user
73
+ units and the root is pinned with `preserveAspectRatio="none"`. For an extension
74
+ with no measurable literal size, absence of a
75
+ `BELOW_READABLE_SIZE` warning is therefore not proof that its labels are
76
+ readable. Callers that know the task, viewing distance, or display conditions
77
+ should select a task-specific floor rather than relying on the default.
78
+
79
+ The bytes-only browser convenience call returns only PNG bytes. Use
80
+ `renderMermaidPNGWithReceipt` on a bound browser renderer, or
81
+ `renderMermaidPNGInBrowserWithReceipt`, when the caller must inspect browser
82
+ diagnostics.
83
+
84
+ Note for third-party rasterizers: the SVG declares fonts as
85
+ `font-family: var(--font, 'Face')`, and static rasterizers (resvg, librsvg)
86
+ do not resolve CSS custom properties — `renderMermaidPNG` inlines the
87
+ resolved family before rasterizing; do the same if you feed the raw SVG to
88
+ your own pipeline.
89
+
90
+ For complete custom-Style recipes using `font`, `fontDirs`, browser faces, and
91
+ SVG font declarations, see [Fonts in custom styles](./custom-fonts.md).
92
+
93
+ PNG output declares the shared sRGB policy with `sRGB` and `cICP` metadata,
94
+ places `cICP` before image data, and deliberately emits no conflicting ICC
95
+ profile. SVG and PNG consume the same resolved graphical colors before
96
+ rasterization.
97
+
98
+ ### Trusted host-selected graphical backends
99
+
100
+ Executable Scene painting backends are bound by the host, never selected by `RenderOptions` or
101
+ serialized Style data. These factories apply the same canonical request,
102
+ Scene-admission, SVG-security, receipt, PNG-output-policy, and color-profile
103
+ contracts as their default counterparts:
104
+
105
+ ```ts
106
+ import {
107
+ createMermaidBrowserPNGRenderer,
108
+ createMermaidRenderer,
109
+ } from 'agentic-mermaid'
110
+ import { createMermaidPNGRenderer } from 'agentic-mermaid/agent'
111
+
112
+ const backendPolicy = { selectBackend: () => 'backend:acme/renderer' }
113
+ const svgRenderer = createMermaidRenderer({ backendPolicy })
114
+ const nodePngRenderer = createMermaidPNGRenderer({ backendPolicy })
115
+ const browserPngRenderer = createMermaidBrowserPNGRenderer({
116
+ backendPolicy,
117
+ rasterize: async (securedSvg, context) => ({
118
+ png: await rasterizeWithCanvas(securedSvg, context.outputPolicy),
119
+ }),
120
+ })
121
+ ```
122
+
123
+ Register and conformance-check the named backend before constructing these
124
+ renderers. The Node/Bun factory reuses the built-in `@resvg/resvg-js` adapter;
125
+ the browser factory wraps a trusted injected rasterizer, which receives only
126
+ the admitted and secured SVG plus the complete resolved portable output policy.
127
+ Its rasterizer must apply `fitTo` and `background`, not only `scale`.
128
+ `renderMermaidSVG`, `renderMermaidPNG`, and
129
+ `renderMermaidPNGInBrowserWithReceipt` remain the compatible default-backend
130
+ entry points.
131
+
132
+ ### Trusted host-selected pixel metrics
133
+
134
+ The same three factories accept `textMeasurement`, a named, versioned
135
+ `TextMeasurementProfile` with a synchronous `measure(input)` callback returning
136
+ the run's natural width in pixels. Inputs include displayed `text`,
137
+ `fontFamily`, `fontSize`, `fontWeight`, `fontStyle`, and `monospace`. Letter
138
+ spacing and wrapping remain the library's responsibility. The host supplies
139
+ the font measurement implementation and makes its fonts available to the
140
+ selected SVG/PNG consumer; no Canvas or system-font measurement is enabled
141
+ implicitly. See [custom fonts](./custom-fonts.md#trusted-font-measurement-profiles)
142
+ for an example and reproducibility requirements.
143
+
144
+ This is an in-process host option, separate from serializable `RenderOptions`,
145
+ Style data, Mermaid source, editor state, CLI, and MCP inputs. Bound renderers
146
+ capture the profile's name, version, and function once. Layout, prepared pixel
147
+ text, SVG advances, and both PNG adapters use those same metrics. Receipts
148
+ record its identity and include custom identity in request digests. Terminal
149
+ cell widths remain independent. Omitting the profile keeps the existing
150
+ deterministic Inter estimate, SVG output, and receipt shape unchanged.
151
+
152
+ ## SVG semantic identity and accessibility
153
+
154
+ All built-in families expose the same inspectable element contract:
155
+
156
+ - every Scene part with source-facing semantics has a deterministic `data-id` and closed
157
+ `data-role`; identity is unique within one SVG (layout furniture retains typed
158
+ Scene identity without bloating the DOM);
159
+ - source relations use `data-from` and `data-to`; source `className` tokens stay
160
+ on the identified element's `class` attribute;
161
+ - typed relations expose `role="graphics-symbol"`,
162
+ `aria-roledescription="relation"`, and an `aria-label` derived from endpoints
163
+ plus the authored relation label;
164
+ - public Scene types expose `SvgSemanticIdentity`,
165
+ `SvgSemanticAccessibility`, and `SvgRelationSemantics`;
166
+ - `idPrefix` rewrites local DOM `id` references, not source-facing `data-id`.
167
+
168
+ Built-in concrete palettes are contrast-normalized at render time: normal text
169
+ roles meet WCAG AA 4.5:1 and meaningful relation lines/markers meet 3:1 against
170
+ the page background. Unresolved runtime CSS variables cannot be statically
171
+ certified and pass through unchanged. See
172
+ [`svg-semantic-contract.md`](./svg-semantic-contract.md) for the complete contract.
173
+
174
+ For JSON files, use
175
+ [`docs/schemas/style-spec.schema.json`](./schemas/style-spec.schema.json). The
176
+ same schema is exported from the npm package as
177
+ `agentic-mermaid/style-spec.schema.json`; see
178
+ [`custom-style-cookbook.md`](./custom-style-cookbook.md) for complete style
179
+ files and screenshots, and [`custom-fonts.md`](./custom-fonts.md) for font
180
+ resolution across output surfaces.
181
+
182
+ ## Observe a native parser
183
+
184
+ The root library exports `withParserObservation(family, observer, parse)`. Wrap
185
+ one synchronous parser call to receive its actual consumed statements and
186
+ builder writes. Each event names its native kind, family and unit
187
+ (`statement`, `token` or `mutation`). Source coordinates explicitly distinguish
188
+ physical input from a parser's normalized view. Mutation operands are copied at
189
+ the call boundary, retaining identities, parent and membership fields.
190
+
191
+ ```ts
192
+ import { parseRegisteredMermaid, withParserObservation } from 'agentic-mermaid'
193
+
194
+ const observations: import('agentic-mermaid').ParserObservation[] = []
195
+ const result = withParserObservation(
196
+ 'flowchart',
197
+ event => observations.push(event),
198
+ () => parseRegisteredMermaid('flowchart LR\nA --> B'),
199
+ )
200
+ ```
201
+
202
+ Nested scopes restore their caller, including after an exception. An observer
203
+ callback does not implicitly observe a parser it invokes itself. Promise-returning
204
+ callbacks are rejected because the scope is synchronous. Observation is a
205
+ trusted in-process diagnostic API, outside serializable render options.
206
+
207
+ Native statement kinds and builder operations describe our implementations;
208
+ they are not Mermaid terminal kinds or its `yy` method protocol. Flowchart also
209
+ exposes consumed compound node/link fragments. Other native parsers expose
210
+ classified statements rather than a homologous token stream. The modern
211
+ assessment compares explicitly scoped semantic fields using independent
212
+ reference adapters and records unavailable comparisons honestly.
213
+
214
+ Flowchart/State positioned graphs also carry a `certification` receipt after
215
+ bounded final geometry checking. At most four deterministic candidates are
216
+ considered. Exhaustion throws `LayoutCertificationError` with code
217
+ `LAYOUT_CERTIFICATION_FAILED` and per-candidate reasons. This certifies hard graph
218
+ invariants, not an optimal layout. The common positioning boundary also vetoes
219
+ hard family-rubric violations in every native family's final projection.
220
+ Specialized family layouters get one attempt and fail explicitly; their checks
221
+ do not imply graph route guarantees or certify soft aesthetic quality.
222
+
223
+ The family registry is the operation authority. Use `am capabilities --json`
224
+ for the current roster and field schemas, or call `describeOps(family)` and
225
+ `opSignatures(family)` at runtime. The generated SDK declaration projects the
226
+ same descriptors; this reference deliberately does not copy an exhaustive
227
+ family/operation table.
228
+
229
+ ### Preserved Sequence and XY label facts
230
+
231
+ Sequence facts include recognized messages inside preserved segments as
232
+ `preserved-message#<segment>.<statement> ...` and their title directives.
233
+ These identifiers do not change the typed `message#<index>` mutation indexes.
234
+ XY facts include authored point labels as `series#<index> point#<index> : <label>`;
235
+ the point index stays aligned with the data even when labels are sparse.
236
+ Consumers using `exact: true` must add these facts to their reviewed expected
237
+ inventory. Subset checks can keep their existing required facts. Do not build
238
+ an expected inventory by copying the output being checked.
239
+
240
+ ### Class relation facts and `exact: true`
241
+
242
+ Class facts retain their existing class/member/relation lines and add endpoint
243
+ marker ownership and shaft style. A caller with a hardcoded complete fact set
244
+ must include these additions when using `exact: true`. For example:
245
+
246
+ ```ts
247
+ const parsed = parseRegisteredMermaid('classDiagram\nPerson --|> Animal')
248
+ if (!parsed.ok) throw new Error('Invalid Class source')
249
+
250
+ const legacy = [
251
+ 'class Animal',
252
+ 'class Person',
253
+ 'family class',
254
+ 'relation Person inheritance Animal',
255
+ 'relation#0 Person inheritance Animal',
256
+ ]
257
+ const expected = [
258
+ ...legacy,
259
+ 'relation#0 Person inheritance Animal marker to',
260
+ 'relation#0 Person inheritance Animal line solid',
261
+ ]
262
+ checkMermaid(parsed.value, { include: expected, exact: true }) // ok: true
263
+ ```
264
+
265
+ Using `legacy` alone returns `ok: false` and lists the two new lines in
266
+ `unexpected`. The expanded expectation also rejects `Person <|-- Animal`,
267
+ because that relationship has `marker from`. Two-ended relationships add
268
+ `relation#0 from marker <kind>` and `relation#0 to marker <kind>` facts so
269
+ different marker kinds at the two ends remain distinguishable. Keep reviewed
270
+ expectations independent of the output being checked; deriving them from that
271
+ same output would accept its mistakes. Subset checks omit `exact: true` and
272
+ must still require the marker/shaft facts whose preservation matters.
273
+
274
+ ### Authoring Class endpoint markers and shafts
275
+
276
+ Use `add_interface` to create a one-ended lollipop occurrence explicitly:
277
+
278
+ ```ts
279
+ const op = {
280
+ kind: 'add_interface', class: 'Service', label: 'Protocol',
281
+ side: 'to', relationLabel: 'provides', lineStyle: 'solid',
282
+ } as const
283
+ ```
284
+
285
+ Each operation creates a separate interface occurrence. Its `label` names the
286
+ interface; `relationLabel` names the connection. Ordinary classes with the same
287
+ spelling remain distinct. `add_relation` rejects one-ended lollipops between
288
+ ordinary class IDs and points callers to `add_interface`, since canonical
289
+ Mermaid source would otherwise change endpoint identity.
290
+
291
+ Class `add_relation` accepts optional `markerAt`, `fromKind`, `toKind` and
292
+ `lineStyle` fields. Existing calls that omit them retain the relation kind's
293
+ defaults. For example, this operation writes `Port ()..o Service`:
294
+
295
+ ```ts
296
+ const op = {
297
+ kind: 'add_relation', from: 'Port', to: 'Service',
298
+ relKind: 'lollipop', markerAt: 'both', toKind: 'aggregation',
299
+ lineStyle: 'dashed',
300
+ } as const
301
+ ```
302
+
303
+ `markerAt` selects the active endpoints; endpoint kinds on inactive sides are
304
+ refused. The primary `relKind`, endpoint kinds and shaft must agree with the
305
+ relationship read back from the emitted source. Contradictory combinations
306
+ return `INVALID_OP` instead of silently changing kind on reload. Cardinalities,
307
+ labels and authored endpoint identities already present in parsed relationships
308
+ survive unrelated edits. Relationship label/cardinality line breaks export as
309
+ Mermaid `<br/>` markup so they remain on one source line. Direct `add_class`
310
+ copies initial members; member
311
+ authoring refuses blank/comment-form text, accessibility directives and physical
312
+ or entity-decoded line breaks rather than admitting text that disappears or
313
+ changes structure. The source reader still accepts diagram accessibility
314
+ directives; they cannot be authored through a member operation.
315
+
316
+ Opaque fallback bodies (any unmodeled syntax) are source-level-only: edit source deliberately, then parse and verify again.
317
+
318
+ ## Capability and extension discovery
319
+
320
+ `am capabilities --json` reports the live family registry. (The Section A
321
+ capability report and its `createSectionACapabilityReport()` audit module are no
322
+ longer published.)
323
+
324
+ Canonical extension identities are kind-qualified (`look:`, `palette:`,
325
+ `backend:`, `family:`, `role:`, and `resource:`), versioned, provenance-bearing,
326
+ and collision-safe. New graphical backends declare feature/operation-level
327
+ Scene primitive capability claims; the registry rejects an empty, duplicate,
328
+ cross-target, or otherwise invalid claim set. Every external backend, and every
329
+ external family that supplies `lowerScene`, must also declare an explicit
330
+ compatible `identity.compatibility.scene` range (Scene v2: `^2.0.0`). The host
331
+ checks that range before running backend conformance or other executable
332
+ witnesses; only the internal built-in enrollment path receives compatibility
333
+ defaults.
334
+
335
+ ### Current customization and extension inventory
336
+
337
+ This is the current authoritative inventory. See the
338
+ [render-options table](./api.md#render-options) and
339
+ [StyleSpec reference](./style-authoring.md) for field details.
340
+
341
+ | Level | Public seam | What it can change | Boundary and availability |
342
+ |---|---|---|---|
343
+ | Mermaid-authored appearance | frontmatter/init config, theme variables, family style statements such as classes and link styles | Syntax-defined colors, labels, family geometry, and interaction metadata where the family advertises support | Source-level and family-dependent. Raw `themeCSS` is recognized but diagnosed at the render boundary because its selectors and markup can escape an imported SVG; use `StyleSpec` instead. |
344
+ | One-off render overrides | `RenderOptions` | Palette channels, font family, spacing/geometry controls, deterministic seed, security, accessibility-related output options, and a Style stack | The generated field×surface matrix marks each serializable shared field `forwarded`, `host-enforced`, or `unavailable`. Hosted SVG and editor SVG enforce strict security with external font imports disabled; effective receipts reflect those constraints. Host callbacks are library-only and never enter receipts. |
345
+ | One-off declarative style | inline `StyleSpec` or a left-to-right `StyleInput[]` stack | Safe palette, font, stroke/fill treatment, backdrop, exact semantic-role defaults, named semantic slots, V1 `category` bindings, non-color cues, and inspect-only contrast/accent-area/mono-role constraints | JSON-safe and executable-code-free. Bindings supply defaults beneath authored family paint and semantics; constraints diagnose final effective paint without repainting or relayout. This is the lowest-complexity custom Style path. |
346
+ | Named Palette/Look | `registerStyle`, `getStyle`, `knownStyleDescriptors` | Installs a versioned `palette:` or `look:` name backed by exactly the same `StyleSpec` accepted inline | Descriptors expose one `kind` (`look` or `palette`), explicit `isDefault`, and one stable `inputName`. In-process host registry. A CLI/MCP/server sees a registration only when that host installs it at startup. |
347
+ | Theme conversion | `fromShikiTheme` | Converts a Shiki-compatible editor theme into diagram colors | Pure library helper; the result is ordinary declarative color input. |
348
+ | Live host retheming | CSS custom-property values in graphical color/font inputs | Lets a host page switch SVG palette and font values without re-rendering | SVG/browser-only and limited to safe property values; this is not a raw CSS rule or selector hook. Static outputs need values resolved under their rasterization environment to remain reproducible. |
349
+ | Terminal output projection | `AsciiRenderOptions` (`useAscii`, `paddingX`, `paddingY`, `boxBorderPadding`, `colorMode`, `theme`, `targetWidth`/`maxWidth`, `onProjectionDiagnostic`) | Selects Unicode/ASCII encoding, cell spacing, width policy, ANSI/HTML colors, terminal-only theme overrides, and projection-loss reporting | Output-adapter customization, not a second shared Style system. Serializable fields have transport-specific availability; the diagnostic callback is host-only and remains outside receipts. |
350
+ | Fonts and installed resources | `font`, Node PNG `fontDirs`/`loadSystemFonts`/`onWarning`, browser `BrowserPngRasterizer`, `ResourceManifest`, and repository host tooling via `NodeResourceResolver` | Selects a safe font stack, supplies host-dependent raster fonts, reports missing glyph coverage, or verifies bounded installed bytes | Font family names do not install fonts. Browser and warning callbacks remain outside serializable options and every digest. Node `fontDirs`/`loadSystemFonts` are trusted host inputs outside shared `RenderOptions` and the shared/appearance digests, but their resolved PNG output policy is included in the output-specific request digest; runtime provenance still marks host-dependent resources explicitly. Manifests require path, size, media-type, digest, and licence evidence and never fall back to network access. |
351
+ | Graphical backend | `registerBackend`, `runBackendConformance`, `createMermaidRenderer`, `createMermaidPNGRenderer`, `createMermaidBrowserPNGRenderer` (each with a host-only `backendPolicy`) | Serializes the typed Scene contract with a different drawing implementation for SVG, native Node/Bun PNG, and injected-rasterizer browser PNG | Trusted in-process host only. Host registrations must explicitly declare compatible core and Scene ranges; identity/compatibility admission precedes executable conformance. Registration then must pass bounded, deterministic, semantic, well-formed, secure SVG conformance plus an exact witness for every first-party core Scene primitive/feature/operation claim; namespaced extension claims without a core witness remain explicitly unverified. All listed factories use the same admitted and secured graphical request; PNG adapters do not reparse or rerender source. Serializable styles and `RenderOptions` cannot select arbitrary executable backends. |
352
+ | Diagram family | `registerFamily`, `getFamilyConformanceReport`, `parseRegisteredMermaid`, `projectPositionedView` | Adds a namespaced language with detection, parse/preservation, verification, layout, Scene/SVG, terminal, and discovery claims | Every versioned `family:<owner/name>` descriptor declares a compatible core range and supplies one bounded canonical `example`. It also lists consumed family-scoped shared fields in `applicableRenderOptions`; omission means none, unknown or duplicate fields fail registration, and the frozen declaration appears in the capability report. Registration stages the frozen candidate, runs native claims twice through canonical parse/serialize, non-empty positive-bounds layout, strict SVG, portable PNG pre-raster, terminal, Scene and verify paths, and rolls back on failure, reentrancy or nondeterminism. Discovery reports `native` only beside a passed per-capability witness. Native tuples still require layout + `projectPositioned`, Scene requires layout + `lowerScene`, and extension verification requires its hook plus executable SVG. An external Scene family additionally declares a compatible Scene range, and its example witnesses every positive role/primitive cell. Built-in-only unions stay closed; extension bodies use the open envelope. Remote transports gain the family only when their trusted host installs it. |
353
+ | Scene semantics | `SceneDoc`, typed connectors/markers/hit geometry, namespaced `SceneRole` | Lets a family/backend exchange identity, relationship, accessibility, geometry, and terminal-projection intent | This is a versioned typed contract, not a raw SVG hook. Unknown namespaced roles deliberately receive inert identity-only traits and cannot acquire core behavior by local-name collision. There is no public arbitrary Scene primitive/trait mutation registry. |
354
+ | Browser PNG host adapter | `renderMermaidPNGInBrowserWithReceipt(..., rasterize)` or reusable `createMermaidBrowserPNGRenderer({ rasterize, backendPolicy? })` | Supplies Canvas/OffscreenCanvas rasterization and reports font provenance | Trusted callback receives only the admitted, secured canonical SVG; the library re-applies the PNG color-profile gate and retains the same logical receipt as the native PNG path. |
355
+ | Identity plumbing | `canonicalExtensionId`, `parseExtensionId`, `createExtensionIdentity`, `registerExtension`, `ExtensionCollisionError` | Gives kind-specific registries stable names, parsing, versions, provenance, compatibility ranges, and collision rejection | Low-level plumbing, not a stand-alone extension registry or rendering hook. Stable short inputs belong to kind-specific descriptors. |
356
+
357
+ There is currently no BrandPack registry, public role-trait registration,
358
+ arbitrary SVG/CSS hook, or Treatment hook. Semantic slots and the closed V1
359
+ `category` binding API are ordinary `StyleSpec` fields; other Scene channels are
360
+ not publicly bindable without new executable family witnesses. B4 remains the
361
+ unpromoted, evidence-gated BrandPack distribution envelope only. A future
362
+ Treatment seam is a separate decision and is not implied by B4.
363
+
364
+ ## Graph layout hints
365
+
366
+ Flowchart and State graphical renders accept explicit deterministic preferences:
367
+
368
+ ```ts
369
+ const options = {
370
+ layoutHints: {
371
+ ranks: { UI: 0, API: 1, Cache: 2, DB: 3 },
372
+ adjacent: [['Cache', 'DB']],
373
+ shortEdges: ['API->Cache'],
374
+ },
375
+ }
376
+ ```
377
+
378
+ Ranks are ordered ELK partitions, with unlisted nodes in partition zero; they
379
+ are not absolute pixel positions. Adjacency prefers consecutive sibling model
380
+ order within one container. Short-edge preferences use authored IDs or
381
+ `from->to` / `from->to#k` occurrence IDs. All references are checked; unknown
382
+ identities and conflicting adjacency groups fail explicitly. These preferences
383
+ never delete relationships, remain subject to geometry certification, and do not
384
+ guarantee a shortest route or fixed positions. Retain render options beside the
385
+ Mermaid source; hints participate in request digests, editor config, and receipts.