agentic-mermaid 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/AGENT_NATIVE.md +155 -91
  2. package/CHANGELOG.md +163 -4
  3. package/Instructions_for_agents.md +10 -10
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/README.md +31 -38
  6. package/THIRD_PARTY_NOTICES.md +29 -0
  7. package/assets/hero.png +0 -0
  8. package/dist/agent-core.d.ts +463 -0
  9. package/dist/agent-core.js +397 -0
  10. package/dist/agent.d.ts +73 -1868
  11. package/dist/agent.js +336 -37325
  12. package/dist/agentic-mermaid-mcp.js +7 -38399
  13. package/dist/am.js +33626 -40446
  14. package/dist/chunk-2P5FKUQC.js +3485 -0
  15. package/dist/chunk-2S3VSS6I.js +149 -0
  16. package/dist/chunk-2SILJDW2.js +37 -0
  17. package/dist/chunk-BJYMBT4I.js +61963 -0
  18. package/dist/chunk-FDM43XU7.js +615 -0
  19. package/dist/chunk-MYPDVZCO.js +4702 -0
  20. package/dist/index-DWPa2MJs.d.ts +6780 -0
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +310 -33014
  23. package/dist/mcp-cli-5J47WEY3.js +17 -0
  24. package/docs/README.md +39 -31
  25. package/docs/agent-api-cookbook.md +44 -35
  26. package/docs/agent-mutation-policy.md +1 -1
  27. package/docs/agent-workflow-examples.md +2 -2
  28. package/docs/api.md +284 -77
  29. package/docs/ascii.md +26 -16
  30. package/docs/code-mode-impact.md +214 -0
  31. package/docs/comparison.md +23 -11
  32. package/docs/computational-aesthetics-prototype-plan.md +252 -0
  33. package/docs/config.md +26 -10
  34. package/docs/custom-fonts.md +265 -0
  35. package/docs/custom-style-cookbook.md +130 -9
  36. package/docs/diagram-families.md +48 -23
  37. package/docs/features.md +59 -52
  38. package/docs/fork-differences.md +6 -3
  39. package/docs/getting-started.md +23 -16
  40. package/docs/issue-derived-test-cases.md +29 -22
  41. package/docs/mcp-code-mode-rationale.md +13 -6
  42. package/docs/mcp-http-transport.md +20 -13
  43. package/docs/mermaid-layout-complaints.md +66 -52
  44. package/docs/mutation-testing.md +145 -66
  45. package/docs/quality.md +23 -14
  46. package/docs/react.md +2 -2
  47. package/docs/schemas/style-spec.schema.json +1221 -30
  48. package/docs/style-authoring.md +241 -38
  49. package/docs/svg-semantic-contract.md +49 -0
  50. package/docs/testing-strategy.md +166 -58
  51. package/docs/theming.md +19 -32
  52. package/examples/styles/catalog.json +54 -0
  53. package/examples/styles/cloudflare-workers-inspired-prototype.mmd +9 -0
  54. package/examples/styles/cloudflare-workers-inspired-prototype.style.json +110 -0
  55. package/examples/styles/cupertino-prototype.mmd +10 -0
  56. package/examples/styles/cupertino-prototype.style.json +63 -0
  57. package/examples/styles/mid-century-report.style.json +2 -2
  58. package/examples/styles/star-chart-atlas.style.json +2 -1
  59. package/examples/styles/transit-route-map.style.json +2 -2
  60. package/examples/styles/vercel-inspired-prototype.mmd +6 -0
  61. package/examples/styles/vercel-inspired-prototype.style.json +87 -0
  62. package/package.json +85 -45
  63. package/server.json +2 -2
  64. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +17 -36
  65. package/skills/agentic-mermaid-diagram-workflow/references/cli.md +4 -5
  66. package/skills/agentic-mermaid-diagram-workflow/references/code-mode.md +15 -31
  67. package/skills/agentic-mermaid-diagram-workflow/references/sequence.md +10 -14
  68. package/skills/agentic-mermaid-live-editor/SKILL.md +100 -206
  69. package/TODO.md +0 -684
  70. package/dist/index-wjRjbsP-.d.ts +0 -1102
  71. package/docs/assets/improvements/box-start-connector.png +0 -0
  72. package/docs/assets/improvements/comment-dropped-lint.png +0 -0
  73. package/docs/assets/improvements/er-content-loss.png +0 -0
  74. package/docs/assets/improvements/fan-in-trunks.png +0 -0
  75. package/docs/assets/improvements/gantt-family.png +0 -0
  76. package/docs/assets/improvements/gantt-milestone-clamp.png +0 -0
  77. package/docs/assets/improvements/gantt-verify-seam.png +0 -0
  78. package/docs/assets/improvements/subgraph-container-edges.png +0 -0
  79. package/docs/assets/improvements/wrapper-frontmatter.png +0 -0
  80. package/docs/assets/improvements/wrapper-init-directive.png +0 -0
  81. package/docs/assets/improvements/wrapper-leading-comment.png +0 -0
  82. package/docs/assets/style-cookbook/mid-century-report.png +0 -0
  83. package/docs/assets/style-cookbook/star-chart-atlas.png +0 -0
  84. package/docs/assets/style-cookbook/transit-route-map.png +0 -0
  85. package/docs/contributing/adding-diagram-types.md +0 -144
  86. package/docs/contributing/diagram-family-citizenship.matrix.json +0 -2127
  87. package/docs/contributing/diagram-family-citizenship.md +0 -82
  88. package/docs/contributing/harvesting-upstream-tests.md +0 -126
  89. package/docs/contributing/lessons-learned.md +0 -276
  90. package/docs/contributing/releasing.md +0 -82
  91. package/docs/contributing/visual-review-evidence.md +0 -53
  92. package/docs/design/families/README.md +0 -26
  93. package/docs/design/families/architecture-beta.md +0 -48
  94. package/docs/design/families/flowchart-parser-conformance.md +0 -22
  95. package/docs/design/families/gantt-research.md +0 -137
  96. package/docs/design/families/gantt.md +0 -329
  97. package/docs/design/families/journey-agentic-cards-before.png +0 -0
  98. package/docs/design/families/journey-experience-curve-implementation.png +0 -0
  99. package/docs/design/families/journey-mermaid-classic-implementation.png +0 -0
  100. package/docs/design/families/journey-mermaid-classic-prototype.png +0 -0
  101. package/docs/design/families/journey-mermaid-classic-prototype.svg +0 -163
  102. package/docs/design/families/journey-mermaid-classic-prototype.svg.png +0 -0
  103. package/docs/design/families/journey-migration-parity.md +0 -439
  104. package/docs/design/families/journey-section-overlap-after.png +0 -0
  105. package/docs/design/families/journey-section-overlap-before.png +0 -0
  106. package/docs/design/families/journey-usage-research.md +0 -423
  107. package/docs/design/families/journey.md +0 -153
  108. package/docs/design/families/xychart.md +0 -85
  109. package/docs/design/system/README.md +0 -45
  110. package/docs/design/system/abstraction-audit.md +0 -224
  111. package/docs/design/system/abstraction-recommendations.md +0 -655
  112. package/docs/design/system/architecture.mmd +0 -29
  113. package/docs/design/system/architecture.svg +0 -137
  114. package/docs/design/system/layout-guarantees-and-robustness.md +0 -351
  115. package/docs/design/system/layout-rubric.md +0 -138
  116. package/docs/design/system/route-contracts.md +0 -848
  117. package/docs/design/system/source-preservation-ladder.md +0 -52
  118. package/docs/design/system/styles-rollout.md +0 -216
  119. package/docs/design/system/ugly-layouts.md +0 -119
  120. package/docs/layout-characterization/README.md +0 -245
  121. package/docs/layout-characterization/contact-sheet-families.md +0 -498
  122. package/docs/layout-characterization/contact-sheet.md +0 -638
  123. package/docs/layout-characterization/properties.md +0 -281
  124. package/docs/layout-characterization/visual-quality.md +0 -160
  125. package/docs/layout-characterization/visual-snapshots/architecture.svg +0 -79
  126. package/docs/layout-characterization/visual-snapshots/class.svg +0 -60
  127. package/docs/layout-characterization/visual-snapshots/er.svg +0 -61
  128. package/docs/layout-characterization/visual-snapshots/flowchart.svg +0 -58
  129. package/docs/layout-characterization/visual-snapshots/gantt.svg +0 -52
  130. package/docs/layout-characterization/visual-snapshots/journey.svg +0 -98
  131. package/docs/layout-characterization/visual-snapshots/pie.svg +0 -36
  132. package/docs/layout-characterization/visual-snapshots/quadrant.svg +0 -47
  133. package/docs/layout-characterization/visual-snapshots/sequence.svg +0 -59
  134. package/docs/layout-characterization/visual-snapshots/state.svg +0 -52
  135. package/docs/layout-characterization/visual-snapshots/timeline.svg +0 -64
  136. package/docs/layout-characterization/visual-snapshots/xychart.svg +0 -97
  137. package/docs/project/divergences.md +0 -98
  138. package/docs/project/dogfooding-docs-strategy.md +0 -66
  139. package/docs/project/hosted-mcp-cloudflare-plan.md +0 -338
  140. package/docs/project/lessons-learned.md +0 -1019
  141. package/docs/project/remove-role-styling-plan.md +0 -176
  142. package/examples/agent-improve-auth-flow.ts +0 -206
  143. package/examples/agent-loop.ts +0 -53
  144. package/examples/mcp-vs-cli-complex-diagrams.ts +0 -133
  145. package/llms.txt +0 -104
  146. package/skill-evals/README.md +0 -77
  147. package/skill-evals/fixtures/architecture-cache/input.mmd +0 -5
  148. package/skill-evals/fixtures/class-payment/input.mmd +0 -4
  149. package/skill-evals/fixtures/er-orders/input.mmd +0 -10
  150. package/skill-evals/fixtures/flowchart-cache/input.mmd +0 -3
  151. package/skill-evals/fixtures/gantt-release/input.mmd +0 -7
  152. package/skill-evals/fixtures/journey-checkout/input.mmd +0 -6
  153. package/skill-evals/fixtures/pie-exports/input.mmd +0 -5
  154. package/skill-evals/fixtures/quadrant-priorities/input.mmd +0 -11
  155. package/skill-evals/fixtures/sequence-retry/input.mmd +0 -8
  156. package/skill-evals/fixtures/state-lifecycle/input.mmd +0 -5
  157. package/skill-evals/fixtures/timeline-release/input.mmd +0 -6
  158. package/skill-evals/fixtures/xychart-growth/input.mmd +0 -5
  159. package/skill-evals/shared-benchmark.json +0 -510
  160. package/src/agent/analyze.ts +0 -157
  161. package/src/agent/apply.ts +0 -146
  162. package/src/agent/architecture-body.ts +0 -458
  163. package/src/agent/certificates.ts +0 -110
  164. package/src/agent/class-body.ts +0 -319
  165. package/src/agent/core.ts +0 -207
  166. package/src/agent/create.ts +0 -106
  167. package/src/agent/describe.ts +0 -368
  168. package/src/agent/er-body.ts +0 -224
  169. package/src/agent/facts.ts +0 -360
  170. package/src/agent/families-builtin.ts +0 -920
  171. package/src/agent/families.ts +0 -232
  172. package/src/agent/family-layouts.ts +0 -832
  173. package/src/agent/flowchart-body.ts +0 -372
  174. package/src/agent/flowchart-unsupported.ts +0 -243
  175. package/src/agent/font-coverage.ts +0 -288
  176. package/src/agent/gantt-body.ts +0 -495
  177. package/src/agent/index.ts +0 -10
  178. package/src/agent/journey-body.ts +0 -374
  179. package/src/agent/label-metrics.ts +0 -28
  180. package/src/agent/layout-to-rendered.ts +0 -63
  181. package/src/agent/mutate.ts +0 -97
  182. package/src/agent/mutation-ops.ts +0 -51
  183. package/src/agent/op-schema.ts +0 -443
  184. package/src/agent/parse.ts +0 -223
  185. package/src/agent/pie-body.ts +0 -270
  186. package/src/agent/png.ts +0 -171
  187. package/src/agent/quadrant-body.ts +0 -336
  188. package/src/agent/quality.ts +0 -363
  189. package/src/agent/readability-audit.ts +0 -92
  190. package/src/agent/rendered-route-audit.ts +0 -61
  191. package/src/agent/sequence-body.ts +0 -345
  192. package/src/agent/serialize.ts +0 -214
  193. package/src/agent/state-body.ts +0 -589
  194. package/src/agent/structural-count.ts +0 -150
  195. package/src/agent/timeline-body.ts +0 -280
  196. package/src/agent/trace-log.ts +0 -43
  197. package/src/agent/types.ts +0 -995
  198. package/src/agent/verify.ts +0 -603
  199. package/src/agent/xychart-body.ts +0 -472
  200. package/src/architecture/config.ts +0 -282
  201. package/src/architecture/layout.ts +0 -496
  202. package/src/architecture/parser.ts +0 -375
  203. package/src/architecture/renderer.ts +0 -611
  204. package/src/architecture/types.ts +0 -113
  205. package/src/ascii/ansi.ts +0 -423
  206. package/src/ascii/architecture.ts +0 -210
  207. package/src/ascii/canvas.ts +0 -443
  208. package/src/ascii/class-diagram.ts +0 -697
  209. package/src/ascii/converter.ts +0 -475
  210. package/src/ascii/draw.ts +0 -1693
  211. package/src/ascii/edge-bundling.ts +0 -328
  212. package/src/ascii/edge-routing.ts +0 -330
  213. package/src/ascii/er-diagram.ts +0 -439
  214. package/src/ascii/gantt.ts +0 -276
  215. package/src/ascii/grid.ts +0 -747
  216. package/src/ascii/index.ts +0 -196
  217. package/src/ascii/journey.ts +0 -169
  218. package/src/ascii/meta.ts +0 -244
  219. package/src/ascii/multiline-utils.ts +0 -80
  220. package/src/ascii/pathfinder.ts +0 -301
  221. package/src/ascii/pie.ts +0 -67
  222. package/src/ascii/quadrant.ts +0 -158
  223. package/src/ascii/reverse.ts +0 -216
  224. package/src/ascii/sequence.ts +0 -499
  225. package/src/ascii/shapes/circle.ts +0 -27
  226. package/src/ascii/shapes/corners.ts +0 -143
  227. package/src/ascii/shapes/diamond.ts +0 -27
  228. package/src/ascii/shapes/hexagon.ts +0 -27
  229. package/src/ascii/shapes/index.ts +0 -106
  230. package/src/ascii/shapes/rectangle.ts +0 -168
  231. package/src/ascii/shapes/rounded.ts +0 -27
  232. package/src/ascii/shapes/special.ts +0 -332
  233. package/src/ascii/shapes/stadium.ts +0 -110
  234. package/src/ascii/shapes/state.ts +0 -192
  235. package/src/ascii/shapes/types.ts +0 -73
  236. package/src/ascii/timeline.ts +0 -141
  237. package/src/ascii/types.ts +0 -312
  238. package/src/ascii/validate.ts +0 -120
  239. package/src/ascii/width.ts +0 -81
  240. package/src/ascii/wrap.ts +0 -131
  241. package/src/ascii/xychart.ts +0 -919
  242. package/src/browser.ts +0 -29
  243. package/src/class/layout.ts +0 -240
  244. package/src/class/parser.ts +0 -332
  245. package/src/class/renderer.ts +0 -638
  246. package/src/class/types.ts +0 -129
  247. package/src/cli/agent-instructions.ts +0 -1
  248. package/src/cli/am-bin.ts +0 -6
  249. package/src/cli/exit-codes.ts +0 -18
  250. package/src/cli/index.ts +0 -1132
  251. package/src/cli/init-agent.ts +0 -147
  252. package/src/cli/run-entrypoint.ts +0 -10
  253. package/src/color-resolver.ts +0 -152
  254. package/src/elk-instance.ts +0 -114
  255. package/src/er/layout.ts +0 -187
  256. package/src/er/parser.ts +0 -226
  257. package/src/er/renderer.ts +0 -792
  258. package/src/er/types.ts +0 -99
  259. package/src/family-rubric.ts +0 -425
  260. package/src/font-manifest.ts +0 -31
  261. package/src/gantt/layout.ts +0 -365
  262. package/src/gantt/parser.ts +0 -282
  263. package/src/gantt/pipeline.ts +0 -27
  264. package/src/gantt/renderer.ts +0 -414
  265. package/src/gantt/schedule.ts +0 -513
  266. package/src/gantt/types.ts +0 -255
  267. package/src/index.ts +0 -368
  268. package/src/journey/layout.ts +0 -554
  269. package/src/journey/parse-core.ts +0 -251
  270. package/src/journey/parser.ts +0 -101
  271. package/src/journey/renderer.ts +0 -917
  272. package/src/journey/types.ts +0 -144
  273. package/src/layout/geometry.ts +0 -182
  274. package/src/layout/pass.ts +0 -142
  275. package/src/layout/passes/index.ts +0 -3916
  276. package/src/layout-engine.ts +0 -1565
  277. package/src/layout-rubric.ts +0 -659
  278. package/src/mcp/artifacts.ts +0 -137
  279. package/src/mcp/dynamic-harness.ts +0 -31
  280. package/src/mcp/dynamic-modules.d.ts +0 -7
  281. package/src/mcp/facade.ts +0 -608
  282. package/src/mcp/harness-runtime.ts +0 -203
  283. package/src/mcp/hosted-server.ts +0 -468
  284. package/src/mcp/mcp-bin.ts +0 -3
  285. package/src/mcp/mcp-cli.ts +0 -82
  286. package/src/mcp/protocol.ts +0 -13
  287. package/src/mcp/sandbox.ts +0 -195
  288. package/src/mcp/sdk-decl.ts +0 -391
  289. package/src/mcp/server.ts +0 -362
  290. package/src/mcp/tool-surface.ts +0 -146
  291. package/src/mermaid-source.ts +0 -655
  292. package/src/multiline-utils.ts +0 -228
  293. package/src/parser.ts +0 -1031
  294. package/src/pie/layout.ts +0 -168
  295. package/src/pie/parser.ts +0 -136
  296. package/src/pie/renderer.ts +0 -234
  297. package/src/pie/types.ts +0 -82
  298. package/src/quadrant/layout.ts +0 -191
  299. package/src/quadrant/parser.ts +0 -183
  300. package/src/quadrant/renderer.ts +0 -322
  301. package/src/quadrant/types.ts +0 -113
  302. package/src/render-family-hooks.ts +0 -244
  303. package/src/renderer.ts +0 -1099
  304. package/src/route-contracts.ts +0 -2723
  305. package/src/scene/backend.ts +0 -76
  306. package/src/scene/fidelity.ts +0 -183
  307. package/src/scene/hybrid-backend.ts +0 -174
  308. package/src/scene/ir.ts +0 -181
  309. package/src/scene/marks.ts +0 -127
  310. package/src/scene/rough-backend.ts +0 -378
  311. package/src/scene/seed.ts +0 -46
  312. package/src/scene/style-registry.ts +0 -556
  313. package/src/sequence/layout.ts +0 -456
  314. package/src/sequence/parser.ts +0 -255
  315. package/src/sequence/renderer.ts +0 -604
  316. package/src/sequence/types.ts +0 -154
  317. package/src/shape-clipping.ts +0 -351
  318. package/src/shared/accessibility-directives.ts +0 -22
  319. package/src/shared/batched.ts +0 -61
  320. package/src/shared/color-math.ts +0 -93
  321. package/src/shared/svg-a11y.ts +0 -29
  322. package/src/shared/syntax-error.ts +0 -17
  323. package/src/shared/unicode-ranges.ts +0 -135
  324. package/src/styles.ts +0 -318
  325. package/src/svg-paths.ts +0 -28
  326. package/src/text-metrics.ts +0 -248
  327. package/src/theme.ts +0 -710
  328. package/src/timeline/layout.ts +0 -381
  329. package/src/timeline/parser.ts +0 -215
  330. package/src/timeline/renderer.ts +0 -538
  331. package/src/timeline/types.ts +0 -105
  332. package/src/types.ts +0 -462
  333. package/src/website-worker-modules.d.ts +0 -18
  334. package/src/xychart/axis-utils.ts +0 -109
  335. package/src/xychart/colors.ts +0 -124
  336. package/src/xychart/config.ts +0 -88
  337. package/src/xychart/layout.ts +0 -656
  338. package/src/xychart/parser.ts +0 -504
  339. package/src/xychart/renderer.ts +0 -640
  340. package/src/xychart/types.ts +0 -282
