agentic-mermaid 0.1.1 → 0.1.2

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 (336) hide show
  1. package/CHANGELOG.md +144 -4
  2. package/LICENSES/Apache-2.0.txt +202 -0
  3. package/README.md +25 -32
  4. package/THIRD_PARTY_NOTICES.md +29 -0
  5. package/dist/agent-core.d.ts +463 -0
  6. package/dist/agent-core.js +397 -0
  7. package/dist/agent.d.ts +73 -1868
  8. package/dist/agent.js +336 -37325
  9. package/dist/agentic-mermaid-mcp.js +7 -38399
  10. package/dist/am.js +33632 -40445
  11. package/dist/chunk-4QECACIA.js +4702 -0
  12. package/dist/chunk-CDPKJ2BQ.js +37 -0
  13. package/dist/chunk-QKDLMOJJ.js +3487 -0
  14. package/dist/chunk-WI35L7IR.js +615 -0
  15. package/dist/chunk-WN3YDOBG.js +149 -0
  16. package/dist/chunk-ZYMMKQ3I.js +62637 -0
  17. package/dist/index-D54dqSdC.d.ts +6777 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +310 -33014
  20. package/dist/mcp-cli-SBQSTJFC.js +17 -0
  21. package/docs/README.md +14 -6
  22. package/docs/schemas/style-spec.schema.json +1221 -30
  23. package/examples/styles/catalog.json +54 -0
  24. package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
  25. package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
  26. package/examples/styles/cupertino-prototype.mmd +10 -0
  27. package/examples/styles/cupertino-prototype.style.json +63 -0
  28. package/examples/styles/mid-century-report.style.json +2 -2
  29. package/examples/styles/star-chart-atlas.style.json +2 -1
  30. package/examples/styles/transit-route-map.style.json +2 -2
  31. package/examples/styles/vercel-inspired-prototype.mmd +6 -0
  32. package/examples/styles/vercel-inspired-prototype.style.json +87 -0
  33. package/package.json +68 -43
  34. package/server.json +2 -2
  35. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
  36. package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
  37. package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
  38. package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
  39. package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
  40. package/AGENT_NATIVE.md +0 -607
  41. package/Instructions_for_agents.md +0 -89
  42. package/TODO.md +0 -684
  43. package/assets/hero.png +0 -0
  44. package/dist/index-wjRjbsP-.d.ts +0 -1102
  45. package/docs/agent-api-cookbook.md +0 -308
  46. package/docs/agent-mutation-policy.md +0 -104
  47. package/docs/agent-workflow-examples.md +0 -46
  48. package/docs/api.md +0 -211
  49. package/docs/ascii.md +0 -103
  50. package/docs/assets/improvements/box-start-connector.png +0 -0
  51. package/docs/assets/improvements/comment-dropped-lint.png +0 -0
  52. package/docs/assets/improvements/er-content-loss.png +0 -0
  53. package/docs/assets/improvements/fan-in-trunks.png +0 -0
  54. package/docs/assets/improvements/gantt-family.png +0 -0
  55. package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
  56. package/docs/assets/improvements/gantt-verify-seam.png +0 -0
  57. package/docs/assets/improvements/subgraph-container-edges.png +0 -0
  58. package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
  59. package/docs/assets/improvements/wrapper-init-directive.png +0 -0
  60. package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
  61. package/docs/assets/style-cookbook/mid-century-report.png +0 -0
  62. package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
  63. package/docs/assets/style-cookbook/transit-route-map.png +0 -0
  64. package/docs/comparison.md +0 -94
  65. package/docs/config.md +0 -105
  66. package/docs/contributing/adding-diagram-types.md +0 -144
  67. package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
  68. package/docs/contributing/diagram-family-citizenship.md +0 -82
  69. package/docs/contributing/harvesting-upstream-tests.md +0 -126
  70. package/docs/contributing/lessons-learned.md +0 -276
  71. package/docs/contributing/releasing.md +0 -82
  72. package/docs/contributing/visual-review-evidence.md +0 -53
  73. package/docs/custom-style-cookbook.md +0 -154
  74. package/docs/design/families/README.md +0 -26
  75. package/docs/design/families/architecture-beta.md +0 -48
  76. package/docs/design/families/flowchart-parser-conformance.md +0 -22
  77. package/docs/design/families/gantt-research.md +0 -137
  78. package/docs/design/families/gantt.md +0 -329
  79. package/docs/design/families/journey-agentic-cards-before.png +0 -0
  80. package/docs/design/families/journey-experience-curve-implementation.png +0 -0
  81. package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
  82. package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
  83. package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
  84. package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
  85. package/docs/design/families/journey-migration-parity.md +0 -439
  86. package/docs/design/families/journey-section-overlap-after.png +0 -0
  87. package/docs/design/families/journey-section-overlap-before.png +0 -0
  88. package/docs/design/families/journey-usage-research.md +0 -423
  89. package/docs/design/families/journey.md +0 -153
  90. package/docs/design/families/xychart.md +0 -85
  91. package/docs/design/system/README.md +0 -45
  92. package/docs/design/system/abstraction-audit.md +0 -224
  93. package/docs/design/system/abstraction-recommendations.md +0 -655
  94. package/docs/design/system/architecture.mmd +0 -29
  95. package/docs/design/system/architecture.svg +0 -137
  96. package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
  97. package/docs/design/system/layout-rubric.md +0 -138
  98. package/docs/design/system/route-contracts.md +0 -848
  99. package/docs/design/system/source-preservation-ladder.md +0 -52
  100. package/docs/design/system/styles-rollout.md +0 -216
  101. package/docs/design/system/ugly-layouts.md +0 -119
  102. package/docs/diagram-families.md +0 -193
  103. package/docs/features.md +0 -147
  104. package/docs/fork-differences.md +0 -130
  105. package/docs/getting-started.md +0 -175
  106. package/docs/issue-derived-test-cases.md +0 -156
  107. package/docs/layout-characterization/README.md +0 -245
  108. package/docs/layout-characterization/contact-sheet-families.md +0 -498
  109. package/docs/layout-characterization/contact-sheet.md +0 -638
  110. package/docs/layout-characterization/properties.md +0 -281
  111. package/docs/layout-characterization/visual-quality.md +0 -160
  112. package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
  113. package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
  114. package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
  115. package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
  116. package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
  117. package/docs/layout-characterization/visual-snapshots/journey.svg +0 -98
  118. package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
  119. package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
  120. package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
  121. package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
  122. package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
  123. package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
  124. package/docs/mcp-code-mode-rationale.md +0 -101
  125. package/docs/mcp-http-transport.md +0 -223
  126. package/docs/mermaid-layout-complaints.md +0 -837
  127. package/docs/mutation-testing.md +0 -206
  128. package/docs/project/divergences.md +0 -98
  129. package/docs/project/dogfooding-docs-strategy.md +0 -66
  130. package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
  131. package/docs/project/lessons-learned.md +0 -1019
  132. package/docs/project/remove-role-styling-plan.md +0 -176
  133. package/docs/quality.md +0 -215
  134. package/docs/react.md +0 -97
  135. package/docs/style-authoring.md +0 -133
  136. package/docs/testing-strategy.md +0 -335
  137. package/docs/theming.md +0 -162
  138. package/examples/agent-improve-auth-flow.ts +0 -206
  139. package/examples/agent-loop.ts +0 -53
  140. package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
  141. package/llms.txt +0 -104
  142. package/skill-evals/README.md +0 -77
  143. package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
  144. package/skill-evals/fixtures/class-payment/input.mmd +0 -4
  145. package/skill-evals/fixtures/er-orders/input.mmd +0 -10
  146. package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
  147. package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
  148. package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
  149. package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
  150. package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
  151. package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
  152. package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
  153. package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
  154. package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
  155. package/skill-evals/shared-benchmark.json +0 -510
  156. package/src/agent/analyze.ts +0 -157
  157. package/src/agent/apply.ts +0 -146
  158. package/src/agent/architecture-body.ts +0 -458
  159. package/src/agent/certificates.ts +0 -110
  160. package/src/agent/class-body.ts +0 -319
  161. package/src/agent/core.ts +0 -207
  162. package/src/agent/create.ts +0 -106
  163. package/src/agent/describe.ts +0 -368
  164. package/src/agent/er-body.ts +0 -224
  165. package/src/agent/facts.ts +0 -360
  166. package/src/agent/families-builtin.ts +0 -920
  167. package/src/agent/families.ts +0 -232
  168. package/src/agent/family-layouts.ts +0 -832
  169. package/src/agent/flowchart-body.ts +0 -372
  170. package/src/agent/flowchart-unsupported.ts +0 -243
  171. package/src/agent/font-coverage.ts +0 -288
  172. package/src/agent/gantt-body.ts +0 -495
  173. package/src/agent/index.ts +0 -10
  174. package/src/agent/journey-body.ts +0 -374
  175. package/src/agent/label-metrics.ts +0 -28
  176. package/src/agent/layout-to-rendered.ts +0 -63
  177. package/src/agent/mutate.ts +0 -97
  178. package/src/agent/mutation-ops.ts +0 -51
  179. package/src/agent/op-schema.ts +0 -443
  180. package/src/agent/parse.ts +0 -223
  181. package/src/agent/pie-body.ts +0 -270
  182. package/src/agent/png.ts +0 -171
  183. package/src/agent/quadrant-body.ts +0 -336
  184. package/src/agent/quality.ts +0 -363
  185. package/src/agent/readability-audit.ts +0 -92
  186. package/src/agent/rendered-route-audit.ts +0 -61
  187. package/src/agent/sequence-body.ts +0 -345
  188. package/src/agent/serialize.ts +0 -214
  189. package/src/agent/state-body.ts +0 -589
  190. package/src/agent/structural-count.ts +0 -150
  191. package/src/agent/timeline-body.ts +0 -280
  192. package/src/agent/trace-log.ts +0 -43
  193. package/src/agent/types.ts +0 -995
  194. package/src/agent/verify.ts +0 -603
  195. package/src/agent/xychart-body.ts +0 -472
  196. package/src/architecture/config.ts +0 -282
  197. package/src/architecture/layout.ts +0 -496
  198. package/src/architecture/parser.ts +0 -375
  199. package/src/architecture/renderer.ts +0 -611
  200. package/src/architecture/types.ts +0 -113
  201. package/src/ascii/ansi.ts +0 -423
  202. package/src/ascii/architecture.ts +0 -210
  203. package/src/ascii/canvas.ts +0 -443
  204. package/src/ascii/class-diagram.ts +0 -697
  205. package/src/ascii/converter.ts +0 -475
  206. package/src/ascii/draw.ts +0 -1693
  207. package/src/ascii/edge-bundling.ts +0 -328
  208. package/src/ascii/edge-routing.ts +0 -330
  209. package/src/ascii/er-diagram.ts +0 -439
  210. package/src/ascii/gantt.ts +0 -276
  211. package/src/ascii/grid.ts +0 -747
  212. package/src/ascii/index.ts +0 -196
  213. package/src/ascii/journey.ts +0 -169
  214. package/src/ascii/meta.ts +0 -244
  215. package/src/ascii/multiline-utils.ts +0 -80
  216. package/src/ascii/pathfinder.ts +0 -301
  217. package/src/ascii/pie.ts +0 -67
  218. package/src/ascii/quadrant.ts +0 -158
  219. package/src/ascii/reverse.ts +0 -216
  220. package/src/ascii/sequence.ts +0 -499
  221. package/src/ascii/shapes/circle.ts +0 -27
  222. package/src/ascii/shapes/corners.ts +0 -143
  223. package/src/ascii/shapes/diamond.ts +0 -27
  224. package/src/ascii/shapes/hexagon.ts +0 -27
  225. package/src/ascii/shapes/index.ts +0 -106
  226. package/src/ascii/shapes/rectangle.ts +0 -168
  227. package/src/ascii/shapes/rounded.ts +0 -27
  228. package/src/ascii/shapes/special.ts +0 -332
  229. package/src/ascii/shapes/stadium.ts +0 -110
  230. package/src/ascii/shapes/state.ts +0 -192
  231. package/src/ascii/shapes/types.ts +0 -73
  232. package/src/ascii/timeline.ts +0 -141
  233. package/src/ascii/types.ts +0 -312
  234. package/src/ascii/validate.ts +0 -120
  235. package/src/ascii/width.ts +0 -81
  236. package/src/ascii/wrap.ts +0 -131
  237. package/src/ascii/xychart.ts +0 -919
  238. package/src/browser.ts +0 -29
  239. package/src/class/layout.ts +0 -240
  240. package/src/class/parser.ts +0 -332
  241. package/src/class/renderer.ts +0 -638
  242. package/src/class/types.ts +0 -129
  243. package/src/cli/agent-instructions.ts +0 -1
  244. package/src/cli/am-bin.ts +0 -6
  245. package/src/cli/exit-codes.ts +0 -18
  246. package/src/cli/index.ts +0 -1132
  247. package/src/cli/init-agent.ts +0 -147
  248. package/src/cli/run-entrypoint.ts +0 -10
  249. package/src/color-resolver.ts +0 -152
  250. package/src/elk-instance.ts +0 -114
  251. package/src/er/layout.ts +0 -187
  252. package/src/er/parser.ts +0 -226
  253. package/src/er/renderer.ts +0 -792
  254. package/src/er/types.ts +0 -99
  255. package/src/family-rubric.ts +0 -425
  256. package/src/font-manifest.ts +0 -31
  257. package/src/gantt/layout.ts +0 -365
  258. package/src/gantt/parser.ts +0 -282
  259. package/src/gantt/pipeline.ts +0 -27
  260. package/src/gantt/renderer.ts +0 -414
  261. package/src/gantt/schedule.ts +0 -513
  262. package/src/gantt/types.ts +0 -255
  263. package/src/index.ts +0 -368
  264. package/src/journey/layout.ts +0 -554
  265. package/src/journey/parse-core.ts +0 -251
  266. package/src/journey/parser.ts +0 -101
  267. package/src/journey/renderer.ts +0 -917
  268. package/src/journey/types.ts +0 -144
  269. package/src/layout/geometry.ts +0 -182
  270. package/src/layout/pass.ts +0 -142
  271. package/src/layout/passes/index.ts +0 -3916
  272. package/src/layout-engine.ts +0 -1565
  273. package/src/layout-rubric.ts +0 -659
  274. package/src/mcp/artifacts.ts +0 -137
  275. package/src/mcp/dynamic-harness.ts +0 -31
  276. package/src/mcp/dynamic-modules.d.ts +0 -7
  277. package/src/mcp/facade.ts +0 -608
  278. package/src/mcp/harness-runtime.ts +0 -203
  279. package/src/mcp/hosted-server.ts +0 -468
  280. package/src/mcp/mcp-bin.ts +0 -3
  281. package/src/mcp/mcp-cli.ts +0 -82
  282. package/src/mcp/protocol.ts +0 -13
  283. package/src/mcp/sandbox.ts +0 -195
  284. package/src/mcp/sdk-decl.ts +0 -391
  285. package/src/mcp/server.ts +0 -362
  286. package/src/mcp/tool-surface.ts +0 -146
  287. package/src/mermaid-source.ts +0 -655
  288. package/src/multiline-utils.ts +0 -228
  289. package/src/parser.ts +0 -1031
  290. package/src/pie/layout.ts +0 -168
  291. package/src/pie/parser.ts +0 -136
  292. package/src/pie/renderer.ts +0 -234
  293. package/src/pie/types.ts +0 -82
  294. package/src/quadrant/layout.ts +0 -191
  295. package/src/quadrant/parser.ts +0 -183
  296. package/src/quadrant/renderer.ts +0 -322
  297. package/src/quadrant/types.ts +0 -113
  298. package/src/render-family-hooks.ts +0 -244
  299. package/src/renderer.ts +0 -1099
  300. package/src/route-contracts.ts +0 -2723
  301. package/src/scene/backend.ts +0 -76
  302. package/src/scene/fidelity.ts +0 -183
  303. package/src/scene/hybrid-backend.ts +0 -174
  304. package/src/scene/ir.ts +0 -181
  305. package/src/scene/marks.ts +0 -127
  306. package/src/scene/rough-backend.ts +0 -378
  307. package/src/scene/seed.ts +0 -46
  308. package/src/scene/style-registry.ts +0 -556
  309. package/src/sequence/layout.ts +0 -456
  310. package/src/sequence/parser.ts +0 -255
  311. package/src/sequence/renderer.ts +0 -604
  312. package/src/sequence/types.ts +0 -154
  313. package/src/shape-clipping.ts +0 -351
  314. package/src/shared/accessibility-directives.ts +0 -22
  315. package/src/shared/batched.ts +0 -61
  316. package/src/shared/color-math.ts +0 -93
  317. package/src/shared/svg-a11y.ts +0 -29
  318. package/src/shared/syntax-error.ts +0 -17
  319. package/src/shared/unicode-ranges.ts +0 -135
  320. package/src/styles.ts +0 -318
  321. package/src/svg-paths.ts +0 -28
  322. package/src/text-metrics.ts +0 -248
  323. package/src/theme.ts +0 -710
  324. package/src/timeline/layout.ts +0 -381
  325. package/src/timeline/parser.ts +0 -215
  326. package/src/timeline/renderer.ts +0 -538
  327. package/src/timeline/types.ts +0 -105
  328. package/src/types.ts +0 -462
  329. package/src/website-worker-modules.d.ts +0 -18
  330. package/src/xychart/axis-utils.ts +0 -109
  331. package/src/xychart/colors.ts +0 -124
  332. package/src/xychart/config.ts +0 -88
  333. package/src/xychart/layout.ts +0 -656
  334. package/src/xychart/parser.ts +0 -504
  335. package/src/xychart/renderer.ts +0 -640
  336. package/src/xychart/types.ts +0 -282
