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
@@ -2,9 +2,9 @@
2
2
 
3
3
  `agentic-mermaid-mcp` defaults to stdio for local MCP clients. Use HTTP/SSE only when a client needs a reachable endpoint or when PNG artifacts should be fetched by file/URL instead of returned as large base64 strings.
4
4
 
5
- > Looking for a zero-setup endpoint? A **hosted** MCP already runs at `https://agentic-mermaid.dev/mcp` (`claude mcp add --transport http agentic-mermaid https://agentic-mermaid.dev/mcp`). It is a different implementation — stateless Streamable HTTP, Cloudflare-backed, tools `execute`/`describe_sdk`/`render_svg`/`render_ascii`/`render_png`/`verify`/`describe`/`mutate`/`build`, inputs capped at 64KB, and no file/URL PNG artifacts (base64 only). See the [as-built record](./project/archive/hosted-mcp-cloudflare-plan.md). Run the local server below when you need file/URL artifacts, larger inputs, offline use, or your own auth.
5
+ > Looking for a zero-setup endpoint? A **hosted** MCP already runs at `https://agentic-mermaid.dev/mcp` (`claude mcp add --transport http agentic-mermaid https://agentic-mermaid.dev/mcp`). It is a different implementation — stateless Streamable HTTP, Cloudflare-backed, inputs capped at 64KB, and no file/URL PNG artifacts (base64 only) — with the tools <!-- BEGIN GENERATED: hosted-mcp-tools -->`execute`, `describe_sdk`, `render_svg`, `render_ascii`, `render_png`, `verify`, `describe`, `mutate`, and `build`<!-- END GENERATED: hosted-mcp-tools -->. See the [as-built record](./project/archive/hosted-mcp-cloudflare-plan.md). Run the local server below when you need file/URL artifacts, larger inputs, offline use, or your own auth.
6
6
  >
7
- > **Protocol versions.** The hosted endpoint is dual-era: it serves the handshake-based revisions `2024-11-05`, `2025-03-26`, `2025-06-18`, and `2025-11-25`, and the stateless `2026-07-28` revision that replaces the `initialize` handshake with per-request `_meta` and a mandatory `server/discover`. Clients need do nothing special — send whatever revision you speak in `MCP-Protocol-Version`, and an unsupported one comes back as `-32022` listing the versions we accept. One precision worth stating: `2024-11-05` here is protocol-*version* support only. A client using the 2024-11-05-era HTTP+SSE *transport* (opening with `GET` and expecting an `endpoint` event) receives 405 and cannot connect; that entry exists for Streamable HTTP clients that negotiate the older protocol version. The local server below still pins `2024-11-05`, matching its own SSE transport.
7
+ > **Protocol versions.** The hosted endpoint is dual-era: it accepts <!-- BEGIN GENERATED: hosted-protocol-versions -->`2025-03-26`, `2025-06-18`, `2025-11-25`, and `2026-07-28`<!-- END GENERATED: hosted-protocol-versions -->. Every revision before `2026-07-28` is handshake-based; `2026-07-28` is the stateless revision that replaces the `initialize` handshake with per-request `_meta` and a mandatory `server/discover`. Clients need do nothing special — send whatever revision you speak in `MCP-Protocol-Version`, and an unsupported one comes back as `-32022` listing the versions we accept. The hosted endpoint does not accept `2024-11-05`: that revision is the HTTP+SSE *transport* (opening with `GET` and expecting an `endpoint` event), and a client using it receives 405. The local server below accepts <!-- BEGIN GENERATED: stdio-protocol-versions -->`2024-11-05`, `2025-06-18`, `2025-11-25`, and `2026-07-28`<!-- END GENERATED: stdio-protocol-versions --> over stdio and <!-- BEGIN GENERATED: http-sse-protocol-versions -->`2024-11-05`<!-- END GENERATED: http-sse-protocol-versions --> over its HTTP+SSE transport.
8
8
  >
9
9
  > **Privacy and caching:** every hosted call (`execute`, `render_*`, `verify`, `describe`, `mutate`, `build`) sends your diagram source or code to the agentic-mermaid.dev server. Successful deterministic pure-tool results may be reused by a private server-side Workers Cache for up to 24 hours; `execute`, `mutate`, and `build` bypass it. The JSON-RPC HTTP response itself is always `cache-control: no-store`; `x-agentic-mermaid-compute-cache` reports `hit`, `miss`, `mixed`, `bypass`, or `disabled`. For diagrams that must not leave your machine, use the library, the CLI, or the local stdio/HTTP server on this page — the pipeline is fully local and needs no network.