@@ -1,10 +1,15 @@
1
1
  # Mermaid layout complaints: catalog, root causes, and coverage
2
2
 
3
+ Status: evidence and capability-coverage scorecard, not a roadmap or backlog.
4
+ `TODO.md` is the sole authority for scheduled work. Historical issues and specs
5
+ below retain candidate contract evidence only; they do not schedule
6
+ implementation unless a stable root TODO item promotes them.
7
+
3
8
  This document maps what users actually complain about in Mermaid's layout →
4
9
  why those failures happen → which Agentic Mermaid work addresses each one
5
- (landed, specced, or deliberately out of scope). It is the durable version of
6
- a June 2026 research pass and should be updated when complaint-relevant work
7
- lands.
10
+ (landed, retained as candidate evidence, or deliberately out of scope). It is
11
+ the durable version of a June 2026 research pass and should be updated when
12
+ complaint-relevant work lands.
8
13
 
9
14
  Companions:
10
15
 
@@ -35,7 +40,7 @@ Status legend used below:
35
40
  |---|---|
36
41
  | **landed** | shipped in this repo with tests |
37
42
  | **partial** | some of the complaint class is covered, the rest is not |
38
- | **specced** | designed in #25/#26/PR #24 with acceptance criteria, not implemented |
43
+ | **candidate evidence** | described in a historical issue/spec, but unscheduled unless promoted to root `TODO.md` |
39
44
  | **out of scope** | deliberately not addressed; the reason is stated |