@@ -1,82 +0,0 @@
1
- # Diagram-family citizenship ratchet
2
-
3
- Issue: #41. Status: enforced checklist + checked matrix.
4
-
5
- A diagram family is a **good citizen** when it is integrated into every runtime, documentation, agent, editor, eval, and distribution surface that teaches users or agents what Agentic Mermaid supports. Rendering is not enough: a family must be discoverable, safely editable when its modeled body narrows, verifiable before render, represented in examples/evals, and either backed by evidence or tracked as an explicit exception.
6
-
7
- ## Source of truth
8
-
9
- `BUILTIN_FAMILY_METADATA` in `src/agent/families.ts` is the canonical shipped-family registry. It records the family id, label, Mermaid headers, typed narrower, live-editor example id/type, and editor glyph. The registry has compile-time coverage against `DiagramKind`; tests then project it into CLI capabilities, MCP/Code Mode, docs, editor examples, eval fixtures, package keywords, and generated discovery docs.
10
-
11
- The checked citizenship matrix lives at [`diagram-family-citizenship.matrix.json`](./diagram-family-citizenship.matrix.json). It is intentionally separate from the registry: the registry says “this family ships”; the matrix says “these citizenship surfaces are satisfied, and these remaining gaps are tracked.”
12
-
13
- ## Semantic correctness vs. system citizenship
14
-
15
- Keep these distinct in reviews:
16
-
17
- - **Semantic correctness** asks whether a parser/IR/serializer/verifier/renderer preserves the family’s own Mermaid meaning. Examples: Gantt schedule resolution, flowchart route certificates, sequence segment preservation, pie percentage invariants, XY axis/domain laws.
18
- - **System citizenship** asks whether every supported entry point points to the same typed path. Examples: `am capabilities`, `llms.txt`, `am init-agent`, MCP initialize guidance, SDK declarations, Code Mode sandbox narrowers, editor examples/glyphs, eval fixtures, generated site samples, package exports, and docs tables.
19
-
20
- A new family can be semantically good and still fail citizenship if an agent discovering the package through a different surface cannot find the same parse → narrow → mutate → verify → serialize path.
21
-
22
- ## Checklist surfaces
23
-
24
- The matrix has one cell per family for each surface below. A cell is either `satisfied` with concrete evidence paths, or `exception` with a tracked TODO/issue reference. CI fails if a registered family is missing a row, a surface, evidence, or exception tracking.
25
-
26
- | Surface | Contract |
27
- |---|---|
28
- | `registryDiscovery` | Family appears in `BUILTIN_FAMILY_METADATA`, registered plugins, CLI capability metadata, and typed IDs. |
29
- | `detectionParse` | Shared detector, agent parse, SVG render, ASCII render, CLI, and MCP paths route consistently; state’s flowchart renderer split is the only documented exception. |
30
- | `semanticModel` | Modeled syntax subset and opaque/source-preservation ladder are explicit. |
31
- | `serializeRoundTrip` | Modeled syntax has parse → serialize → parse stability; opaque/segment-preserved syntax round-trips losslessly. |
32
- | `typedMutation` | A public narrower and mutation ops exist, and opaque fallback bodies do not fake structured mutation. |
33
- | `verifyRenderSeam` | Modeled syntax has no “verify ok, render throws” path; render-blocking conditions surface as named warnings/errors. |
34
- | `determinism` | No ambient wall clock/random/locale/process-order dependence; runtime knobs such as `ganttToday` are explicit. |
35
- | `svgRender` | SVG/PNG-capable rendering path is covered for the family. |
36
- | `asciiUnicodeRender` | ASCII/Unicode output is covered when advertised. |
37
- | `layoutProjection` | `layoutMermaid`, quality metrics, and verify layout expose truthful geometry, not placeholder data. |
38
- | `stableRegions` | Region metadata for editor/TUI/accessibility is present or explicitly tracked as a gap. |
39
- | `editorExample` | Live editor has a working `Supported diagrams` example and explicit glyph for the family. |
40
- | `docsAgentSurfaces` | README/docs/spec/skills/agent instructions/SDK declaration/llms surfaces stay in sync. |
41
- | `evalFixture` | Shared skill benchmark has at least one fixture-backed case tagged `family:<id>`. |
42
- | `upstreamHarvest` | Official upstream Mermaid examples/tests are harvested into an executable docs corpus, family bench, or accounted parser/DB bench. |
43
- | `divergenceLedger` | Known compatibility divergences in harvested upstream examples/tests are executable and cannot rot, or tracked for ledger work. |
44
- | `domainProperties` | Family-specific invariants/properties exist beyond “renders without throwing.” |
45
- | `goldensEvidence` | Text/SVG/visual evidence exists where reviewer judgment needs artifacts. |
46
- | `generatedSite` | Site samples/gallery/generated docs include the family or have explicit exceptions. |
47
- | `distributionPackage` | Package exports/files/consumer init artifacts include the public family surface. |
48
- | `mutationLane` | Targeted mutation/sabotage lane exists, or a tracked exception explains the gap. |
49
-
50
- ## Worked example: Gantt
51
-
52
- Gantt is the bar for a new family entering the system:
53
-
54
- - registry + mutation: `BUILTIN_FAMILY_METADATA`, `asGantt`, typed Gantt ops, CLI capabilities, SDK declaration, MCP sandbox, and `am init-agent` all expose the same path;
55
- - semantics: `src/gantt/parser.ts`, `src/gantt/schedule.ts`, `src/gantt/layout.ts`, and `src/agent/gantt-body.ts` keep scheduling pure and wall-clock-free;
56
- - verify/render seam: `UNRESOLVABLE_SCHEDULE` turns render-blocking schedule failures into named verification output;
57
- - compatibility: `eval/mermaid-gantt-bench/` has cases plus executable exclusions; `src/__tests__/gantt-upstream-bench.test.ts` runs it;
58
- - properties: `src/__tests__/property-gantt-schedule.test.ts` includes the CPM shadow-model property;
59
- - evidence: SVG snapshots, ASCII/Unicode goldens, `docs/assets/improvements/gantt-family.png`, and `mutation-test:gantt` cover reviewer-visible and sabotage paths;
60
- - editor/skill-evals/docs: editor examples, eval fixtures, docs, `llms.txt`, and MCP/Code Mode surfaces are all registry-checked.
61
-
62
- ## Non-Gantt audit: XY chart
63
-
64
- XY chart proves the checklist works for an older family that was promoted after the registry existed:
65
-
66
- - citizenship surfaces are satisfied for registry, detection, typed mutation (`asXyChart`), CLI/MCP docs, editor examples, eval fixtures, generated site samples, package exposure, SVG/ASCII output, and layout projection;
67
- - semantic correctness is pinned by parser/integration/layout/renderer tests and `src/__tests__/property-xychart.test.ts`;
68
- - mutation-testing citizenship is satisfied through `mutation-test:families`, which mutates `src/xychart/*` together with Architecture;
69
- - stable region citizenship is satisfied through `src/__tests__/agent-ascii-meta.test.ts`;
70
- - upstream-docs harvest/divergence citizenship is satisfied through the regenerated `eval/mermaid-docs-corpus/corpus.json`, executable `divergences.json` ledger, `eval/mermaid-gantt-bench/`, and the fully accounted cross-family parser/DB bench in `eval/mermaid-upstream-suite-bench/`.
71
-
72
- This is the intended ratchet shape: historical gaps are either closed or represented by a live checked cell. After the BUILD-22 backfill, the matrix has zero exceptions; if a future family introduces one, it must be tracked before merge.
73
-
74
- ## Review workflow
75
-
76
- When adding or changing a family:
77
-
78
- 1. Add/update `BUILTIN_FAMILY_METADATA` first.
79
- 2. Add/update parser, renderer, agent body, mutation ops, verify behavior, and examples.
80
- 3. Update the citizenship matrix row in the same PR. Prefer `satisfied` with evidence; use `exception` only with a concrete TODO/issue reference.
81
- 4. Run `bun test src/__tests__/diagram-family-citizenship.test.ts src/__tests__/agent-doc-sync.test.ts src/__tests__/editor-examples.test.ts src/__tests__/cli-capabilities.test.ts` before wider validation.
82
- 5. For any matrix exception introduced by the PR, add a follow-up issue or `TODO.md` entry before merge.
@@ -1,126 +0,0 @@
1
- # Harvesting Upstream Test Suites
2
-
3
- How to turn "we are compatible with Mermaid" from a claim into a measured,
4
- CI-gated number — by vendoring the *actual test suites* of upstream
5
- implementations and running their inputs against ours. First applied to Gantt
6
- (`eval/mermaid-gantt-bench/`); this guide generalizes the method so any family
7
- can repeat it. Pairs with [`adding-diagram-types.md`](./adding-diagram-types.md):
8
- do the harvest no later than the family's first release, and for not-yet-built
9
- families do it **before** implementation — it is the cheapest way to learn the
10
- real (as opposed to documented) semantics.
11
-
12
- ## What a harvest produces
13
-
14
- ```
15
- eval/mermaid-<family>-bench/
16
- README.md provenance (repos, files, fetch date, licenses), schema, reason codes
17
- cases.json portable parity cases: upstream inputs + upstream-derived expectations
18
- exclusions.json every upstream case we deliberately do NOT match, each with a reason
19
- src/__tests__/<family>-upstream-bench.test.ts the runner (CI, every PR)
20
- ```
21
-
22
- The contract that keeps it honest:
23
-
24
- 1. **Every portable case passes.** Cases assert what upstream asserts —
25
- nothing more (our own stronger guarantees belong in our unit/property
26
- tests, not in the parity bench).
27
- 2. **Every exclusion is explained by a reason code**, and where the entry
28
- names an `oursErrorCode`, the runner **executes it** — proving we fail
29
- with exactly that named error. A divergence ledger that runs cannot rot.
30
- 3. **API-internal upstream tests are listed as not-portable** in the bench
31
- README (state-reset tests, internal helper unit tests, renderer DOM
32
- assertions) so "the entirety of their suite" is fully accounted for.
33
-
34
- Template to copy: `eval/mermaid-gantt-bench/` +
35
- `src/__tests__/gantt-upstream-bench.test.ts`.
36
-
37
- ## Where the upstream tests live
38
-
39
- | Source | Path | What to take |
40
- |---|---|---|
41
- | mermaid grammar specs | `packages/mermaid/src/diagrams/<family>/parser/<family>.spec.js` | Source strings + structural assertions (titles, ids, tags, click bindings). Mostly portable. |
42
- | mermaid semantics specs | `packages/mermaid/src/diagrams/<family>/<family>Db.spec.ts` (some families: `<family>Db.spec.js`, or logic specs beside the db) | The valuable layer: resolved values, ordering, edge cases. Portable after normalization; this is where wall-clock/TZ landmines hide. |
43
- | mermaid rendering specs | `cypress/integration/rendering/<family>.spec.js` | Inputs only — assertions target THEIR svg dom. Usually redundant with the docs corpus. |
44
- | mermaid docs examples | `packages/mermaid/src/docs/syntax/<file>.md` | Already wired: add the file to `FILE_TO_FAMILY` in `eval/mermaid-docs-corpus/build-corpus.ts` and floors to `src/__tests__/agent-mermaid-corpus.test.ts`. Docs are de facto behavior — they contain tolerated junk (see gotcha 3). |
45
- | ASCII forks | `pgavlin/mermaid-ascii` (`pkg/<family>/<family>_test.go`), `kais-radwan/ascii-mermaid` (`ts/test/<family>.test.js`), `AlexanderGrooff/mermaid-ascii` | Inputs + render-smoke only; their byte-level output assertions are theirs. |
46
- | oracle library | `mermaid-ast` (already a dependency) | A parsing differential (`<Family>.parse(...).toAST()`), not a semantics oracle — it does not resolve values. |
47
-
48
- Fetch raw files from the `develop` branch
49
- (`https://raw.githubusercontent.com/mermaid-js/mermaid/develop/<path>`), record
50
- the fetch date in the bench README, and **check the license before vendoring**
51
- (mermaid and both ASCII forks are MIT — attribute in the README; a repo with
52
- no license file must not be vendored, only summarized).
53
-
54
- ## The method
55
-
56
- 1. **Read both spec files end to end** before extracting anything. Count the
57
- `it(`/`it.each` blocks; every one must land in cases.json, exclusions.json,
58
- or the README's not-portable list.
59
- 2. **Classify each test**: `parse` (structural fields), `schedule`/semantic
60
- (resolved values), `error` (both sides reject), excluded (reason code), or
61
- API-internal (not representable as diagram source — note it).
62
- 3. **Normalize expectations, never inputs.** Inputs are vendored verbatim.
63
- Their local-time `new Date(y, m, d)` tuples become UTC ISO strings; their
64
- auto-synthesized ids (`task1`…) become index-based assertions; their
65
- boolean tag flags become tag sets.
66
- 4. **Run, and treat every failure as information.** A failing harvested case
67
- is one of: a real bug in ours (fix it), a deliberate spec divergence (move
68
- to exclusions with a reason + executable error code), or an upstream
69
- behavior our spec should adopt (change ours — the gantt `tickInterval
70
- 1decade` case). Decide explicitly; never weaken a case to make it pass.
71
- 5. **Gate it**: the runner is a normal `bun test` file; the docs-corpus floors
72
- are evidence-based and regression-only, with a comment naming each entry
73
- that holds the floor below 1.00 and why that is honest.
74
- 6. **Re-run the search before each release** for new upstream tests (the
75
- family's design doc should carry the watchlist of in-flight upstream
76
- syntax, as `docs/design/families/gantt.md` does).
77
-
78
- ## Exclusion reason codes
79
-
80
- Reuse these before inventing new ones, and document any new code in the bench
81
- README (the runner asserts every reason is documented):
82
-
83
- - `wall-clock-fallback` — upstream substitutes `new Date()` for missing or
84
- unparseable inputs; our determinism contract mandates named errors. Always
85
- executable (`oursErrorCode`).
86
- - `local-tz` — the upstream test only means something in a specific timezone
87
- (they themselves gate the gantt DST test behind `TZ=America/Los_Angeles`).
88
- - `silent-ignore-vs-named-error` — upstream tolerates a token its own docs
89
- call unsupported; we error by name per the family spec.
90
- - `exclude-boundary-model` (and siblings) — a real semantic difference,
91
- precisely characterized. Where possible state the conservation law both
92
- sides satisfy and exactly which inputs diverge.
93
-
94
- ## Gotchas the gantt harvest hit (check for each of these)
95
-
96
- 1. **Wall-clock expectations hide inside table tests** — scan for
97
- `new Date()` with no arguments and `setHours(0, 0, 0, 0)` in expected
98
- values, not just in implementation code.
99
- 2. **TZ/DST-gated tests** can't run verbatim against a UTC-only engine; port
100
- the input, assert our UTC behavior, ledger the difference.
101
- 3. **Official docs contain tolerated junk** (`tickInterval 1decade`, a task
102
- ending `1s %% not yet official`). Docs examples are inputs users will
103
- paste, so decide tolerate-vs-error consciously against the family spec and
104
- put the decision in the ledger either way.
105
- 4. **Boundary semantics can differ while conservation laws agree** — gantt's
106
- exclude-walk counts `(start, end]` upstream vs our `[start, end)`. A
107
- property test of the conservation law plus a ledger entry for the boundary
108
- beats chasing instant-for-instant parity.
109
- 5. **The harvest finds seams, not just bugs**: the very first harvested gantt
110
- case exposed verify saying ok while render threw, which became the
111
- `UNRESOLVABLE_SCHEDULE` warning. When a harvested input behaves
112
- inconsistently across our own surfaces (parse vs verify vs render), that
113
- inconsistency is the finding.
114
- 6. **Upstream resolves more than you may assume** — their gantt resolver
115
- handles forward references; we had documented the opposite. The harvest
116
- corrects folklore about upstream as a side effect.
117
-
118
- ## Definition of done
119
-
120
- - Every upstream test block accounted for (cases / exclusions / not-portable).
121
- - All cases green; all executable exclusions green; bench README has
122
- provenance, fetch date, licenses, schema, and reason codes.
123
- - Docs-corpus family entries + floors wired (`build-corpus.ts`,
124
- `agent-mermaid-corpus.test.ts`).
125
- - Divergences that changed our behavior are reflected in the family's design
126
- doc and CHANGELOG.
@@ -1,276 +0,0 @@
1
- # Lessons learned
2
-
3
- Process lessons this repo has paid for, so they only have to be paid for once.
4
- Each entry names the incident that taught it. Add new lessons at the top with a
5
- date; do not delete old ones — supersede them in place.
6
-
7
- > **Scope.** This is the dated contributor process log. For the long-form
8
- > cumulative fork narrative (loops 1–22), see
9
- > [`../project/lessons-learned.md`](../project/lessons-learned.md).
10
-
11
- ## 2026-07 — style coverage and typography semantics
12
-
13
- **A style transform is a semantic contract, not a blanket SVG rewrite.**
14
- The first style-coverage pass made typography expressive enough to expose an
15
- important boundary: class names, entity names, relationship labels, section
16
- labels, chart titles, and task labels are diagram labels; class members and ER
17
- attributes are schema/code-like literals. Uppercasing `Account` to `ACCOUNT`
18
- is a look. Uppercasing `displayName`, `createdAt`, `orderId`, or
19
- `closeAccount(reason: string)` destroys authored signal. Rule: label transforms
20
- apply to labels; syntax-like internals still participate in role-token paint
21
- and contrast audits, but keep authored casing unless a future explicit
22
- `member`/`attribute`/`syntaxText` policy says otherwise.
23
-
24
- **Measure the text the renderer will actually draw.** Aggressive typography is
25
- not layout-neutral: uppercase, weight, letter spacing, and compact labels all
26
- change measured width and row/axis/title budgets. The Gantt fix had to measure
27
- the transformed/tracked text, not the Mermaid source token, before rendering
28
- compact task labels and axes. Rule: any layout that reserves space for text
29
- must run the same transform path that the renderer uses, or the style will pass
30
- unit tests while visibly clipping in the editor.
31
-
32
- **Coverage evidence has to separate plumbing, readability, and taste.** The
33
- state-space diagram and galleries explain what the style catalog covers, but
34
- the durable gate is `style:audit`: every built-in family is rendered with
35
- sentinel role tokens, role propagation is checked, and contrast floors are
36
- enforced. Visual galleries answer "are these looks differentiated?"; the audit
37
- answers "does the style system reach the elements it claims to reach?" Keep
38
- both, and be explicit about the remaining gap: arbitrary user-authored
39
- style/palette stacks are not yet universally WCAG-proved.
40
-
41
- ## 2026-07 — the layout-shift audit and look-control rework
42
-
43
- **User-initiated layout shift is CLS-exempt but still visible jank — diff
44
- positions, don't trust the metric.** A whole-site audit read CLS 0.000
45
- everywhere, yet clicking the home "Use with an agent" button slid its
46
- neighbours 83px, selecting a diagram style reflowed the wrapped mobile topbar
47
- by a full row (the theme dropdown jumped 284px), and the editor's "Copy agent
48
- prompt" slid 81px. All fired within 500ms of the click, so `hadRecentInput`
49
- flagged them out of the Core Web Vitals number. Rule: to audit click-induced
50
- shift, diff each anchor's bounding rect before/after the interaction and read
51
- the raw (unfiltered) `layout-shift` entries — CLS alone certifies nothing about
52
- what the user sees at the moment they click.
53
-
54
- **A width reservation is only correct once you check every breakpoint it
55
- crosses.** The Share button grew ~7px when its label became "Copied"; the
56
- obvious fix — a permanent inline `min-width` — would have overridden the
57
- ≤760px `font-size:0` rule and broken the mobile icon-only square, because
58
- inline styles beat media queries. Reserving the label's width in `em` instead
59
- collapsed to 0 exactly when the mobile rule zeroed the font. Rule: prefer a
60
- unit/property the responsive rules can still override, and verify the
61
- reservation at each breakpoint it passes through before shipping it.
62
-
63
- **A layout invariant stated in a component's own copy is a test spec.** The
64
- seed-shuffle button's tooltip said "(never moves layout)" — true when clicked,
65
- false when it *appeared*, which is what reflowed the topbar. The existing
66
- style-switch test asserted "the chrome never moves" but only compared colours,
67
- so the regression passed straight through it. Rule: when a component claims a
68
- layout invariant (in a tooltip, a comment, or a test's own name), the guarding
69
- test must assert positions, not a proxy like colour.
70
-
71
- **Restructure by re-wrapping markup and re-scoping CSS; touch the JS only when
72
- an id or class contract actually changes.** Fusing the Style and Theme
73
- dropdowns into one split pill kept every button/wrap/menu id and the `.open`
74
- class the shared popup controller toggles, so selection, keyboard, and focus
75
- logic ran unchanged — the only rename was a CSS-only button class. Rule: when
76
- JS binds elements by id and toggles known classes, a visual restructure is a
77
- markup + CSS job; reading the id/class contracts first tells you whether the JS
78
- is even in scope.
79
-
80
- **Label from the code's own vocabulary, and check the word against its sibling
81
- controls.** "Theme" for the palette axis collided with the adjacent light/dark
82
- toggle and with Mermaid's `themeVariables`, and was category-muddy (internally
83
- a theme is a palette-only style) — while the style registry, CLI, and docs
84
- already called it a "palette." Relabelling to "Palette" was three visible
85
- strings with no code rename: there is no public `theme` render field, and
86
- renaming `state.theme` / `data-theme` / the localStorage key would have broken
87
- saved editor state and share links. Rule: audit where a term is actually used
88
- before putting it on a control; a user-facing label is not an API, and the two
89
- are allowed to differ.
90
-
91
- ## 2026-07 — the website consolidation PR (#113)
92
-
93
- **A long-running branch that commits generated output collides catastrophically
94
- with a base that stops committing it — keep website changes source-only.** PR
95
- #113 committed the whole `website/public` bundle (100+ files) across nine
96
- commits. Meanwhile `main` (#110) had made `website/public` a gitignored build
97
- artifact, rebuilt by the test preload and at deploy. The result was a "dirty"
98
- PR whose merge was ~20 modify/delete conflicts on generated pages — the actual
99
- change (five source files) was buried under hundreds of artifact diffs.
100
- Resolution was to adopt the artifact model (`git rm -r website/public`, keep
101
- only `build.ts`, `source/pages`, the contract test, and `TODO.md`), which
102
- collapsed the PR from ~86 changed files to 5. Rule: never commit
103
- `website/public`; a website PR's diff is source only. A committed generated
104
- bundle turns every base change into a conflict and hides the real edit in noise.
105
-
106
- **Deterministic build + `website:check` can pass on wrong-but-deterministic
107
- output — assert content, not existence.** The sitemap (the PR's headline
108
- feature) shipped with only an `existsSync` gate. Because the build is
109
- deterministic and `website:check` only diffs regenerated-vs-committed output, a
110
- stale or malformed sitemap would regenerate identically and pass every gate —
111
- the wrong output is reproduced, not caught. A multi-agent audit flagged it; the
112
- fix asserts the sitemap lists exactly the live pages (no removed routes, no
113
- machine artifacts, one `<loc>` per page) and was verified red→green by injecting
114
- a removed route. Rule: for generated content, the test must *discriminate*
115
- correct from incorrect output, because determinism guarantees a wrong generator
116
- passes a same-vs-same check.
117
-
118
- **`bun test` green is not `tsc` green, and a piped exit code lies.** A new test
119
- passed `bun test` but failed strict `bun x tsc --noEmit` — a `matchAll` capture
120
- group is typed `string | undefined`. It nearly shipped because
121
- `bunx tsc … | tail` printed "exit: 0": the pipeline's status was `tail`'s, not
122
- tsc's, masking two real type errors. Rule: run the actual CI gate
123
- (`bun x tsc --noEmit`) after adding tests, and read `${PIPESTATUS[0]}` (or drop
124
- the pipe) so a tool's failure is never hidden behind a successful `tail`/`grep`.
125
-
126
- **Check what the platform already serves before adding a competing file.**
127
- Production serves Cloudflare's *managed* content-signals `robots.txt` at the
128
- edge; a repo `website/public/robots.txt` would likely have been shadowed and
129
- never delivered its `Sitemap:` line. A live `curl` settled it — the repo file
130
- was removed and the directive routed to the Cloudflare dashboard (TODO DEC-5).
131
- Corollary: for platform-managed surfaces (robots.txt, headers, redirects),
132
- verify the live response before shipping an asset that may never win. And a
133
- related cleanup that landed the same PR: hand-maintained parallel route lists
134
- drift (the `_redirects` list had silently dropped `/about/design`) — derive
135
- them from one source (here, the emitted-pages map) to delete the drift class.
136
-
137
- ## 2026-07 — the brand-system and chrome-polish passes
138
-
139
- **Design intent and shipped hex drift apart; compute claims on what shipped.**
140
- The pine accent was chosen 28° of OkLCH hue from the semantic success green —
141
- in the design tool. The shipped hexes had converged to 15° apart (11° in dark
142
- mode): links and "Copied" confirmations read as one colour, worse for
143
- deuteranopes, and the review that picked pine had cited the design-intent
144
- number. The separation now lives as an executable claim
145
- (`chrome-token-lockstep.test.ts` asserts ≥ 20° on the shipped values). Rule:
146
- any colour-relationship claim is computed on the committed hex, and if the
147
- relationship matters, it becomes a test.
148
-
149
- **A "keep in lockstep" comment is a hope; a test is a guarantee.** Three files
150
- carried the shared chrome tokens (site stylesheet, editor stylesheet, and the
151
- editor's `chromeThemeColors()` in JS), synchronized only by comments — and a
152
- 12% vs 13% hairline drift had already shipped that way. The lockstep test now
153
- extracts the triplet, brand chip, functional hues (both polarities), radii,
154
- motion tokens, and the hairline mix from all three sources and asserts
155
- equality. Corollary: the first draft of that test was itself rejected by the
156
- repo's test-quality lint (`toBeTruthy`) — new guard code has to pass the
157
- house's existing guards.
158
-
159
- **A rebrand includes the assets nobody opens.** Months of chrome work shipped
160
- while `og-image.png` still read "Beautiful Mermaid — by the team at Craft":
161
- the upstream project's card, wrong name, pre-fork palette, posted on every
162
- social share of the site. The CSS was audited to the percent; the PNG was
163
- never looked at. Rule: a brand change enumerates its raster/social surfaces —
164
- og-image, touch icons, favicon, README-rendered artifacts, repo social
165
- preview — and someone *views* each one.
166
-
167
- **Breakpoint boundaries hide unreachable controls; probe them mechanically.**
168
- Between 761 and ~1000px the editor topbar clipped with no scroll path — Copy
169
- agent prompt and Export Image were simply unreachable on an iPad portrait,
170
- 8px above the mobile breakpoint. Nothing failed: no overflow, no console
171
- error, desktop and phone both fine. The check that catches it is mechanical
172
- (every interactive element's bounding rect inside `innerWidth`, sampled just
173
- above each breakpoint), and the fix is a policy, not a tweak: toolbars either
174
- wrap or scroll; they never assume they fit.
175
-
176
- **When one value moves, its coupled values move with it.** The iOS input-zoom
177
- fix (16px fields under coarse pointers) would have silently desynced the
178
- line-number gutter, which shares the textarea's font metrics row-for-row; the
179
- `forced-colors` block predated the new functional tokens and left them
180
- unmapped under Windows High Contrast. Both were caught only by asking "what
181
- else derives from or aligns with this?" before shipping. Same failure shape
182
- in both: a correct local change, an unenumerated dependency.
183
-
184
- **Verify a suspected gap exists before fixing it.** A review flagged popover
185
- keyboard handling (Escape, focus restore) as unaudited. The audit found a
186
- shared `createPopupController` already covering all seven popovers, including
187
- roving tabindex in the theme listbox. "Audited, no change needed" is a
188
- result worth reporting; patching per-component without looking for the shared
189
- mechanism would have added the inconsistency it meant to prevent.
190
-
191
- **Consistency work starts with a census, not a scroll-through.** Grep every
192
- value class and count occurrences (radii, durations, easings, font sizes,
193
- press scales, icon strokes, z-indexes, gaps) — the count-one entries are the
194
- findings. This surfaced 58 untokenized transition durations, three press
195
- scales where the system wanted one, five icon stroke weights where two were
196
- deliberate, and seven magic z-indexes with an accidental popover-above-popover
197
- ordering. Eyeballing pages finds none of these reliably.
198
-
199
- ## 2026-07 — the label-overlap audit and remediation
200
-
201
- **A metric you never measure is a defect class you ship.** No gate measured
202
- label-label or label-box occlusion in any family until the 2026-07 audit — and
203
- the curated, human-reviewed corpus itself carried collisions in five families
204
- (architecture edge-label pairs, quadrant point labels, gantt compact rows,
205
- state reciprocal pills, flowchart feedback pills). The blind spot had even been
206
- *seen* and deferred (issue #42's review explicitly carved out "a separate
207
- label-lane/self-loop policy") — deferral without an owner issue is how a known
208
- gap becomes an ambient defect. Rule: every deferral gets a filed issue at
209
- deferral time (see the closure-hygiene lesson below).
210
-
211
- **Detector first, then the fix, then the detector becomes the gate.** The
212
- remediation sequence that worked: build the overlap auditor → calibrate it on
213
- the curated corpus (which also separates auditor bugs from real defects — two
214
- of the initial finding classes were the auditor's own rotation and region-
215
- border mistakes) → fix family by family with the detector red first → land the
216
- detector as a permanent gate (`label-overlap-gate.test.ts`: corpus at zero,
217
- per-family fuzz ratchets). A fix without the standing gate would regress
218
- silently; a gate calibrated before the corpus was clean would have been
219
- disabled as noisy.
220
-
221
- **"Generator noise" is a hypothesis, not a verdict.** The deep-fuzz
222
- `offOutlineEndpoints` hits were dismissed as duplicate-parallel-edge generator
223
- artifacts — but duplicate parallel edges are *valid Mermaid*, and that same
224
- input class turned out to break certificate completeness (#83) and stack labels
225
- (70% of fuzzed state diagrams). When a fuzz class is excused, the excuse needs
226
- the same evidence bar as a fix: either the input is genuinely invalid, or the
227
- class gets an owner issue.
228
-
229
- **Fixing one flaky suite does not fix the policy.** Hours after the
230
- route-contracts seeds were pinned (#86), a *different* property file
231
- (`property-mermaid-source-and-parser.test.ts`) failed CI on a rolled seed — its
232
- generator emitted grammar-ambiguous ids (`s---Py3` reads as the link
233
- `s --- Py3`, in this engine and in Mermaid) that only rare seeds produce. Two
234
- sub-lessons: property generators must be constrained to inputs whose expected
235
- behavior is actually unambiguous, and a determinism policy has to be applied as
236
- a sweep (every fast-check suite), not incident-by-incident.
237
-
238
- **An invariant enforced by a random property is a lottery, not a gate.**
239
- Certificate completeness was guarded only by an unpinned fast-check property —
240
- it fired roughly one CI run in seven, which reads as "flaky CI" rather than
241
- "real bug" and trains people to re-run. Invariants get deterministic gates
242
- (enumerated corpus + pinned seeds); randomness is for *finding* new
243
- counterexamples (deep fuzz lanes), not for *holding* known ground.
244
-
245
- **A dead quality signal is worse than no signal.** Every CI run printed "the
246
- mutation score is the adequacy signal" while the nightly mutation lane had been
247
- timing out (cancelled) for over a week — the signal's *existence* was asserted
248
- by docs while its *output* was absent, and nothing alarmed. If a scheduled
249
- gate's failure/cancellation isn't itself surfaced (a required check, a badge, a
250
- notification), the gate will die quietly exactly when it matters.
251
-
252
- ## 2026-07 — tracker archaeology (issues 1–83)
253
-
254
- **Closure needs receipts on the issue, at closure time.** The audit found
255
- issues closed with zero receipts (#29, #34, #36, #41), an issue closed against
256
- its own last comment (#32), and closures that predated their fix (#37, #38's
257
- first close). Each needed a later archaeology pass to reconstruct. The rule
258
- this repo now follows: an issue closes with a comment naming the receipts
259
- (tests, docs, PRs, measurements) — and if part of the scope is deferred, the
260
- follow-up issue is filed *in the same action* (#87–#90 are the back-fill for
261
- past deferrals).
262
-
263
- **A pass that mutates geometry owns the consequences of the mutation.** Three
264
- post-freeze repairs re-routed edges and dropped their certificates without
265
- re-issuing them (#83); the shove pass moved nodes and left overlaps behind
266
- (#81). The doctrine that fixed both: any pass that mutates layout state must
267
- hand every invariant on — re-anchor the edges it moves, re-certify the routes
268
- it rewrites, re-separate the boxes it displaces. "A later pass will catch it"
269
- is how symptom-repair whack-a-mole starts.
270
-
271
- **Fix the invariant upstream, keep the net downstream.** The #81 degenerate
272
- class (18 fuzz signatures) collapsed to zero by restoring one upstream
273
- invariant (no node overlaps after a shove) — after a session of fixing
274
- individual routing symptoms had removed only one sub-class. The post-freeze
275
- nets stay as insurance, but they are gated on violations that should never
276
- occur, not used as the primary mechanism.
@@ -1,82 +0,0 @@
1
- # Releasing `agentic-mermaid` to npm
2
-
3
- The package is published by [`.github/workflows/publish.yml`](../../.github/workflows/publish.yml),
4
- which triggers on a **published GitHub Release**. The workflow reproduces CI's
5
- deterministic gate (tests, `tsc`, `hero:check`, `website:check`, golden-drift,
6
- incremental mutation), fuzzes the built bundle + packed tarball under Node,
7
- builds with `tsup`, and runs `npm publish --access public`. There is no manual
8
- `npm publish` step. After npm succeeds, a separate dependent job publishes
9
- [`server.json`](../../server.json) to the official MCP Registry. Keeping that
10
- step separate lets a failed registry publication be retried without attempting
11
- to republish an immutable npm version.
12
-
13
- Publishing uses **npm OIDC trusted publishing** — no `NPM_TOKEN` secret. The
14
- workflow mints a short-lived OIDC id-token (`permissions: id-token: write`), npm
15
- verifies it against the trusted-publisher config, and **provenance is generated
16
- automatically** (no `--provenance` flag).
17
-
18
- ## Preconditions (one-time, before the first release)
19
-
20
- - **Register the trusted publisher on npmjs.com.** On the (first-time: create the
21
- placeholder package, or use the org's package settings) package's
22
- Settings → Publishing access → "Add trusted publisher" → GitHub Actions, set:
23
- organization/user `adewale`, repository `agentic-mermaid`, workflow filename
24
- `publish.yml` (leave environment blank). This must be done before the first
25
- `npm publish` or it fails with an auth error.
26
- - **The GitHub repo must be public.** Provenance writes to a public transparency
27
- log and is **not** generated for private repos. If the repo must stay private,
28
- publishing works but without provenance.
29
- - **Three-way repository match.** The OIDC token's repo, the npmjs.com
30
- trusted-publisher config, and `package.json#repository.url`
31
- (`git+https://github.com/adewale/agentic-mermaid.git`) must all agree — they do.
32
- - **Account 2FA** on the publishing account (WebAuthn/FIDO; TOTP is being
33
- deprecated).
34
- - `npm view agentic-mermaid version` — confirm the version isn't already
35
- published (first release: expect a 404).
36
-
37
- The workflow pins Node 22 and upgrades to the latest npm (trusted publishing
38
- needs npm ≥ 11.5.1 / Node ≥ 22.14).
39
-
40
- ## Cutting a release
41
-
42
- 1. **Land everything on `main` green.** Releases are cut from `main`, whose CI
43
- has already run; `publish.yml` re-runs the deterministic gate + artifact fuzz
44
- as a backstop.
45
- 2. **Bump the package and MCP server versions together.** Update `version` in
46
- `package.json`, the top-level `version` in `server.json`, and
47
- `packages[0].version` in `server.json`. The readiness tests require an exact
48
- match. `llms.txt` / `am capabilities` derive the version from `package.json`,
49
- so no manual edit is needed for those files.
50
- 3. **Roll the changelog.** Retitle `## Unreleased` in
51
- [`CHANGELOG.md`](../../CHANGELOG.md) to `## <version> — <YYYY-MM-DD>` and open a
52
- fresh empty `## Unreleased` above it.
53
- 4. **Flip the "published" copy** (see below), commit via PR, and merge to `main`.
54
- 5. **Create the GitHub Release** on the merge commit (tag `v<version>`). Its
55
- publication fires `publish.yml`, which gates, builds, publishes to npm, and
56
- then publishes the matching server metadata to the MCP Registry.
57
- 6. **Verify:** `npm view agentic-mermaid version` shows the new version;
58
- `npm install agentic-mermaid` into a scratch project resolves and its bins
59
- run; and
60
- `curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.adewale/agentic-mermaid"`
61
- returns the matching server and version. The official registry is still in
62
- preview, so verify its record after every release.
63
- 7. **After the first publish,** set the package on npmjs.com to
64
- "Require two-factor authentication and disallow tokens" — trusted publishing
65
- keeps working, and token-based publishing is locked out.
66
-
67
- ## The "published" flip
68
-
69
- Before the first npm publish, the repo deliberately said *"not yet published;
70
- install from source"*. The 0.1.0 release-prep PR flips these surfaces to the
71
- published copy:
72
-
73
- - **Website** — the install card is generated by [`website/build.ts`](../../website/build.ts)
74
- (run via `bun run website`, deployed to Cloudflare Workers with `wrangler` via
75
- [`.github/workflows/deploy-cloudflare.yml`](../../.github/workflows/deploy-cloudflare.yml)).
76
- The default release build shows `npm i agentic-mermaid`; use
77
- `SITE_NPM_STATUS=source` or `SITE_NPM_PUBLISHED=0` only for pre-publish source
78
- install previews.
79
- - **README** — npm-install-first [Installation](../../README.md#installation)
80
- copy and the `Published on npm as agentic-mermaid` status line.
81
- - **`docs/getting-started.md`** — `npm install agentic-mermaid` is the primary
82
- Install block.
@@ -1,53 +0,0 @@
1
- # Visual review evidence
2
-
3
- Agentic Mermaid layout changes need evidence that is reproducible from source,
4
- not hand-edited screenshots. Use the smallest artifact that matches the change.
5
-
6
- ## Required evidence by change type
7
-
8
- | Change type | Required evidence |
9
- |---|---|
10
- | Route contracts, ports, shape anchors, or contact geometry | `bun test src/__tests__/route-contracts.test.ts src/__tests__/contact-sheet.test.ts`; regenerate/review `docs/pr-assets/contact-sheet.png` when scenarios or geometry intentionally change. |
11
- | Duplicate / parallel edges (a multigraph — the same directed pair written more than once) | `bun test src/__tests__/route-contracts.test.ts`; review the duplicate/parallel cases on the contact sheet (`AP`–`AR`) and the crossing ratchet in `layout-rubric.test.ts`. A duplicate-specific before/after lives at `docs/pr-assets/issue-62-duplicate-edge-lanes-before-after.png` (regenerate with `bun run scripts/pr-assets/issue-62-evidence.ts`). |
12
- | ASCII/Unicode routing or region metadata | Exact goldens/tests: `bun run goldens:ascii:check` plus relevant `src/__tests__/ascii*.test.ts` / `agent-ascii-meta.test.ts`. |
13
- | Family renderer/layout changes | Family parser/layout/renderer tests, SVG snapshot where available, and `agent-family-layouts.test.ts`. |
14
- | Broad layout heuristics | `bun run rubric:visual` and/or `eval/layout-compare` before/after output attached to the PR. Commit only small canonical assets; attach large HTML reports as artifacts. |
15
- | Website/editor visual changes | `bun test e2e/browser.test.ts`; inspect captured screenshots when baselines or UI structure change. |
16
- | Region/action metadata only | Prefer JSON/SVG metadata assertions over raster screenshots; include one representative fixture proving stable `data-region`/sidecar IDs. |
17
-
18
- ## Artifact meanings
19
-
20
- - `docs/pr-assets/contact-sheet.png` is the committed reviewer contact sheet for route/port geometry. The byte-match test ensures it reflects the current renderer. Scenarios `AP`–`AR` cover duplicate/parallel edges: duplicates must render as evenly-separated, nested (non-crossing) parallel lanes — never a collapsed single line or a crossed pair.
21
- - The duplicate-edge crossing ratchet (`layout-rubric.test.ts`) counts duplicate-pair crossings over the random-flowchart generator and holds the count at or below its pinned baseline. Duplicate edges share both endpoints, so a crossing between them is never logically required; the baseline is a regression ceiling whose target is zero — lower it when the count drops.
22
- - `eval/visual-rubric` produces deterministic scored galleries. Its scores are a gate for obvious regressions, not a replacement for human review.
23
- - `eval/layout-compare` compares before/after layout faithfulness and quality over a corpus. “0 regressions” means no configured metric/faithfulness regression, not a claim of pixel parity with Mermaid.js.
24
- - Browser screenshots prove the shipped site/editor still renders and remains usable. Pixel-diff is only active when dependencies are available, so reviewer inspection still matters.
25
-
26
- ## Golden-snapshot drift gate (`[approve-goldens]`)
27
-
28
- Committed goldens under `src/__tests__/testdata/` are a **hard CI gate**, not an
29
- ignorable warning. The `ci.yml` "Golden snapshot drift" step fails the build if:
30
-
31
- - running the suite leaves **uncommitted** changes under `testdata/` (regenerate
32
- and commit them), or
33
- - the PR's HEAD commit **modifies** committed goldens **without** an approval
34
- line starting with `[approve-goldens]`.
35
-
36
- So when a renderer change legitimately moves goldens: regenerate them, **review
37
- the diff** (this is the human decision the gate enforces), commit the result,
38
- and **start a commit-message line** with `[approve-goldens]`. The token only
39
- counts at the start of a line — merely mentioning it mid-sentence (as this doc
40
- does) is not approval, so prose about the gate can't trip it. A standalone
41
- `[approve-goldens]` line on a commit that changes no goldens also fails, to keep
42
- the token meaningful. The gate logic lives in `scripts/ci/golden-drift.ts` and is
43
- unit-tested; the PR template restates it as a checklist item.
44
-
45
- ## Reviewer checklist
46
-
47
- 1. Does the PR say which visual command was run?
48
- 2. Are generated artifacts reproducible from committed source/fixtures?
49
- 3. If a committed PNG/snapshot changed, is the change explained in the PR body?
50
- 4. If a visual check is skipped, is there a reason and an alternate structural test?
51
- 5. Are large generated reports linked/attached rather than committed?
52
- 6. For peer fan-in/fan-out screenshots, is the hub centered over the peer group?
53
- 7. Does the review wrapper match the rendered diagram background, or use a neutral surface, so it does not create false label/background contrast?