10
10
 
@@ -24,14 +24,14 @@ The local `/sse` + `/message` pair is the MCP SSE session transport: `POST /mess
24
24
  Loopback/local development:
25
25
 
26
26
  ```sh
27
- npx -y agentic-mermaid-mcp --transport http --host 127.0.0.1 --port 3000 \
27
+ npx -y agentic-mermaid mcp --transport http --host 127.0.0.1 --port 3000 \
28
28
  --artifact-dir .agentic-mermaid-artifacts
29
29
  ```
30
30
 
31
31
  Remote binding requires a bearer token:
32
32
 
33
33
  ```sh
34
- npx -y agentic-mermaid-mcp --transport http --host 0.0.0.0 --port 3000 \
34
+ npx -y agentic-mermaid mcp --transport http --host 0.0.0.0 --port 3000 \
35
35
  --artifact-dir .agentic-mermaid-artifacts \
36
36
  --auth-token "$AGENTIC_MERMAID_MCP_TOKEN"
37
37
  ```
@@ -88,7 +88,7 @@ Response shape:
88
88
  "content": [
89
89
  {
90
90
  "type": "text",
91
- "text": "{\"ok\":true,\"png_base64\":\"iVBORw0KGgo...\",\"warnings\":[]}"
91
+ "text": "{\"ok\":true,\"png_base64\":\"iVBORw0KGgo…\",\"receipt\":{\"version\":2,\"output\":\"png\",…},\"runtime\":{\"engine\":\"resvg\",\"binding\":\"napi\",…},\"warnings\":[]}"
92
92
  }
93
93
  ],
94
94
  "isError": false
@@ -96,7 +96,7 @@ Response shape:
96
96
  }
97
97
  ```
98
98
 
99
- `warnings` always appears. `PNG_FONT_COVERAGE` names missing CJK/emoji coverage and points to `fontDirs`/`loadSystemFonts`; source configuration diagnostics use the same deterministic warning envelope.
99
+ `receipt` is the render request receipt (request/appearance digests plus the capability and execution decisions) and `runtime` records rasterizer provenance (engine, binding, font sources, reproducibility); both are also present on file and URL responses. `warnings` always appears. `PNG_FONT_COVERAGE` names missing CJK/emoji coverage and points to `fontDirs`/`loadSystemFonts`; source configuration diagnostics use the same deterministic warning envelope.
100
100
 
101
101
  ### File output
102
102
 
@@ -127,7 +127,10 @@ Response shape (`content[0].text` is JSON):
127
127
  "mimeType": "image/png",
128
128
  "bytes": 12345,
129
129
  "sha256": "64 lowercase hex characters"
130
- }
130
+ },
131
+ "receipt": { "version": 2, "output": "png", … },
132
+ "runtime": { "engine": "resvg", "binding": "napi", … },
133
+ "warnings": []
131
134
  }
132
135
  ```
133
136
 
@@ -162,7 +165,10 @@ Response shape (`content[0].text` is JSON):
162
165
  "mimeType": "image/png",
163
166
  "bytes": 12345,
164
167
  "sha256": "64 lowercase hex characters"
165
- }
168
+ },
169
+ "receipt": { "version": 2, "output": "png", … },
170
+ "runtime": { "engine": "resvg", "binding": "napi", … },
171
+ "warnings": []
166
172
  }
167
173
  ```
168
174
 
package/docs/quality.md CHANGED
@@ -2,37 +2,42 @@
2
2
 
3
3
  A diagram is considered **good looking** when it satisfies, in order:
4
4
 
5
- 1. **All Tier 1 structural checks pass.** No `EMPTY_DIAGRAM`, no
6
- `EDGE_MISANCHORED`, no `OFF_CANVAS`, no `GROUP_BREACH`, no
7
- `UNKNOWN_SHAPE`, no `LABEL_OVERFLOW` (default cap: 40 chars).
8
- This is non-negotiable — fix the source before judging visuals.
5
+ 1. **All Tier 1 structural checks pass.** None of
6
+ <!-- BEGIN GENERATED: warning-codes:structural -->`EMPTY_DIAGRAM`, `EDGE_MISANCHORED`, `OFF_CANVAS`, `GROUP_BREACH`, `UNKNOWN_SHAPE`, `LABEL_OVERFLOW`, `UNRESOLVABLE_SCHEDULE`, `RENDER_FAILED`, `INTERNAL_ERROR`<!-- END GENERATED: warning-codes:structural -->
7
+ fires (`LABEL_OVERFLOW` default cap: 40 chars).
8
+ Resolve the reported structural or rendering failure before judging aesthetics.
9
9
 
