merm 0.1.0__tar.gz

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 (552) hide show
  1. merm-0.1.0/.claude/agents/product-manager.md +95 -0
  2. merm-0.1.0/.claude/agents/software-engineer.md +91 -0
  3. merm-0.1.0/.claude/agents/tester.md +101 -0
  4. merm-0.1.0/.github/workflows/test.yml +18 -0
  5. merm-0.1.0/.gitignore +16 -0
  6. merm-0.1.0/Makefile +25 -0
  7. merm-0.1.0/PKG-INFO +91 -0
  8. merm-0.1.0/README.md +68 -0
  9. merm-0.1.0/benchmark/README.md +43 -0
  10. merm-0.1.0/benchmark/results/benchmark_20260306_061159.json +389 -0
  11. merm-0.1.0/benchmark/run_benchmark.py +319 -0
  12. merm-0.1.0/benchmark/scenarios/large_chain_50.mmd +11 -0
  13. merm-0.1.0/benchmark/scenarios/lr_complex.mmd +16 -0
  14. merm-0.1.0/benchmark/scenarios/medium_branching.mmd +12 -0
  15. merm-0.1.0/benchmark/scenarios/mixed_shapes.mmd +13 -0
  16. merm-0.1.0/benchmark/scenarios/nested_subgraphs.mmd +28 -0
  17. merm-0.1.0/benchmark/scenarios/small_linear.mmd +2 -0
  18. merm-0.1.0/benchmark/scenarios/wide_fan.mmd +15 -0
  19. merm-0.1.0/docs/PROCESS.md +144 -0
  20. merm-0.1.0/docs/class_demo.png +0 -0
  21. merm-0.1.0/docs/class_demo.svg +72 -0
  22. merm-0.1.0/docs/comparison_gallery.html +802 -0
  23. merm-0.1.0/docs/comparison_report.md +118 -0
  24. merm-0.1.0/docs/demo.png +0 -0
  25. merm-0.1.0/docs/demo.svg +62 -0
  26. merm-0.1.0/problem.md +76 -0
  27. merm-0.1.0/pyproject.toml +67 -0
  28. merm-0.1.0/scripts/regenerate_corpus_references.sh +85 -0
  29. merm-0.1.0/scripts/regenerate_references.sh +37 -0
  30. merm-0.1.0/scripts/render_comparison.py +276 -0
  31. merm-0.1.0/scripts/run_mutation_tests.sh +29 -0
  32. merm-0.1.0/src/merm/__init__.py +93 -0
  33. merm-0.1.0/src/merm/__version__.py +1 -0
  34. merm-0.1.0/src/merm/cli.py +148 -0
  35. merm-0.1.0/src/merm/icons/__init__.py +161 -0
  36. merm-0.1.0/src/merm/icons/arrow-down.svg +3 -0
  37. merm-0.1.0/src/merm/icons/arrow-left.svg +3 -0
  38. merm-0.1.0/src/merm/icons/arrow-right.svg +3 -0
  39. merm-0.1.0/src/merm/icons/arrow-up.svg +3 -0
  40. merm-0.1.0/src/merm/icons/ban.svg +3 -0
  41. merm-0.1.0/src/merm/icons/bell.svg +3 -0
  42. merm-0.1.0/src/merm/icons/bolt.svg +3 -0
  43. merm-0.1.0/src/merm/icons/bookmark.svg +3 -0
  44. merm-0.1.0/src/merm/icons/bug.svg +3 -0
  45. merm-0.1.0/src/merm/icons/calendar.svg +3 -0
  46. merm-0.1.0/src/merm/icons/camera.svg +3 -0
  47. merm-0.1.0/src/merm/icons/car.svg +3 -0
  48. merm-0.1.0/src/merm/icons/cart-shopping.svg +3 -0
  49. merm-0.1.0/src/merm/icons/check.svg +3 -0
  50. merm-0.1.0/src/merm/icons/circle-check.svg +3 -0
  51. merm-0.1.0/src/merm/icons/circle-info.svg +3 -0
  52. merm-0.1.0/src/merm/icons/circle-question.svg +3 -0
  53. merm-0.1.0/src/merm/icons/circle-xmark.svg +3 -0
  54. merm-0.1.0/src/merm/icons/clock.svg +3 -0
  55. merm-0.1.0/src/merm/icons/cloud.svg +3 -0
  56. merm-0.1.0/src/merm/icons/code.svg +3 -0
  57. merm-0.1.0/src/merm/icons/comment.svg +3 -0
  58. merm-0.1.0/src/merm/icons/database.svg +3 -0
  59. merm-0.1.0/src/merm/icons/download.svg +3 -0
  60. merm-0.1.0/src/merm/icons/envelope.svg +3 -0
  61. merm-0.1.0/src/merm/icons/eye.svg +3 -0
  62. merm-0.1.0/src/merm/icons/file.svg +3 -0
  63. merm-0.1.0/src/merm/icons/fire.svg +3 -0
  64. merm-0.1.0/src/merm/icons/flag.svg +3 -0
  65. merm-0.1.0/src/merm/icons/folder.svg +3 -0
  66. merm-0.1.0/src/merm/icons/gear.svg +3 -0
  67. merm-0.1.0/src/merm/icons/gift.svg +3 -0
  68. merm-0.1.0/src/merm/icons/globe.svg +3 -0
  69. merm-0.1.0/src/merm/icons/heart.svg +3 -0
  70. merm-0.1.0/src/merm/icons/house.svg +3 -0
  71. merm-0.1.0/src/merm/icons/image.svg +3 -0
  72. merm-0.1.0/src/merm/icons/laptop.svg +3 -0
  73. merm-0.1.0/src/merm/icons/link.svg +3 -0
  74. merm-0.1.0/src/merm/icons/lock.svg +3 -0
  75. merm-0.1.0/src/merm/icons/magnifying-glass.svg +3 -0
  76. merm-0.1.0/src/merm/icons/minus.svg +3 -0
  77. merm-0.1.0/src/merm/icons/mobile.svg +3 -0
  78. merm-0.1.0/src/merm/icons/phone.svg +3 -0
  79. merm-0.1.0/src/merm/icons/plus.svg +3 -0
  80. merm-0.1.0/src/merm/icons/server.svg +3 -0
  81. merm-0.1.0/src/merm/icons/share.svg +3 -0
  82. merm-0.1.0/src/merm/icons/shield.svg +3 -0
  83. merm-0.1.0/src/merm/icons/spinner.svg +3 -0
  84. merm-0.1.0/src/merm/icons/star.svg +3 -0
  85. merm-0.1.0/src/merm/icons/tag.svg +3 -0
  86. merm-0.1.0/src/merm/icons/terminal.svg +3 -0
  87. merm-0.1.0/src/merm/icons/thumbs-down.svg +3 -0
  88. merm-0.1.0/src/merm/icons/thumbs-up.svg +3 -0
  89. merm-0.1.0/src/merm/icons/trash.svg +3 -0
  90. merm-0.1.0/src/merm/icons/tree.svg +3 -0
  91. merm-0.1.0/src/merm/icons/triangle-exclamation.svg +3 -0
  92. merm-0.1.0/src/merm/icons/unlock.svg +3 -0
  93. merm-0.1.0/src/merm/icons/upload.svg +3 -0
  94. merm-0.1.0/src/merm/icons/user.svg +3 -0
  95. merm-0.1.0/src/merm/icons/wrench.svg +3 -0
  96. merm-0.1.0/src/merm/icons/xmark.svg +3 -0
  97. merm-0.1.0/src/merm/ir/__init__.py +56 -0
  98. merm-0.1.0/src/merm/ir/classdiag.py +72 -0
  99. merm-0.1.0/src/merm/ir/enums.py +66 -0
  100. merm-0.1.0/src/merm/ir/erdiag.py +74 -0
  101. merm-0.1.0/src/merm/ir/gantt.py +32 -0
  102. merm-0.1.0/src/merm/ir/gitgraph.py +40 -0
  103. merm-0.1.0/src/merm/ir/mindmap.py +30 -0
  104. merm-0.1.0/src/merm/ir/pie.py +20 -0
  105. merm-0.1.0/src/merm/ir/sequence.py +76 -0
  106. merm-0.1.0/src/merm/ir/statediag.py +59 -0
  107. merm-0.1.0/src/merm/ir/types.py +94 -0
  108. merm-0.1.0/src/merm/layout/__init__.py +29 -0
  109. merm-0.1.0/src/merm/layout/classdiag.py +188 -0
  110. merm-0.1.0/src/merm/layout/config.py +21 -0
  111. merm-0.1.0/src/merm/layout/erdiag.py +164 -0
  112. merm-0.1.0/src/merm/layout/gitgraph.py +168 -0
  113. merm-0.1.0/src/merm/layout/mindmap.py +156 -0
  114. merm-0.1.0/src/merm/layout/sequence.py +373 -0
  115. merm-0.1.0/src/merm/layout/statediag.py +168 -0
  116. merm-0.1.0/src/merm/layout/sugiyama.py +1696 -0
  117. merm-0.1.0/src/merm/layout/types.py +52 -0
  118. merm-0.1.0/src/merm/measure/__init__.py +5 -0
  119. merm-0.1.0/src/merm/measure/text.py +249 -0
  120. merm-0.1.0/src/merm/parser/__init__.py +18 -0
  121. merm-0.1.0/src/merm/parser/classdiag.py +469 -0
  122. merm-0.1.0/src/merm/parser/erdiag.py +261 -0
  123. merm-0.1.0/src/merm/parser/flowchart.py +899 -0
  124. merm-0.1.0/src/merm/parser/gantt.py +229 -0
  125. merm-0.1.0/src/merm/parser/gitgraph.py +215 -0
  126. merm-0.1.0/src/merm/parser/mindmap.py +139 -0
  127. merm-0.1.0/src/merm/parser/pie.py +94 -0
  128. merm-0.1.0/src/merm/parser/sequence.py +309 -0
  129. merm-0.1.0/src/merm/parser/statediag.py +314 -0
  130. merm-0.1.0/src/merm/render/__init__.py +7 -0
  131. merm-0.1.0/src/merm/render/classdiag.py +514 -0
  132. merm-0.1.0/src/merm/render/edges.py +539 -0
  133. merm-0.1.0/src/merm/render/erdiag.py +456 -0
  134. merm-0.1.0/src/merm/render/gantt.py +245 -0
  135. merm-0.1.0/src/merm/render/gitgraph.py +187 -0
  136. merm-0.1.0/src/merm/render/mindmap.py +220 -0
  137. merm-0.1.0/src/merm/render/pie.py +147 -0
  138. merm-0.1.0/src/merm/render/sequence.py +454 -0
  139. merm-0.1.0/src/merm/render/shapes.py +468 -0
  140. merm-0.1.0/src/merm/render/statediag.py +375 -0
  141. merm-0.1.0/src/merm/render/svg.py +495 -0
  142. merm-0.1.0/src/merm/theme.py +61 -0
  143. merm-0.1.0/tasks/done/01-project-setup.done.md +91 -0
  144. merm-0.1.0/tasks/done/02-comparison-test-infra.done.md +93 -0
  145. merm-0.1.0/tasks/done/03-intermediate-representation.done.md +109 -0
  146. merm-0.1.0/tasks/done/04-flowchart-parser.done.md +221 -0
  147. merm-0.1.0/tasks/done/05-text-measurement.done.md +132 -0
  148. merm-0.1.0/tasks/done/06-sugiyama-layout.done.md +150 -0
  149. merm-0.1.0/tasks/done/07-svg-renderer-core.done.md +145 -0
  150. merm-0.1.0/tasks/done/08-node-shape-renderers.done.md +142 -0
  151. merm-0.1.0/tasks/done/09-edge-renderers.done.md +168 -0
  152. merm-0.1.0/tasks/done/10-subgraph-support.done.md +90 -0
  153. merm-0.1.0/tasks/done/11-styling-support.done.md +95 -0
  154. merm-0.1.0/tasks/done/12-cli-interface.done.md +100 -0
  155. merm-0.1.0/tasks/done/13-integration-tests.done.md +97 -0
  156. merm-0.1.0/tasks/done/14-sequence-diagram.done.md +140 -0
  157. merm-0.1.0/tasks/done/15-class-diagram.done.md +111 -0
  158. merm-0.1.0/tasks/done/16-state-diagram.done.md +103 -0
  159. merm-0.1.0/tasks/done/17-code-restructure.done.md +69 -0
  160. merm-0.1.0/tasks/done/18-svg-visual-quality.done.md +157 -0
  161. merm-0.1.0/tasks/done/19-comprehensive-comparison-tests.done.md +188 -0
  162. merm-0.1.0/tasks/done/20-font-awesome-icons.done.md +56 -0
  163. merm-0.1.0/tasks/done/21-visual-comparison.done.md +52 -0
  164. merm-0.1.0/tasks/done/22-node-sizing-and-text-rendering.done.md +89 -0
  165. merm-0.1.0/tasks/done/23-disconnected-component-layout.done.md +111 -0
  166. merm-0.1.0/tasks/done/24-self-loop-rendering.done.md +72 -0
  167. merm-0.1.0/tasks/done/25-arrowhead-and-edge-stroke-scaling.done.md +92 -0
  168. merm-0.1.0/tasks/done/26-horizontal-direction-layout-lr-rl.done.md +53 -0
  169. merm-0.1.0/tasks/done/27-subgraph-boundary-and-title-rendering.done.md +101 -0
  170. merm-0.1.0/tasks/done/28-edge-label-overlap-and-positioning.done.md +48 -0
  171. merm-0.1.0/tasks/done/29-inter-layer-spacing.done.md +50 -0
  172. merm-0.1.0/tasks/done/30-text-missing-from-mmdc-reference.done.md +50 -0
  173. merm-0.1.0/tasks/done/31-svg-emoji-support.done.md +121 -0
  174. merm-0.1.0/tasks/done/32-text-clipping-outside-viewport.done.md +46 -0
  175. merm-0.1.0/tasks/done/33-text-overflow-in-shapes.done.md +87 -0
  176. merm-0.1.0/tasks/done/34-back-edge-routing.done.md +97 -0
  177. merm-0.1.0/tasks/done/35-empty-node-text-missing.done.md +46 -0
  178. merm-0.1.0/tasks/done/36-lr-subgraph-overlap.done.md +120 -0
  179. merm-0.1.0/tasks/done/37-arrow-node-gap.done.md +65 -0
  180. merm-0.1.0/tasks/done/38-self-loop-shape-and-stroke.done.md +81 -0
  181. merm-0.1.0/tasks/done/39-subgraph-title-clipping-and-boundary-width.done.md +54 -0
  182. merm-0.1.0/tasks/done/40-long-text-wrapping-and-node-sizing.done.md +38 -0
  183. merm-0.1.0/tasks/done/41-html-entity-escaping.done.md +67 -0
  184. merm-0.1.0/tasks/done/42-edge-endpoint-precision.done.md +109 -0
  185. merm-0.1.0/tasks/done/43-edge-label-positioning-and-overlap.done.md +104 -0
  186. merm-0.1.0/tasks/done/44-expand-test-corpus.done.md +77 -0
  187. merm-0.1.0/tasks/done/45-er-diagram-support.done.md +306 -0
  188. merm-0.1.0/tasks/done/46-pie-chart-support.done.md +209 -0
  189. merm-0.1.0/tasks/done/47-gantt-chart-support.done.md +277 -0
  190. merm-0.1.0/tasks/done/48-mindmap-support.done.md +208 -0
  191. merm-0.1.0/tasks/done/49-gitgraph-support.done.md +312 -0
  192. merm-0.1.0/tasks/done/50-class-diagram-rendering-quality.done.md +138 -0
  193. merm-0.1.0/tasks/done/51-flowchart-rendering-quality.done.md +150 -0
  194. merm-0.1.0/tasks/done/52-edge-node-connection-gap.done.md +140 -0
  195. merm-0.1.0/tasks/done/53-edge-label-overlap-and-visibility.done.md +95 -0
  196. merm-0.1.0/tasks/done/54-sequence-diagram-text-and-sizing.done.md +171 -0
  197. merm-0.1.0/tasks/done/55-lr-subgraph-layout-broken.done.md +108 -0
  198. merm-0.1.0/tasks/done/56-mutation-testing.done.md +53 -0
  199. merm-0.1.0/tasks/done/57-extract-icon-svgs-to-files.done.md +34 -0
  200. merm-0.1.0/tasks/done/58-remove-future-annotations.done.md +29 -0
  201. merm-0.1.0/tasks/plan.md +182 -0
  202. merm-0.1.0/tests/__init__.py +0 -0
  203. merm-0.1.0/tests/comparison.py +669 -0
  204. merm-0.1.0/tests/fixtures/.gitkeep +0 -0
  205. merm-0.1.0/tests/fixtures/corpus/basic/diamond.mmd +5 -0
  206. merm-0.1.0/tests/fixtures/corpus/basic/fan_in.mmd +6 -0
  207. merm-0.1.0/tests/fixtures/corpus/basic/fan_out.mmd +6 -0
  208. merm-0.1.0/tests/fixtures/corpus/basic/linear_chain.mmd +2 -0
  209. merm-0.1.0/tests/fixtures/corpus/basic/parallel_paths.mmd +3 -0
  210. merm-0.1.0/tests/fixtures/corpus/basic/self_loop.mmd +2 -0
  211. merm-0.1.0/tests/fixtures/corpus/basic/single_node.mmd +2 -0
  212. merm-0.1.0/tests/fixtures/corpus/basic/two_nodes.mmd +2 -0
  213. merm-0.1.0/tests/fixtures/corpus/class/all_relationships.mmd +7 -0
  214. merm-0.1.0/tests/fixtures/corpus/class/annotations.mmd +18 -0
  215. merm-0.1.0/tests/fixtures/corpus/class/basic.mmd +11 -0
  216. merm-0.1.0/tests/fixtures/corpus/class/cardinality.mmd +21 -0
  217. merm-0.1.0/tests/fixtures/corpus/class/complex.mmd +23 -0
  218. merm-0.1.0/tests/fixtures/corpus/class/inheritance.mmd +23 -0
  219. merm-0.1.0/tests/fixtures/corpus/class/interface_realization.mmd +25 -0
  220. merm-0.1.0/tests/fixtures/corpus/class/many_members.mmd +18 -0
  221. merm-0.1.0/tests/fixtures/corpus/class/members.mmd +12 -0
  222. merm-0.1.0/tests/fixtures/corpus/class/relationships.mmd +8 -0
  223. merm-0.1.0/tests/fixtures/corpus/direction/bt.mmd +2 -0
  224. merm-0.1.0/tests/fixtures/corpus/direction/lr.mmd +2 -0
  225. merm-0.1.0/tests/fixtures/corpus/direction/rl.mmd +2 -0
  226. merm-0.1.0/tests/fixtures/corpus/direction/tb.mmd +2 -0
  227. merm-0.1.0/tests/fixtures/corpus/direction/td.mmd +2 -0
  228. merm-0.1.0/tests/fixtures/corpus/edges/arrow.mmd +3 -0
  229. merm-0.1.0/tests/fixtures/corpus/edges/circle_endpoint.mmd +3 -0
  230. merm-0.1.0/tests/fixtures/corpus/edges/cross_endpoint.mmd +3 -0
  231. merm-0.1.0/tests/fixtures/corpus/edges/dotted.mmd +3 -0
  232. merm-0.1.0/tests/fixtures/corpus/edges/invisible.mmd +3 -0
  233. merm-0.1.0/tests/fixtures/corpus/edges/labeled_edges.mmd +6 -0
  234. merm-0.1.0/tests/fixtures/corpus/edges/open_link.mmd +3 -0
  235. merm-0.1.0/tests/fixtures/corpus/edges/thick.mmd +3 -0
  236. merm-0.1.0/tests/fixtures/corpus/er/all_cardinalities.mmd +6 -0
  237. merm-0.1.0/tests/fixtures/corpus/er/attributes.mmd +12 -0
  238. merm-0.1.0/tests/fixtures/corpus/er/basic.mmd +3 -0
  239. merm-0.1.0/tests/fixtures/corpus/er/complex.mmd +34 -0
  240. merm-0.1.0/tests/fixtures/corpus/er/dashed_lines.mmd +4 -0
  241. merm-0.1.0/tests/fixtures/corpus/flowchart/api_request.mmd +12 -0
  242. merm-0.1.0/tests/fixtures/corpus/flowchart/ci_pipeline.mmd +18 -0
  243. merm-0.1.0/tests/fixtures/corpus/flowchart/coffee_machine.mmd +8 -0
  244. merm-0.1.0/tests/fixtures/corpus/flowchart/debug_loop.mmd +8 -0
  245. merm-0.1.0/tests/fixtures/corpus/flowchart/elt_bigquery.mmd +16 -0
  246. merm-0.1.0/tests/fixtures/corpus/flowchart/emoji.mmd +6 -0
  247. merm-0.1.0/tests/fixtures/corpus/flowchart/emoji_workflow.mmd +11 -0
  248. merm-0.1.0/tests/fixtures/corpus/flowchart/etl_postgres.mmd +14 -0
  249. merm-0.1.0/tests/fixtures/corpus/flowchart/etl_simple.mmd +3 -0
  250. merm-0.1.0/tests/fixtures/corpus/flowchart/icons.mmd +7 -0
  251. merm-0.1.0/tests/fixtures/corpus/flowchart/registration.mmd +15 -0
  252. merm-0.1.0/tests/fixtures/corpus/gantt/basic.mmd +9 -0
  253. merm-0.1.0/tests/fixtures/corpus/gantt/modifiers.mmd +12 -0
  254. merm-0.1.0/tests/fixtures/corpus/gantt/no_title.mmd +6 -0
  255. merm-0.1.0/tests/fixtures/corpus/gantt/single_section.mmd +8 -0
  256. merm-0.1.0/tests/fixtures/corpus/gitgraph/basic.mmd +4 -0
  257. merm-0.1.0/tests/fixtures/corpus/gitgraph/branching.mmd +10 -0
  258. merm-0.1.0/tests/fixtures/corpus/gitgraph/cherry_pick.mmd +9 -0
  259. merm-0.1.0/tests/fixtures/corpus/gitgraph/complex.mmd +17 -0
  260. merm-0.1.0/tests/fixtures/corpus/mindmap/basic.mmd +11 -0
  261. merm-0.1.0/tests/fixtures/corpus/mindmap/deep_tree.mmd +18 -0
  262. merm-0.1.0/tests/fixtures/corpus/mindmap/shapes.mmd +6 -0
  263. merm-0.1.0/tests/fixtures/corpus/mindmap/single_root.mmd +2 -0
  264. merm-0.1.0/tests/fixtures/corpus/pie/basic.mmd +4 -0
  265. merm-0.1.0/tests/fixtures/corpus/pie/many_slices.mmd +12 -0
  266. merm-0.1.0/tests/fixtures/corpus/pie/no_title.mmd +3 -0
  267. merm-0.1.0/tests/fixtures/corpus/pie/show_data.mmd +6 -0
  268. merm-0.1.0/tests/fixtures/corpus/pie/single_slice.mmd +2 -0
  269. merm-0.1.0/tests/fixtures/corpus/scale/large.mmd +61 -0
  270. merm-0.1.0/tests/fixtures/corpus/scale/medium.mmd +18 -0
  271. merm-0.1.0/tests/fixtures/corpus/scale/small.mmd +2 -0
  272. merm-0.1.0/tests/fixtures/corpus/sequence/activations.mmd +5 -0
  273. merm-0.1.0/tests/fixtures/corpus/sequence/arrows.mmd +9 -0
  274. merm-0.1.0/tests/fixtures/corpus/sequence/basic.mmd +4 -0
  275. merm-0.1.0/tests/fixtures/corpus/sequence/complex.mmd +26 -0
  276. merm-0.1.0/tests/fixtures/corpus/sequence/flink_late_event.mmd +20 -0
  277. merm-0.1.0/tests/fixtures/corpus/sequence/flink_late_upsert.mmd +23 -0
  278. merm-0.1.0/tests/fixtures/corpus/sequence/loops.mmd +14 -0
  279. merm-0.1.0/tests/fixtures/corpus/sequence/notes.mmd +8 -0
  280. merm-0.1.0/tests/fixtures/corpus/shapes/asymmetric.mmd +2 -0
  281. merm-0.1.0/tests/fixtures/corpus/shapes/circle.mmd +2 -0
  282. merm-0.1.0/tests/fixtures/corpus/shapes/cylinder.mmd +2 -0
  283. merm-0.1.0/tests/fixtures/corpus/shapes/diamond.mmd +2 -0
  284. merm-0.1.0/tests/fixtures/corpus/shapes/double_circle.mmd +2 -0
  285. merm-0.1.0/tests/fixtures/corpus/shapes/hexagon.mmd +2 -0
  286. merm-0.1.0/tests/fixtures/corpus/shapes/mixed_shapes.mmd +6 -0
  287. merm-0.1.0/tests/fixtures/corpus/shapes/parallelogram.mmd +2 -0
  288. merm-0.1.0/tests/fixtures/corpus/shapes/parallelogram_alt.mmd +2 -0
  289. merm-0.1.0/tests/fixtures/corpus/shapes/rect.mmd +2 -0
  290. merm-0.1.0/tests/fixtures/corpus/shapes/rounded.mmd +2 -0
  291. merm-0.1.0/tests/fixtures/corpus/shapes/stadium.mmd +2 -0
  292. merm-0.1.0/tests/fixtures/corpus/shapes/subroutine.mmd +2 -0
  293. merm-0.1.0/tests/fixtures/corpus/shapes/trapezoid.mmd +2 -0
  294. merm-0.1.0/tests/fixtures/corpus/shapes/trapezoid_alt.mmd +2 -0
  295. merm-0.1.0/tests/fixtures/corpus/state/basic.mmd +5 -0
  296. merm-0.1.0/tests/fixtures/corpus/state/choice.mmd +7 -0
  297. merm-0.1.0/tests/fixtures/corpus/state/complex.mmd +17 -0
  298. merm-0.1.0/tests/fixtures/corpus/state/fork_join.mmd +11 -0
  299. merm-0.1.0/tests/fixtures/corpus/state/nested.mmd +9 -0
  300. merm-0.1.0/tests/fixtures/corpus/styling/classdef_multiple.mmd +5 -0
  301. merm-0.1.0/tests/fixtures/corpus/styling/classdef_single.mmd +3 -0
  302. merm-0.1.0/tests/fixtures/corpus/styling/default_class.mmd +3 -0
  303. merm-0.1.0/tests/fixtures/corpus/styling/inline_style.mmd +4 -0
  304. merm-0.1.0/tests/fixtures/corpus/styling/mixed_styled_unstyled.mmd +5 -0
  305. merm-0.1.0/tests/fixtures/corpus/subgraphs/cross_boundary_edges.mmd +9 -0
  306. merm-0.1.0/tests/fixtures/corpus/subgraphs/nested_subgraphs.mmd +8 -0
  307. merm-0.1.0/tests/fixtures/corpus/subgraphs/sibling_subgraphs.mmd +8 -0
  308. merm-0.1.0/tests/fixtures/corpus/subgraphs/single_subgraph.mmd +5 -0
  309. merm-0.1.0/tests/fixtures/corpus/subgraphs/subgraph_direction.mmd +6 -0
  310. merm-0.1.0/tests/fixtures/corpus/subgraphs/subgraph_with_title.mmd +8 -0
  311. merm-0.1.0/tests/fixtures/corpus/text/long_text.mmd +2 -0
  312. merm-0.1.0/tests/fixtures/corpus/text/multiline.mmd +2 -0
  313. merm-0.1.0/tests/fixtures/corpus/text/quoted_labels.mmd +3 -0
  314. merm-0.1.0/tests/fixtures/corpus/text/short_text.mmd +2 -0
  315. merm-0.1.0/tests/fixtures/corpus/text/special_chars.mmd +2 -0
  316. merm-0.1.0/tests/fixtures/github/api_request.mmd +12 -0
  317. merm-0.1.0/tests/fixtures/github/ci_pipeline.mmd +18 -0
  318. merm-0.1.0/tests/fixtures/github/coffee_machine.mmd +8 -0
  319. merm-0.1.0/tests/fixtures/github/debug_loop.mmd +8 -0
  320. merm-0.1.0/tests/fixtures/github/elt_bigquery.mmd +16 -0
  321. merm-0.1.0/tests/fixtures/github/emoji_workflow.mmd +11 -0
  322. merm-0.1.0/tests/fixtures/github/etl_postgres.mmd +14 -0
  323. merm-0.1.0/tests/fixtures/github/etl_simple.mmd +3 -0
  324. merm-0.1.0/tests/fixtures/github/flink_late_event.mmd +20 -0
  325. merm-0.1.0/tests/fixtures/github/flink_late_upsert.mmd +23 -0
  326. merm-0.1.0/tests/fixtures/github/rag_pipeline.mmd +6 -0
  327. merm-0.1.0/tests/fixtures/github/registration.mmd +15 -0
  328. merm-0.1.0/tests/fixtures/github/xmas_tree.mmd +7 -0
  329. merm-0.1.0/tests/fixtures/multiple_shapes.mmd +5 -0
  330. merm-0.1.0/tests/fixtures/simple_flowchart.mmd +3 -0
  331. merm-0.1.0/tests/fixtures/styling.mmd +9 -0
  332. merm-0.1.0/tests/fixtures/subgraphs.mmd +8 -0
  333. merm-0.1.0/tests/mmdc-config.json +7 -0
  334. merm-0.1.0/tests/puppeteer-config.json +3 -0
  335. merm-0.1.0/tests/reference/.gitkeep +0 -0
  336. merm-0.1.0/tests/reference/corpus/basic/diamond.png +0 -0
  337. merm-0.1.0/tests/reference/corpus/basic/diamond.svg +1 -0
  338. merm-0.1.0/tests/reference/corpus/basic/fan_in.png +0 -0
  339. merm-0.1.0/tests/reference/corpus/basic/fan_in.svg +1 -0
  340. merm-0.1.0/tests/reference/corpus/basic/fan_out.png +0 -0
  341. merm-0.1.0/tests/reference/corpus/basic/fan_out.svg +1 -0
  342. merm-0.1.0/tests/reference/corpus/basic/linear_chain.png +0 -0
  343. merm-0.1.0/tests/reference/corpus/basic/linear_chain.svg +1 -0
  344. merm-0.1.0/tests/reference/corpus/basic/parallel_paths.png +0 -0
  345. merm-0.1.0/tests/reference/corpus/basic/parallel_paths.svg +1 -0
  346. merm-0.1.0/tests/reference/corpus/basic/self_loop.png +0 -0
  347. merm-0.1.0/tests/reference/corpus/basic/self_loop.svg +1 -0
  348. merm-0.1.0/tests/reference/corpus/basic/single_node.png +0 -0
  349. merm-0.1.0/tests/reference/corpus/basic/single_node.svg +1 -0
  350. merm-0.1.0/tests/reference/corpus/basic/two_nodes.png +0 -0
  351. merm-0.1.0/tests/reference/corpus/basic/two_nodes.svg +1 -0
  352. merm-0.1.0/tests/reference/corpus/class/all_relationships.png +0 -0
  353. merm-0.1.0/tests/reference/corpus/class/annotations.png +0 -0
  354. merm-0.1.0/tests/reference/corpus/class/basic.png +0 -0
  355. merm-0.1.0/tests/reference/corpus/class/cardinality.png +0 -0
  356. merm-0.1.0/tests/reference/corpus/class/complex.png +0 -0
  357. merm-0.1.0/tests/reference/corpus/class/inheritance.png +0 -0
  358. merm-0.1.0/tests/reference/corpus/class/interface_realization.png +0 -0
  359. merm-0.1.0/tests/reference/corpus/class/many_members.png +0 -0
  360. merm-0.1.0/tests/reference/corpus/class/members.png +0 -0
  361. merm-0.1.0/tests/reference/corpus/class/relationships.png +0 -0
  362. merm-0.1.0/tests/reference/corpus/direction/bt.png +0 -0
  363. merm-0.1.0/tests/reference/corpus/direction/bt.svg +1 -0
  364. merm-0.1.0/tests/reference/corpus/direction/lr.png +0 -0
  365. merm-0.1.0/tests/reference/corpus/direction/lr.svg +1 -0
  366. merm-0.1.0/tests/reference/corpus/direction/rl.png +0 -0
  367. merm-0.1.0/tests/reference/corpus/direction/rl.svg +1 -0
  368. merm-0.1.0/tests/reference/corpus/direction/tb.png +0 -0
  369. merm-0.1.0/tests/reference/corpus/direction/tb.svg +1 -0
  370. merm-0.1.0/tests/reference/corpus/direction/td.png +0 -0
  371. merm-0.1.0/tests/reference/corpus/direction/td.svg +1 -0
  372. merm-0.1.0/tests/reference/corpus/edges/arrow.png +0 -0
  373. merm-0.1.0/tests/reference/corpus/edges/arrow.svg +1 -0
  374. merm-0.1.0/tests/reference/corpus/edges/circle_endpoint.png +0 -0
  375. merm-0.1.0/tests/reference/corpus/edges/circle_endpoint.svg +1 -0
  376. merm-0.1.0/tests/reference/corpus/edges/cross_endpoint.png +0 -0
  377. merm-0.1.0/tests/reference/corpus/edges/cross_endpoint.svg +1 -0
  378. merm-0.1.0/tests/reference/corpus/edges/dotted.png +0 -0
  379. merm-0.1.0/tests/reference/corpus/edges/dotted.svg +1 -0
  380. merm-0.1.0/tests/reference/corpus/edges/invisible.png +0 -0
  381. merm-0.1.0/tests/reference/corpus/edges/invisible.svg +1 -0
  382. merm-0.1.0/tests/reference/corpus/edges/labeled_edges.png +0 -0
  383. merm-0.1.0/tests/reference/corpus/edges/labeled_edges.svg +1 -0
  384. merm-0.1.0/tests/reference/corpus/edges/open_link.png +0 -0
  385. merm-0.1.0/tests/reference/corpus/edges/open_link.svg +1 -0
  386. merm-0.1.0/tests/reference/corpus/edges/thick.png +0 -0
  387. merm-0.1.0/tests/reference/corpus/edges/thick.svg +1 -0
  388. merm-0.1.0/tests/reference/corpus/er/all_cardinalities.png +0 -0
  389. merm-0.1.0/tests/reference/corpus/er/attributes.png +0 -0
  390. merm-0.1.0/tests/reference/corpus/er/basic.png +0 -0
  391. merm-0.1.0/tests/reference/corpus/er/complex.png +0 -0
  392. merm-0.1.0/tests/reference/corpus/er/dashed_lines.png +0 -0
  393. merm-0.1.0/tests/reference/corpus/flowchart/api_request.png +0 -0
  394. merm-0.1.0/tests/reference/corpus/flowchart/ci_pipeline.png +0 -0
  395. merm-0.1.0/tests/reference/corpus/flowchart/coffee_machine.png +0 -0
  396. merm-0.1.0/tests/reference/corpus/flowchart/debug_loop.png +0 -0
  397. merm-0.1.0/tests/reference/corpus/flowchart/elt_bigquery.png +0 -0
  398. merm-0.1.0/tests/reference/corpus/flowchart/emoji.png +0 -0
  399. merm-0.1.0/tests/reference/corpus/flowchart/emoji_workflow.png +0 -0
  400. merm-0.1.0/tests/reference/corpus/flowchart/etl_postgres.png +0 -0
  401. merm-0.1.0/tests/reference/corpus/flowchart/etl_simple.png +0 -0
  402. merm-0.1.0/tests/reference/corpus/flowchart/icons.png +0 -0
  403. merm-0.1.0/tests/reference/corpus/flowchart/registration.png +0 -0
  404. merm-0.1.0/tests/reference/corpus/gantt/basic.png +0 -0
  405. merm-0.1.0/tests/reference/corpus/gantt/modifiers.png +0 -0
  406. merm-0.1.0/tests/reference/corpus/gantt/no_title.png +0 -0
  407. merm-0.1.0/tests/reference/corpus/gantt/single_section.png +0 -0
  408. merm-0.1.0/tests/reference/corpus/gitgraph/basic.png +0 -0
  409. merm-0.1.0/tests/reference/corpus/gitgraph/branching.png +0 -0
  410. merm-0.1.0/tests/reference/corpus/gitgraph/cherry_pick.png +0 -0
  411. merm-0.1.0/tests/reference/corpus/gitgraph/complex.png +0 -0
  412. merm-0.1.0/tests/reference/corpus/mindmap/basic.png +0 -0
  413. merm-0.1.0/tests/reference/corpus/mindmap/deep_tree.png +0 -0
  414. merm-0.1.0/tests/reference/corpus/mindmap/shapes.png +0 -0
  415. merm-0.1.0/tests/reference/corpus/mindmap/single_root.png +0 -0
  416. merm-0.1.0/tests/reference/corpus/pie/basic.png +0 -0
  417. merm-0.1.0/tests/reference/corpus/pie/many_slices.png +0 -0
  418. merm-0.1.0/tests/reference/corpus/pie/no_title.png +0 -0
  419. merm-0.1.0/tests/reference/corpus/pie/show_data.png +0 -0
  420. merm-0.1.0/tests/reference/corpus/pie/single_slice.png +0 -0
  421. merm-0.1.0/tests/reference/corpus/scale/large.png +0 -0
  422. merm-0.1.0/tests/reference/corpus/scale/large.svg +1 -0
  423. merm-0.1.0/tests/reference/corpus/scale/medium.png +0 -0
  424. merm-0.1.0/tests/reference/corpus/scale/medium.svg +1 -0
  425. merm-0.1.0/tests/reference/corpus/scale/small.png +0 -0
  426. merm-0.1.0/tests/reference/corpus/scale/small.svg +1 -0
  427. merm-0.1.0/tests/reference/corpus/sequence/activations.png +0 -0
  428. merm-0.1.0/tests/reference/corpus/sequence/arrows.png +0 -0
  429. merm-0.1.0/tests/reference/corpus/sequence/basic.png +0 -0
  430. merm-0.1.0/tests/reference/corpus/sequence/complex.png +0 -0
  431. merm-0.1.0/tests/reference/corpus/sequence/flink_late_event.png +0 -0
  432. merm-0.1.0/tests/reference/corpus/sequence/flink_late_upsert.png +0 -0
  433. merm-0.1.0/tests/reference/corpus/sequence/loops.png +0 -0
  434. merm-0.1.0/tests/reference/corpus/sequence/notes.png +0 -0
  435. merm-0.1.0/tests/reference/corpus/shapes/circle.png +0 -0
  436. merm-0.1.0/tests/reference/corpus/shapes/circle.svg +1 -0
  437. merm-0.1.0/tests/reference/corpus/shapes/cylinder.png +0 -0
  438. merm-0.1.0/tests/reference/corpus/shapes/cylinder.svg +1 -0
  439. merm-0.1.0/tests/reference/corpus/shapes/diamond.png +0 -0
  440. merm-0.1.0/tests/reference/corpus/shapes/diamond.svg +1 -0
  441. merm-0.1.0/tests/reference/corpus/shapes/double_circle.png +0 -0
  442. merm-0.1.0/tests/reference/corpus/shapes/double_circle.svg +1 -0
  443. merm-0.1.0/tests/reference/corpus/shapes/hexagon.png +0 -0
  444. merm-0.1.0/tests/reference/corpus/shapes/hexagon.svg +1 -0
  445. merm-0.1.0/tests/reference/corpus/shapes/mixed_shapes.png +0 -0
  446. merm-0.1.0/tests/reference/corpus/shapes/mixed_shapes.svg +1 -0
  447. merm-0.1.0/tests/reference/corpus/shapes/parallelogram.png +0 -0
  448. merm-0.1.0/tests/reference/corpus/shapes/parallelogram.svg +1 -0
  449. merm-0.1.0/tests/reference/corpus/shapes/parallelogram_alt.png +0 -0
  450. merm-0.1.0/tests/reference/corpus/shapes/parallelogram_alt.svg +1 -0
  451. merm-0.1.0/tests/reference/corpus/shapes/rect.png +0 -0
  452. merm-0.1.0/tests/reference/corpus/shapes/rect.svg +1 -0
  453. merm-0.1.0/tests/reference/corpus/shapes/rounded.png +0 -0
  454. merm-0.1.0/tests/reference/corpus/shapes/rounded.svg +1 -0
  455. merm-0.1.0/tests/reference/corpus/shapes/stadium.png +0 -0
  456. merm-0.1.0/tests/reference/corpus/shapes/stadium.svg +1 -0
  457. merm-0.1.0/tests/reference/corpus/shapes/subroutine.png +0 -0
  458. merm-0.1.0/tests/reference/corpus/shapes/subroutine.svg +1 -0
  459. merm-0.1.0/tests/reference/corpus/shapes/trapezoid.png +0 -0
  460. merm-0.1.0/tests/reference/corpus/shapes/trapezoid.svg +1 -0
  461. merm-0.1.0/tests/reference/corpus/shapes/trapezoid_alt.png +0 -0
  462. merm-0.1.0/tests/reference/corpus/shapes/trapezoid_alt.svg +1 -0
  463. merm-0.1.0/tests/reference/corpus/state/basic.png +0 -0
  464. merm-0.1.0/tests/reference/corpus/state/choice.png +0 -0
  465. merm-0.1.0/tests/reference/corpus/state/complex.png +0 -0
  466. merm-0.1.0/tests/reference/corpus/state/fork_join.png +0 -0
  467. merm-0.1.0/tests/reference/corpus/state/nested.png +0 -0
  468. merm-0.1.0/tests/reference/corpus/styling/classdef_multiple.png +0 -0
  469. merm-0.1.0/tests/reference/corpus/styling/classdef_multiple.svg +1 -0
  470. merm-0.1.0/tests/reference/corpus/styling/classdef_single.png +0 -0
  471. merm-0.1.0/tests/reference/corpus/styling/classdef_single.svg +1 -0
  472. merm-0.1.0/tests/reference/corpus/styling/default_class.png +0 -0
  473. merm-0.1.0/tests/reference/corpus/styling/default_class.svg +1 -0
  474. merm-0.1.0/tests/reference/corpus/styling/inline_style.png +0 -0
  475. merm-0.1.0/tests/reference/corpus/styling/inline_style.svg +1 -0
  476. merm-0.1.0/tests/reference/corpus/styling/mixed_styled_unstyled.png +0 -0
  477. merm-0.1.0/tests/reference/corpus/styling/mixed_styled_unstyled.svg +1 -0
  478. merm-0.1.0/tests/reference/corpus/subgraphs/cross_boundary_edges.png +0 -0
  479. merm-0.1.0/tests/reference/corpus/subgraphs/cross_boundary_edges.svg +1 -0
  480. merm-0.1.0/tests/reference/corpus/subgraphs/nested_subgraphs.png +0 -0
  481. merm-0.1.0/tests/reference/corpus/subgraphs/nested_subgraphs.svg +1 -0
  482. merm-0.1.0/tests/reference/corpus/subgraphs/sibling_subgraphs.png +0 -0
  483. merm-0.1.0/tests/reference/corpus/subgraphs/sibling_subgraphs.svg +1 -0
  484. merm-0.1.0/tests/reference/corpus/subgraphs/single_subgraph.png +0 -0
  485. merm-0.1.0/tests/reference/corpus/subgraphs/single_subgraph.svg +1 -0
  486. merm-0.1.0/tests/reference/corpus/subgraphs/subgraph_direction.png +0 -0
  487. merm-0.1.0/tests/reference/corpus/subgraphs/subgraph_direction.svg +1 -0
  488. merm-0.1.0/tests/reference/corpus/subgraphs/subgraph_with_title.png +0 -0
  489. merm-0.1.0/tests/reference/corpus/subgraphs/subgraph_with_title.svg +1 -0
  490. merm-0.1.0/tests/reference/corpus/text/long_text.png +0 -0
  491. merm-0.1.0/tests/reference/corpus/text/long_text.svg +1 -0
  492. merm-0.1.0/tests/reference/corpus/text/multiline.png +0 -0
  493. merm-0.1.0/tests/reference/corpus/text/multiline.svg +1 -0
  494. merm-0.1.0/tests/reference/corpus/text/quoted_labels.png +0 -0
  495. merm-0.1.0/tests/reference/corpus/text/quoted_labels.svg +1 -0
  496. merm-0.1.0/tests/reference/corpus/text/short_text.png +0 -0
  497. merm-0.1.0/tests/reference/corpus/text/short_text.svg +1 -0
  498. merm-0.1.0/tests/reference/corpus/text/special_chars.png +0 -0
  499. merm-0.1.0/tests/reference/corpus/text/special_chars.svg +1 -0
  500. merm-0.1.0/tests/reference/multiple_shapes.svg +1 -0
  501. merm-0.1.0/tests/reference/simple_flowchart.svg +1 -0
  502. merm-0.1.0/tests/reference/styling.svg +1 -0
  503. merm-0.1.0/tests/reference/subgraphs.svg +1 -0
  504. merm-0.1.0/tests/test_arrow_node_gap.py +262 -0
  505. merm-0.1.0/tests/test_back_edge_routing.py +423 -0
  506. merm-0.1.0/tests/test_class_diagram_quality.py +360 -0
  507. merm-0.1.0/tests/test_classdiag.py +615 -0
  508. merm-0.1.0/tests/test_cli.py +152 -0
  509. merm-0.1.0/tests/test_comparison.py +104 -0
  510. merm-0.1.0/tests/test_corpus.py +400 -0
  511. merm-0.1.0/tests/test_corpus_rendering.py +48 -0
  512. merm-0.1.0/tests/test_edge_connection_gap.py +551 -0
  513. merm-0.1.0/tests/test_edge_endpoint_precision.py +503 -0
  514. merm-0.1.0/tests/test_edge_label_positioning.py +313 -0
  515. merm-0.1.0/tests/test_edge_stroke_scaling.py +89 -0
  516. merm-0.1.0/tests/test_edges.py +518 -0
  517. merm-0.1.0/tests/test_emoji.py +192 -0
  518. merm-0.1.0/tests/test_erdiag.py +525 -0
  519. merm-0.1.0/tests/test_flowchart_parser.py +513 -0
  520. merm-0.1.0/tests/test_flowchart_rendering_quality.py +624 -0
  521. merm-0.1.0/tests/test_gantt.py +471 -0
  522. merm-0.1.0/tests/test_gitgraph.py +427 -0
  523. merm-0.1.0/tests/test_html_entity_escaping.py +169 -0
  524. merm-0.1.0/tests/test_icon_extraction.py +135 -0
  525. merm-0.1.0/tests/test_icons.py +289 -0
  526. merm-0.1.0/tests/test_integration.py +296 -0
  527. merm-0.1.0/tests/test_ir.py +176 -0
  528. merm-0.1.0/tests/test_layout.py +545 -0
  529. merm-0.1.0/tests/test_lr_subgraph_layout.py +364 -0
  530. merm-0.1.0/tests/test_lr_subgraph_overlap.py +350 -0
  531. merm-0.1.0/tests/test_measure.py +227 -0
  532. merm-0.1.0/tests/test_mindmap.py +341 -0
  533. merm-0.1.0/tests/test_mutation_killing.py +346 -0
  534. merm-0.1.0/tests/test_node_sizing_calibration.py +259 -0
  535. merm-0.1.0/tests/test_parser.py +1 -0
  536. merm-0.1.0/tests/test_pie.py +279 -0
  537. merm-0.1.0/tests/test_render.py +469 -0
  538. merm-0.1.0/tests/test_self_loop_fix.py +325 -0
  539. merm-0.1.0/tests/test_sequence.py +568 -0
  540. merm-0.1.0/tests/test_sequence_text_sizing.py +333 -0
  541. merm-0.1.0/tests/test_shapes.py +414 -0
  542. merm-0.1.0/tests/test_smoke.py +16 -0
  543. merm-0.1.0/tests/test_statediag.py +578 -0
  544. merm-0.1.0/tests/test_styling.py +345 -0
  545. merm-0.1.0/tests/test_subgraph.py +447 -0
  546. merm-0.1.0/tests/test_subgraph_title_clipping.py +251 -0
  547. merm-0.1.0/tests/test_svg_parsing.py +183 -0
  548. merm-0.1.0/tests/test_task53_edge_label_overlap_and_visibility.py +299 -0
  549. merm-0.1.0/tests/test_text_overflow_shapes.py +351 -0
  550. merm-0.1.0/tests/test_text_rendering_fixes.py +275 -0
  551. merm-0.1.0/tests/test_theme.py +296 -0
  552. merm-0.1.0/uv.lock +2086 -0
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: product-manager
3
+ description: Grooms .todo tasks into agent-ready .groomed specs AND does final acceptance review after tester passes.
4
+ tools: Read, Edit, Write, Bash, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ # Product Manager Agent
9
+
10
+ You have two roles:
11
+
12
+ 1. **Grooming** -- Take `.todo.md` tasks and add concrete acceptance criteria and test scenarios, then rename to `.groomed.md`.
13
+ 2. **Acceptance Review** -- After the tester passes, do a final review. Verify the implementation matches what was specified.
14
+
15
+ ## Part 1: Grooming
16
+
17
+ ### Input
18
+
19
+ A task filename (e.g. `tasks/01-project-setup.todo.md`).
20
+
21
+ ### Workflow
22
+
23
+ 1. Read the task file
24
+ 2. Read `tasks/plan.md` for overall project context
25
+ 3. Check what already exists in the codebase (if anything)
26
+ 4. Ensure the task has:
27
+ - Clear scope
28
+ - Concrete acceptance criteria (testable, specific)
29
+ - Test scenarios (what pytest tests should verify)
30
+ - Dependencies listed (which other tasks must be `.done.md` first)
31
+ - **For rendering/visual tasks:** Include visual acceptance criteria — specify which diagrams must render correctly, what the expected output should look like, and require PNG visual verification as part of testing
32
+ - **CRITICAL: Every rendering task MUST include a PNG verification criterion.** SVG source can look correct structurally but render incorrectly (marker overlap, text clipping, invisible elements). Always add: "Render to PNG with cairosvg and visually verify [specific thing]". Never accept SVG-only checks for visual tasks.
33
+ 5. If the task is missing any of the above, add them
34
+ 6. Rename: `mv tasks/NN-name.todo.md tasks/NN-name.groomed.md`
35
+
36
+ ### Acceptance Criteria Format
37
+
38
+ Every criterion must be testable:
39
+
40
+ ```markdown
41
+ ## Acceptance Criteria
42
+
43
+ - [ ] `from pymermaid.ir import Node, Edge, Diagram` works
44
+ - [ ] `Node` dataclass has fields: id, label, shape
45
+ - [ ] `uv run pytest tests/test_ir.py` passes with 10+ tests
46
+ ```
47
+
48
+ ### Test Scenarios Format
49
+
50
+ ```markdown
51
+ ## Test Scenarios
52
+
53
+ ### Unit: Node creation
54
+ - Create a Node with all fields, verify attributes
55
+ - Create a Node with minimal fields, verify defaults
56
+
57
+ ### Unit: Edge validation
58
+ - Edge with valid source/target succeeds
59
+ - Edge with empty source raises ValueError
60
+ ```
61
+
62
+ ## Part 2: Acceptance Review
63
+
64
+ ### Input
65
+
66
+ A task filename (`.in-progress.md`) and confirmation that the tester passed.
67
+
68
+ ### Workflow
69
+
70
+ 1. Read the task file for acceptance criteria
71
+ 2. Read the tester's report
72
+ 3. Review the code changes: `git diff --stat` and `git diff`
73
+ 4. Verify:
74
+ - [ ] All acceptance criteria are met
75
+ - [ ] Implementation matches the spec (not over-engineered, not under-built)
76
+ - [ ] Tests are meaningful (not just smoke tests)
77
+ - [ ] Code is clean and follows project patterns
78
+ 5. **Visual verification (for rendering/SVG tasks):**
79
+ - [ ] Render representative diagrams and **read the output SVG/PNG** yourself — do not rely solely on the tester's report
80
+ - [ ] If the task adds or modifies visual elements, convert SVG to PNG and view it to confirm it looks correct
81
+ - [ ] Compare against mmdc reference if available — check that we're not regressing
82
+ - [ ] Do NOT accept work where the output "has the right structure" but doesn't actually render correctly
83
+ 6. Verdict:
84
+ - **ACCEPT** -- Engineer can commit. Task moves to `.done.md`.
85
+ - **REJECT** -- List specific issues. Engineer must fix.
86
+
87
+ ### When to Reject
88
+
89
+ - Tester only did structural checks without visual verification on a rendering task
90
+ - SVG output renders but looks obviously wrong (overlapping elements, missing labels, broken layout)
91
+ - Tests pass but don't actually validate the visual correctness of the output
92
+ - Engineer claims something works but the PNG evidence shows otherwise
93
+ - The tester passed it with "tests pass" but the output is visually broken
94
+ - Acceptance criteria for a rendering task don't include PNG verification — reject and require the engineer to add PNG verification and confirm visually before resubmitting
95
+ - SVG was checked but PNG was not — SVG source can look fine while the actual rendered PNG shows problems (e.g., markers overlapping nodes, text outside viewport, invisible elements)
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: software-engineer
3
+ description: Implements a task from tasks/. Writes code and tests. Does NOT commit until tester passes and PM accepts.
4
+ tools: Read, Edit, Write, Bash, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ # Software Engineer Agent
9
+
10
+ You implement a single task for the pymermaid project. You receive a task filename, write the code and tests locally. You do NOT commit until the tester has reviewed and the PM has accepted.
11
+
12
+ Before starting, read `tasks/plan.md` for project context and `docs/PROCESS.md` for the development workflow.
13
+
14
+ ## Input
15
+
16
+ You receive a task filename (e.g. `tasks/03-intermediate-representation.groomed.md`).
17
+
18
+ ## Workflow
19
+
20
+ ### 1. Understand the Task
21
+
22
+ Read the task file. Understand the scope, acceptance criteria, and test scenarios.
23
+
24
+ ### 2. Implement
25
+
26
+ - Write clean, minimal code -- only what the task asks for
27
+ - Follow existing patterns in the codebase
28
+ - All code goes in `src/pymermaid/`
29
+ - Use Python 3.10+ features (dataclasses, match, type hints)
30
+ - No unnecessary dependencies
31
+
32
+ ### 3. Write Tests
33
+
34
+ Every task must include pytest tests in `tests/`.
35
+
36
+ ```bash
37
+ uv run pytest tests/ -v
38
+ ```
39
+
40
+ Tests must pass before reporting done.
41
+
42
+ ### 4. Lint
43
+
44
+ ```bash
45
+ uv run ruff check src/ tests/
46
+ ```
47
+
48
+ Fix any issues.
49
+
50
+ ### 5. Rename Task to In Progress
51
+
52
+ ```bash
53
+ mv tasks/NN-name.groomed.md tasks/NN-name.in-progress.md
54
+ ```
55
+
56
+ ### 6. Report to Orchestrator
57
+
58
+ Report:
59
+ - What files were created/modified
60
+ - Test results (count passing/failing)
61
+ - What works
62
+ - Known limitations
63
+
64
+ Do NOT commit. Wait for tester review.
65
+
66
+ ### 7. Handle Tester Feedback
67
+
68
+ When you receive feedback:
69
+ 1. Fix each issue
70
+ 2. Run tests again
71
+ 3. Report fixes
72
+
73
+ Repeat until tester passes.
74
+
75
+ ### 8. Commit (only after PM accepts)
76
+
77
+ Only after PM reports "ACCEPT":
78
+
79
+ ```bash
80
+ mv tasks/NN-name.in-progress.md tasks/NN-name.done.md
81
+ git add .
82
+ git commit -m "Implement task NN: short description"
83
+ ```
84
+
85
+ ## Rules
86
+
87
+ - Do NOT commit until PM accepts
88
+ - Implement exactly what the task asks for -- no extra features
89
+ - Every task must include tests
90
+ - Follow existing patterns
91
+ - Use `uv` for all Python commands
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: tester
3
+ description: Reviews engineer's uncommitted work against task acceptance criteria. Runs tests. Gives concrete feedback. Approves before commit.
4
+ tools: Read, Edit, Write, Bash, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ # Tester Agent
9
+
10
+ You review the software engineer's work for a specific task. The code is local and uncommitted. You verify it meets the acceptance criteria, find issues, and give concrete feedback. You iterate with the engineer until the task is complete.
11
+
12
+ Before starting, read `tasks/plan.md` for project context and `docs/PROCESS.md` for the development workflow.
13
+
14
+ ## Input
15
+
16
+ You receive a task filename (e.g. `tasks/03-intermediate-representation.in-progress.md`) and a summary of what the engineer did.
17
+
18
+ ## Workflow
19
+
20
+ ### 1. Understand What Was Expected
21
+
22
+ Read the task file for acceptance criteria.
23
+
24
+ ### 2. Review the Code
25
+
26
+ Check what changed:
27
+
28
+ ```bash
29
+ git diff --stat
30
+ git diff
31
+ ```
32
+
33
+ Verify:
34
+
35
+ #### Code Quality
36
+ - [ ] Code follows existing patterns
37
+ - [ ] Type hints present
38
+ - [ ] No unnecessary dependencies
39
+ - [ ] No hardcoded values that should be configurable
40
+
41
+ #### Tests
42
+ - [ ] Tests exist in `tests/`
43
+ - [ ] All tests pass (`uv run pytest -v`)
44
+ - [ ] Tests cover the acceptance criteria
45
+ - [ ] Edge cases tested
46
+
47
+ #### Visual Output Verification (for rendering/SVG tasks)
48
+ - [ ] Render at least 3 representative diagrams to SVG using `render_diagram()`
49
+ - [ ] Read each SVG file and verify the output is structurally valid (proper XML, no empty/broken elements)
50
+ - [ ] If the task involves SVG path data (icons, shapes, markers), verify path `d` attributes contain valid SVG path commands (M, L, C, Z, etc.), NOT placeholder text or garbage
51
+ - [ ] Convert SVGs to PNG using cairosvg and **read the PNG** to visually confirm correctness — do not trust structural checks alone
52
+ - [ ] If a reference mmdc rendering exists in `tests/reference/`, compare against it
53
+ - [ ] Any visual regression (elements missing, overlapping, misaligned) is a **FAIL**
54
+
55
+ #### Lint
56
+ - [ ] `uv run ruff check src/ tests/` passes
57
+
58
+ ### 3. Run All Tests
59
+
60
+ ```bash
61
+ uv run pytest tests/ -v
62
+ uv run ruff check src/ tests/
63
+ ```
64
+
65
+ Both must pass.
66
+
67
+ ### 4. Check Acceptance Criteria
68
+
69
+ Go through each criterion from the task. Mark pass/fail with specifics.
70
+
71
+ ### 5. Give Verdict
72
+
73
+ **FAIL** -- issues found. List each issue with what's wrong, what was expected, and how to fix it.
74
+
75
+ **PASS** -- approve for PM review. Confirm all acceptance criteria met.
76
+
77
+ ### 6. Re-review After Fixes
78
+
79
+ When the engineer applies fixes:
80
+ 1. Review changed files
81
+ 2. Run tests
82
+ 3. Check only the specific issues you flagged
83
+ 4. Verify fixes don't break anything else
84
+
85
+ ## When to Fail vs Pass
86
+
87
+ ### Always fail
88
+ - Missing tests
89
+ - Tests fail
90
+ - Core acceptance criteria not met
91
+ - Lint errors
92
+ - SVG output contains invalid/broken elements (empty paths, placeholder text in `d` attributes, missing required elements)
93
+ - Visual output doesn't render correctly when converted to PNG (cairosvg crash, blank image, missing elements)
94
+ - Tests only check structural existence (e.g. "path element exists") without verifying the content is valid/correct
95
+ - Rendered output has obvious visual defects (overlapping text, misaligned nodes, disconnected edges)
96
+
97
+ ### Pass with note (don't block)
98
+ - Minor style issues
99
+ - Edge cases not in acceptance criteria
100
+ - Could be more efficient (if it works)
101
+ - Minor visual differences from mmdc reference (different fonts, slight spacing differences)
@@ -0,0 +1,18 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: ${{ matrix.python-version }}
16
+ - run: pip install uv
17
+ - run: uv sync
18
+ - run: uv run pytest
merm-0.1.0/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ *.egg
5
+ dist/
6
+ build/
7
+ .venv/
8
+ .ruff_cache/
9
+ .pytest_cache/
10
+ *.so
11
+ .eggs/
12
+ .tmp/
13
+ docs/comparisons/
14
+ docs/comparison_scores.json
15
+ .mutmut-cache/
16
+ mutants/
merm-0.1.0/Makefile ADDED
@@ -0,0 +1,25 @@
1
+ .PHONY: test setup shell coverage publish-build publish-test publish publish-clean
2
+
3
+ test:
4
+ uv run pytest
5
+
6
+ setup:
7
+ uv sync --dev
8
+
9
+ shell:
10
+ uv shell
11
+
12
+ coverage:
13
+ uv run pytest --cov=merm --cov-report=term-missing
14
+
15
+ publish-build:
16
+ uv run hatch build
17
+
18
+ publish-test:
19
+ uv run hatch publish --repo test
20
+
21
+ publish:
22
+ uv run hatch publish
23
+
24
+ publish-clean:
25
+ rm -r dist/
merm-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: merm
3
+ Version: 0.1.0
4
+ Summary: Pure Python Mermaid diagram renderer
5
+ License-Expression: MIT
6
+ Keywords: diagram,flowchart,mermaid,sequence-diagram,svg
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Multimedia :: Graphics
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.10
18
+ Provides-Extra: fonts
19
+ Requires-Dist: fonttools; extra == 'fonts'
20
+ Provides-Extra: png
21
+ Requires-Dist: pillow; extra == 'png'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # merm
25
+
26
+ Pure Python Mermaid diagram renderer. Converts Mermaid markup to SVG with zero JavaScript dependencies.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install merm
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Command line
37
+
38
+ ```bash
39
+ # File to file
40
+ merm -i diagram.mmd -o diagram.svg
41
+
42
+ # Pipe
43
+ echo 'graph LR
44
+ A --> B --> C' | merm > diagram.svg
45
+
46
+ # With uvx (no install needed)
47
+ uvx merm -i diagram.mmd -o diagram.svg
48
+ ```
49
+
50
+ ### Python API
51
+
52
+ ```python
53
+ from merm import render_diagram
54
+
55
+ svg = render_diagram("""
56
+ flowchart TD
57
+ A[Start] --> B{Decision}
58
+ B -->|Yes| C[OK]
59
+ B -->|No| D[End]
60
+ """)
61
+ ```
62
+
63
+ ## Supported diagram types
64
+
65
+ - **Flowchart** (`graph` / `flowchart`) — all directions (TD, LR, BT, RL), subgraphs, shapes, edge labels
66
+ - **Sequence** (`sequenceDiagram`) — participants, messages, loops, alt/opt/par fragments
67
+ - **Class** (`classDiagram`) — classes, methods, attributes, relationships
68
+ - **State** (`stateDiagram`) — states, transitions, composite states, forks/joins
69
+
70
+ ## Features
71
+
72
+ - Pure Python — no Node.js, no browser, no Puppeteer
73
+ - Fast — ~200x faster than mermaid-cli (mmdc)
74
+ - SVG output with clean markup
75
+ - All flowchart shapes and edge types
76
+ - Subgraph nesting and styling
77
+ - Edge labels and arrow markers
78
+
79
+ ## Performance
80
+
81
+ Benchmarked against mermaid-cli (mmdc) across 28 scenarios:
82
+
83
+ | | merm | mmdc |
84
+ |---|---|---|
85
+ | Average render time | ~1 ms | ~200 ms |
86
+ | Dependencies | 0 | Node.js + Puppeteer |
87
+ | Startup overhead | None | ~500 ms |
88
+
89
+ ## License
90
+
91
+ MIT
merm-0.1.0/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # merm
2
+
3
+ Pure Python Mermaid diagram renderer. Converts Mermaid markup to SVG with zero JavaScript dependencies.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install merm
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Command line
14
+
15
+ ```bash
16
+ # File to file
17
+ merm -i diagram.mmd -o diagram.svg
18
+
19
+ # Pipe
20
+ echo 'graph LR
21
+ A --> B --> C' | merm > diagram.svg
22
+
23
+ # With uvx (no install needed)
24
+ uvx merm -i diagram.mmd -o diagram.svg
25
+ ```
26
+
27
+ ### Python API
28
+
29
+ ```python
30
+ from merm import render_diagram
31
+
32
+ svg = render_diagram("""
33
+ flowchart TD
34
+ A[Start] --> B{Decision}
35
+ B -->|Yes| C[OK]
36
+ B -->|No| D[End]
37
+ """)
38
+ ```
39
+
40
+ ## Supported diagram types
41
+
42
+ - **Flowchart** (`graph` / `flowchart`) — all directions (TD, LR, BT, RL), subgraphs, shapes, edge labels
43
+ - **Sequence** (`sequenceDiagram`) — participants, messages, loops, alt/opt/par fragments
44
+ - **Class** (`classDiagram`) — classes, methods, attributes, relationships
45
+ - **State** (`stateDiagram`) — states, transitions, composite states, forks/joins
46
+
47
+ ## Features
48
+
49
+ - Pure Python — no Node.js, no browser, no Puppeteer
50
+ - Fast — ~200x faster than mermaid-cli (mmdc)
51
+ - SVG output with clean markup
52
+ - All flowchart shapes and edge types
53
+ - Subgraph nesting and styling
54
+ - Edge labels and arrow markers
55
+
56
+ ## Performance
57
+
58
+ Benchmarked against mermaid-cli (mmdc) across 28 scenarios:
59
+
60
+ | | merm | mmdc |
61
+ |---|---|---|
62
+ | Average render time | ~1 ms | ~200 ms |
63
+ | Dependencies | 0 | Node.js + Puppeteer |
64
+ | Startup overhead | None | ~500 ms |
65
+
66
+ ## License
67
+
68
+ MIT
@@ -0,0 +1,43 @@
1
+ # merm Benchmarks
2
+
3
+ Performance benchmarks comparing merm (pure Python) against mmdc (mermaid-cli, Node.js + Puppeteer).
4
+
5
+ ## Running
6
+
7
+ ```bash
8
+ # Full benchmark with mmdc comparison
9
+ uv run benchmark/run_benchmark.py --save
10
+
11
+ # merm only (skip mmdc)
12
+ uv run benchmark/run_benchmark.py --no-mmdc
13
+
14
+ # Custom iterations
15
+ uv run benchmark/run_benchmark.py --iterations 200 --mmdc-iterations 5
16
+ ```
17
+
18
+ ## Scenarios
19
+
20
+ **Synthetic** (`benchmark/scenarios/`):
21
+ - `small_linear` — 5-node chain (baseline)
22
+ - `medium_branching` — fan-out/fan-in with 15 nodes
23
+ - `large_chain_50` — 50-node linear chain (stress test)
24
+ - `wide_fan` — 10-way fan with 33 nodes
25
+ - `nested_subgraphs` — 3 levels of nesting
26
+ - `mixed_shapes` — all supported shape types
27
+ - `lr_complex` — left-to-right with subgraphs
28
+
29
+ **Real-world** (`tests/fixtures/github/`):
30
+ - CI pipelines, ETL flows, API request handling, registration flows, etc.
31
+
32
+ **Corpus** (`tests/fixtures/corpus/`):
33
+ - One representative from each diagram type: sequence, class, state, ER, gantt, mindmap, gitgraph, pie
34
+
35
+ ## Results
36
+
37
+ Results are saved as JSON in `benchmark/results/` with timestamps.
38
+
39
+ Each result includes:
40
+ - `total_ms` — end-to-end render time
41
+ - `parse_ms`, `layout_ms`, `render_ms` — breakdown (flowcharts only)
42
+ - `peak_memory_bytes` — peak memory for a single render
43
+ - `mmdc.total_ms` — mmdc comparison time (when available)