Skip to content

refactor: migrate remaining locate buttons to shared LocateNodeButton#13795

Open
mattmillerai wants to merge 1 commit into
matt/be-2256-locate-node-buttonfrom
matt/be-3475-locate-node-button-migration
Open

refactor: migrate remaining locate buttons to shared LocateNodeButton#13795
mattmillerai wants to merge 1 commit into
matt/be-2256-locate-node-buttonfrom
matt/be-3475-locate-node-button-migration

Conversation

@mattmillerai

Copy link
Copy Markdown
Contributor

ELI-5

The error / missing-resource panels have several little "locate this node on
the canvas" buttons. #13401 turned that button into one shared
LocateNodeButton component for the errors panel. This PR swaps the five
remaining hand-rolled copies (in the swap-node, missing-model, and
missing-media rows) over to that same shared component so they all look and
behave identically — including a screen-reader label that names the specific
node ("Locate LoadImage" instead of a generic "Locate node on canvas").

Summary

Stacked on #13401 (base branch matt/be-2256-locate-node-button). That PR
extracted LocateNodeButton.vue for the errors panel but intentionally left
the platform-sibling rows untouched. This PR migrates the remaining five inline
Button + icon-[lucide--locate] usages:

  • SwapNodeGroupRow.vue (2 — header + per-node list)
  • MissingModelRow.vue (2 — header + per-reference list)
  • MissingMediaCard.vue (1)

Each inline button becomes <LocateNodeButton :label @locate />, with a
node-specific accessible label built from rightSidePanel.locateNodeFor
(Locate {item}), matching the pattern already used in
ErrorNodeCard / ErrorGroupList / MissingPackGroupRow:

  • MissingMediaCard already used locateNodeFor — label unchanged.
  • SwapNodeGroupRow and MissingModelRow previously used a generic
    "Locate node on canvas" label; they now name the node type / display name.

Behavior note: click.stop

LocateNodeButton stops click propagation, whereas the swap-node and
missing-model rows previously used a plain @click. Stopping propagation is
the desired, consistent behavior and is safe here: the parent components
(SwapNodesCard, MissingModelCard) only bind the custom @locate-node /
@locate-model events and no ancestor binds a DOM click handler on the row,
so nothing relied on the native click bubbling.

Tests

  • SwapNodeGroupRow.test.ts: updated the locate-button assertions to the new
    node-specific accessible names and added a test asserting each control gets a
    node-specific label.
  • MissingModelRow.test.ts: added a test asserting the header locate button
    exposes the node-specific aria-label and emits locateModel.
  • MissingMediaCard.test.ts: added a locate emit test (the existing
    special-characters aria-label test already covers the node-specific label).

All three files' tests plus the parent-card and LocateNodeButton tests pass;
typecheck and eslint are clean on the changed files.

Notes / judgment calls

  • The rightSidePanel.missingModels.locateNode string is now unused but kept in
    main.json to avoid churning the other locale files; happy to drop it if
    preferred.
  • SectionWidgets.vue also has a lucide--locate button, but it lives in the
    parameters panel (a different context, generic label) and is not one of the
    five usages this ticket scopes — left untouched.

Replace the five inline lucide--locate Button usages in
SwapNodeGroupRow, MissingModelRow, and MissingMediaCard with the shared
LocateNodeButton component, passing node-specific accessible labels via
rightSidePanel.locateNodeFor to match the errors-panel siblings. This
also gives the swap-node and missing-model locate buttons click.stop
(harmless: no ancestor binds a DOM click handler) and node-specific
aria-labels in place of the previous generic label.
@mattmillerai mattmillerai added agent-coded Opened by the agent-work code loop cursor-review Trigger multi-model Cursor agent review on this PR labels Jul 18, 2026
@mattmillerai
mattmillerai marked this pull request as ready for review July 18, 2026 13:50
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0e8c9f4b-3228-42a4-b13d-95dd36322734

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-3475-locate-node-button-migration

Comment @coderabbitai help to get the list of available commands.

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 18, 2026
@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown

🎭 Playwright: ❌ 1710 passed, 2 failed · 2 flaky

❌ Failed Tests

📊 Browser Reports
  • chromium: View Report (✅ 1691 / ❌ 2 / ⚠️ 1 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 16 / ❌ 0 / ⚠️ 1 / ⏭️ 0)

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 07/18/2026, 01:52:02 PM UTC

