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