10
10
  2. **Tier 2 geometric checks are within bounds.** `NODE_OVERLAP` count
11
11
  and `ROUTE_SELF_CROSS` count are advisory but not catastrophic. A
12
12
  diagram with a single intentional overlap (e.g., a self-loop) is
13
13
  still considered good. The `ROUTE_*` codes (`ROUTE_HITCH`,
14
14
  `ROUTE_UNEXPLAINED_BEND`, `ROUTE_LABEL_ON_SHARED_TRUNK`,
15
- `ROUTE_CONTAINER_MISANCHOR`, `ROUTE_SHAPE_MISANCHOR`,
15
+ `ROUTE_SELF_LOOP_OCCUPANCY`, `ROUTE_CONTAINER_MISANCHOR`, `ROUTE_SHAPE_MISANCHOR`,
16
16
  `ROUTE_STALE_AFTER_NODE_MOVE`) should always be zero — they are
17
17
  route-contract tripwires (see `docs/design/system/route-contracts.md`), and
18
18
  any hit means the layout pipeline regressed, not the diagram.
19
+ <!-- complete: warning-codes:geometric -->
19
20
 
20
21
  3. **Perceptual metrics fall in the default `QualityBounds` band:**
21
22
 
22
23
  | metric | meaning | default |
23
24
  |---|---|---|
24
- | `edgeCrossings` | pairs of edge segments that visually intersect | ≤ 5% of edge pairs |
25
- | `labelLegibility` | fraction of node labels whose rendered length fits the node width | ≥ 85% |
25
+ | `edgeCrossings` | visible proper crossing incidences per logical edge pair and location | ≤ 5% of visible edge pairs |
26
+ | `labelLegibility` | fraction of measured visible labels whose retained text bounds fit their actual containing region | ≥ 85% |
26
27
  | `whitespaceBalance` | node area ÷ canvas area | 5%–55% (too sparse AND too dense lose) |
27
28
  | `labelEdgeProximity` | min pixel distance between any edge-label box and a non-attached node, another edge-label box, or another edge path (graph families; cross-family label/box occlusion is gated by `eval/overlap-audit` + `label-overlap-gate.test.ts`) | ≥ 4 px |
28
- | `minimumNodeSpacing` | nearest gap between semantically distinct node/mark boxes; XY and Radar same-coordinate series adjacency/overlays are excluded | ≥ 8 px |
29
+ | `labelConflicts` | counts of padded graph label pills intersecting another label, a node, or another visible route; reported for Flowchart and State | minimize after crossings in candidate selection; no default quality bound |
30
+ | `routeOverlaps` | Flowchart/State edge pairs sharing opposing-direction ink or same-endpoint parallel ink (parallel excludes self-loops) | reported separately from crossings; no default quality bound |
31
+ | `minimumNodeSpacing` | nearest gap between semantically distinct node/mark boxes; authored coincident Quadrant points and XY/Radar data overlays are excluded | ≥ 8 px |
29
32
  | `elementDensity` | nodes + edges per 10,000 canvas pixels | 0.02–6 |
30
33
  | `minimumTextContrast` | WCAG contrast ratio between foreground and supplied background/surface colors; `null` when a requested paint cannot be resolved | ≥ 4.5:1 |
31
34
  | `aspectRatio` | canvas w/h | 0.2–5.0 |
32
35
 
33
- These are computed by `measureQuality(layout)` and gated by
34
- `checkQuality(layout)`. They are **deterministic** and cheap — they
35
- run on every PR.
36
+ These are computed by `measureQuality(layout)`; `checkQuality(layout)` applies
37
+ the configured bounds. `labelConflicts` is reported without a quality-bound
38
+ threshold, as is `routeOverlaps`. A low crossing count cannot establish
39
+ readability when routes instead share ambiguous collinear ink. These
40
+ measurements are **deterministic** and run on every PR.
36
41
 
37
42
  4. **LLM-as-judge median ≥ 4.0** on the configured stratified sample of the
38
43
  Mermaid-docs corpus across three axes. Since QUAL-1, perceptual metrics and
@@ -45,6 +50,123 @@ A diagram is considered **good looking** when it satisfies, in order:
45
50
  supports pre-release sign-off when explicitly run. See
46
51
  `eval/llm-judge/judge.ts`.
47
52
 
53
+ ## Layout priorities and their limits
54
+
55
+ Authored meaning and deterministic execution constrain every aesthetic choice:
56
+ identities, endpoint markers, membership, labels and operation order must survive.
57
+ An authored data coordinate is meaning, so separating coincident chart points to
58
+ improve a spacing score is wrong. Resource admission also happens before layout;
59
+ a work-limit refusal is not a poor aesthetic score.
60
+
61
+ For automatic graph layout, apply the following order:
62
+
63
+ 1. **Feasibility and readable ownership:** finite in-bounds geometry, containment,
64
+ non-overlapping graph nodes, endpoints on the rendered outline, routes that
65
+ avoid unrelated nodes, and labels associated with their own route. Among
66
+ feasible candidates, prefer readable group titles.
67
+ 2. **Crossings, then soft label conflicts:** reduce crossings within the feasible
68
+ set. When crossing counts tie, prefer fewer padded label-conflict pairs.
69
+ These counts keep distinguishing layouts after minimum clearance reaches zero,
70
+ but reducing a soft overlap count cannot buy additional crossings. Hard
71
+ node-avoidance and own-label-association requirements still apply first.
72
+ 3. **Continuity and unnecessary bends:** prefer clear direct lanes; distinguish
73
+ unexplained detours from declared symmetric convergence.
74
+ 4. **Canonical ports:** prefer side midpoints or declared slots. An endpoint on
75
+ the correct outline is mandatory; the preferred point on that outline is a
76
+ softer choice and can yield to a simpler safe route.
77
+ 5. **Symmetry and alignment:** improve balance without silently trading away
78
+ higher-priority constraints. Bundle-owned convergence is an explicit route
79
+ policy, with justified bends excluded from the avoidable-bend metric.
80
+ 6. **Compactness, fill and aspect ratio:** use these as family-aware heuristics.
81
+ A data plot with sparse authored coordinates must not fail a graph box-fill
82
+ default; explicit caller bounds still apply.
83
+
84
+ This is a policy order, not a claim that the current heuristic pipeline solves a
85
+ global lexicographic optimum. Several older contracts pull in different
86
+ directions:
87
+
88
+ - Verification treats some overlap warnings as advisory, while the graph rubric
89
+ treats node overlap as hard. Graph final certification uses the stricter graph
90
+ contract; specialized plots need semantic overlap rules rather than a blanket
91
+ node-box rule.
92
+ - Cosmetic straightening and tightening must preserve crossings. Repairs of hard
93
+ node avoidance or own-label association may need a crossing; their conditional
94
+ pass budgets require a measured higher-priority repair. A padded label-conflict
95
+ count is a separate soft preference, not an additional hard feasibility gate.
96
+ - Symmetric fan-in can add geometric bends. The route classifier explains those
97
+ bends as convergence. This is a declared exception, not evidence that raw bend
98
+ count always decreases.
99
+ - Equalizing node dimensions can temporarily move centers before alignment
100
+ passes. Its old per-pass promise to improve symmetry was false and has been
101
+ removed. Preparation and final aesthetic claims are different obligations.
102
+ - A character-count `LABEL_OVERFLOW` guard does not measure rendered fit. Retained
103
+ prepared text and final containing bounds supply that evidence; missing
104
+ measurements produce an explicit quality warning.
105
+
106
+ The pass runner enforces declared before/after metric budgets in production,
107
+ including conditional allowances. Ordering, budgets and post-freeze contracts
108
+ always apply; there is no audit flag that disables them. A duplicate-lane proposal may introduce at
109
+ most one crossing per actual shared duplicate route pair it separates; unrelated
110
+ bucket improvements cannot pay for that proposal. Preferred endpoint spacing or
111
+ fewer bends alone cannot buy a crossing. Canonical ports may yield when the
112
+ certifying route owner measurably repairs hard geometry, reduces crossings or
113
+ removes bends.
114
+ The graph engine independently certifies the
115
+ final candidate before returning it, with at most four deterministic placement candidates
116
+ and an explicit `LAYOUT_CERTIFICATION_FAILED` error on exhaustion. This certifies
117
+ hard graph geometry, not minimum crossings or universal aesthetic quality.
118
+ Within 64 nodes/groups and 128 edges, a certified graph with crossings or label
119
+ conflicts may try one additional distinct strategy. Feasible candidates compare
120
+ readable group titles, crossings, label-conflict pairs, avoidable bends,
121
+ canonical endpoints, symmetry and area in that order.
122
+
123
+ The engine first chooses a certified bundled placement using those existing
124
+ strategies. Only the selected placement may then compare one completed generic
125
+ unbundled route proposal, using the same ELK result and the same preference
126
+ order. The decision to try this proposal reuses the selected placement's existing
127
+ certification score, including the final comparison: unchanged selected geometry
128
+ is not certified a second time. It does not explore an unbundled version of
129
+ every placement strategy.
130
+ Symmetric fan-in/fan-out routing remains enabled.
131
+ Graphs containing parallel edges keep their specialized route owners and skip
132
+ the generic unbundled proposal. A smaller proper-crossing count alone does not
133
+ prove that duplicate endpoint lanes remain visibly distinct.
134
+
135
+ The receipt's `preference.compared` entries retain the certified bundled
136
+ placement scores. `preference.selectedScore` describes the actual final routes,
137
+ and `preference.routing` records the selected placement's bundled/unbundled
138
+ comparison, scores and deciding criterion.
139
+ The receipt's `attempts` counts placement productions; the optional final route
140
+ comparison is recorded separately.
141
+ Clean graphs, equivalent strategies and larger inputs skip these comparisons;
142
+ the upper bound is four placement pipelines plus one unbundled route pipeline,
143
+ with the existing maximum of 16 ELK attempts. The unbundled proposal reuses the
144
+ selected placement's ELK result. Search decisions use graph
145
+ work counts, never elapsed time, so machine speed cannot change the drawing.
146
+ These route comparisons apply to Flowchart and State, which retain the scored
147
+ routes. Architecture uses the graph engine for placement and keeps its existing
148
+ feasibility/title fallback before independently routing authored endpoint sides.
149
+ The common positioning boundary also checks the final projection of every
150
+ native family against the family rubric's hard geometry rules. Specialized
151
+ layouters get one attempt and fail explicitly; their identical layout is not
152
+ repeated as a pretend fallback. Verification and quality reuse that retained
153
+ projection rather than positioning or projecting the artifact again.
154
+
155
+ Route proposals, final ranking, pass budgets and public quality share the crossing predicate in
156
+ `src/shared/edge-crossings.ts`. It excludes invisible shafts, endpoint contacts,
157
+ tangencies and shared collinear ink. It counts each crossing location once per
158
+ logical edge pair, including crossings far from a shared graph endpoint; route
159
+ subdivision does not change the count. Endpoint tolerance is 0.01 physical
160
+ pixels, independent of segment length. Public graph nodes, groups, paths, label
161
+ anchors and canvas bounds retain subpixel coordinates so projection cannot erase
162
+ this evidence or introduce a containment error.
163
+ Invisible links may still have visible labels: those pills remain obstacles.
164
+ Label-conflict counts share one implementation and the renderer's eight-pixel
165
+ pill padding. A bundle certificate or matching text does not authorize two
166
+ distinct labels to occupy the same space.
167
+ Label/node conflicts use conservative node bounding rectangles; hard route/node
168
+ avoidance retains its separate shape-aware contract.
169
+
48
170
  ## The rubric (used by both the LLM judge and the perceptual checker)