Links

📦 Bundle Size

⏳ Size data collection in progress…

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.7 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 51.6 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 72.6 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 54.4 MB heap
large-graph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.0 MB heap
large-graph-pan: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.2 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.9 MB heap
minimap-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.6 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.0 MB heap
subgraph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.2 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 48.8 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 128ms TBT · 81.2 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 72.0 MB heap
vue-large-graph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 164.9 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 34ms TBT · 164.0 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 49.4 MB heap

ℹ️ No baseline found — significance unavailable.

Absolute values
Metric Value
canvas-idle: avg frame time 17ms
canvas-idle: p95 frame time 17ms
canvas-idle: layout duration 0ms
canvas-idle: style recalc duration 11ms
canvas-idle: layout count 0
canvas-idle: style recalc count 9
canvas-idle: task duration 436ms
canvas-idle: script duration 20ms
canvas-idle: TBT 0ms
canvas-idle: heap used 57.7 MB
canvas-idle: DOM nodes -124
canvas-idle: event listeners -65
canvas-mouse-sweep: avg frame time 17ms
canvas-mouse-sweep: p95 frame time 17ms
canvas-mouse-sweep: layout duration 4ms
canvas-mouse-sweep: style recalc duration 39ms
canvas-mouse-sweep: layout count 12
canvas-mouse-sweep: style recalc count 74
canvas-mouse-sweep: task duration 800ms
canvas-mouse-sweep: script duration 111ms
canvas-mouse-sweep: TBT 0ms
canvas-mouse-sweep: heap used 51.6 MB
canvas-mouse-sweep: DOM nodes -264
canvas-mouse-sweep: event listeners -133
canvas-zoom-sweep: avg frame time 17ms
canvas-zoom-sweep: p95 frame time 17ms
canvas-zoom-sweep: layout duration 1ms
canvas-zoom-sweep: style recalc duration 17ms
canvas-zoom-sweep: layout count 6
canvas-zoom-sweep: style recalc count 31
canvas-zoom-sweep: task duration 310ms
canvas-zoom-sweep: script duration 19ms
canvas-zoom-sweep: TBT 0ms
canvas-zoom-sweep: heap used 72.6 MB
canvas-zoom-sweep: DOM nodes 79
canvas-zoom-sweep: event listeners 19
dom-widget-clipping: avg frame time 17ms
dom-widget-clipping: p95 frame time 17ms
dom-widget-clipping: layout duration 0ms
dom-widget-clipping: style recalc duration 9ms
dom-widget-clipping: layout count 0
dom-widget-clipping: style recalc count 13
dom-widget-clipping: task duration 338ms
dom-widget-clipping: script duration 54ms
dom-widget-clipping: TBT 0ms
dom-widget-clipping: heap used 54.4 MB
dom-widget-clipping: DOM nodes 21
dom-widget-clipping: event listeners 0
large-graph-idle: avg frame time 17ms
large-graph-idle: p95 frame time 17ms
large-graph-idle: layout duration 0ms
large-graph-idle: style recalc duration 8ms
large-graph-idle: layout count 0
large-graph-idle: style recalc count 10
large-graph-idle: task duration 549ms
large-graph-idle: script duration 85ms
large-graph-idle: TBT 0ms
large-graph-idle: heap used 62.0 MB
large-graph-idle: DOM nodes -266
large-graph-idle: event listeners -129
large-graph-pan: avg frame time 17ms
large-graph-pan: p95 frame time 17ms
large-graph-pan: layout duration 0ms
large-graph-pan: style recalc duration 13ms
large-graph-pan: layout count 0
large-graph-pan: style recalc count 68
large-graph-pan: task duration 1080ms
large-graph-pan: script duration 368ms
large-graph-pan: TBT 0ms
large-graph-pan: heap used 67.2 MB
large-graph-pan: DOM nodes -270
large-graph-pan: event listeners -127
large-graph-zoom: avg frame time 17ms
large-graph-zoom: p95 frame time 17ms
large-graph-zoom: layout duration 8ms
large-graph-zoom: style recalc duration 15ms
large-graph-zoom: layout count 60
large-graph-zoom: style recalc count 66
large-graph-zoom: task duration 1316ms
large-graph-zoom: script duration 451ms
large-graph-zoom: TBT 0ms
large-graph-zoom: heap used 53.9 MB
large-graph-zoom: DOM nodes -273
large-graph-zoom: event listeners -133
minimap-idle: avg frame time 17ms
minimap-idle: p95 frame time 17ms
minimap-idle: layout duration 0ms
minimap-idle: style recalc duration 7ms
minimap-idle: layout count 0
minimap-idle: style recalc count 9
minimap-idle: task duration 536ms
minimap-idle: script duration 84ms
minimap-idle: TBT 0ms
minimap-idle: heap used 63.6 MB
minimap-idle: DOM nodes -268
minimap-idle: event listeners -129
subgraph-dom-widget-clipping: avg frame time 17ms
subgraph-dom-widget-clipping: p95 frame time 17ms
subgraph-dom-widget-clipping: layout duration 0ms
subgraph-dom-widget-clipping: style recalc duration 11ms
subgraph-dom-widget-clipping: layout count 0
subgraph-dom-widget-clipping: style recalc count 48
subgraph-dom-widget-clipping: task duration 365ms
subgraph-dom-widget-clipping: script duration 118ms
subgraph-dom-widget-clipping: TBT 0ms
subgraph-dom-widget-clipping: heap used 55.0 MB
subgraph-dom-widget-clipping: DOM nodes 21
subgraph-dom-widget-clipping: event listeners 6
subgraph-idle: avg frame time 17ms
subgraph-idle: p95 frame time 17ms
subgraph-idle: layout duration 0ms
subgraph-idle: style recalc duration 8ms
subgraph-idle: layout count 0
subgraph-idle: style recalc count 11
subgraph-idle: task duration 404ms
subgraph-idle: script duration 14ms
subgraph-idle: TBT 0ms
subgraph-idle: heap used 46.2 MB
subgraph-idle: DOM nodes -262
subgraph-idle: event listeners -133
subgraph-mouse-sweep: avg frame time 17ms
subgraph-mouse-sweep: p95 frame time 17ms
subgraph-mouse-sweep: layout duration 4ms
subgraph-mouse-sweep: style recalc duration 38ms
subgraph-mouse-sweep: layout count 16
subgraph-mouse-sweep: style recalc count 77
subgraph-mouse-sweep: task duration 733ms
subgraph-mouse-sweep: script duration 90ms
subgraph-mouse-sweep: TBT 0ms
subgraph-mouse-sweep: heap used 48.8 MB
subgraph-mouse-sweep: DOM nodes -263
subgraph-mouse-sweep: event listeners -133
subgraph-transition-enter: avg frame time 17ms
subgraph-transition-enter: p95 frame time 17ms
subgraph-transition-enter: layout duration 12ms
subgraph-transition-enter: style recalc duration 28ms
subgraph-transition-enter: layout count 15
subgraph-transition-enter: style recalc count 19
subgraph-transition-enter: task duration 694ms
subgraph-transition-enter: script duration 27ms
subgraph-transition-enter: TBT 128ms
subgraph-transition-enter: heap used 81.2 MB
subgraph-transition-enter: DOM nodes 13673
subgraph-transition-enter: event listeners 2369
viewport-pan-sweep: avg frame time 17ms
viewport-pan-sweep: p95 frame time 17ms
viewport-pan-sweep: layout duration 0ms
viewport-pan-sweep: style recalc duration 38ms
viewport-pan-sweep: layout count 0
viewport-pan-sweep: style recalc count 251
viewport-pan-sweep: task duration 3707ms
viewport-pan-sweep: script duration 1159ms
viewport-pan-sweep: TBT 0ms
viewport-pan-sweep: heap used 72.0 MB
viewport-pan-sweep: DOM nodes -265
viewport-pan-sweep: event listeners -113
vue-large-graph-idle: avg frame time 17ms
vue-large-graph-idle: p95 frame time 17ms
vue-large-graph-idle: layout duration 0ms
vue-large-graph-idle: style recalc duration 0ms
vue-large-graph-idle: layout count 0
vue-large-graph-idle: style recalc count 0
vue-large-graph-idle: task duration 11085ms
vue-large-graph-idle: script duration 542ms
vue-large-graph-idle: TBT 0ms
vue-large-graph-idle: heap used 164.9 MB
vue-large-graph-idle: DOM nodes -8311
vue-large-graph-idle: event listeners -16386
vue-large-graph-pan: avg frame time 17ms
vue-large-graph-pan: p95 frame time 17ms
vue-large-graph-pan: layout duration 0ms
vue-large-graph-pan: style recalc duration 12ms
vue-large-graph-pan: layout count 0
vue-large-graph-pan: style recalc count 67
vue-large-graph-pan: task duration 13592ms
vue-large-graph-pan: script duration 828ms
vue-large-graph-pan: TBT 34ms
vue-large-graph-pan: heap used 164.0 MB
vue-large-graph-pan: DOM nodes -8311
vue-large-graph-pan: event listeners -16382
workflow-execution: avg frame time 17ms
workflow-execution: p95 frame time 17ms
workflow-execution: layout duration 1ms
workflow-execution: style recalc duration 21ms
workflow-execution: layout count 3
workflow-execution: style recalc count 16
workflow-execution: task duration 120ms
workflow-execution: script duration 10ms
workflow-execution: TBT 0ms
workflow-execution: heap used 49.4 MB
workflow-execution: DOM nodes 128
workflow-execution: event listeners 65
Raw data
{
  "timestamp": "2026-07-18T14:00:36.959Z",
  "gitSha": "adc479d5192c87a545f3b83458d9d78335e106f3",
  "branch": "matt/be-3475-locate-node-button-migration",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2086.0409999999947,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.461999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 436.89399999999995,
      "heapDeltaBytes": 3935664,
      "heapUsedBytes": 72857588,
      "domNodes": 18,
      "jsHeapTotalBytes": 19677184,
      "scriptDurationMs": 21.178,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-idle",
      "durationMs": 2073.120000000017,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 14.609999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 434.464,
      "heapDeltaBytes": -20922168,
      "heapUsedBytes": 48084592,
      "domNodes": -266,
      "jsHeapTotalBytes": 18755584,
      "scriptDurationMs": 18.266,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1832.868999999988,
      "styleRecalcs": 73,
      "styleRecalcDurationMs": 40.186,
      "layouts": 12,
      "layoutDurationMs": 3.875,
      "taskDurationMs": 801.6450000000001,
      "heapDeltaBytes": -15160772,
      "heapUsedBytes": 53767068,
      "domNodes": -263,
      "jsHeapTotalBytes": 21114880,
      "scriptDurationMs": 112.949,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1828.125,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 36.888999999999996,
      "layouts": 12,
      "layoutDurationMs": 3.9390000000000005,
      "taskDurationMs": 797.5070000000001,
      "heapDeltaBytes": -14465376,
      "heapUsedBytes": 54368904,
      "domNodes": -264,
      "jsHeapTotalBytes": 20590592,
      "scriptDurationMs": 109.416,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1664.1180000000304,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 16.518,
      "layouts": 6,
      "layoutDurationMs": 0.5690000000000001,
      "taskDurationMs": 308.774,
      "heapDeltaBytes": 7127484,
      "heapUsedBytes": 75884432,
      "domNodes": 79,
      "jsHeapTotalBytes": 19677184,
      "scriptDurationMs": 18.362000000000002,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1722.912000000008,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 16.88,
      "layouts": 6,
      "layoutDurationMs": 0.727,
      "taskDurationMs": 310.86400000000003,
      "heapDeltaBytes": 7480792,
      "heapUsedBytes": 76458032,
      "domNodes": 78,
      "jsHeapTotalBytes": 19415040,
      "scriptDurationMs": 20.135,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 581.3150000000178,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 8.361000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 342.38,
      "heapDeltaBytes": -11794468,
      "heapUsedBytes": 57136964,
      "domNodes": 22,
      "jsHeapTotalBytes": 19939328,
      "scriptDurationMs": 54.544000000000004,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666682,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 561.5829999999846,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 9.455000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 333.982,
      "heapDeltaBytes": -11865876,
      "heapUsedBytes": 56859148,
      "domNodes": 20,
      "jsHeapTotalBytes": 19677184,
      "scriptDurationMs": 52.616,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2006.8049999999857,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 9.536000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 549.342,
      "heapDeltaBytes": 4676996,
      "heapUsedBytes": 65641732,
      "domNodes": -265,
      "jsHeapTotalBytes": 5193728,
      "scriptDurationMs": 84.14099999999999,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2024.6669999999654,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.356,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 548.621,
      "heapDeltaBytes": 5365312,
      "heapUsedBytes": 64416812,
      "domNodes": -267,
      "jsHeapTotalBytes": 4931584,
      "scriptDurationMs": 85.253,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2142.1919999999946,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 14.232000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1088.4930000000002,
      "heapDeltaBytes": 24857920,
      "heapUsedBytes": 85123380,
      "domNodes": -268,
      "jsHeapTotalBytes": 5136384,
      "scriptDurationMs": 375.967,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2090.8469999999966,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 12.33,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1072.492,
      "heapDeltaBytes": -4583128,
      "heapUsedBytes": 55811488,
      "domNodes": -271,
      "jsHeapTotalBytes": 4931584,
      "scriptDurationMs": 359.993,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3136.1870000000067,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 15.616000000000001,
      "layouts": 60,
      "layoutDurationMs": 7.681,
      "taskDurationMs": 1295.569,
      "heapDeltaBytes": -5220780,
      "heapUsedBytes": 56623404,
      "domNodes": -273,
      "jsHeapTotalBytes": 8077312,
      "scriptDurationMs": 444.821,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3152.0830000000046,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 14.677,
      "layouts": 60,
      "layoutDurationMs": 7.772999999999999,
      "taskDurationMs": 1336.923,
      "heapDeltaBytes": -5502528,
      "heapUsedBytes": 56363460,
      "domNodes": -273,
      "jsHeapTotalBytes": 8339456,
      "scriptDurationMs": 458.09700000000004,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2032.3480000000131,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.977999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 533.3090000000001,
      "heapDeltaBytes": 5681684,
      "heapUsedBytes": 67513748,
      "domNodes": -267,
      "jsHeapTotalBytes": 4931584,
      "scriptDurationMs": 82.996,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "minimap-idle",
      "durationMs": 2017.1059999999557,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 6.710000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 538.932,
      "heapDeltaBytes": 5011960,
      "heapUsedBytes": 65965360,
      "domNodes": -269,
      "jsHeapTotalBytes": 5455872,
      "scriptDurationMs": 85.463,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 602.3610000000303,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 9.621,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 363.453,
      "heapDeltaBytes": -11076504,
      "heapUsedBytes": 57794052,
      "domNodes": 18,
      "jsHeapTotalBytes": 20725760,
      "scriptDurationMs": 120.26200000000001,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 574.6489999999653,
      "styleRecalcs": 49,
      "styleRecalcDurationMs": 12.74,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 367.39300000000003,
      "heapDeltaBytes": -11280120,
      "heapUsedBytes": 57539108,
      "domNodes": 24,
      "jsHeapTotalBytes": 20987904,
      "scriptDurationMs": 115.82000000000001,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2019.8450000000037,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 7.863000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 400.47200000000004,
      "heapDeltaBytes": -21212340,
      "heapUsedBytes": 47767988,
      "domNodes": -262,
      "jsHeapTotalBytes": 19804160,
      "scriptDurationMs": 14.191,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2032.5300000000084,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.122999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 408.004,
      "heapDeltaBytes": -19668844,
      "heapUsedBytes": 49201920,
      "domNodes": -261,
      "jsHeapTotalBytes": 20066304,
      "scriptDurationMs": 14.746,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1749.0319999999997,
      "styleRecalcs": 78,
      "styleRecalcDurationMs": 39.25,
      "layouts": 16,
      "layoutDurationMs": 4.5040000000000004,
      "taskDurationMs": 733.43,
      "heapDeltaBytes": -17779056,
      "heapUsedBytes": 51140636,
      "domNodes": -263,
      "jsHeapTotalBytes": 20328448,
      "scriptDurationMs": 93.741,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1715.2130000000056,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 35.939,
      "layouts": 16,
      "layoutDurationMs": 4.144,
      "taskDurationMs": 733.0859999999999,
      "heapDeltaBytes": -17842040,
      "heapUsedBytes": 51150160,
      "domNodes": -263,
      "jsHeapTotalBytes": 20328448,
      "scriptDurationMs": 85.87899999999999,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 914.8979999999938,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 28.022999999999993,
      "layouts": 15,
      "layoutDurationMs": 12.431,
      "taskDurationMs": 694.2600000000001,
      "heapDeltaBytes": 1166696,
      "heapUsedBytes": 85154724,
      "domNodes": 13673,
      "jsHeapTotalBytes": 15990784,
      "scriptDurationMs": 26.644000000000002,
      "eventListeners": 2369,
      "totalBlockingTimeMs": 128,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8206.929000000002,
      "styleRecalcs": 251,
      "styleRecalcDurationMs": 38.800000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3734.6650000000004,
      "heapDeltaBytes": 16346584,
      "heapUsedBytes": 77558284,
      "domNodes": -264,
      "jsHeapTotalBytes": 6971392,
      "scriptDurationMs": 1163.6419999999998,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.80000000000109
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8137.034999999969,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 38.065000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3679.7819999999992,
      "heapDeltaBytes": 14211752,
      "heapUsedBytes": 73471076,
      "domNodes": -265,
      "jsHeapTotalBytes": 5136384,
      "scriptDurationMs": 1153.988,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11049.216999999999,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11033.335000000001,
      "heapDeltaBytes": -35322184,
      "heapUsedBytes": 170731624,
      "domNodes": -8311,
      "jsHeapTotalBytes": -10395648,
      "scriptDurationMs": 563.013,
      "eventListeners": -16386,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11151.402999999958,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11137.455000000002,
      "heapDeltaBytes": -49993164,
      "heapUsedBytes": 175027028,
      "domNodes": -8311,
      "jsHeapTotalBytes": -9900032,
      "scriptDurationMs": 521.909,
      "eventListeners": -16386,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13618.743999999992,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 12.205999999999994,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13594.025000000001,
      "heapDeltaBytes": -31532976,
      "heapUsedBytes": 177075272,
      "domNodes": -8311,
      "jsHeapTotalBytes": -17063936,
      "scriptDurationMs": 855.193,
      "eventListeners": -16384,
      "totalBlockingTimeMs": 56,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13609.797999999955,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 11.943000000000008,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13590.131,
      "heapDeltaBytes": -51478176,
      "heapUsedBytes": 166954900,
      "domNodes": -8311,
      "jsHeapTotalBytes": -13307904,
      "scriptDurationMs": 800.455,
      "eventListeners": -16380,
      "totalBlockingTimeMs": 11,
      "frameDurationMs": 17.216666666666665,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 456.0989999999947,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 21.182,
      "layouts": 3,
      "layoutDurationMs": 0.6689999999999999,
      "taskDurationMs": 121.191,
      "heapDeltaBytes": -16110376,
      "heapUsedBytes": 51871236,
      "domNodes": 134,
      "jsHeapTotalBytes": 6569984,
      "scriptDurationMs": 9.577000000000002,
      "eventListeners": 65,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "workflow-execution",
      "durationMs": 461.3650000000007,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 20.071,
      "layouts": 3,
      "layoutDurationMs": 0.5820000000000001,
      "taskDurationMs": 118.451,
      "heapDeltaBytes": -16275452,
      "heapUsedBytes": 51796524,
      "domNodes": 121,
      "jsHeapTotalBytes": 7094272,
      "scriptDurationMs": 9.863,
      "eventListeners": 65,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.699999999999818
    }
  ]
}

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

✅ No high-signal findings.

Panel: 8/8 reviewers contributed findings.

@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@                         Coverage Diff                         @@
##           matt/be-2256-locate-node-button   #13795      +/-   ##
===================================================================
- Coverage                            77.81%   77.81%   -0.01%     
===================================================================
  Files                                 1687     1687              
  Lines                                95618    95613       -5     
  Branches                             33646    32894     -752     
===================================================================
- Hits                                 74409    74404       -5     
  Misses                               20775    20775              
  Partials                               434      434              
Flag Coverage Δ
unit 67.28% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...tform/missingMedia/components/MissingMediaCard.vue 96.55% <100.00%> (+3.21%) ⬆️
...atform/missingModel/components/MissingModelRow.vue 92.10% <100.00%> (ø)
...rm/nodeReplacement/components/SwapNodeGroupRow.vue 98.43% <100.00%> (-0.10%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded Opened by the agent-work code loop cursor-review Trigger multi-model Cursor agent review on this PR size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant