Fix mermaid rendering for debug plans already on disk - #1817
Merged
Nathan (nturinski) merged 1 commit intoSep 10, 2026
Merged
Nathan (nturinski) merged 1 commit into
Nathan (nturinski) merged 1 commit into
Conversation
#1813 taught the azure-debug-plan template to quote every flowchart label, which fixes plans generated from now on. It does nothing for a `.azure/vscode-debug-plan.md` already sitting in a workspace, and it is only a request the model can decline. Those diagrams still render as mermaid's syntax-error graphic. Normalize the diagram in the webview instead, right before `mermaid.render()`. `quoteMermaidLabels` quotes any flowchart node or edge label that is not quoted already, so a package name like `@azure/storage-blob` in an edge label is read as text rather than as mermaid v11 edge-ID syntax. It is deliberately narrow, since the failure mode of a bad rewrite is a diagram that used to work and no longer does: - Only `graph` / `flowchart` diagrams are touched. Elsewhere `[]`, `{}` and `|` mean something else entirely. - Lines carrying v11 metadata (`id@{ shape: rect }`, `e1@{ animate: true }`) are exempt from the rhombus rule. That syntax is brace-delimited configuration, not a label. - Rewrites skip the inside of existing `"..."` strings, so brackets or braces within an already-quoted label survive, and the transform is idempotent. - Cylinder, circle, stadium, subroutine, hexagon, parallelogram and trapezoid delimiters are preserved rather than flattened to a rectangle. Verified with real mermaid 11.17.0 under jsdom, driving `parseLocalDebugPlanMarkdown` over the plans: the reported diagram fails as-authored and parses once normalized, and all four checked-in plan fixtures parse both before and after. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Nathan (nturinski)
merged commit Sep 10, 2026
fa923b8
into
nturinski-mermaid-label-quoting-490
2 checks passed
Nathan (nturinski)
deleted the
nturinski-mermaid-render-normalization
branch
September 10, 2026 17:26
Nathan (nturinski)
added a commit
that referenced
this pull request
Sep 10, 2026
This reverts commit 773b038. The round rule it added guarded with `/^[["/\\]/`, which only inspects the first character of a label. Parentheses appearing *inside* a label body therefore slipped past the guard and were re-quoted by the round rule in the same chained pass, regressing cases that #1817 had correctly fixed: Web[Attendance Web<br/>(Vite dev server)] -> ["Attendance Web<br/>("Vite dev server")"] Web[Vite(5173)] -> ["Vite("5173")"] A -->|calls (async)| B -> |calls ("async")| The first of those is the attendance fixture's own label in its unquoted form, i.e. exactly what a debug plan written before #1813 looks like on disk, so the regression would have reached real user files. PR #1820 supersedes this commit with a correct fix: it runs the round rule as a second pass over a re-split line, so parens inside a label are already within a quoted segment and are structurally unreachable rather than merely guarded against. That approach needs no guard at all and additionally fixes a double-circle regression, `A(((Core)))`, that #1817 introduced. Reverting here so the two round-shape rules don't compete. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1813 — please review/merge that one first. Base branch is
nturinski-mermaid-label-quoting-490.Why a second PR
#1813 fixes the generation side: it adds an unconditional "quote every node and edge label" rule to
resources/agents/azure-debug-plan/references/plan-template.mdand to the CoR docs instructions. That is prevention at the source, and it has two gaps:.azure/vscode-debug-plan.mdthat is already on disk in a user's workspace. Those diagrams still fail to render today.This PR closes both gaps by normalizing at render time.
The failure
The generated diagram contains:
Mermaid v11 reserves
@for edge-ID (e1@-->) and node-metadata (id@{ shape: ... }) syntax, so an@at the start of an unquoted label lexes asLINK_IDand the whole diagram fails to parse — the webview shows mermaid's "Syntax error in text" bomb graphic instead of the architecture diagram. An@mid-label is fine; quoting the label fixes it.This is not a mermaid version regression — it reproduces identically on 11.14.0, 11.15.0 and 11.17.0, so the
mermaiddependency is untouched.parseLocalDebugPlanMarkdownis innocent: it extracts the fenced block faithfully. The gap was thatMermaidBlockhanded that string straight tomermaid.render()with no normalization.What changed
src/webviews/copilotOnRails/views/utils/quoteMermaidLabels.ts— quotes any flowchart node or edge label that is not quoted already.LocalPlanView.tsx'sMermaidBlocknow callsmermaid.render(id, quoteMermaidLabels(code)). The error fallback still shows the code the author actually wrote.test/copilotOnRails/quoteMermaidLabels.test.ts— 22 unit tests in the existing suite's style, no new test framework.The transform is deliberately narrow, because the failure mode of a bad rewrite is a diagram that used to work and no longer does:
graph/flowchartdiagrams are rewritten[],{}and|mean something else entirely in sequence, class, ER, state and pie diagrams — those come back byte-identical@{are exempt from the rhombus ruleA@{ shape: rect },e1@{ animate: true }) is brace-delimited configuration, not a label. Rewritinge1@{ animate: true }toe1@{"animate: true"}would change what it means. This is explicit rather than accidental"…"stringsA["Blob (hot tier) [preview]"]), and makes the transform idempotent[…]rule;/and\(parallelogram/trapezoid) left aloneNet effect: it is a no-op on any diagram that already renders.
Validation
Real mermaid 11.17.0 under jsdom, driving the actual
parseLocalDebugPlanMarkdownover plan markdown — 107/107 checks pass:test/testProjects/copilotOnRails/attendance/vscode-debug-plan.mdtest/testProjects/copilotOnRails/scrapbook/vscode-debug-plan.mdevals/grader-certification/reference-node-fullstack/.azure/vscode-debug-plan.mdevals/grader-certification/stage-local-dev/.azure/vscode-debug-plan.mdsubgraph,classDef+class, bareA --> B --> C, rhombus, circle, cylinder, hexagon, stadium, subroutine, parallelogram, trapezoid,style,linkStyle,clickcallbacks, markdown-string labels (["`**bold**`"]),%%comments,%%{init: …}%%directives, YAML frontmatter, and v11id@{ shape }/e1@-->metadata.@-leading labels broken before / fixed after in every shape: edge label, rect, cylinder, circle, rhombus.Repo gates — all green:
npm run build:check(tsc --noEmit)npm run lintevals:driftagent-assets.lock.jsonis untouchedevals:typecheck,lint,certify(152/152),imports:self-test,stacks:check,gates,phases:check,seed:contract,clean-machine:checkevals/results/grader-certification/offline/report.jsonwas restored aftercertifyso itsgeneratedAtchurn does not leak into this PR, andpackage-lock.jsonwas restored after the localnpm i. The diff is three files.Docs
No update needed in
docs/copilot-create-project.md: no command, MCP tool, agent,.azure/*artifact orworkspaceStatekey changed, and no UI surface was added, removed or restyled. The debug plan view's intended appearance is unchanged — this only makes diagrams that were showing the error graphic render as designed.08-debug-plan-view.pngis therefore only stale if it happens to have been captured while a diagram was failing to parse; worth a glance, but no placeholder was added or removed.