40
45
 
41
46
  ---
@@ -62,15 +67,14 @@ tricks. This is the loudest and oldest theme.
62
67
  diagram is visually laid out there's not really an easy way to change it"
63
68
  ([41262756](https://news.ycombinator.com/item?id=41262756)).
64
69
  - Root cause: R3 (missing control surface).
65
- - Status here: **out of scope, by policy.** Issue #25 (open question 2)
66
- recommends against route/position hints: "Keep route intent inferred from
67
- semantics and author order unless Mermaid core standardizes hints," and
68
- syntax invention is a stated non-goal. The substitute is actuation through
69
- the agent loop: deterministic layout (`measureQuality`, `checkQuality`,
70
- `eval/layout-compare/`) makes bad layout *detectable*, typed mutation makes
71
- source restructuring cheap, and #25's route certificates would make
72
- detours *explained* — so a program can iterate where a human would drag a
73
- node. This substitutes for manual positioning; it does not provide it.
70
+ - Status here: **manual coordinates and post-hoc nudging remain out of scope.**
71
+ `BUILD-24` now owns a narrower response: typed, deterministic structural
72
+ constraints for rank/layer, adjacency, and edge-length preference. They are
73
+ render/mutation metadata, not Agentic-only Mermaid syntax, and therefore do
74
+ not contradict #25's rule against inventing route syntax. Deterministic
75
+ quality measurement and route certificates remain the feedback loop; the
76
+ hints let an agent state topology-preserving intent without deleting a real
77
+ edge. This still does not provide arbitrary node coordinates or dragging.
74
78
 
75
79
  ### C2. Layout collapses at scale
76
80
 
@@ -128,11 +132,14 @@ sibling clusters overlap.
128
132
  a Tier 1 `GROUP_BREACH` warning.
129
133
  - Status here: **landed** (PRs #17, #21, #22). Residual: cross-hierarchy and
130
134
  container-edge *route classes* — making the SVG router treat boundary
131
- edges semantically rather than via representative children — are specced
132
- (#25 §8.3, #26 workstream 2).
135
+ edges semantically rather than via representative children — remain candidate
136
+ contract evidence in #25 §8.3 and #26 workstream 2, not scheduled work.
133
137
 
134
138
  ### C4. Erratic edge routing: avoidable crossings, overlaps, doglegs
135
139
 
140
+ Here and in the scorecard, **C4 means complaint category 4**, not Mermaid's C4
141
+ diagram family.
142
+
136
143
  Edges cross when they obviously need not, overlap each other or pass through
137
144
  nodes, and acquire small unexplained doglegs ("hitches"). Users untangle by
138
145
  trial-and-error reordering of source lines.
@@ -168,15 +175,16 @@ trial-and-error reordering of source lines.
168
175
  tie-breaking in the ASCII pathfinder
169
176
  (`src/__tests__/ascii-pathfinder-determinism.test.ts`).
170
177
  - Status here: **partial today, with the route-contract core landed and the
171
- broader program still specced.** #25 defines route classes
178
+ broader program retained as candidate evidence.** #25 defines route classes
172
179
  (`primary-forward`/`feedback`/fan trunks/…), the straight-primary and
173
180
  hitch invariants (§11.1–11.2), the certifying simplifier (§12), and the
174
181
  hard rule "no node-coordinate mutation after route extraction unless all
175
182
  incident routes are rerouted or recertified" (§9). The current tests now
176
183
  include route-certificate geometry and property coverage across dotted,
177
- thick, bidirectional, marker, and labeled edge forms. Remaining work lives
178
- in the still-open route/port issues (#32, #35, #38 and the #26 umbrella),
179
- plus cross-renderer adoption.
184
+ thick, bidirectional, marker, and labeled edge forms. The still-open
185
+ route/port issues (#32, #35, #38 and the #26 umbrella) retain unscheduled
186
+ evidence; any implementation or cross-renderer adoption requires promotion
187
+ to root `TODO.md`.
180
188
 
181
189
  ### C5. Edge labels overlap edges, nodes, and each other
182
190
 
@@ -190,7 +198,6 @@ edge they describe.
190
198
  integrated-labeling concept yFiles ships, see R3),
191
199
  [mermaid#2131 mis-aligned state labels](https://github.com/mermaid-js/mermaid/issues/2131),
192
200
  [mermaid#2525 "messages appear with line through them"](https://github.com/mermaid-js/mermaid/issues/2525),
193
- [mermaid#7492 C4 label/text/arrow chaos](https://github.com/mermaid-js/mermaid/issues/7492),
194
201
  [mermaid#1233](https://github.com/mermaid-js/mermaid/issues/1233).
195
202
  - Root cause: R1 (label placement is NP-hard and classically solved *after*
196
203
  layout; dagre models labels as mid-edge dummy nodes), R4/R5 (renderers do
@@ -297,7 +304,8 @@ at layout time, and no width budget for CJK/long words.
297
304
  - Status here: **landed**, with an honest gap: the 7px/char SVG heuristic is
298
305
  approximate (`docs/quality.md`), and the shared text-measurement contract
299
306
  that would unify SVG/ASCII/quality measurement (CJK, emoji, ambiguous
300
- width) is specced as #26 workstream 8. Regression coverage now includes
307
+ width) remains candidate evidence in #26 workstream 8. Regression coverage
308
+ now includes
301
309
  emoji-presentation selectors and East Asian ambiguous-width symbols, so
302
310
  common Unicode labels cannot silently drift between SVG metrics and
303
311
  terminal-width assumptions.
@@ -343,8 +351,9 @@ take long unexplained detours.
343
351
  (Tier 2) and self-loop clearance heuristics
344
352
  (`layout-quality-heuristics.test.ts`) guard regressions. SVG self-loop
345
353
  port policy (N/S side by clearance) is #25 §8.1; mermaid#6049 is listed as
346
- a future fixture in [`issue-derived-test-cases.md`](./issue-derived-test-cases.md).
347
- - Status here: **partial** (ASCII decent + guarded; SVG semantics specced).
354
+ candidate fixture evidence in [`issue-derived-test-cases.md`](./issue-derived-test-cases.md).
355
+ - Status here: **partial** (ASCII decent + guarded; SVG semantics retained as
356
+ candidate evidence, not scheduled).
348
357
 
349
358
  ### C11. Unstable output across versions and renderers
350
359
 
@@ -395,15 +404,14 @@ titles, notes colliding with lifelines.
395
404
 
396
405
  ### C13. Chart families: hard-coded geometry breaks on real data
397
406
 
398
- Gantt axis dates overlap on long ranges, pie titles/labels clip, radar axis
399
- labels compress, C4 is widely considered the worst-layouted type. These are
407
+ Gantt axis dates overlap on long ranges, pie titles/labels clip, and radar axis
408
+ labels compress. These are
400
409
  not dagre problems — each chart type has bespoke geometry with no collision
401
410
  handling.
402
411
 
403
412
  - Evidence: [mermaid#1301 gantt axis overlap](https://github.com/mermaid-js/mermaid/issues/1301)
404
413
  (23R), [mermaid#6232 pie title cut off](https://github.com/mermaid-js/mermaid/issues/6232),
405
- [mermaid#7683 radar labels clipped](https://github.com/mermaid-js/mermaid/issues/7683),
406
- [mermaid#7492 C4](https://github.com/mermaid-js/mermaid/issues/7492).
414
+ and [mermaid#7683 radar labels clipped](https://github.com/mermaid-js/mermaid/issues/7683).
407
415
  - Root cause: R5 (per-family renderer-first geometry; semantics inferred at
408
416
  draw time — the exact anti-pattern #26's guiding principle names).
409
417
  - Fixture/test: pie and quadrant landed source-level with geometry tests
@@ -412,10 +420,10 @@ handling.
412
420
  pure, clock-free schedule resolver *before* layout, family validators
413
421
  (deterministic task intervals, milestone zero-width markers,
414
422
  non-overlapping compact rows) designed against precisely the mermaid#1301
415
- class. C4, radar, and mindmap are not supported at all.
416
- - Status here: **partial** (pie/quadrant/gantt landed; C4/radar/mindmap
417
- absent — see [`comparison.md`](./comparison.md) for the current
418
- family-coverage trade).
423
+ class. Mindmap now has deterministic tree geometry; Radar has deterministic
424
+ radial layout, bounded labels, ring ticks, and cross-format render contracts.
425
+ - Status here: **covered for every registered chart family**; remaining work is
426
+ tracked as family-specific quality improvement, not missing Radar support.
419
427
 
420
428
  ---
421
429
 
@@ -448,7 +456,8 @@ directly:
448
456
  Harvard TR-05-91), and edge-label placement specifically is NP-hard
449
457
  ([Kakoulis & Tollis 2001](https://www.sciencedirect.com/science/article/pii/S0925772100000250),
450
458
  Comput. Geom. 18(1)). No engine "chooses" the avoidable crossing in
451
- C4 — it fails to find the better optimum it cannot afford to search for.
459
+ complaint C4 — it fails to find the better optimum it cannot afford to
460
+ search for.
452
461
  2. **Phases cannot revisit earlier decisions.** Layering fixes ranks before
453
462
  crossing minimization sees them; coordinates are assigned before routing.
454
463
  A route that needs a node nudged one lane over cannot get it. This is
@@ -590,7 +599,8 @@ assignment is
590
599
  in `lib/position/bk.js`) and then stops: there is no routing phase at all —
591
600
  edges are interpolated through dummy-node points.
592
601
  [dagre-d3#291](https://github.com/dagrejs/dagre-d3/issues/291) is the
593
- user-visible result, and C4/C5 are the Mermaid-visible results. Cluster
602
+ user-visible result, and complaint categories C4/C5 are the Mermaid-visible
603
+ results. Cluster
594
604
  support follows Sander/Forster on paper (per
595
605
  [dagre's wiki](https://github.com/dagrejs/dagre/wiki)) but fails on nesting
596
606
  and compound edges in practice
@@ -625,8 +635,8 @@ docs) — selected via frontmatter `config.layout`, and per the
625
635
  edge-overlap ask
626
636
  [mermaid#1006](https://github.com/mermaid-js/mermaid/issues/1006) was
627
637
  closed *Wont Fix*. GitHub's native rendering still runs the dagre default —
628
- so most readers see the unfixed engine (C2, C3, C4, C9), and even opted-in
629
- users get the better engine for two of ~25 families. PlantUML made the
638
+ so most readers see the unfixed engine (complaint categories C2, C3, C4, C9),
639
+ and even opted-in users get the better engine for two of ~25 families. PlantUML made the
630
640
  opposite bet decades earlier: it
631
641
  [delegates class/state/component/usecase layout to Graphviz dot](https://plantuml.com/graphviz-dot),
632
642
  inheriting dot's router and rank constraints along with its weaknesses.
@@ -688,7 +698,10 @@ model, derive layout intent, compute geometry, certify, then render —
688
698
  with renderers as projections of shared intent rather than the place where
689
699
  intent is invented.
690
700
 
691
- ### Root causes → issue #26 workstreams
701
+ ### Root causes → historical issue #26 workstream evidence
702
+
703
+ This crosswalk preserves the research decomposition only. It does not make the
704
+ issue workstreams an active schedule; root `TODO.md` must own any promoted work.
692
705
 
693
706
  | Root cause | #26 workstream(s) |
694
707
  |---|---|
@@ -700,7 +713,7 @@ intent is invented.
700
713
  | R4 rectangular/port-less model | WS3 semantic ports and shape-aware anchors |
701
714
  | R5 renderer-first semantics | WS5 Gantt resolver model (landed); WS7 class/ER contracts; WS10 region tree; WS13 preservation ladder |
702
715
  | Unreviewable visual change (meta) | WS12 reproducible before/after evidence |
703
- | Generic metrics miss failures (meta, C4 worked example) | WS11 family-specific validators |
716
+ | Generic metrics miss failures (meta, complaint C4 worked example) | WS11 family-specific validators |
704
717
 
705
718
  ---
706
719
 
@@ -711,13 +724,13 @@ intent is invented.
711
724
  | C1 | Manual positioning | mermaid#5420 (47R), #270 (2016–) | **out of scope** by policy | #25 OQ2; agent loop as substitute |
712
725
  | C2 | Scale collapse | mermaid#1984 (39R) | **partial** (detection only) | `quality.ts` bands; `eval/layout-compare/` |
713
726
  | C3 | Subgraphs | mermaid#2509 (189R) | **landed** | `subgraph-direction.test.ts`; PRs #17/#21/#22 |
714
- | C4 | Erratic routing | mermaid#6476, #5601 | **partial**; fix **specced** | #25 §11–12; MFA worked example above |
715
- | C5 | Edge-label overlap | mermaid#2131, #7492 | **partial** | inline ELK labels; `labelEdgeProximity`; #25 §11.4 |
727
+ | C4 | Erratic routing | mermaid#6476, #5601 | **partial**; candidate fix evidence only | #25 §11–12; MFA worked example above |
728
+ | C5 | Edge-label overlap | mermaid#2131 | **partial** | inline ELK labels; `labelEdgeProximity`; #25 §11.4 |
716
729
  | C6 | Order control / edit stability | mermaid#3723 (86R), #815 (45R) | **partial** | model-order ELK opts; `agent-auth-flow.test.ts`; edit-stability tests |
717
730
  | C7 | Default aesthetics | HN 30339032 | **landed** (upstream + fork) | theming; Style + Palette; contrast tests |
718
- | C8 | Text clipping | mermaid#2688 (24R) | **landed** | zero-DOM text; `LABEL_OVERFLOW`; CJK tests; WS8 specced |
731
+ | C8 | Text clipping | mermaid#2688 (24R) | **landed** | zero-DOM text; `LABEL_OVERFLOW`; CJK tests; WS8 candidate evidence |
719
732
  | C9 | dagre stagnation | Mermaid docs' own ELK advice | **landed** structurally | `layout-engine.ts`; `elk-instance.ts`; #25 §10 |
720
- | C10 | Self-loops | mermaid#6336 (31R) | **partial** | clearance heuristics; #25 §8.1 specced |
733
+ | C10 | Self-loops | mermaid#6336 (31R) | **partial** | clearance heuristics; #25 §8.1 candidate evidence |
721
734
  | C11 | Version/renderer instability | mermaid#5813 (28R) | **landed** | determinism suite; `eval/layout-compare/`; goldens |
722
735
  | C12 | Sequence alignment | mermaid#1765 (28R) | **partial**; first properties landed | #25 §14.2; #26 WS11; `sequence-layout.test.ts` |
723
736
  | C13 | Chart-family geometry | mermaid#1301 (23R) | **partial** | PR #24 (gantt); pie/quadrant/gantt geometry tests |
@@ -728,10 +741,11 @@ intent is invented.
728
741
 
729
742
  Stated plainly so the scorecard cannot oversell:
730
743
 
731
- 1. **Manual positioning (C1).** The loudest single ask is answered with a
732
- substitute (deterministic + measurable + explainable auto-layout for
733
- editing programs), not a solution. If Mermaid core standardizes layout
734
- hints, this fork follows; it will not invent them (#25 non-goals).
744
+ 1. **Manual positioning (C1).** Arbitrary coordinates and post-layout nudging
745
+ remain deliberately unsupported. `BUILD-24` schedules only typed structural
746
+ auto-layout constraints (rank, adjacency, short-edge preference), without
747
+ inventing Mermaid source syntax. If Mermaid core standardizes compatible
748
+ source hints, this fork can map them into the same typed contract.
735
749
  2. **Large-diagram compaction (C2).** Detection exists; no compaction work
736
750
  is scheduled. Source-order priority can make wide diagrams wider — the
737
751
  Auth Flow aspect band in `agent-auth-flow.test.ts` is widened to 7
@@ -743,14 +757,14 @@ Stated plainly so the scorecard cannot oversell:
743
757
  applies to diagrams rendered through this stack (agent pipelines, CI,
744
758
  terminals, the editor) plus whatever is upstreamed per the
745
759
  [upstreaming strategy](./fork-differences.md#upstreaming-strategy).
746
- 4. **Family coverage.** 12 families vs Mermaid's ~25. Gantt is now rendered
747
- and characterized in this fork; C4/radar/mindmap and many other Mermaid
748
- families remain outside the current engine.
760
+ 4. **Family coverage.** The checked runtime registry is the source of truth for
761
+ supported families. Every registered family, including Radar, is rendered and
762
+ characterized; Mermaid families outside that registry remain unsupported.
749
763
  5. **Metric honesty.** Today's perceptual metrics pass diagrams whose
750
- routing is visibly wrong (C4 worked example). Until #25 certificates and
751
- #26 family validators land, `verify.ok` + `checkQuality` must not be
752
- read as "looks right" — `docs/quality.md` already says this; the MFA
753
- fixture proves it.
764
+ routing is visibly wrong (complaint C4 worked example). Unless and until the
765
+ #25 certificate and #26 family-validator candidates are promoted in root
766
+ `TODO.md` and land, `verify.ok` + `checkQuality` must not be read as "looks
767
+ right" — `docs/quality.md` already says this; the MFA fixture proves it.
754
768
 
755
769
  ---
756
770
 
@@ -1,49 +1,120 @@
1
- # Mutation testing (ASCII layout core)
1
+ # Mutation testing
2
2
 
3
- Stryker mutation testing is scoped to the five ASCII layout modules where a
3
+ The original ASCII Stryker lane is scoped to the five layout modules where a
4
4
  silent logic regression is most expensive: `src/ascii/pathfinder.ts`,
5
5
  `src/ascii/edge-routing.ts`, `src/ascii/converter.ts`, `src/ascii/grid.ts`,
6
6
  `src/ascii/draw.ts`.
7
- The config is `stryker.ascii.config.json`; its command runner executes the
7
+ The `ascii` profile in the single `stryker.config.mjs` authority executes the
8
8
  ASCII test files (goldens, invariants, properties, unit tests) per mutant.
9
9
 
10
10
  ## Running
11
11
 
12
12
  ```bash
13
13
  # One module (preferred — a full module takes 5–15 minutes):
14
- npx stryker run stryker.ascii.config.json --mutate 'src/ascii/pathfinder.ts'
14
+ bun run mutation-test -- ascii --mutate 'src/ascii/pathfinder.ts'
15
15
 
16
- # All five (also available as `bun run mutation-test:ascii`):
17
- npx stryker run stryker.ascii.config.json
16
+ # All five:
17
+ bun run mutation-test -- ascii
18
+
19
+ # Discover every available profile:
20
+ bun run mutation-test -- --list
18
21
  ```
19
22
 
20
- (`stryker.families.config.json` / `bun run mutation-test:families` covers the
21
- agent family parsers, and `stryker.routes.config.json` / `bun run
22
- mutation-test:routes` covers the route-contracts module
23
+ (`bun run mutation-test -- families` covers the
24
+ shared Architecture, XYChart, Mindmap, GitGraph, and Radar parser/layout/renderer
25
+ cores plus Radar's structured editing body, and `bun run mutation-test -- routes` covers
26
+ the route-contracts module
23
27
  (`docs/design/system/route-contracts.md`), all with the same policy.)
24
28
 
25
29
  Narrow lanes for PR-scale survivor harvests:
26
30
 
27
31
  ```bash
28
- bun run mutation-test:links # text-embedded link-length parsing
29
- bun run mutation-test:routes:certs # route-certificate finality + stale-route audit
30
- bun run mutation-test:routes:subgraph # subgraph endpoint/LCA routing
32
+ bun run mutation-test -- links # text-embedded link-length parsing
33
+ bun run mutation-test -- routes:certs # route-certificate finality + stale-route audit
34
+ bun run mutation-test -- routes:subgraph # subgraph endpoint/LCA routing
31
35
  bun run sabotage:routes # one-line revert checks against committed HEAD; expects focused tests to fail
32
36
  ```
33
37
 
34
- The JSON report lands in `reports/mutation/` (gitignored). Beyond the lanes
35
- documented here, `stryker.*.config.json` also covers the per-family parsers
36
- (state/sequence/timeline/class/er/journey/pie/quadrant/gantt via
37
- `mutation-test:families`), characterization, and the link-grammar lane — see
38
- `package.json` scripts for the full index. Broad route lanes
39
- are intentionally not part of the PR gate, but `.github/workflows/nightly-route-mutation.yml`
40
- runs `mutation-test:routes`, `mutation-test:routes:certs`,
41
- `mutation-test:routes:subgraph`, and `sabotage:routes` nightly and on manual
42
- `workflow_dispatch`, uploading reports as artifacts — though every scheduled
43
- run to date has been cancelled at the 90-minute cap before uploading anything
44
- (the unsharded routes lane exceeds it; PR #63 carries the sharding fix), so
45
- current scores come from local runs. Run the narrow lane locally
46
- when you touch ASCII/route core logic and want immediate proof the tests bite.
38
+ JSON reports land in `reports/mutation/` (gitignored). The single executable
39
+ config resolves route-certificate, subgraph-routing, and link-grammar ranges
40
+ from source-adjacent markers; inserting code above the behavior cannot silently
41
+ move those lanes onto unrelated lines.
42
+
43
+ Beyond the lanes documented here, configs exist for every built-in renderable
44
+ family through named profiles: flowchart uses `mutation-test -- routes`;
45
+ XYChart, Architecture, and Radar share `mutation-test -- families`; State, Sequence,
46
+ Timeline, Class, ER, Journey, Pie, Quadrant, Gantt, Mindmap, and GitGraph each
47
+ have a focused command. These are **opt-in diagnostic survivor harvests**. They
48
+ emit scores and JSON reports, but have no `thresholds.break` and are neither
49
+ scheduled nor acceptance gates.
50
+
51
+ Two bounded checks run automatically on each PR:
52
+
53
+ - `mutation-test -- incremental` mutates one small, pure module in about one minute
54
+ and enforces its measured score.
55
+ - `sabotage:routes` injects five named one-line regressions and requires the
56
+ focused behavioral tests to fail.
57
+
58
+ This distinction is deliberate. Mutation testing is useful when it challenges
59
+ a specific test or design assumption; family membership alone is not a reason
60
+ to enroll code in an expensive recurring sweep. A local mutation score without
61
+ a retained report is diagnostic evidence, not a repository acceptance claim.
62
+
63
+ ## Why broad scheduled mutation was retired (2026-07-14)
64
+
65
+ The nightly workflow, its sharder, mutant-set oracle, aggregate verifier, and
66
+ orchestration tests were retired and deleted. The operational evidence did
67
+ not support maintaining them:
68
+
69
+ - all 26 scheduled runs from 19 June through 14 July failed or were cancelled;
70
+ - the workflow expanded from four route checks to every family while it was
71
+ still unable to produce a successful retained run;
72
+ - the final repair grew to 39 coverage workers (41 jobs total), yet long lanes
73
+ still timed out and hosted runners disappeared before producing reports; and
74
+ - rerunning unchanged mutation-relevant code consumed runner-hours without
75
+ adding information.
76
+
77
+ The [last scheduled baseline](https://github.com/adewale/agentic-mermaid/actions/runs/29309167850),
78
+ [calibration diagnostic](https://github.com/adewale/agentic-mermaid/actions/runs/29327418603),
79
+ and [cancelled 41-job repair](https://github.com/adewale/agentic-mermaid/actions/runs/29340333016)
80
+ are retained as historical evidence, not as acceptance authority. The focused
81
+ configs, marker-based scopes, survivor classifications, incremental gate, and
82
+ sabotage probes remain because they are independently useful.
83
+
84
+ The causal record is in
85
+ [`project/archive/mutation-infrastructure-postmortem-2026-07.md`](./project/archive/mutation-infrastructure-postmortem-2026-07.md).
86
+ The durable stop rule is: after three consecutive scheduled failures, an owner
87
+ must fix, narrow, disable, or delete the diagnostic before adding scope. Any new
88
+ recurring lane also needs a demonstrated fault class, one complete retained
89
+ baseline, a runner-minute budget, an owner, and a removal criterion. No single
90
+ proxy—coverage, mutation score, assertion count, or matrix enrollment—is “the”
91
+ adequacy signal.
92
+
93
+ ## Focused Mindmap/GitGraph historical local measurement (2026-07-10)
94
+
95
+ These figures came from local runs. Their JSON reports are gitignored and no
96
+ immutable CI artifact URL is committed, so they are diagnostic history—not a
97
+ PR acceptance gate or a current break floor.
98
+
99
+ | Lane | Mutants | Killed | Survived | Score |
100
+ |---|---:|---:|---:|---:|
101
+ | `bun run mutation-test -- mindmap` (`src/agent/mindmap-body.ts`) | 405 | 400 | 5 | **98.77%** |
102
+ | `bun run mutation-test -- gitgraph` (`src/agent/gitgraph-body.ts`) | 303 | 294 | 9 | **97.03%** |
103
+
104
+ The operation suites exercise every happy path, validation branch, source-order
105
+ rewrite, recursive/cycle guard, null-clearing path, and verification warning.
106
+ Mindmap's five survivors are two correlated node-syntax tuple guards plus
107
+ three exception-path mutations around the node/body stability probes (two
108
+ empty `catch` forms remain falsy; one `false`→`true` mutation is retained as a
109
+ non-gating test gap). GitGraph's nine
110
+ survivors are canonical serialization equivalents (trimming an already
111
+ canonical header, explicit `NORMAL`, and optional attribute whitespace),
112
+ merge-field guards implied by the discriminated model, or widened
113
+ statement-kind guards that serialize identically on valid replay state. Reports
114
+ are generated at `reports/mutation/{mindmap,gitgraph}-mutation.json`
115
+ (gitignored); the committed configs make the runs reproducible. The measured
116
+ scores above are not acceptance evidence: any separately owned acceptance claim
117
+ must cite retained CI artifacts or a content-addressed report.
47
118
 
48
119
  ## Policy
49
120
 
@@ -61,19 +132,22 @@ documented, not killed with synthetic inputs.
61
132
  | converter.ts | 38.4% | 94 | 151 |
62
133
  | grid.ts | 70.1% | 421 | 180 |
63
134
  | layout/passes/index.ts:931-1165 (linkrank packing repair) | 49.86% → 65.07% after the geometry-characterization harvest (355 mutants; killed 176 → 230+1 timeout). The +54 kills were the repair's candidate ORDERING / ahead-node selection / push-delta arithmetic — invisible to HARD-metric assertions (a mutant picking a different clear lane still yields zero violations), pinned instead by per-repro geometry snapshots in `linkrank-packing.test.ts` (layout determinism makes them stable). | 355 | 124 — see classification below |
64
- | route-contracts.ts | 58.1% → 72.3% → 75.6% → 73.1% across the first three batches; 54.31% at 0b43c90, then 50.69% at 526d9cf after the slanted-family batch (shapePorts generalization, convex-polygon geometry: 2659 → 2740 mutants — absolute kills 1444 → 1381). The percentage fell purely on denominator growth (~3× since batch 3); a survivor-harvest batch is the documented next quality step. | 882 → 2740 | 50.69% (1381 killed) — survivor harvest pending |
135
+ | route-contracts.ts | 58.1% → 72.3% → 75.6% → 73.1% across the first three batches; 54.31% at 0b43c90, then 50.69% at 526d9cf after the slanted-family batch (shapePorts generalization, convex-polygon geometry: 2659 → 2740 mutants — absolute kills 1444 → 1381). The percentage fell on denominator growth (~3× since batch 3); residuals from that run are classified below. | 882 → 2740 | 50.69% (1381 killed) — historical snapshot |
65
136
 
66
137
  (Numbers from the June 2026 runs; regenerate rather than trusting this
67
138
  table — the report lands in `reports/mutation/`.)
68
139
 
69
- ## Survivor classification
140
+ ## Historical survivor classification
141
+
142
+ This section explains the recorded run; it is not a secondary test backlog.
143
+ Only root `TODO.md` can schedule a new fixture or survivor-harvest package.
70
144
 
71
145
  **linkrank lane residual (124 at the 65.07% run)**, classified:
72
146
 
73
- - **Real gap, next harvest**: the subgraph-scoped `separationUnit` branch (walk the
74
- overlapped node's scope chain, push its outermost subgraph unit) never fires — the
75
- degenerate repro set has no subgraphs. Killing these needs a subgraph + long-link
76
- shove-overlap fixture.
147
+ - **Unexercised branch in the recorded corpus**: the subgraph-scoped
148
+ `separationUnit` branch (walk the overlapped node's scope chain, push its
149
+ outermost subgraph unit) did not fire because the degenerate repro set had no
150
+ subgraphs. A subgraph + long-link shove-overlap fixture was not part of that run.
77
151
  - **Unexercised defensive fallbacks**: the `rungSource` feedback family and some
78
152
  min-lane branches fire only on inputs the deterministic enumeration no longer
79
153
  produces (0 residual signatures); every adopted route is still runtime-validated by
@@ -93,8 +167,8 @@ be preserved).
93
167
  **Accepted — performance guards, not behavior** (pathfinder): the #66
94
168
  bounded-search mutants (`next.x > boundX || next.y > boundY` weakenings,
95
169
  `maxIterations` arithmetic). They change how much work an unreachable-target
96
- search does before returning null, not what any reachable search returns. A
97
- test would need to time the search, which is flakier than the risk warrants.
170
+ search does before returning null, not what any reachable search returns.
171
+ Timing the search was judged less reliable than the risk warranted.
98
172
 
99
173
  **Accepted — unreachable via convention** (pathfinder): the `dy`-dominant
100
174
  fallback in `buildMoveDirs` (lines ~157–159). All nine 3×3 `Direction`
@@ -136,59 +210,62 @@ reachability verdicts, on the small graphs flowcharts produce.
136
210
 
137
211
  **Accepted — bounded-iteration guard** (route-contracts): the fixed-point
138
212
  loop's `round < 4` weakenings only change how many re-prove rounds run;
139
- the duplicate-edge regression pins one unblocking round, and constructing
140
- a graph that needs three chained rounds would be a synthetic-input test.
213
+ the duplicate-edge regression pins one unblocking round, while three chained
214
+ rounds were outside the recorded real-input corpus.
141
215
 
142
- **Open test gaps** (highest-value first):
216
+ **Residual observations from that run** (not scheduled):
143
217
  - `directLaneBlockers` label-rect axis ternaries retain a few survivors on
144
- rect width/height swaps for near-square pills; a multi-line (taller than
145
- wide) label obstacle fixture would discriminate them.
218
+ rect width/height swaps for near-square pills; the corpus lacked a multi-line
219
+ (taller than wide) label obstacle.
146
220
  - `findLabelSlot`'s rect-overlap conjunction retains sign-variant survivors
147
- for rects that only graze on one axis; corner-touching fixtures would
148
- pin them.
221
+ for rects that only graze on one axis; corner-touching fixtures were absent.
149
222
  - The audit's pill-hit prefilter (`hitsPill`) retains inclusive-vs-strict
150
223
  comparison survivors for segments that exactly graze the pill border;
151
224
  they only widen the prefilter the collinearity check still gates.
152
- - The container repair's reversed-order gaps (target above / left of
153
- source) lack fixtures; the gap arithmetic is symmetric with the two
225
+ - The container repair's reversed-order gaps (target above / left of source)
226
+ were absent; the recorded classification relied on symmetry with the two
154
227
  covered directions.
155
228
  - `grid.ts` `ensureSubgraphSpacing` (~48 survivors): the overlap/min-spacing
156
229
  resolution between root subgraphs is never triggered by the corpus —
157
- placement upstream appears to avoid overlaps already. Needs either a
158
- corpus sample that genuinely overlaps or a dead-code verdict.
230
+ placement upstream appeared to avoid overlaps, so the run could not
231
+ distinguish reachable behavior from defensive dead code.
159
232
  - `converter.ts` entry/exit attachment roles and phantom still-used checks
160
233
  (`resolveSubgraphEdges` area): rendered-output invariants tolerate several
161
- mutants because other mechanisms compensate. Needs assertions on the
162
- resolved edge structure, not just the rendered text.
234
+ mutants because other mechanisms compensate; the run asserted rendered text,
235
+ not the intermediate resolved edge structure.
163
236
  - `edge-routing.ts` label segment filter (`width >= lenLabel && index > 1 &&
164
237
  orientationMatches`): the labeled-fanout invariants pin the TD vertical-drop
165
238
  case; LR orientation and the index>1 exclusion lack direct coverage.
166
239
 
167
- ## Incremental per-PR lane (`stryker.incremental.config.json`)
240
+ ## Incremental per-PR profile
168
241
 
169
242
  A fast lane gates the small, pure faithfulness counter on every PR (the
170
- `mutation-incremental` CI job), separate from the broad nightly lanes. It
243
+ `mutation-incremental` CI job), separate from the opt-in diagnostic configs. It
171
244
  mutates `src/agent/structural-count.ts` (the counter + `faithfulnessWarning` +
172
245
  `isDrop`), run by the sub-second `structural-count.test.ts` unit runner. A full
173
246
  run is ~1 min, so it runs in full each PR.
174
247
 
175
- Score is ~96% (regenerate to confirm; the report lands in `reports/mutation/`),
176
- gated by `thresholds.break: 90`. The few survivors are all equivalent mutants,
177
- accepted not chased:
248
+ The 2026-07-14 post-Radar run scored **97.01%** (130 killed / 134 valid; regenerate to
249
+ confirm, with the report in `reports/mutation/`), gated by
250
+ `thresholds.break: 90`. The retained floor deliberately remains below the
251
+ measured score; this result for one small pure module is not a repository policy
252
+ or a reason to expand mutation scope.
253
+
254
+ The survivor review found real valid-domain gaps rather than accepting a score:
255
+ the State counter needed both a doubly nested composite and concurrent-region
256
+ fixtures; ER needed a semantic-subgraph fixture and the public empty body with
257
+ its optional `groups` field absent; and `nodes = services + junctions` needed an
258
+ Architecture fixture containing a junction. These cases remain because they
259
+ pin real behavior, not because they improve a metric.
178
260
 
179
- - `structural-count.ts:96` (`case 'opaque': return null`) — two mutants
180
- (the case label + its string). Equivalent: an opaque body returns `null`, and
181
- the `default` branch *also* returns `null`, so mutating the `opaque` case
182
- cannot change the result for any input.
183
- - `structural-count.ts:98` (`default:` exhaustiveness branch) — two mutants
184
- (the branch condition + its block). Unreachable by construction: all twelve
185
- families are handled explicitly and the `const _never: never = body` assigns
186
- compile-time exhaustiveness, so the branch never executes at runtime.
261
+ Four survivors are classified rather than killed with invalid inputs or by
262
+ weakening the code's forward-compatibility tripwire:
187
263
 
188
- What earlier survivors taught us (now killed, kept as regression fixtures): the
189
- recursive `edges += inner.edges` state accumulation needed a *doubly-nested*
190
- composite-state fixture, and `nodes = services + junctions` needed an
191
- architecture fixture that actually contains a junction.
264
+ - two mutations to `case 'opaque': return null` are equivalent because the
265
+ exhaustive default also returns `null`; and
266
+ - two mutations to the `default` branch are unreachable for the valid
267
+ discriminated union. Its `const _never: never = body` assignment is retained
268
+ so adding a family without a count remains a compile-time error.
192
269
 
193
270
  ### Why `verify.ts`'s faithfulness wrapper is NOT in the gated mutate set
194
271
 
@@ -199,8 +276,10 @@ the `catch` — which no *real* diagram exercises: a structured diagram's
199
276
  serialization always re-parses, and re-parses structured (not opaque), and never
200
277
  throws. Those branches are therefore unkillable through real `verifyMermaid`
201
278
  inputs without a synthetic drop, and the *decision logic* they guard already
202
- lives in `faithfulnessWarning`, which the incremental lane gates at 96%+. Adding
203
- the wrapper to the gated `mutate` would crater the score to ~27% and force either
279
+ lives in `faithfulnessWarning`, which the incremental lane currently measures
280
+ at 97.01%. Adding the wrapper to the gated `mutate` would crater the score to
281
+ ~27% and force either
204
282
  a meaningless break threshold or a pile of accepted survivors. So the wrapper
205
283
  stays out of the gated set and is recorded here as I/O-glue equivalents; its
206
- logic is covered where it actually lives.
284
+ logic is covered where it actually lives, where the current measured score is
285
+ 97.01%.