You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm happy to work on this one, but wanted to track the proposal first, especially given the related issue.
A rendered Mermaid diagram is currently an all-or-nothing annotation target. Pinpoint skips it entirely (data-pinpoint-ignore on the grab container, added in #819 so that releasing a pan-drag stopped creating a whole-block annotation), and text selection is excluded along with it. The only way to comment on a diagram today is to toggle Show source and annotate the whole fenced block as one code block, which points the agent at the entire diagram.
Reviewers want to point at a specific node, edge, edge label, or subgraph and say what is wrong with that one thing.
Relation to existing issues
#911 tracks diagram generation and iteration and does not cover annotating a rendered diagram. Its one comment asks for something adjacent: freehand circling on a Mermaid diagram, with the resulting image handed back to a multimodal agent. That is a different mechanism (raster capture through the Image Annotator) reaching for a similar goal, and the two can coexist. Structured targeting gives the agent the source identifier of the thing being discussed. Freehand gives it a picture.
Nothing else in the tracker covers per-element diagram commenting.
Feasibility
I rendered the common diagram types through the pinned Mermaid 11 configuration (securityLevel: 'strict', htmlLabels: true) in a browser and inspected the emitted SVG and its hit behavior.
Mermaid emits source-derived identity for flowchart, class, state, and ER diagrams:
Surface
DOM
Anchor
Node
<g id="flowchart-A-0" class="node">
source key A
Edge
<path id="L_A_B_0" class="flowchart-link">
fully semantic
Subgraph
<g id="grp" class="cluster">
source id verbatim
Edge label
<g class="edgeLabel">
ordinal plus text
Re-rendering identical source reproduces those ids exactly. Inserting a node upstream shifts only the trailing counter (flowchart-A-0 becomes flowchart-A-1) while the source key and every edge id survive unchanged. So the durable anchor is the source key plus a text snapshot, resolved back through g.node[id^="flowchart-A-"] and verified against the snapshot. That is the same fail-closed shape as the existing HtmlElementAnchor.
Sequence, pie, and gantt diagrams carry no source-derived ids. Actors are #root-0, pie slices are anonymous path.pieCircle. Those degrade to class, ordinal, and text.
Hit-testing needs one instrumentation pass. Untouched, clicking an edge misses it: edge paths are 1px fill:none strokes, and foreignObject label boxes sit on top and absorb the hit. Cloning each edge path as a transparent stroke-width:16; pointer-events:stroke sibling, then setting pointer-events:none on foreignObject and auto on the label spans, makes every surface resolve correctly from elementFromPoint plus closest(). I confirmed this in the browser for nodes, edges, edge labels, and the subgraph frame. closest() crosses the foreignObject boundary, so a click on a node's HTML label resolves to its <g>.
Painting is cheaper here than on the HTML surface. A highlight rect derived from getBBox() and inserted inside the annotated <g> lives in the diagram's own coordinate space. It pans and zooms with the diagram for free and clips naturally when panned out of view, so there is no overlay reprojection to maintain.
Proposal
Add a diagram target kind to the existing Pinpoint pipeline.
Anchor. A new additive field on Annotation, alongside mathTargets and htmlAnchor: { kind: 'node' | 'edge' | 'edgeLabel' | 'cluster', sourceKey, label }. Resolution matches on the source key and verifies the label snapshot, failing closed when the diagram has changed underneath.
Targeting.usePinpoint already branches out of the range path for code blocks. A diagram branch slots in the same way, fed by a resolver over the instrumented SVG.
Export. Match the source key back to its line in the fence body so the exported feedback quotes the real Mermaid source (B -->|no| C[(Database)]) rather than only a rendered label, and derive startOffset from that line so the existing export ordering holds.
Scope
Comparable to the math annotation feature, not to the raw-HTML pinpoint surface. Server-side changes are not required.
Flowchart family first, where identity is strong.
Ordinal-anchored families (sequence, pie, gantt) as a follow-up, or explicitly out of scope for a first version.
Risks
data-pinpoint-ignore must be narrowed rather than removed. Text selection has to stay excluded, or web-highlighter will attempt to mark inside foreignObject.
The SVG is re-injected through dangerouslySetInnerHTML on content change, and the expanded view remounts it into a portal. Annotations must be re-resolved on each, under the same contract onCodeHighlightSwap already enforces for code-block marks.
Share links will not carry diagram anchors. That is the existing documented contract for htmlAnchor, which restores by text search only. Either extend the share payload or accept the degradation.
The text-selection path is not a viable alternative. With htmlLabels: true the labels are real HTML and selectable, but offsets would address the fence source, which has no correspondence to the rendered label.
Open decisions
Whether the ordinal-anchored diagram families ship at all, given that their anchors break on any reordering.
I'm happy to work on this one, but wanted to track the proposal first, especially given the related issue.
A rendered Mermaid diagram is currently an all-or-nothing annotation target. Pinpoint skips it entirely (
data-pinpoint-ignoreon the grab container, added in #819 so that releasing a pan-drag stopped creating a whole-block annotation), and text selection is excluded along with it. The only way to comment on a diagram today is to toggle Show source and annotate the whole fenced block as one code block, which points the agent at the entire diagram.Reviewers want to point at a specific node, edge, edge label, or subgraph and say what is wrong with that one thing.
Relation to existing issues
#911 tracks diagram generation and iteration and does not cover annotating a rendered diagram. Its one comment asks for something adjacent: freehand circling on a Mermaid diagram, with the resulting image handed back to a multimodal agent. That is a different mechanism (raster capture through the Image Annotator) reaching for a similar goal, and the two can coexist. Structured targeting gives the agent the source identifier of the thing being discussed. Freehand gives it a picture.
Nothing else in the tracker covers per-element diagram commenting.
Feasibility
I rendered the common diagram types through the pinned Mermaid 11 configuration (
securityLevel: 'strict',htmlLabels: true) in a browser and inspected the emitted SVG and its hit behavior.Mermaid emits source-derived identity for flowchart, class, state, and ER diagrams:
<g id="flowchart-A-0" class="node">A<path id="L_A_B_0" class="flowchart-link"><g id="grp" class="cluster"><g class="edgeLabel">Re-rendering identical source reproduces those ids exactly. Inserting a node upstream shifts only the trailing counter (
flowchart-A-0becomesflowchart-A-1) while the source key and every edge id survive unchanged. So the durable anchor is the source key plus a text snapshot, resolved back throughg.node[id^="flowchart-A-"]and verified against the snapshot. That is the same fail-closed shape as the existingHtmlElementAnchor.Sequence, pie, and gantt diagrams carry no source-derived ids. Actors are
#root-0, pie slices are anonymouspath.pieCircle. Those degrade to class, ordinal, and text.Hit-testing needs one instrumentation pass. Untouched, clicking an edge misses it: edge paths are 1px
fill:nonestrokes, andforeignObjectlabel boxes sit on top and absorb the hit. Cloning each edge path as a transparentstroke-width:16; pointer-events:strokesibling, then settingpointer-events:noneonforeignObjectandautoon the label spans, makes every surface resolve correctly fromelementFromPointplusclosest(). I confirmed this in the browser for nodes, edges, edge labels, and the subgraph frame.closest()crosses theforeignObjectboundary, so a click on a node's HTML label resolves to its<g>.Painting is cheaper here than on the HTML surface. A highlight rect derived from
getBBox()and inserted inside the annotated<g>lives in the diagram's own coordinate space. It pans and zooms with the diagram for free and clips naturally when panned out of view, so there is no overlay reprojection to maintain.Proposal
Add a diagram target kind to the existing Pinpoint pipeline.
Annotation, alongsidemathTargetsandhtmlAnchor:{ kind: 'node' | 'edge' | 'edgeLabel' | 'cluster', sourceKey, label }. Resolution matches on the source key and verifies the label snapshot, failing closed when the diagram has changed underneath.usePinpointalready branches out of the range path for code blocks. A diagram branch slots in the same way, fed by a resolver over the instrumented SVG.B -->|no| C[(Database)]) rather than only a rendered label, and derivestartOffsetfrom that line so the existing export ordering holds.Scope
Comparable to the math annotation feature, not to the raw-HTML pinpoint surface. Server-side changes are not required.
Risks
data-pinpoint-ignoremust be narrowed rather than removed. Text selection has to stay excluded, or web-highlighter will attempt to mark insideforeignObject.dangerouslySetInnerHTMLon content change, and the expanded view remounts it into a portal. Annotations must be re-resolved on each, under the same contractonCodeHighlightSwapalready enforces for code-block marks.htmlAnchor, which restores by text search only. Either extend the share payload or accept the degradation.htmlLabels: truethe labels are real HTML and selectable, but offsets would address the fence source, which has no correspondence to the rendered label.Open decisions