49
171
 
50
172
  ```
@@ -113,9 +235,10 @@ geometry assertions, screenshot/PNG review, or human inspection.
113
235
  (not bytes-only) for each. The adapters parse `d.canonicalSource` via the
114
236
  legacy per-family parser + layouter — the same geometry the SVG renderer draws
115
237
  — so an opaque-but-renderable body is still measured; an invalid opaque body
116
- degrades to an empty layout instead of throwing. What `nodes` / `edges` /
238
+ fails explicitly with `FamilyLayoutError`; verification reports the failure. What `nodes` / `edges` /
117
239
  `groups` mean per family:
118
240
 
241
+ <!-- complete: family-ids -->
119
242
  | Family | nodes | edges | groups |
120
243
  |---------------|------------------------------------|--------------|----------------------|
121
244
  | flowchart | graph nodes (ELK) | graph edges | subgraphs |
@@ -133,12 +256,19 @@ geometry assertions, screenshot/PNG review, or human inspection.
133
256
  | mindmap | hierarchy nodes | parent links | — |
134
257
  | gitgraph | commits | parent links | — |
135
258
  | radar | curve vertices (one ring per axis) | — | axis spokes/grid |
259
+ | sankey | node rectangles | ribbon links (from/to) | — |
136
260
 
137
261
  Families with no structural relations (pie/quadrant/xychart/journey/gantt/radar) carry an
138
262
  honestly-empty `edges` array. Bounds is the family layout's canvas size.
139
- - **No font-substitution check.** Different OSes render different
140
- default fonts. Our `labelLegibility` heuristic uses a 7 px-per-char
141
- approximation; under condensed fonts it under-estimates fit.
263
+ - **No font-substitution check.** Quality checks consume retained prepared pixel
264
+ text and renderer anchors; they do not guess width from character count.
265
+ `labelMeasurement` reports measured, unmeasured, hidden and semantic-only
266
+ labels, and missing visible-label evidence makes `checkQuality` warn. Painted
267
+ text in `layout.labels` participates without changing semantic node counts;
268
+ XYChart retains its point text and chart chrome there. Final canvas and
269
+ readability checks consume those retained bounds. A trusted
270
+ host measurement profile can improve pixel metrics, but neither that profile
271
+ nor a prepared block proves which font the display ultimately substituted.
142
272
  - **Contrast needs resolved paints.** `measureQuality(layout)` scores the crisp
143
273
  default palette. For a custom style, pass `{ foreground, background,
144
274
  surfaces }` as its second argument, or pass the actual rendered text/surface
package/docs/react.md CHANGED
@@ -1,29 +1,75 @@
1
1
  # React integration
2
2
 
3
- Agentic Mermaid renders synchronously to SVG strings, so React apps do not need iframe renderers, hidden browser sessions, or client-side Mermaid hydration.
3
+ Browser-rendered React components should use the browser ESM entry. It loads the
4
+ selected diagram family on demand and does not pull the Node/native package
5
+ entry into a client bundle.
4
6
 
5
7
  ## Basic component
6
8
 
7
9
  ```tsx
8
- import { useMemo } from 'react'
9
- import { renderMermaidSVG } from 'agentic-mermaid'
10
+ 'use client'
10
11
 
11
- export function MermaidDiagram({ source }: { source: string }) {
12
- const svg = useMemo(
13
- () => renderMermaidSVG(source, { security: 'strict' }),
14
- [source],
15
- )
12
+ import { useEffect, useId, useRef, useState } from 'react'
13
+ import { renderMermaidSVGAsync } from 'agentic-mermaid/browser/lazy'
16
14
 
17
- return <div className="diagram" dangerouslySetInnerHTML={{ __html: svg }} />
15
+ export function MermaidDiagram({ source }: { source: string }) {
16
+ const output = useRef<HTMLDivElement>(null)
17
+ const idPrefix = `diagram-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}`
18
+ const [loading, setLoading] = useState(true)
19
+ const [error, setError] = useState('')
20
+
21
+ useEffect(() => {
22
+ let current = true
23
+ const host = output.current
24
+ if (!host) return
25
+ host.replaceChildren()
26
+ setLoading(true)
27
+ setError('')
28
+ renderMermaidSVGAsync(source, { security: 'strict', idPrefix }).then(
29
+ result => {
30
+ if (!current) return
31
+ const parsed = new DOMParser().parseFromString(result, 'image/svg+xml')
32
+ if (parsed.querySelector('parsererror') || parsed.documentElement.localName !== 'svg') {
33
+ setError('Renderer returned invalid SVG')
34
+ setLoading(false)
35
+ return
36
+ }
37
+ host.replaceChildren(document.importNode(parsed.documentElement, true))
38
+ setLoading(false)
39
+ setError('')
40
+ },
41
+ ).catch(cause => {
42
+ if (!current) return
43
+ setError(cause instanceof Error ? cause.message : String(cause))
44
+ setLoading(false)
45
+ })
46
+ return () => { current = false }
47
+ }, [source, idPrefix])
48
+
49
+ return <>
50
+ {error && <pre role="alert">{error}</pre>}
51
+ <div ref={output} className="diagram diagram-surface" aria-busy={loading} />
52
+ </>
18
53
  }
19
54
  ```
20
55
 
21
- `security: 'strict'` removes external-fetch references and is the safest default for user- or agent-generated diagrams.
56
+ `security: 'strict'` removes external-fetch references and is the safest default
57
+ for user- or agent-generated diagrams. The cancellation guard prevents an older
58
+ render from replacing a newer source after it resolves. The per-component
59
+ `idPrefix` prevents collisions between SVG definitions in multiple diagrams.
60
+ Insert only this renderer's strict output, not arbitrary SVG: XML parsing is
61
+ not sanitization. Rendering policy and the host's DOM/CSP policy remain separate.
62
+
63
+ This basic recipe assumes the host does not enforce Trusted Types. With
64
+ `require-trusted-types-for 'script'`, `DOMParser.parseFromString` is also a
65
+ protected sink: adapt insertion through the application's reviewed,
66
+ narrowly scoped TrustedHTML policy. Do not add a permissive default policy or
67
+ disable CSP to make the example work. See [`browser.md`](./browser.md).
22
68
 
23
69
  ## Theme from CSS variables
24
70
 
25
71
  ```tsx
26
- const svg = renderMermaidSVG(source, {
72
+ const svg = await renderMermaidSVGAsync(source, {
27
73
  bg: 'var(--diagram-bg)',
28
74
  fg: 'var(--diagram-fg)',
29
75
  accent: 'var(--diagram-accent)',
@@ -55,7 +101,7 @@ Because the SVG keeps CSS variables in place, toggling `.dark` updates existing
55
101
 
56
102
  ## PNG export button
57
103
 
58
- PNG rendering returns bytes. In browser-oriented React apps, call the PNG helper from a server action/API route or other Node-capable boundary where `@resvg/resvg-js` is available.
104
+ PNG rendering returns bytes. The native helper below needs a server action/API route or other Node-capable boundary where `@resvg/resvg-js` is available.
59
105
 
60
106
  ```ts
61
107
  import { renderMermaidPNG } from 'agentic-mermaid/agent'
@@ -65,31 +111,30 @@ export function renderDiagramPng(source: string) {
65
111
  }
66
112
  ```
67
113
 
68
- For client-only exports, use the live editor/browser's existing download path or post the source to a server endpoint.
114
+ For client-only exports, the root `agentic-mermaid` entry also exports a
115
+ host-injected browser PNG path: `renderMermaidPNGInBrowserWithReceipt(source,
116
+ options, output, rasterize)` or the reusable
117
+ `createMermaidBrowserPNGRenderer({ rasterize })`. No browser rasterizer ships
118
+ with the library: the host supplies `rasterize(securedSvg, context)` (for
119
+ example with Canvas/OffscreenCanvas), which must resolve to `{ png }` bytes at
120
+ exactly `context.rasterDimensions` on `context.rasterBackground`, and may report
121
+ `fontSources` and `diagnostics`. See [browser PNG details](./api-advanced.md#png-fonts-portability-and-rasterization). Otherwise, post
122
+ the source to a server endpoint.
69
123
 
70
124
  ## Error handling
71
125
 
72
- For untrusted source, parse or verify before rendering:
73
-
74
- ```tsx
75
- import { parseRegisteredMermaid, verifyMermaid, renderMermaidSVG } from 'agentic-mermaid/agent'
76
-
77
- export function SafeDiagram({ source }: { source: string }) {
78
- const result = useMemo(() => {
79
- const parsed = parseRegisteredMermaid(source)
80
- if (!parsed.ok) return { ok: false, message: parsed.error.map(e => e.message).join('\n') }
126
+ The component above reports parse and render failures through its `role="alert"`
127
+ fallback. If a client workflow also needs structured parse/verify results, use
128
+ the runtime-neutral agent entry; do not import the Node/native
129
+ `agentic-mermaid/agent` entry into the browser bundle:
81
130
 
82
- const verify = verifyMermaid(parsed.value)
83
- if (!verify.ok) return { ok: false, message: verify.warnings.map(w => w.code).join(', ') }
84
-
85
- return { ok: true, svg: renderMermaidSVG(parsed.value, { security: 'strict' }) }
86
- }, [source])
87
-
88
- if (!result.ok) return <pre>{result.message}</pre>
89
- return <div dangerouslySetInnerHTML={{ __html: result.svg }} />
90
- }
131
+ ```ts
132
+ import { parseRegisteredMermaid, verifyMermaid } from 'agentic-mermaid/agent/core'
91
133
  ```
92
134
 
135
+ For server components, build steps, and API routes, the synchronous
136
+ `renderMermaidSVG` export from `agentic-mermaid` remains appropriate.
137
+
93
138
  ## See also
94
139
 
95
140
  - [`api.md`](./api.md) for render options.
@@ -98,6 +98,19 @@ not-applicable evidence; they never repaint or relayout. Transparent output has
98
98
  no known host backdrop, so contrast reports unmeasurable rather than inventing
99
99
  a ratio.
100
100
 
101
+ Treemap retains explicit Scene text ink when deriving automatic category fills. Its
102
+ shared palette chooses readable, page-visible and distinguishable colors
103
+ together, before brand constraints inspect the Scene. Sketch labels that already
104
+ read on the selected backend's page-colored halo do not constrain the cell fill.
105
+ The actual graphical backend includes host overrides; layout models its nominal
106
+ Style backend. Authored fills stay exact.
107
+ The shared sketch backend still applies its existing page-halo readability
108
+ policy to ink that does not read on that page.
109
+ If bounded search cannot satisfy concrete ink/page choices, choose another text
110
+ color or an explicit readable fill; the renderer reports that configuration
111
+ limit. Unresolved and translucent inks retain their authored values without a
112
+ contrast guarantee.
113
+
101
114
  ### Export and edit a built-in
102
115
 
103
116
  Built-ins dogfood this same record format. Export one with `getStyle`, validate
@@ -130,11 +143,8 @@ BrandPack registry is deliberately **not promoted**. Render-time semver ranges,
130
143
  dependency solving, ambient resource loading, and a second inheritance system
131
144
  remain absent.
132
145
 
133
- The generated [Section B capability report](./project/section-b-capability-report.md)
134
- accounts for every role leaf, private-face projection, role fallback, admitted
135
- family role/channel, and built-in export.
136
- The [all-family evidence sheet](./design/families/section-b-brand-evidence.png)
137
- shows one deliberately distinctive sentinel plus three holdout styles; its receipt
146
+ The [reviewed all-family rendering golden](../src/__tests__/testdata/section-b-brand-evidence.png)
147
+ shows one deliberately distinctive sentinel plus three holdout styles; its review record
138
148
  and honest hard-error baseline live in `eval/section-b-brand-evidence/`.
139
149
 
140
150
  Every field is optional in a reusable fragment, but the resolved final stack
@@ -162,7 +172,7 @@ accepted as a Style name.
162
172
  sets via `RenderOptions` colors or Mermaid `themeVariables` wins. The full
163
173
  precedence is one line: `defaults < style stack (left→right) <
164
174
  themeVariables < explicit color options`.
165
- - **Determinism.** All stochastic marks are seeded
175
+ - **Determinism.** All stochastic artwork is seeded
166
176
  `hash(options.seed, stableNodeId, substream)`. Source, resolved options,
167
177
  frozen registry/capability/resource snapshots, runtime contract and seed fix
168
178
  the bytes. `seed` re-rolls wobble without moving layout. Opt-in caller or
@@ -241,12 +251,14 @@ layout-aware dialect) justifies code. Trusted hosts can implement and register
241
251
  a namespaced `StyleBackend`; selection is an in-process `HostBackendPolicy`,
242
252
  not serializable Style data or a CLI/MCP/editor field. Keep the determinism rule
243
253
  (seed in, bytes out). Backends never dispatch on diagram family — they see
244
- semantic scene marks and paint channels. A registered backend also declares
254
+ semantic Scene parts and paint channels. Existing `SceneNode` and `*Mark` type
255
+ names refer to those parts; see the [shared vocabulary](./api.md#vocabulary).
256
+ A registered backend also declares
245
257
  feature/operation-level `PrimitiveCapabilityClaim`s for every core Scene
246
258
  primitive; registration rejects empty, duplicate, or cross-target claims so an
247
259
  extension cannot imply support it has not described. Registration then executes
248
260
  a frozen document fixture plus one exact witness for each declared first-party
249
- core primitive/feature/operation claim. It rejects a backend that varies
261
+ core Scene primitive/feature/operation claim. It rejects a backend that varies
250
262
  identical `drawNode`/`render` calls, emits unsafe or malformed SVG, drops the
251
263
  document sentinels, or fails any claim-keyed witness. Namespaced extension claims
252
264
  with no core witness remain explicitly `unverified-extension`.
@@ -260,7 +272,7 @@ contract explicitly; no built-in compatibility default is borrowed by
260
272
  ```ts
261
273
  registerBackend(backend, {
262
274
  version: '1.0.0',
263
- compatibility: { core: '^0.4.0', scene: '^2.0.0' },
275
+ compatibility: { core: '^0.5.0', scene: '^2.0.0' },
264
276
  provenance: { owner: 'acme-diagrams', source: 'application-startup' },
265
277
  })
266
278
  ```
@@ -330,7 +342,7 @@ bun test src/__tests__/styled-output.test.ts --timeout 30000 # determinism + g
330
342
  bun test src/__tests__/scene-fidelity.test.ts # semantic/backend agreement
331
343
  ```
332
344
 
333
- Then render your style across every registered diagram type and *look at it small*
334
- — the poster/contact-sheet harness in `scripts/sketch-prototype/` is the
345
+ Then render your style across every registered diagram family and *look at it small*
346
+ — the optional research poster/contact-sheet harness in `scripts/sketch-prototype/` is the
335
347
  visual-review surface. A style ships when it is distinctive at a glance,
336
348
  legible at cell size, and honest to its intent.