Skip to content

fix: decouple subgraph preview/output display from the promotion system - #14569

Open
claude[bot] wants to merge 15 commits into
mainfrom
fix/decouple-subgraph-preview-outputs
Open

fix: decouple subgraph preview/output display from the promotion system#14569
claude[bot] wants to merge 15 commits into
mainfrom
fix/decouple-subgraph-preview-outputs

Conversation

@claude

@claude claude Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Requested by Christian Byrne · Slack thread

Summary

Fixes incident-94 bug #3: when a subgraph host has multiple interior nodes producing live previews concurrently (e.g. two KSamplers in one subgraph), only one of them showed on the host, and it could go stale.

Before: the only path from an interior node's live output to the SubgraphNode host was previewExposureStore. The root cause is not the exposure record itself but how exposures get created: a one-shot autoExposeKnownPreviewNodes pass that runs once, the first time the subgraph's previewExposures property is undefined. If a second interior node (a second KSampler, or one added after that one-shot pass already ran) never got an exposure, its live preview had nowhere to render on the host — invisible, even while executing.

After: the host also derives an ambient rollup, independent of promotion, by reading each direct interior node's own output/preview state straight from nodeOutputStore — the same store every regular node's own preview already reads from. Any interior node currently producing output shows on the host, whether or not anyone promoted it. An explicit exposure for a node still wins (keeps its promoted name/ordering); the ambient rollup only fills in nodes that have live output but no exposure. Two concurrently-executing KSamplers in one subgraph now both show and update independently instead of one overwriting/hiding the other.

How

  • src/composables/node/useAmbientSubgraphPreviews.ts (new): a computed that mirrors the shape of executionStore's nodeLocationProgressStates — which already bubbles up execution progress to a subgraph host independent of promotion — but for preview images. For a SubgraphNode host it walks host.subgraph.nodes (direct interior nodes only; nested SubgraphNodes derive their own previews independently) and, for each one with live output/preview data in nodeOutputStore, builds a preview entry via the same getNodeImageUrls a regular node's own preview already uses. Deliberately a computed, not a watch(), per this repo's existing review pushback on watcher-based state derivation.
  • src/composables/node/usePromotedPreviews.ts: exported the existing PromotedPreview type and getPreviewMediaType helper (previously private) so the new ambient composable can share them — no behavior change to the exposure-driven path itself.
  • src/renderer/extensions/vueNodes/components/LGraphNode.vue: added useAmbientSubgraphPreviews alongside the existing usePromotedPreviews, merged into a subgraphPreviews computed (exposure-driven entries first, then any ambient entries for interior nodes not already exposed, deduped by source node id), and swapped the render v-for / hasCustomContent check from promotedPreviews to subgraphPreviews. The render list already supported an arbitrary number of previews — no new render component needed.
  • previewExposureStore's schema, the promotion/exposure mechanism, and the canvasImagePreviewTypes.ts allowlist are untouched — this is purely additive.

Test plan

  • src/composables/node/useAmbientSubgraphPreviews.test.ts (new, red→green): unit tests the new rollup directly — empty/detached/no-output cases, a single exposed-free interior node with live output, and the core regression case of two concurrently-executing interior nodes producing distinct previews without either being registered as an exposure.
  • browser_tests/tests/subgraph/subgraphConcurrentPreviews.spec.ts + browser_tests/assets/subgraphs/subgraph-with-two-live-samplers.json (new): e2e regression with two KSamplers in one subgraph where only one has a baked-in previewExposures entry (simulating a node added after the subgraph's one-shot auto-expose already ran). Drives two live b_preview WS frames at distinct interior execution IDs and asserts both show on the host, and that each updates independently as new frames arrive.
  • Confirmed red on main: before the fix, the unit test fails because useAmbientSubgraphPreviews doesn't exist yet (module-not-found), and the e2e scenario only shows the exposed sampler's preview.
  • Confirmed green after the fix: both new test files pass; broader regression run (usePromotedPreviews, previewExposureStore, nodeOutputStore, executionStore, nodeIdentification, LGraphNode/LGraphNode.subgraph, promotionUtils — 31 files / 550 tests) all pass, so single-KSampler-in-subgraph and the SamplerCustomAdvanced allowlist-gap fix (fix: derive subgraph preview promotion for any interior node type #14551) are unaffected.
  • pnpm typecheck, pnpm typecheck:browser, and oxlint/eslint/oxfmt on all touched files are clean.
  • Not run: the full Playwright browser suite, since this sandbox has no live ComfyUI backend available (cross-org repo, can't attach comfyanonymous/ComfyUI alongside this session's Comfy-Org sources) — the e2e spec was verified via playwright test --list (compiles, discovers under @vue-nodes/@subgraph) and vue-tsc --project browser_tests/tsconfig.json, but not executed end-to-end. Recommend running it in CI/a full local checkout before merge.

Linked issues

This PR changes only the Vue nodes renderer. The classic litegraph canvas still resolves host previews from previewExposureStore alone (litegraphService.ts:193), and Comfy.VueNodes.Enabled defaults to false for OSS local installs, so classic-canvas parity is the other half of this incident and is not addressed here.

Note: #14551 was closed in favour of this PR (same mechanism, this one better guarded). Its SamplerCustomAdvanced e2e fixture and spec still need porting here so the non-allowlisted node type stays pinned.


Generated by Claude Code

claude added 2 commits August 2, 2026 06:56
…or preview

Two KSamplers in one subgraph, only one wired into previewExposureStore
(the other simulates a node added after the subgraph's one-shot
auto-expose already ran). The unit test targets the not-yet-existing
useAmbientSubgraphPreviews composable; the e2e spec drives two live
b_preview WS frames at distinct interior execution IDs and asserts both
show on the collapsed SubgraphNode host.
…t exposures

Subgraph previews were 1:1 with previewExposureStore, so a second
interior node producing output concurrently (e.g. a 2nd KSampler with
no exposure) had nowhere to render and stayed invisible on the
collapsed host.

Add useAmbientSubgraphPreviews, a computed rollup that mirrors how
executionStore's nodeLocationProgressStates bubbles up progress
regardless of promotion: it reads each direct interior node's own
output/preview state from nodeOutputStore, independent of exposures.
LGraphNode.vue merges it underneath the existing exposure-driven
promotedPreviews (an explicit exposure still wins for that node), so
every concurrently-executing interior node shows and updates on its
own, not just the promoted one.
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1986 passed, 0 failed · 2 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1965 / ❌ 0 / ⚠️ 2 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 18 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • New-test walkthrough (chromium, recorded video): View Report

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 08/23/2026, 05:51:12 AM UTC

Links

📦 Bundle: 9.11 MB gzip 🔴 +759 B

Details

Summary

  • Raw size: 38.6 MB baseline 38.6 MB — 🔴 +3.44 kB
  • Gzip: 9.11 MB baseline 9.11 MB — 🔴 +759 B
  • Brotli: 6.38 MB baseline 6.37 MB — 🔴 +360 B
  • Bundles: 438 current • 438 baseline • 144 added / 144 removed

Category Glance
Graph Workspace 🔴 +3.44 kB (1.38 MB) · Vendor & Third-Party ⚪ 0 B (18.1 MB) · Other ⚪ 0 B (14.1 MB) · Data & Services ⚪ 0 B (3.53 MB) · Panels & Settings ⚪ 0 B (591 kB) · Utilities & Hooks ⚪ 0 B (549 kB) · + 5 more

App Entry Points — 3.71 kB (baseline 3.71 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-Cgxa3K7_.js (new) 3.71 kB 🔴 +3.71 kB 🔴 +1.85 kB 🔴 +1.63 kB
assets/index-Dk97gSRP.js (removed) 3.71 kB 🟢 -3.71 kB 🟢 -1.86 kB 🟢 -1.63 kB

Status: 1 added / 1 removed

Graph Workspace — 1.38 MB (baseline 1.38 MB) • 🔴 +3.44 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-DXQCgcKo.js (new) 1.37 MB 🔴 +1.37 MB 🔴 +300 kB 🔴 +226 kB
assets/GraphView-0orTaboD.js (removed) 1.37 MB 🟢 -1.37 MB 🟢 -299 kB 🟢 -225 kB
assets/WidgetCompositor-Dia_Rgmt.js (new) 8.17 kB 🔴 +8.17 kB 🔴 +2.75 kB 🔴 +2.47 kB
assets/WidgetCompositor-DJjpg5bG.js (removed) 8.17 kB 🟢 -8.17 kB 🟢 -2.76 kB 🟢 -2.45 kB

Status: 2 added / 2 removed / 1 unchanged

Views & Navigation — 124 kB (baseline 124 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-B0CRxC4l.js (new) 25 kB 🔴 +25 kB 🔴 +6.25 kB 🔴 +5.53 kB
assets/CloudSurveyView-DAP9EQEJ.js (removed) 25 kB 🟢 -25 kB 🟢 -6.25 kB 🟢 -5.52 kB
assets/CloudLayoutView-CT0wNII8.js (removed) 21.8 kB 🟢 -21.8 kB 🟢 -6.56 kB 🟢 -5.74 kB
assets/CloudLayoutView-CzHdC5pN.js (new) 21.8 kB 🔴 +21.8 kB 🔴 +6.56 kB 🔴 +5.73 kB
assets/UserCheckView-__NBt-8G.js (new) 8.75 kB 🔴 +8.75 kB 🔴 +2.19 kB 🔴 +1.9 kB
assets/UserCheckView-CyBXkl4F.js (removed) 8.75 kB 🟢 -8.75 kB 🟢 -2.19 kB 🟢 -1.9 kB
assets/CloudLoginView-CNvC9kti.js (new) 8.74 kB 🔴 +8.74 kB 🔴 +2.55 kB 🔴 +2.27 kB
assets/CloudLoginView-D8QPsJsQ.js (removed) 8.74 kB 🟢 -8.74 kB 🟢 -2.55 kB 🟢 -2.26 kB
assets/useCloudAuthPage-BsbDsJZm.js (new) 7.08 kB 🔴 +7.08 kB 🔴 +2.51 kB 🔴 +2.2 kB
assets/useCloudAuthPage-D4v2k5zO.js (removed) 7.08 kB 🟢 -7.08 kB 🟢 -2.51 kB 🟢 -2.2 kB
assets/CloudSignupView-AmlG3we9.js (new) 6.96 kB 🔴 +6.96 kB 🔴 +2.27 kB 🔴 +2 kB
assets/CloudSignupView-GdrPZHT9.js (removed) 6.96 kB 🟢 -6.96 kB 🟢 -2.28 kB 🟢 -2 kB
assets/WidgetTextPreview-0omoYxJI.js (removed) 6.07 kB 🟢 -6.07 kB 🟢 -2.13 kB 🟢 -1.9 kB
assets/WidgetTextPreview-FeyzhSmw.js (new) 6.07 kB 🔴 +6.07 kB 🔴 +2.13 kB 🔴 +1.89 kB
assets/CloudSubscriptionRedirectView-BX1SnQXJ.js (removed) 6.05 kB 🟢 -6.05 kB 🟢 -2.25 kB 🟢 -1.97 kB
assets/CloudSubscriptionRedirectView-CSLlvVNG.js (new) 6.05 kB 🔴 +6.05 kB 🔴 +2.25 kB 🔴 +1.96 kB
assets/UserSelectView-B6mdpAcy.js (new) 5.49 kB 🔴 +5.49 kB 🔴 +1.96 kB 🔴 +1.71 kB
assets/UserSelectView-BjN2MVK3.js (removed) 5.49 kB 🟢 -5.49 kB 🟢 -1.96 kB 🟢 -1.71 kB
assets/CloudForgotPasswordView-BftlLRXk.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.72 kB 🟢 -1.49 kB
assets/CloudForgotPasswordView-Dp6NA3w1.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.72 kB 🔴 +1.49 kB
assets/CloudAuthTimeoutView-0MFT7KBE.js (removed) 4.43 kB 🟢 -4.43 kB 🟢 -1.54 kB 🟢 -1.33 kB
assets/CloudAuthTimeoutView-COiO7NQH.js (new) 4.43 kB 🔴 +4.43 kB 🔴 +1.54 kB 🔴 +1.33 kB
assets/OAuthLayoutView-B6mnlHLO.js (removed) 1.31 kB 🟢 -1.31 kB 🟢 -700 B 🟢 -596 B
assets/OAuthLayoutView-H_MnMndX.js (new) 1.31 kB 🔴 +1.31 kB 🔴 +700 B 🔴 +586 B
assets/WidgetTextPreview-CrXbIqBk.js (new) 131 B 🔴 +131 B 🔴 +100 B 🔴 +89 B
assets/WidgetTextPreview-RDfLHHr0.js (removed) 131 B 🟢 -131 B 🟢 -100 B 🟢 -89 B

Status: 13 added / 13 removed / 4 unchanged

Panels & Settings — 591 kB (baseline 591 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-BPQSSD_i.js (removed) 49.4 kB 🟢 -49.4 kB 🟢 -9.94 kB 🟢 -8.8 kB
assets/KeybindingPanel-BZcGww1D.js (new) 49.4 kB 🔴 +49.4 kB 🔴 +9.94 kB 🔴 +8.79 kB
assets/CreditsPanel-DVXpOzEJ.js (removed) 36.6 kB 🟢 -36.6 kB 🟢 -8.9 kB 🟢 -7.81 kB
assets/CreditsPanel-nv_lyL_T.js (new) 36.6 kB 🔴 +36.6 kB 🔴 +8.9 kB 🔴 +7.8 kB
assets/SecretsPanel-CKzivshP.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +7.88 kB 🔴 +6.9 kB
assets/SecretsPanel-oR3nEE9B.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -7.88 kB 🟢 -6.9 kB
assets/AboutPanel-CgO2gF0e.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.12 kB 🔴 +2.8 kB
assets/AboutPanel-krs88tme.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.12 kB 🟢 -2.81 kB
assets/ExtensionPanel-BF0RBTBy.js (new) 9.19 kB 🔴 +9.19 kB 🔴 +2.51 kB 🔴 +2.23 kB
assets/ExtensionPanel-DAMb5B6k.js (removed) 9.19 kB 🟢 -9.19 kB 🟢 -2.51 kB 🟢 -2.23 kB
assets/ServerConfigPanel-CPL3CqNt.js (removed) 6.09 kB 🟢 -6.09 kB 🟢 -1.94 kB 🟢 -1.72 kB
assets/ServerConfigPanel-wygd9jXy.js (new) 6.09 kB 🔴 +6.09 kB 🔴 +1.94 kB 🔴 +1.72 kB
assets/UserPanel-BrlI3wwP.js (new) 5.73 kB 🔴 +5.73 kB 🔴 +1.78 kB 🔴 +1.54 kB
assets/UserPanel-DcvYBDms.js (removed) 5.73 kB 🟢 -5.73 kB 🟢 -1.78 kB 🟢 -1.54 kB
assets/refreshRemoteConfig-BiZm1eQP.js (removed) 4.24 kB 🟢 -4.24 kB 🟢 -1.51 kB 🟢 -1.33 kB
assets/refreshRemoteConfig-DEn9UvpR.js (new) 4.24 kB 🔴 +4.24 kB 🔴 +1.51 kB 🔴 +1.34 kB
assets/cloudRemoteConfig-Bl-yKOwr.js (new) 951 B 🔴 +951 B 🔴 +514 B 🔴 +420 B
assets/cloudRemoteConfig-BXOgC_yK.js (removed) 951 B 🟢 -951 B 🟢 -516 B 🟢 -421 B
assets/CreditsPanel-BB4xwvoG.js (new) 116 B 🔴 +116 B 🔴 +95 B 🔴 +88 B
assets/CreditsPanel-sJR9TMxm.js (removed) 116 B 🟢 -116 B 🟢 -95 B 🟢 -92 B
assets/refreshRemoteConfig-BGAHizIm.js (removed) 110 B 🟢 -110 B 🟢 -89 B 🟢 -76 B
assets/refreshRemoteConfig-Xm4pnhWE.js (new) 110 B 🔴 +110 B 🔴 +89 B 🔴 +94 B

Status: 11 added / 11 removed / 16 unchanged

User & Accounts — 27.5 kB (baseline 27.5 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SignUpForm-BmL-QXHZ.js (removed) 13.3 kB 🟢 -13.3 kB 🟢 -4.52 kB 🟢 -3.93 kB
assets/SignUpForm-Cb2txuxQ.js (new) 13.3 kB 🔴 +13.3 kB 🔴 +4.52 kB 🔴 +3.93 kB
assets/auth-C9b4-Jj3.js (new) 3.48 kB 🔴 +3.48 kB 🔴 +1.2 kB 🔴 +1.01 kB
assets/auth-CgBfKYWk.js (removed) 3.48 kB 🟢 -3.48 kB 🟢 -1.2 kB 🟢 -1.01 kB
assets/UpdatePasswordContent-BI2AxJ02.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -841 B 🟢 -733 B
assets/UpdatePasswordContent-D1z0wBAc.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +839 B 🔴 +735 B
assets/authStore-B5-hlut0.js (new) 128 B 🔴 +128 B 🔴 +104 B 🔴 +106 B
assets/authStore-BAd45DeC.js (removed) 128 B 🟢 -128 B 🟢 -104 B 🟢 -104 B
assets/workspaceAuthStore-D-_yk2st.js (removed) 108 B 🟢 -108 B 🟢 -99 B 🟢 -110 B
assets/workspaceAuthStore-f-ZeghHO.js (new) 108 B 🔴 +108 B 🔴 +99 B 🔴 +102 B
assets/auth-C61VtKzo.js (new) 105 B 🔴 +105 B 🔴 +96 B 🔴 +79 B
assets/auth-DS-S8fm8.js (removed) 105 B 🟢 -105 B 🟢 -96 B 🟢 -87 B

Status: 6 added / 6 removed / 5 unchanged

Editors & Dialogs — 125 kB (baseline 125 kB) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyHubPublishDialog-CS42G3ES.js (new) 90.1 kB 🔴 +90.1 kB 🔴 +19.3 kB 🔴 +16.5 kB
assets/ComfyHubPublishDialog-D_zbaISO.js (removed) 90.1 kB 🟢 -90.1 kB 🟢 -19.3 kB 🟢 -16.5 kB
assets/useShareDialog-CaENaIRe.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +5.69 kB 🔴 +5.04 kB
assets/useShareDialog-CFjoxAiq.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -5.7 kB 🟢 -5.05 kB
assets/feedbackDialog-BI-mkErT.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.86 kB 🟢 -1.59 kB
assets/feedbackDialog-PiH3lCI1.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.86 kB 🔴 +1.59 kB
assets/useRangeEditor-Bw_OEUSM.js (new) 3.29 kB 🔴 +3.29 kB 🔴 +1.14 kB 🔴 +1.03 kB
assets/useRangeEditor-GqjRid3r.js (removed) 3.29 kB 🟢 -3.29 kB 🟢 -1.14 kB 🟢 -1.04 kB
assets/useLayerEditor-6mWeZPhk.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -491 B 🟢 -405 B
assets/useLayerEditor-BtS-xgd5.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +489 B 🔴 +406 B
assets/ComfyHubPublishDialog-B5Zqw4hB.js (removed) 143 B 🟢 -143 B 🟢 -105 B 🟢 -91 B
assets/ComfyHubPublishDialog-DOLLI28f.js (new) 143 B 🔴 +143 B 🔴 +105 B 🔴 +91 B
assets/useSubscriptionDialog-BNPecsgC.js (new) 108 B 🔴 +108 B 🔴 +102 B 🔴 +89 B
assets/useSubscriptionDialog-DgVHZsDG.js (removed) 108 B 🟢 -108 B 🟢 -102 B 🟢 -91 B

Status: 7 added / 7 removed / 1 unchanged

UI Components — 67.1 kB (baseline 67.1 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-BgQ4pOtQ.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.97 kB 🔴 +3.52 kB
assets/ComfyQueueButton-CePFPEGk.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.97 kB 🟢 -3.52 kB
assets/useTerminalTabs-BSDOA8dR.js (new) 11.8 kB 🔴 +11.8 kB 🔴 +3.69 kB 🔴 +3.27 kB
assets/useTerminalTabs-CdD_xmFG.js (removed) 11.8 kB 🟢 -11.8 kB 🟢 -3.69 kB 🟢 -3.28 kB
assets/InviteMembersForm-3kS4Gr_b.js (removed) 8.23 kB 🟢 -8.23 kB 🟢 -2.74 kB 🟢 -2.43 kB
assets/InviteMembersForm-DtCtOSHq.js (new) 8.23 kB 🔴 +8.23 kB 🔴 +2.74 kB 🔴 +2.43 kB
assets/SubscribeButton-DJD5g26j.js (removed) 2.15 kB 🟢 -2.15 kB 🟢 -968 B 🟢 -845 B
assets/SubscribeButton-DopjmRaF.js (new) 2.15 kB 🔴 +2.15 kB 🔴 +966 B 🔴 +846 B
assets/cloudFeedbackTopbarButton-1TcvacUd.js (removed) 705 B 🟢 -705 B 🟢 -419 B 🟢 -361 B
assets/cloudFeedbackTopbarButton-D42Ai2uY.js (new) 705 B 🔴 +705 B 🔴 +420 B 🔴 +358 B
assets/ComfyQueueButton-B1ti2kAv.js (new) 128 B 🔴 +128 B 🔴 +99 B 🔴 +89 B
assets/ComfyQueueButton-twbNQbYd.js (removed) 128 B 🟢 -128 B 🟢 -99 B 🟢 -91 B

Status: 6 added / 6 removed / 8 unchanged

Data & Services — 3.53 MB (baseline 3.53 MB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settingStore-8D7_BEUp.js (removed) 3.17 MB 🟢 -3.17 MB 🟢 -743 kB 🟢 -559 kB
assets/settingStore-Cssm-NTk.js (new) 3.17 MB 🔴 +3.17 MB 🔴 +743 kB 🔴 +558 kB
assets/api-CbABqadH.js (new) 186 kB 🔴 +186 kB 🔴 +39.8 kB 🔴 +33.3 kB
assets/api-oBDMF4nf.js (removed) 186 kB 🟢 -186 kB 🟢 -39.8 kB 🟢 -33.3 kB
assets/load3dService-BIYA2zk2.js (removed) 131 kB 🟢 -131 kB 🟢 -29.2 kB 🟢 -24.6 kB
assets/load3dService-BnIVt2X6.js (new) 131 kB 🔴 +131 kB 🔴 +29.2 kB 🔴 +24.6 kB
assets/workflowShareService-DUXAzkZT.js (removed) 16.5 kB 🟢 -16.5 kB 🟢 -4.91 kB 🟢 -4.35 kB
assets/workflowShareService-R_sPPMi4.js (new) 16.5 kB 🔴 +16.5 kB 🔴 +4.91 kB 🔴 +4.35 kB
assets/keybindingService-BArZBVRP.js (new) 6.95 kB 🔴 +6.95 kB 🔴 +1.74 kB 🔴 +1.5 kB
assets/keybindingService-CmKRLaUl.js (removed) 6.95 kB 🟢 -6.95 kB 🟢 -1.74 kB 🟢 -1.51 kB
assets/releaseStore-C-kPZBuW.js (removed) 6.72 kB 🟢 -6.72 kB 🟢 -2.03 kB 🟢 -1.77 kB
assets/releaseStore-CvdjLmzm.js (new) 6.72 kB 🔴 +6.72 kB 🔴 +2.03 kB 🔴 +1.77 kB
assets/systemStatsStore-Lt3NSt2x.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.74 kB 🟢 -1.47 kB
assets/systemStatsStore-mCL2igQc.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.74 kB 🔴 +1.47 kB
assets/userStore-01NrfhOO.js (removed) 2.38 kB 🟢 -2.38 kB 🟢 -896 B 🟢 -795 B
assets/userStore-Bbxfsc2h.js (new) 2.38 kB 🔴 +2.38 kB 🔴 +897 B 🔴 +794 B
assets/audioService-DI6H4VsN.js (new) 1.71 kB 🔴 +1.71 kB 🔴 +829 B 🔴 +721 B
assets/audioService-M0jKOj85.js (removed) 1.71 kB 🟢 -1.71 kB 🟢 -827 B 🟢 -730 B
assets/dialogService-Bp1xRG3V.js (removed) 98 B 🟢 -98 B 🟢 -97 B 🟢 -75 B
assets/dialogService-DpfEoR6o.js (new) 98 B 🔴 +98 B 🔴 +97 B 🔴 +83 B
assets/releaseStore-BqSTp7Ma.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +84 B
assets/releaseStore-DpIw8k04.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -84 B
assets/settingStore-Cw4NuvFv.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +80 B
assets/settingStore-DYNedWXG.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -89 B
assets/assetsStore-B82CMSHD.js (removed) 94 B 🟢 -94 B 🟢 -92 B 🟢 -85 B
assets/assetsStore-BLmIXRE1.js (new) 94 B 🔴 +94 B 🔴 +92 B 🔴 +83 B
assets/api-CSyaXE37.js (removed) 62 B 🟢 -62 B 🟢 -74 B 🟢 -60 B
assets/api-CymAHF1S.js (new) 62 B 🔴 +62 B 🔴 +74 B 🔴 +66 B

Status: 14 added / 14 removed / 3 unchanged

Utilities & Hooks — 549 kB (baseline 549 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-B1PgwCCm.js (new) 236 kB 🔴 +236 kB 🔴 +53.1 kB 🔴 +43.2 kB
assets/useConflictDetection-qUh4iOpM.js (removed) 236 kB 🟢 -236 kB 🟢 -53.1 kB 🟢 -43.2 kB
assets/useLayerEditorSession-Bb--RSo0.js (removed) 158 kB 🟢 -158 kB 🟢 -40.8 kB 🟢 -34.3 kB
assets/useLayerEditorSession-DS_2b42p.js (new) 158 kB 🔴 +158 kB 🔴 +40.8 kB 🔴 +34.3 kB
assets/useLoad3d--Vif-jSJ.js (removed) 25.8 kB 🟢 -25.8 kB 🟢 -5.81 kB 🟢 -5.16 kB
assets/useLoad3d-CEkHn_Z7.js (new) 25.8 kB 🔴 +25.8 kB 🔴 +5.8 kB 🔴 +5.14 kB
assets/useLoad3dViewer-DD-A8Xzo.js (new) 21.2 kB 🔴 +21.2 kB 🔴 +4.98 kB 🔴 +4.38 kB
assets/useLoad3dViewer-DK3vBVjt.js (removed) 21.2 kB 🟢 -21.2 kB 🟢 -4.98 kB 🟢 -4.37 kB
assets/useImageCrop-C8VYcXVi.js (removed) 14.9 kB 🟢 -14.9 kB 🟢 -3.42 kB 🟢 -2.98 kB
assets/useImageCrop-zkkLECsd.js (new) 14.9 kB 🔴 +14.9 kB 🔴 +3.41 kB 🔴 +2.98 kB
assets/useDowngradeToPersonal-BJJ4z9qf.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -2.74 kB 🟢 -2.35 kB
assets/useDowngradeToPersonal-BjVA7DvX.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +2.73 kB 🔴 +2.35 kB
assets/useFeatureFlags-BkdWQPBC.js (removed) 7.25 kB 🟢 -7.25 kB 🟢 -2.05 kB 🟢 -1.73 kB
assets/useFeatureFlags-DV9-AcM6.js (new) 7.25 kB 🔴 +7.25 kB 🔴 +2.05 kB 🔴 +1.73 kB
assets/useCompositorLayers-CaV9pzRM.js (removed) 2.94 kB 🟢 -2.94 kB 🟢 -899 B 🟢 -804 B
assets/useCompositorLayers-Dih8hfwP.js (new) 2.94 kB 🔴 +2.94 kB 🔴 +896 B 🔴 +803 B
assets/assetPreviewUtil-B0aqBTKh.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -967 B 🟢 -846 B
assets/assetPreviewUtil-fz4TzD8j.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +966 B 🔴 +844 B
assets/useUpstreamValue-0vP3nUSu.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -760 B 🟢 -684 B
assets/useUpstreamValue-ud0eimM_.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +755 B 🔴 +683 B
assets/useWorkspaceTierLabel-BgmOPzRN.js (new) 1.93 kB 🔴 +1.93 kB 🔴 +810 B 🔴 +694 B
assets/useWorkspaceTierLabel-Dt2Yowlg.js (removed) 1.93 kB 🟢 -1.93 kB 🟢 -814 B 🟢 -697 B
assets/subscriptionCheckoutUtil-BP37Nz6Y.js (new) 877 B 🔴 +877 B 🔴 +521 B 🔴 +427 B
assets/subscriptionCheckoutUtil-Cye1qGYu.js (removed) 877 B 🟢 -877 B 🟢 -525 B 🟢 -434 B
assets/useSessionCookie-C9pA63CA.js (new) 652 B 🔴 +652 B 🔴 +335 B 🔴 +292 B
assets/useSessionCookie-DtgORpvD.js (removed) 652 B 🟢 -652 B 🟢 -337 B 🟢 -292 B
assets/useLoad3d-BHss21f6.js (removed) 311 B 🟢 -311 B 🟢 -163 B 🟢 -147 B
assets/useLoad3d-urs0KQJ8.js (new) 311 B 🔴 +311 B 🔴 +166 B 🔴 +148 B
assets/useSessionCookie-DdtqvDQU.js (removed) 101 B 🟢 -101 B 🟢 -86 B 🟢 -82 B
assets/useSessionCookie-JmRE9v2_.js (new) 101 B 🔴 +101 B 🔴 +86 B 🔴 +81 B
assets/useFeatureFlags-80KDWgCf.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +81 B
assets/useFeatureFlags-ZbOnS7nz.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -82 B
assets/useLoad3dViewer-CGmEHeU2.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +86 B
assets/useLoad3dViewer-PGdNf6S0.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -84 B
assets/useCurrentUser-DOZh3oXf.js (new) 94 B 🔴 +94 B 🔴 +95 B 🔴 +85 B
assets/useCurrentUser-t9kD9n5O.js (removed) 94 B 🟢 -94 B 🟢 -95 B 🟢 -89 B

Status: 18 added / 18 removed / 19 unchanged

Vendor & Third-Party — 18.1 MB (baseline 18.1 MB) • ⚪ 0 B

External libraries and shared vendor chunks

Status: 18 unchanged

Other — 14.1 MB (baseline 14.1 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-BRebun6g.js (removed) 115 kB 🟢 -115 kB 🟢 -30.1 kB 🟢 -25.4 kB
assets/core-DErVRqwo.js (new) 115 kB 🔴 +115 kB 🔴 +30.1 kB 🔴 +25.4 kB
assets/WorkspaceSettingsPanelContent-DFZH4bum.js (removed) 109 kB 🟢 -109 kB 🟢 -21.4 kB 🟢 -18.1 kB
assets/WorkspaceSettingsPanelContent-Dp79sKBQ.js (new) 109 kB 🔴 +109 kB 🔴 +21.4 kB 🔴 +18 kB
assets/WidgetSelect-DbyjsyGI.js (removed) 88.8 kB 🟢 -88.8 kB 🟢 -20.1 kB 🟢 -17.2 kB
assets/WidgetSelect-DzhbDrrO.js (new) 88.8 kB 🔴 +88.8 kB 🔴 +20.1 kB 🔴 +17.2 kB
assets/Load3D-BOLgHxQk.js (new) 73.3 kB 🔴 +73.3 kB 🔴 +12.1 kB 🔴 +10.3 kB
assets/Load3D-CUL2KW7g.js (removed) 73.3 kB 🟢 -73.3 kB 🟢 -12.1 kB 🟢 -10.3 kB
assets/WidgetVideoEdit-38k2kybZ.js (new) 71.2 kB 🔴 +71.2 kB 🔴 +16.9 kB 🔴 +14.9 kB
assets/WidgetVideoEdit-DDs9Zcdq.js (removed) 71.2 kB 🟢 -71.2 kB 🟢 -16.9 kB 🟢 -14.9 kB
assets/SubscriptionTransitionPreviewWorkspace-BwdREZfq.js (new) 66.4 kB 🔴 +66.4 kB 🔴 +13.4 kB 🔴 +11.7 kB
assets/SubscriptionTransitionPreviewWorkspace-DFdpGGS8.js (removed) 66.4 kB 🟢 -66.4 kB 🟢 -13.4 kB 🟢 -11.7 kB
assets/Preview3d-B3icTOzC.js (removed) 50.9 kB 🟢 -50.9 kB 🟢 -8.32 kB 🟢 -7.26 kB
assets/Preview3d-BSSGciHt.js (new) 50.9 kB 🔴 +50.9 kB 🔴 +8.31 kB 🔴 +7.25 kB
assets/main-BigAYxSh.js (removed) 47.4 kB 🟢 -47.4 kB 🟢 -13.7 kB 🟢 -11.9 kB
assets/main-BtCoTPTj.js (new) 47.4 kB 🔴 +47.4 kB 🔴 +13.7 kB 🔴 +11.9 kB
assets/SubscriptionRequiredDialogContentUnified-CaZ385uk.js (new) 42.7 kB 🔴 +42.7 kB 🔴 +9.39 kB 🔴 +8.19 kB
assets/SubscriptionRequiredDialogContentUnified-iekiBur_.js (removed) 42.7 kB 🟢 -42.7 kB 🟢 -9.39 kB 🟢 -8.19 kB
assets/LayerEditorContent-DT4x4kI1.js (new) 42.5 kB 🔴 +42.5 kB 🔴 +9.62 kB 🔴 +8.42 kB
assets/LayerEditorContent-oN2bU7bz.js (removed) 42.5 kB 🟢 -42.5 kB 🟢 -9.62 kB 🟢 -8.42 kB
assets/WidgetBoundingBoxes-B1c90OWr.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -9.16 kB 🟢 -8.12 kB
assets/WidgetBoundingBoxes-CcrPgPgO.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +9.16 kB 🔴 +8.12 kB
assets/WidgetPainter-BlNLWRx6.js (new) 32.6 kB 🔴 +32.6 kB 🔴 +7.87 kB 🔴 +6.96 kB
assets/WidgetPainter-CXkn6fw-.js (removed) 32.6 kB 🟢 -32.6 kB 🟢 -7.88 kB 🟢 -6.97 kB
assets/Load3dViewerContent-BXfib0Kx.js (new) 30.8 kB 🔴 +30.8 kB 🔴 +6.28 kB 🔴 +5.45 kB
assets/Load3dViewerContent-DYF3RRgE.js (removed) 30.8 kB 🟢 -30.8 kB 🟢 -6.28 kB 🟢 -5.45 kB
assets/SubscriptionRequiredDialogContent-DvbGPlXP.js (removed) 26.9 kB 🟢 -26.9 kB 🟢 -6.36 kB 🟢 -5.6 kB
assets/SubscriptionRequiredDialogContent-rno0ABlh.js (new) 26.9 kB 🔴 +26.9 kB 🔴 +6.36 kB 🔴 +5.6 kB
assets/SubscriptionRequiredDialogContentWorkspace-D-7rgjuJ.js (removed) 25.1 kB 🟢 -25.1 kB 🟢 -5.81 kB 🟢 -5.11 kB
assets/SubscriptionRequiredDialogContentWorkspace-Y4wEO5Lf.js (new) 25.1 kB 🔴 +25.1 kB 🔴 +5.81 kB 🔴 +5.12 kB
assets/load3d-D-CgNNEz.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.41 kB 🔴 +4.68 kB
assets/load3d-R5nYaRW1.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.41 kB 🟢 -4.68 kB
assets/SignInContent-C0E633lO.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.18 kB 🟢 -4.53 kB
assets/SignInContent-C5F_M2Le.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.17 kB 🔴 +4.53 kB
assets/WidgetRecordAudio-CNmpHcrH.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.6 kB 🟢 -4.11 kB
assets/WidgetRecordAudio-CuPszB1E.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.6 kB 🔴 +4.11 kB
assets/CurrentUserPopoverWorkspace-BYVQEiJi.js (removed) 15.9 kB 🟢 -15.9 kB 🟢 -3.86 kB 🟢 -3.4 kB
assets/CurrentUserPopoverWorkspace-TAdDjpAq.js (new) 15.9 kB 🔴 +15.9 kB 🔴 +3.85 kB 🔴 +3.4 kB
assets/WidgetInputNumber-CY-uAoVt.js (new) 13.9 kB 🔴 +13.9 kB 🔴 +3.63 kB 🔴 +3.21 kB
assets/WidgetInputNumber-D311bX_e.js (removed) 13.9 kB 🟢 -13.9 kB 🟢 -3.63 kB 🟢 -3.22 kB
assets/WidgetRange-D2cd80Sx.js (new) 13.7 kB 🔴 +13.7 kB 🔴 +3.55 kB 🔴 +3.12 kB
assets/WidgetRange-DupIfU2u.js (removed) 13.7 kB 🟢 -13.7 kB 🟢 -3.55 kB 🟢 -3.13 kB
assets/WaveAudioPlayer-CkuL5gEK.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.46 kB 🔴 +3.05 kB
assets/WaveAudioPlayer-Cxr-GqTQ.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.46 kB 🟢 -3.05 kB
assets/WidgetCurve-BOpskj-V.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.47 kB 🟢 -3.14 kB
assets/WidgetCurve-CuNVwnR5.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.47 kB 🔴 +3.14 kB
assets/TeamWorkspacesDialogContent-BJrNgt7F.js (new) 10.3 kB 🔴 +10.3 kB 🔴 +2.97 kB 🔴 +2.62 kB
assets/TeamWorkspacesDialogContent-tASTlq_0.js (removed) 10.3 kB 🟢 -10.3 kB 🟢 -2.97 kB 🟢 -2.63 kB
assets/onboardingCloudRoutes-3DQMF3LK.js (removed) 9.49 kB 🟢 -9.49 kB 🟢 -2.86 kB 🟢 -2.46 kB
assets/onboardingCloudRoutes-BbKx8-rD.js (new) 9.49 kB 🔴 +9.49 kB 🔴 +2.85 kB 🔴 +2.44 kB
assets/Load3DConfiguration-DlizhVpg.js (new) 8.91 kB 🔴 +8.91 kB 🔴 +2.61 kB 🔴 +2.3 kB
assets/Load3DConfiguration-DPfvPxaU.js (removed) 8.91 kB 🟢 -8.91 kB 🟢 -2.61 kB 🟢 -2.3 kB
assets/WidgetImageCrop-DBaAjaKE.js (new) 8.49 kB 🔴 +8.49 kB 🔴 +2.65 kB 🔴 +2.34 kB
assets/WidgetImageCrop-DYtVA3zu.js (removed) 8.49 kB 🟢 -8.49 kB 🟢 -2.66 kB 🟢 -2.34 kB
assets/SetMemberCreditLimitDialogContent-BknRHwLx.js (removed) 8.47 kB 🟢 -8.47 kB 🟢 -2.34 kB 🟢 -2.05 kB
assets/SetMemberCreditLimitDialogContent-CxeqA_z5.js (new) 8.47 kB 🔴 +8.47 kB 🔴 +2.34 kB 🔴 +2.06 kB
assets/nodeTemplates-BxS2Phl_.js (removed) 8.32 kB 🟢 -8.32 kB 🟢 -2.85 kB 🟢 -2.5 kB
assets/nodeTemplates-CK_ZohMO.js (new) 8.32 kB 🔴 +8.32 kB 🔴 +2.85 kB 🔴 +2.5 kB
assets/WorkspaceSwitcherPopover-C0kr2WOP.js (new) 8.01 kB 🔴 +8.01 kB 🔴 +2.38 kB 🔴 +2.12 kB
assets/WorkspaceSwitcherPopover-Cd22Xeim.js (removed) 8.01 kB 🟢 -8.01 kB 🟢 -2.38 kB 🟢 -2.12 kB
assets/NightlySurveyController-CnXs61Qd.js (removed) 7.5 kB 🟢 -7.5 kB 🟢 -2.55 kB 🟢 -2.23 kB
assets/NightlySurveyController-djlUwZCK.js (new) 7.5 kB 🔴 +7.5 kB 🔴 +2.55 kB 🔴 +2.25 kB
assets/CloudRunButtonWrapper--qVLGwH0.js (removed) 7.29 kB 🟢 -7.29 kB 🟢 -2.29 kB 🟢 -2.01 kB
assets/CloudRunButtonWrapper-Dkfc3ZEx.js (new) 7.29 kB 🔴 +7.29 kB 🔴 +2.29 kB 🔴 +2.01 kB
assets/WidgetWithControl-DyCXwvi7.js (new) 6.51 kB 🔴 +6.51 kB 🔴 +2.66 kB 🔴 +2.33 kB
assets/WidgetWithControl-NVcRUZyF.js (removed) 6.51 kB 🟢 -6.51 kB 🟢 -2.66 kB 🟢 -2.37 kB
assets/missingModelMetadata-BNqON3Lf.js (removed) 6.45 kB 🟢 -6.45 kB 🟢 -2.21 kB 🟢 -1.93 kB
assets/missingModelMetadata-C2T93_yP.js (new) 6.45 kB 🔴 +6.45 kB 🔴 +2.21 kB 🔴 +1.93 kB
assets/CancelSubscriptionDialogContent-7jGbE1JP.js (removed) 5.97 kB 🟢 -5.97 kB 🟢 -1.98 kB 🟢 -1.75 kB
assets/CancelSubscriptionDialogContent-DRcbsUMo.js (new) 5.97 kB 🔴 +5.97 kB 🔴 +1.98 kB 🔴 +1.75 kB
assets/load3dPreviewExtensions-C9hPxAWQ.js (new) 5.88 kB 🔴 +5.88 kB 🔴 +1.81 kB 🔴 +1.6 kB
assets/load3dPreviewExtensions-DZuuLIxx.js (removed) 5.88 kB 🟢 -5.88 kB 🟢 -1.81 kB 🟢 -1.6 kB
assets/launchCancellationFlow-DDYWfZ-5.js (removed) 5.18 kB 🟢 -5.18 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/launchCancellationFlow-gaNO5Blo.js (new) 5.18 kB 🔴 +5.18 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CreateWorkspaceDialogContent-C_kTsMpv.js (new) 5.12 kB 🔴 +5.12 kB 🔴 +1.79 kB 🔴 +1.55 kB
assets/CreateWorkspaceDialogContent-CLFBRYxz.js (removed) 5.12 kB 🟢 -5.12 kB 🟢 -1.79 kB 🟢 -1.55 kB
assets/ChangeMemberRoleDialogContent-C4Cyzw-W.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.64 kB 🟢 -1.44 kB
assets/ChangeMemberRoleDialogContent-Cnmat4r9.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.63 kB 🔴 +1.43 kB
assets/InviteMemberDialogContent-CTyd8Yw4.js (new) 4.96 kB 🔴 +4.96 kB 🔴 +1.64 kB 🔴 +1.43 kB
assets/InviteMemberDialogContent-DGMe3uvz.js (removed) 4.96 kB 🟢 -4.96 kB 🟢 -1.64 kB 🟢 -1.44 kB
assets/EditWorkspaceDialogContent-CsipgHcc.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.76 kB 🔴 +1.52 kB
assets/EditWorkspaceDialogContent-DtJ3HmYM.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.76 kB 🟢 -1.52 kB
assets/WidgetTextarea-B58WLAB1.js (removed) 4.83 kB 🟢 -4.83 kB 🟢 -1.88 kB 🟢 -1.64 kB
assets/WidgetTextarea-z5tpQkSq.js (new) 4.83 kB 🔴 +4.83 kB 🔴 +1.88 kB 🔴 +1.64 kB
assets/saveMesh-B0quisbl.js (removed) 4.76 kB 🟢 -4.76 kB 🟢 -1.52 kB 🟢 -1.35 kB
assets/saveMesh-Dm6Unk0g.js (new) 4.76 kB 🔴 +4.76 kB 🔴 +1.52 kB 🔴 +1.34 kB
assets/ValueControlPopover-BIUNrncj.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.55 kB 🟢 -1.38 kB
assets/ValueControlPopover-CRqK1Yxu.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.55 kB 🔴 +1.38 kB
assets/DeleteWorkspaceDialogContent-Bi4UV0yz.js (removed) 3.84 kB 🟢 -3.84 kB 🟢 -1.44 kB 🟢 -1.24 kB
assets/DeleteWorkspaceDialogContent-DrxZGkeH.js (new) 3.84 kB 🔴 +3.84 kB 🔴 +1.44 kB 🔴 +1.24 kB
assets/RemoveMemberDialogContent-C9--z1lS.js (new) 3.76 kB 🔴 +3.76 kB 🔴 +1.38 kB 🔴 +1.2 kB
assets/RemoveMemberDialogContent-DvrIAUFB.js (removed) 3.76 kB 🟢 -3.76 kB 🟢 -1.38 kB 🟢 -1.2 kB
assets/RevokeInviteDialogContent-C3y_Tjqd.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.39 kB 🔴 +1.21 kB
assets/RevokeInviteDialogContent-Cct7nnAr.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.39 kB 🟢 -1.22 kB
assets/LeaveWorkspaceDialogContent-403juBr9.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.39 kB 🟢 -1.19 kB
assets/LeaveWorkspaceDialogContent-CidVsoFw.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.38 kB 🔴 +1.19 kB
assets/InviteMemberUpsellDialogContent-DcB5iJ3_.js (removed) 3.47 kB 🟢 -3.47 kB 🟢 -1.24 kB 🟢 -1.09 kB
assets/InviteMemberUpsellDialogContent-DNzbDrW0.js (new) 3.47 kB 🔴 +3.47 kB 🔴 +1.24 kB 🔴 +1.07 kB
assets/workspaceCheckoutTelemetry-BLYRH4fG.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.52 kB 🟢 -1.32 kB
assets/workspaceCheckoutTelemetry-PlRAWBhS.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.52 kB 🔴 +1.32 kB
assets/GlobalToast-CpMb8kXx.js (new) 3.25 kB 🔴 +3.25 kB 🔴 +1.3 kB 🔴 +1.11 kB
assets/GlobalToast-D6Wu2jwx.js (removed) 3.25 kB 🟢 -3.25 kB 🟢 -1.3 kB 🟢 -1.11 kB
assets/Media3DTop-CDK0Mkkz.js (new) 3.21 kB 🔴 +3.21 kB 🔴 +1.27 kB 🔴 +1.11 kB
assets/Media3DTop-D197TTnG.js (removed) 3.21 kB 🟢 -3.21 kB 🟢 -1.26 kB 🟢 -1.11 kB
assets/load3dAdvanced-B-tx6dfr.js (removed) 2.82 kB 🟢 -2.82 kB 🟢 -1.1 kB 🟢 -954 B
assets/load3dAdvanced-DcDskzwo.js (new) 2.82 kB 🔴 +2.82 kB 🔴 +1.09 kB 🔴 +957 B
assets/SubscribeToRun-B3QFwRAD.js (removed) 2.39 kB 🟢 -2.39 kB 🟢 -1.03 kB 🟢 -904 B
assets/SubscribeToRun-OnG8pBK5.js (new) 2.39 kB 🔴 +2.39 kB 🔴 +1.03 kB 🔴 +904 B
assets/MediaAudioTop-Ci8YVDYH.js (removed) 1.62 kB 🟢 -1.62 kB 🟢 -808 B 🟢 -669 B
assets/MediaAudioTop-DaYPAyex.js (new) 1.62 kB 🔴 +1.62 kB 🔴 +808 B 🔴 +673 B
assets/cloudSessionCookie-AJmtblcQ.js (removed) 933 B 🟢 -933 B 🟢 -432 B 🟢 -379 B
assets/cloudSessionCookie-Ezqtlm53.js (new) 933 B 🔴 +933 B 🔴 +431 B 🔴 +378 B
assets/cloudBadges-D0tEEhg5.js (new) 922 B 🔴 +922 B 🔴 +511 B 🔴 +462 B
assets/cloudBadges-DxLHxOjh.js (removed) 922 B 🟢 -922 B 🟢 -515 B 🟢 -443 B
assets/Load3DAdvanced-BR7t0h8p.js (new) 761 B 🔴 +761 B 🔴 +422 B 🔴 +358 B
assets/Load3DAdvanced-Cb548FX2.js (removed) 761 B 🟢 -761 B 🟢 -424 B 🟢 -359 B
assets/nightlyBadges-WsEuO1UV.js (removed) 411 B 🟢 -411 B 🟢 -274 B 🟢 -231 B
assets/nightlyBadges-xwTbLWzd.js (new) 411 B 🔴 +411 B 🔴 +271 B 🔴 +231 B
assets/Load3dViewerContent-BCRl-BbM.js (new) 137 B 🔴 +137 B 🔴 +103 B 🔴 +91 B
assets/Load3dViewerContent-BNYVfa0h.js (removed) 137 B 🟢 -137 B 🟢 -103 B 🟢 -92 B
assets/missingModelMetadata-C90_ciQs.js (new) 125 B 🔴 +125 B 🔴 +103 B 🔴 +104 B
assets/missingModelMetadata-CGI7-4fH.js (removed) 125 B 🟢 -125 B 🟢 -103 B 🟢 -103 B
assets/Load3DAdvanced-DKrPZVgO.js (new) 122 B 🔴 +122 B 🔴 +97 B 🔴 +91 B
assets/Load3DAdvanced-z9T4uq3m.js (removed) 122 B 🟢 -122 B 🟢 -97 B 🟢 -88 B
assets/WidgetLegacy-B_TFLp9r.js (new) 117 B 🔴 +117 B 🔴 +106 B 🔴 +93 B
assets/WidgetLegacy-n2cYluIO.js (removed) 117 B 🟢 -117 B 🟢 -106 B 🟢 -102 B
assets/workflowDraftStoreV2-Cest0x5E.js (removed) 112 B 🟢 -112 B 🟢 -101 B 🟢 -116 B
assets/workflowDraftStoreV2-Cu_U677-.js (new) 112 B 🔴 +112 B 🔴 +101 B 🔴 +109 B
assets/Load3D-CYqFOKr5.js (removed) 98 B 🟢 -98 B 🟢 -89 B 🟢 -82 B
assets/Load3D-DPJTlDlT.js (new) 98 B 🔴 +98 B 🔴 +89 B 🔴 +89 B
assets/changeTracker-CJeGPL8f.js (new) 91 B 🔴 +91 B 🔴 +93 B 🔴 +84 B
assets/changeTracker-o7q4_wjM.js (removed) 91 B 🟢 -91 B 🟢 -93 B 🟢 -87 B

Status: 66 added / 66 removed / 219 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.0 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.3 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.3 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.3 MB heap
large-graph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.8 MB heap
large-graph-pan: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.3 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.2 MB heap
legacy-node-drag: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.7 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.9 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 70.8 MB heap
subgraph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.8 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.1 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 144ms TBT · 83.0 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 81.2 MB heap
vue-large-graph-idle: · 56.2 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 176.4 MB heap
vue-large-graph-pan: · 56.3 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 71ms TBT · 180.8 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.1 MB heap

⚠️ 6 regressions detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-idle: task duration 482ms 597ms +24% ⚠️ z=6.5
canvas-zoom-sweep: task duration 334ms 403ms +21% ⚠️ z=3.3
large-graph-idle: task duration 592ms 665ms +12% ⚠️ z=2.3
large-graph-pan: task duration 1166ms 1253ms +7% ⚠️ z=4.0
minimap-idle: task duration 585ms 698ms +19% ⚠️ z=3.6
subgraph-idle: task duration 466ms 526ms +13% ⚠️ z=5.0
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms +0% z=-0.1
canvas-idle: p95 frame time 17ms 17ms -0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 7ms 8ms +12% z=-3.2
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 9 8 -11% z=-5.6
canvas-idle: task duration 482ms 597ms +24% ⚠️ z=6.5
canvas-idle: script duration 6ms 10ms +57% z=-7.0
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 73.8 MB 68.0 MB -8%
canvas-idle: DOM nodes -281 -280 -0% z=-237.3
canvas-idle: event listeners -151 -167 +11% z=-37.7
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms -0%
canvas-mouse-sweep: layout duration 3ms 4ms +5% z=-0.5
canvas-mouse-sweep: style recalc duration 34ms 38ms +11% z=-1.5
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 73 74 +1% z=-2.0
canvas-mouse-sweep: task duration 816ms 879ms +8% z=0.2
canvas-mouse-sweep: script duration 103ms 113ms +10% z=-3.5
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 54.5 MB 56.3 MB +3%
canvas-mouse-sweep: DOM nodes -282 -282 +0% z=-133.1
canvas-mouse-sweep: event listeners -151 -151 +0% z=-38.3
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=0.5
canvas-zoom-sweep: p95 frame time 17ms 17ms -0%
canvas-zoom-sweep: layout duration 1ms 1ms +25% z=0.8
canvas-zoom-sweep: style recalc duration 14ms 18ms +23% z=-1.0
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 30 30 +0% z=-2.8
canvas-zoom-sweep: task duration 334ms 403ms +21% ⚠️ z=3.3
canvas-zoom-sweep: script duration 8ms 12ms +41% z=-5.1
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 62.4 MB 62.3 MB -0%
canvas-zoom-sweep: DOM nodes 76 75 -2% z=-6.0
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.2
dom-widget-clipping: p95 frame time 17ms 17ms +0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 7ms 8ms +24% z=-2.0
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 11 11 +0% z=-4.2
dom-widget-clipping: task duration 350ms 369ms +5% z=0.3
dom-widget-clipping: script duration 53ms 57ms +8% z=-3.4
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 69.6 MB 69.3 MB -1%
dom-widget-clipping: DOM nodes 18 18 +0% z=-2.9
dom-widget-clipping: event listeners 2 1 -50% variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=-0.2
large-graph-idle: p95 frame time 17ms 17ms -1%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 10ms 9ms -14% z=-3.2
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 9 -6% z=-9.9
large-graph-idle: task duration 592ms 665ms +12% ⚠️ z=2.3
large-graph-idle: script duration 13ms 17ms +30% z=-8.1
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 69.7 MB 64.8 MB -7%
large-graph-idle: DOM nodes -272 -278 +2% z=-334.9
large-graph-idle: event listeners -151 -166 +10% z=-31.5
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.2
large-graph-pan: p95 frame time 17ms 17ms +0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 13ms 14ms +9% z=-3.9
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 69 69 +0% z=-0.9
large-graph-pan: task duration 1166ms 1253ms +7% ⚠️ z=4.0
large-graph-pan: script duration 338ms 357ms +5% z=-2.6
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 68.8 MB 69.3 MB +1%
large-graph-pan: DOM nodes -279 -262 -6% z=-170.3
large-graph-pan: event listeners -151 -148 -2% z=-184.7
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms +1%
large-graph-zoom: layout duration 7ms 7ms +10%
large-graph-zoom: style recalc duration 13ms 13ms +6%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 64 63 -2%
large-graph-zoom: task duration 1306ms 1428ms +9%
large-graph-zoom: script duration 375ms 393ms +5%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 66.3 MB 69.2 MB +4%
large-graph-zoom: DOM nodes -272 -285 +5%
large-graph-zoom: event listeners -147 -151 +3%
legacy-node-drag: avg frame time 17ms 17ms +0%
legacy-node-drag: p95 frame time 17ms 17ms -0%
legacy-node-drag: layout duration 0ms 0ms +0%
legacy-node-drag: style recalc duration 10ms 10ms +7%
legacy-node-drag: layout count 0 0 +0%
legacy-node-drag: style recalc count 46 45 -3%
legacy-node-drag: task duration 1417ms 1503ms +6%
legacy-node-drag: script duration 469ms 493ms +5%
legacy-node-drag: TBT 0ms 0ms +0%
legacy-node-drag: heap used 66.6 MB 66.7 MB +0%
legacy-node-drag: DOM nodes 10 9 -10%
legacy-node-drag: event listeners 184 186 +1%
minimap-idle: avg frame time 17ms 17ms +0% z=0.1
minimap-idle: p95 frame time 17ms 17ms -1%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 6ms 8ms +26% z=-2.4
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 7 8 +7% z=-3.0
minimap-idle: task duration 585ms 698ms +19% ⚠️ z=3.6
minimap-idle: script duration 13ms 17ms +30% z=-8.2
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 70.6 MB 67.9 MB -4%
minimap-idle: DOM nodes -277 -280 +1% z=-218.7
minimap-idle: event listeners -149 -150 +1% z=-234.1
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.7
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms -0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 10ms 10ms +1% z=-3.3
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 46 45 -2% z=-5.0
subgraph-dom-widget-clipping: task duration 368ms 396ms +8% z=1.0
subgraph-dom-widget-clipping: script duration 115ms 119ms +4% z=-1.4
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 70.7 MB 70.8 MB +0%
subgraph-dom-widget-clipping: DOM nodes 18 16 -11% z=-5.5
subgraph-dom-widget-clipping: event listeners 8 8 +0% z=-1.4
subgraph-idle: avg frame time 17ms 17ms +0% z=0.4
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 6ms 8ms +36% z=-2.7
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 8 8 +0% z=-4.4
subgraph-idle: task duration 466ms 526ms +13% ⚠️ z=5.0
subgraph-idle: script duration 6ms 8ms +40% z=-4.5
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 62.9 MB 66.8 MB +6%
subgraph-idle: DOM nodes -283 -284 +0% z=-204.2
subgraph-idle: event listeners -181 -151 -17% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms -0%
subgraph-mouse-sweep: layout duration 4ms 4ms +8% z=-0.9
subgraph-mouse-sweep: style recalc duration 37ms 37ms -1% z=-1.7
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 76 75 -1% z=-2.7
subgraph-mouse-sweep: task duration 770ms 821ms +7% z=0.8
subgraph-mouse-sweep: script duration 80ms 88ms +10% z=-1.9
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 62.7 MB 65.1 MB +4%
subgraph-mouse-sweep: DOM nodes -281 -282 +0% z=-156.2
subgraph-mouse-sweep: event listeners -151 -152 +1% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms +0%
subgraph-transition-enter: p95 frame time 17ms 17ms +0%
subgraph-transition-enter: layout duration 14ms 15ms +1%
subgraph-transition-enter: style recalc duration 30ms 33ms +9%
subgraph-transition-enter: layout count 14 14 +0%
subgraph-transition-enter: style recalc count 19 19 +0%
subgraph-transition-enter: task duration 917ms 984ms +7%
subgraph-transition-enter: script duration 17ms 18ms +4%
subgraph-transition-enter: TBT 138ms 144ms +4%
subgraph-transition-enter: heap used 91.7 MB 83.0 MB -10%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2375 2373 -0%
viewport-pan-sweep: avg frame time 17ms 17ms -0%
viewport-pan-sweep: p95 frame time 17ms 17ms +1%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 33ms 39ms +17%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 251 +0%
viewport-pan-sweep: task duration 3909ms 4455ms +14%
viewport-pan-sweep: script duration 1005ms 1120ms +11%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 71.3 MB 81.2 MB +14%
viewport-pan-sweep: DOM nodes -278 -255 -8%
viewport-pan-sweep: event listeners -131 -134 +2%
vue-large-graph-idle: avg frame time 18ms 18ms +0%
vue-large-graph-idle: p95 frame time 17ms 17ms +1%
vue-large-graph-idle: layout duration 0ms 0ms +0%
vue-large-graph-idle: style recalc duration 0ms 0ms +0%
vue-large-graph-idle: layout count 0 0 +0%
vue-large-graph-idle: style recalc count 0 0 +0%
vue-large-graph-idle: task duration 15299ms 16415ms +7%
vue-large-graph-idle: script duration 94ms 119ms +26%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 167.6 MB 176.4 MB +5%
vue-large-graph-idle: DOM nodes -8312 -8312 +0%
vue-large-graph-idle: event listeners -16393 -16389 -0%
vue-large-graph-pan: avg frame time 18ms 18ms +0%
vue-large-graph-pan: p95 frame time 17ms 17ms +1%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 16ms 17ms +7%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 167 172 +3%
vue-large-graph-pan: task duration 19410ms 19770ms +2%
vue-large-graph-pan: script duration 422ms 393ms -7%
vue-large-graph-pan: TBT 96ms 71ms -26%
vue-large-graph-pan: heap used 183.5 MB 180.8 MB -1%
vue-large-graph-pan: DOM nodes -8312 -8312 +0%
vue-large-graph-pan: event listeners -16387 -16386 -0%
workflow-execution: avg frame time 17ms 17ms -0% z=0.1
workflow-execution: p95 frame time 17ms 17ms -0%
workflow-execution: layout duration 1ms 1ms +107% z=-3.2
workflow-execution: style recalc duration 17ms 15ms -8% z=-4.0
workflow-execution: layout count 3 3 -17% z=-4.5
workflow-execution: style recalc count 12 8 -38% z=-5.0
workflow-execution: task duration 95ms 81ms -15% z=-3.9
workflow-execution: script duration 7ms 7ms +2% z=-7.5
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 63.2 MB 62.1 MB -2%
workflow-execution: DOM nodes 121 126 +4% z=-5.0
workflow-execution: event listeners 99 26 -74% z=-5.9
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN 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 ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-08-23T06:02:39.962Z",
  "gitSha": "cbe8b71fc5456c1f43fe23e4bef4a7e6f68e8aa3",
  "branch": "fix/decouple-subgraph-preview-outputs",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2158.516999999989,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.748999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 637.899,
      "heapDeltaBytes": 16905520,
      "heapUsedBytes": 78980652,
      "domNodes": -278,
      "jsHeapTotalBytes": 5758976,
      "scriptDurationMs": 9.219999999999999,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-idle",
      "durationMs": 2055.5389999999534,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 7.125999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 556.395,
      "heapDeltaBytes": 1815300,
      "heapUsedBytes": 63712764,
      "domNodes": -282,
      "jsHeapTotalBytes": 4448256,
      "scriptDurationMs": 9.965000000000002,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1808.2140000000209,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 39.54600000000001,
      "layouts": 12,
      "layoutDurationMs": 3.615,
      "taskDurationMs": 878.251,
      "heapDeltaBytes": -1749964,
      "heapUsedBytes": 60692200,
      "domNodes": -280,
      "jsHeapTotalBytes": 4972544,
      "scriptDurationMs": 113.399,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1854.355000000055,
      "styleRecalcs": 73,
      "styleRecalcDurationMs": 36.50299999999999,
      "layouts": 12,
      "layoutDurationMs": 3.404,
      "taskDurationMs": 880.667,
      "heapDeltaBytes": -5023528,
      "heapUsedBytes": 57397612,
      "domNodes": -284,
      "jsHeapTotalBytes": 5496832,
      "scriptDurationMs": 112.62100000000001,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1685.4510000000005,
      "styleRecalcs": 29,
      "styleRecalcDurationMs": 16.721,
      "layouts": 6,
      "layoutDurationMs": 0.673,
      "taskDurationMs": 406.63699999999994,
      "heapDeltaBytes": 2986468,
      "heapUsedBytes": 65615780,
      "domNodes": 75,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 12.482,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1731.9820000000163,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 18.518,
      "layouts": 6,
      "layoutDurationMs": 0.6880000000000001,
      "taskDurationMs": 399.68499999999995,
      "heapDeltaBytes": 3023236,
      "heapUsedBytes": 65059776,
      "domNodes": 74,
      "jsHeapTotalBytes": 4980736,
      "scriptDurationMs": 10.959,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 594.5600000000013,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.301000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 362.24699999999996,
      "heapDeltaBytes": 10326812,
      "heapUsedBytes": 72294788,
      "domNodes": 18,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 56.157000000000004,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 565.3469999999743,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.219999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 375.39899999999994,
      "heapDeltaBytes": 10913448,
      "heapUsedBytes": 72942384,
      "domNodes": 18,
      "jsHeapTotalBytes": 5505024,
      "scriptDurationMs": 57.673,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2070.88200000004,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 10.022,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 659.945,
      "heapDeltaBytes": -3623556,
      "heapUsedBytes": 72990592,
      "domNodes": -274,
      "jsHeapTotalBytes": -528384,
      "scriptDurationMs": 18.120000000000005,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2038.2489999999507,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.7970000000000015,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 670.409,
      "heapDeltaBytes": -13748764,
      "heapUsedBytes": 62848736,
      "domNodes": -282,
      "jsHeapTotalBytes": 4190208,
      "scriptDurationMs": 16.326999999999998,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2264.0119999999797,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 14.210999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1240.47,
      "heapDeltaBytes": -4235492,
      "heapUsedBytes": 73389912,
      "domNodes": -244,
      "jsHeapTotalBytes": 483328,
      "scriptDurationMs": 357.77,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2331.5129999999726,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 14.165000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1265.3210000000001,
      "heapDeltaBytes": -5859316,
      "heapUsedBytes": 71894116,
      "domNodes": -280,
      "jsHeapTotalBytes": -565248,
      "scriptDurationMs": 356.21500000000003,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3196.2720000000218,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 14.200000000000005,
      "layouts": 60,
      "layoutDurationMs": 7.466,
      "taskDurationMs": 1430.7250000000001,
      "heapDeltaBytes": -11176048,
      "heapUsedBytes": 67920780,
      "domNodes": -287,
      "jsHeapTotalBytes": 5500928,
      "scriptDurationMs": 389.492,
      "eventListeners": -155,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3212.4450000000024,
      "styleRecalcs": 62,
      "styleRecalcDurationMs": 12.753999999999998,
      "layouts": 60,
      "layoutDurationMs": 7.296,
      "taskDurationMs": 1425.3890000000001,
      "heapDeltaBytes": -1636852,
      "heapUsedBytes": 77288648,
      "domNodes": -283,
      "jsHeapTotalBytes": -1576960,
      "scriptDurationMs": 397.138,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666696,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "legacy-node-drag",
      "durationMs": 2334.285999999963,
      "styleRecalcs": 44,
      "styleRecalcDurationMs": 10.612,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1448.942,
      "heapDeltaBytes": -15230172,
      "heapUsedBytes": 69854380,
      "domNodes": 8,
      "jsHeapTotalBytes": 8163328,
      "scriptDurationMs": 472.96600000000007,
      "eventListeners": 186,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "legacy-node-drag",
      "durationMs": 2660.70000000002,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 9.783,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1556.144,
      "heapDeltaBytes": -17170296,
      "heapUsedBytes": 70029672,
      "domNodes": 10,
      "jsHeapTotalBytes": 11571200,
      "scriptDurationMs": 513.4680000000001,
      "eventListeners": 186,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2028.9849999999774,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.149999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 685.4149999999998,
      "heapDeltaBytes": -11993484,
      "heapUsedBytes": 71303252,
      "domNodes": -277,
      "jsHeapTotalBytes": 5763072,
      "scriptDurationMs": 16.396,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2042.2479999999723,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 7.081,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 710.664,
      "heapDeltaBytes": -12204412,
      "heapUsedBytes": 71160904,
      "domNodes": -283,
      "jsHeapTotalBytes": 4190208,
      "scriptDurationMs": 16.958000000000002,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 587.805000000003,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 10.431000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 390.58099999999996,
      "heapDeltaBytes": 11407476,
      "heapUsedBytes": 74257816,
      "domNodes": 18,
      "jsHeapTotalBytes": 5767168,
      "scriptDurationMs": 118.14199999999998,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 591.8170000001055,
      "styleRecalcs": 44,
      "styleRecalcDurationMs": 8.857000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 401.37,
      "heapDeltaBytes": 11521892,
      "heapUsedBytes": 74199092,
      "domNodes": 14,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 120.468,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2004.4839999999908,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.244000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 525.331,
      "heapDeltaBytes": 18496704,
      "heapUsedBytes": 81189316,
      "domNodes": -284,
      "jsHeapTotalBytes": 4710400,
      "scriptDurationMs": 7.977000000000001,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2053.943000000004,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.434000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 526.6550000000001,
      "heapDeltaBytes": -3490084,
      "heapUsedBytes": 58902604,
      "domNodes": -283,
      "jsHeapTotalBytes": 4448256,
      "scriptDurationMs": 8.623000000000003,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1738.6139999999841,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 38.624,
      "layouts": 16,
      "layoutDurationMs": 4.997,
      "taskDurationMs": 829.243,
      "heapDeltaBytes": 17762668,
      "heapUsedBytes": 80383632,
      "domNodes": -283,
      "jsHeapTotalBytes": 4448256,
      "scriptDurationMs": 90.846,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1706.9119999999884,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 34.965999999999994,
      "layouts": 16,
      "layoutDurationMs": 3.849,
      "taskDurationMs": 813.091,
      "heapDeltaBytes": -6265020,
      "heapUsedBytes": 56200548,
      "domNodes": -281,
      "jsHeapTotalBytes": 4972544,
      "scriptDurationMs": 85.33699999999999,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1400.6380000000718,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 33.019999999999996,
      "layouts": 14,
      "layoutDurationMs": 14.612,
      "taskDurationMs": 984.3270000000002,
      "heapDeltaBytes": -4004640,
      "heapUsedBytes": 86982984,
      "domNodes": 13673,
      "jsHeapTotalBytes": 11534336,
      "scriptDurationMs": 17.753999999999998,
      "eventListeners": 2373,
      "totalBlockingTimeMs": 144,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8828.016000000047,
      "styleRecalcs": 251,
      "styleRecalcDurationMs": 39.196999999999996,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4454.871000000001,
      "heapDeltaBytes": 9311972,
      "heapUsedBytes": 85881852,
      "domNodes": -269,
      "jsHeapTotalBytes": -40960,
      "scriptDurationMs": 1110.293,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.80000000000109
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8665.409999999953,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 38.190000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4456.055,
      "heapDeltaBytes": 7756636,
      "heapUsedBytes": 84335084,
      "domNodes": -240,
      "jsHeapTotalBytes": -40960,
      "scriptDurationMs": 1129.347,
      "eventListeners": -135,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.80000000000109
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 16974.520999999982,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 16515.299,
      "heapDeltaBytes": -29762380,
      "heapUsedBytes": 189148640,
      "domNodes": -8312,
      "jsHeapTotalBytes": -24010752,
      "scriptDurationMs": 122.90399999999998,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 16891.823999999928,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 16314.695999999998,
      "heapDeltaBytes": -50694472,
      "heapUsedBytes": 180843408,
      "domNodes": -8312,
      "jsHeapTotalBytes": -16191488,
      "scriptDurationMs": 114.169,
      "eventListeners": -16391,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 20080.217000000004,
      "styleRecalcs": 169,
      "styleRecalcDurationMs": 16.573000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 19527.253,
      "heapDeltaBytes": -38395164,
      "heapUsedBytes": 186202644,
      "domNodes": -8312,
      "jsHeapTotalBytes": -16887808,
      "scriptDurationMs": 382.942,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 111,
      "frameDurationMs": 17.776666666666763,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 20541.071999999986,
      "styleRecalcs": 174,
      "styleRecalcDurationMs": 17.762999999999973,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 20012.532,
      "heapDeltaBytes": -19212576,
      "heapUsedBytes": 192991488,
      "domNodes": -8312,
      "jsHeapTotalBytes": -17981440,
      "scriptDurationMs": 402.18700000000007,
      "eventListeners": -16385,
      "totalBlockingTimeMs": 31,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 107.31199999997898,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 14.454999999999998,
      "layouts": 3,
      "layoutDurationMs": 1.15,
      "taskDurationMs": 74.06600000000002,
      "heapDeltaBytes": 2967484,
      "heapUsedBytes": 65216528,
      "domNodes": 123,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 5.36,
      "eventListeners": 25,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "workflow-execution",
      "durationMs": 116.45899999996345,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 16.183999999999997,
      "layouts": 2,
      "layoutDurationMs": 1.013,
      "taskDurationMs": 88.10900000000002,
      "heapDeltaBytes": 3038216,
      "heapUsedBytes": 64941440,
      "domNodes": 128,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 8.300000000000002,
      "eventListeners": 27,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    }
  ]
}

@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.14286% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...erer/extensions/vueNodes/components/LGraphNode.vue 87.50% 1 Missing ⚠️
@@            Coverage Diff             @@
##             main   #14569      +/-   ##
==========================================
+ Coverage   81.32%   81.88%   +0.55%     
==========================================
  Files        1882     1890       +8     
  Lines      107571   107295     -276     
  Branches    33984    34627     +643     
==========================================
+ Hits        87483    87859     +376     
+ Misses      19727    19101     -626     
+ Partials      361      335      -26     
Flag Coverage Δ
e2e 67.44% <100.00%> (+0.72%) ⬆️
unit 73.55% <93.93%> (+0.99%) ⬆️

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

Files with missing lines Coverage Δ
src/composables/node/mergeSubgraphPreviews.ts 100.00% <100.00%> (ø)
src/composables/node/useAmbientSubgraphPreviews.ts 100.00% <100.00%> (ø)
src/composables/node/usePromotedPreviews.ts 100.00% <100.00%> (+3.37%) ⬆️
...erer/extensions/vueNodes/components/LGraphNode.vue 83.67% <87.50%> (-2.88%) ⬇️

... and 205 files 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.

useAmbientSubgraphPreviews treated any interior node with images in
nodeOutputStore as a live preview candidate, including nodes whose only
"output" is an input-type reference (e.g. an unpromoted LoadImage node's
own selected file). That made every such node's thumbnail always visible
on the collapsed subgraph host regardless of promotion state, breaking
promotion exclusivity.

CI caught this: browser_tests/tests/subgraph/subgraphPromotion.spec.ts
"Can promote multiple previews" > "Promote both image previews" failed
consistently (all 4 attempts) on PR #14569 - after promoting only one of
two Load Image previews, the host showed 2 preview elements instead of 1,
because the unpromoted node's own file leaked in via the new ambient
rollup.

Export isInputPreviewOutput from nodeOutputStore and use it to skip
input-only outputs in the ambient computed, so only genuine live
execution results (or streaming preview frames) surface ambiently -
matching the feature's stated intent (a second concurrently-executing
node with no exposure), not static input previews.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FCL4Meqh8o8VYh9xV1h1Ky
@christian-byrne
christian-byrne marked this pull request as ready for review August 4, 2026 00:44
@christian-byrne
christian-byrne requested a review from a team August 4, 2026 00:44
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Aug 4, 2026
@dosubot

dosubot Bot commented Aug 4, 2026

Copy link
Copy Markdown

📄 Knowledge review

Dosu skipped reviewing this PR because your organization has used its 200 included credits for the month. Your usage will reset on 2026-09-01. To have Dosu review this PR before then, ask your organization admin to upgrade to a pro account.


Leave Feedback Ask Dosu about ComfyUI_frontend Add Dosu to your team

#14551 was closed in favor of this PR's ambient-rollup mechanism, but it
carried three artifacts not otherwise covered here:

- browser_tests/assets/nodes/sampler_custom_advanced_in_subgraph.json +
  browser_tests/tests/subgraph/subgraphPreviewAllowlistGap.spec.ts: this
  PR's own e2e fixture uses two KSamplers, both allowlisted, so it would
  pass even if a node-type gate were reintroduced into the ambient path.
  This fixture pins a non-allowlisted node type (SamplerCustomAdvanced)
  instead.
- Two incident-94 expected-fail regression tests (LGraphNode.test.ts,
  imagePreview.spec.ts) pinning the still-open `!lgraphNode?.isSubgraphNode()`
  guard at LGraphNode.vue:172, which neither PR touches.
@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

Ported the three artifacts from #14551 per Christian's closing comment (commit 42b7c92):

  • browser_tests/assets/nodes/sampler_custom_advanced_in_subgraph.json + browser_tests/tests/subgraph/subgraphPreviewAllowlistGap.spec.ts — carried over as-is; this PR's own e2e fixture uses two KSamplers (both allowlisted), so this is the only test that pins a non-allowlisted interior node type (SamplerCustomAdvanced) and would catch a regression if a type gate were reintroduced into the ambient path. Verified with playwright test --list (discovers correctly under @vue-nodes/@subgraph) and vue-tsc --project browser_tests/tsconfig.json.
  • The two incident-94 expected-fail regression tests pinning the still-open !lgraphNode?.isSubgraphNode() guard at LGraphNode.vue:172 — ported verbatim with their breadcrumb comments into LGraphNode.test.ts (it.fails) and imagePreview.spec.ts (test.fail()); neither existed there yet. LGraphNode.test.ts passes locally (14 passed, 1 expected fail).

pnpm typecheck, targeted oxlint --type-aware/eslint/oxfmt --check, and the touched vitest suites (LGraphNode.test.ts, useAmbientSubgraphPreviews.test.ts, usePromotedPreviews.test.ts, promotionUtils.test.ts) are all clean. Full Playwright execution wasn't run (no live backend in this sandbox) — same disclosed gap as this PR's own test plan.


Generated by Claude Code

Comment thread browser_tests/tests/subgraph/subgraphConcurrentPreviews.spec.ts Outdated
Remove comments that restate what the code does or reference the
incident/PR that motivated the change. Keep only comments that capture
a genuine non-obvious invariant, rewritten to describe the invariant
itself instead of pointing at an incident or ticket number.
@tallestbydesign-ui

Copy link
Copy Markdown

Hey, that sounds like an elegant solution. Is there any news on when this could be merged ?

@christian-byrne christian-byrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Multi-agent review: 10 reviewer agents, a verification gate over the compiled findings, and an adversarial cut pass. Re-verified against 62b52fd after the two commits that landed mid-review; the SamplerCustomAdvanced port from #14551 is here and appreciated, and the comment cleanup did not change any of the findings below.

One item that does not anchor to a line, and one correction of my own:

Scope. This changes the Vue node renderer only. The classic litegraph canvas resolves host previews from previewExposureStore alone (litegraphService.ts:193), and Comfy.VueNodes.Enabled is defaultValue: false with defaultsByInstallVersion: { '1.41.0': isCloud || isDesktop }, so OSS local installs are still on the unfixed path. Classic-canvas parity is the other half of this incident.

Correction, mine. I added Fixes #9859 to this PR body earlier and have since downgraded it. #9859 says verbatim "In LG mode, live previews ... can no longer be shown ... In nodes 2.0 it works" — it is a classic-mode report that this PR provably does not fix, and the keyword would have auto-closed it. #14597 does not state its renderer either, so it is now Refs as well. Worth confirming the renderer on both before closing anything.

Follow-ups worth their own PRs rather than changes here: previews are keyed by subgraph definition id throughout nodeOutputStore, so two host instances of one definition share previews (pre-existing, and not fixed by the change suggested below either); nested subgraph hosts never bubble to an outer host even though the ancestor fan-out at app.ts:861 already writes that data to the nested host's locator.

Comment thread src/composables/node/useAmbientSubgraphPreviews.ts Outdated
Comment thread src/renderer/extensions/vueNodes/components/LGraphNode.vue Outdated
Comment thread src/renderer/extensions/vueNodes/components/LGraphNode.vue
Comment thread src/composables/node/useAmbientSubgraphPreviews.test.ts
Comment thread browser_tests/tests/subgraph/subgraphConcurrentPreviews.spec.ts
Comment thread src/composables/node/useAmbientSubgraphPreviews.ts
Comment thread src/composables/node/useAmbientSubgraphPreviews.ts
Comment thread src/renderer/extensions/vueNodes/components/LGraphNode.test.ts
claude added 4 commits August 8, 2026 23:54
Admitting committed nodeOutputs alongside nodePreviewImages made
demoting an exposure a permanent no-op (the ambient rollup kept
re-rendering what removeExposure just deleted, and queueStore
repopulates nodeOutputs on history load so it survived reload), stacked
a preview on the host for every interior output node after every run,
and fed committed-output nodes into buildImageUrls, which appends a
fresh &rand= per call and re-fetches at latent-preview frame rate.

Narrow the gate to nodePreviewImages only. isInputPreviewOutput was
exported from nodeOutputStore solely for the dropped branch and has no
other external callers, so drop the export too - nodeOutputStore.ts's
diff against main is now empty.

Also correct two docblock claims: previews render when the host is
expanded (v-else-if="!isCollapsed" in LGraphNode.vue), not collapsed,
and this composable bails at depth 1 instead of recursing like
nodeLocationProgressStates.
exposedNodeIds was built from promotedPreviews[].sourceNodeId, which is
the chain-resolved leaf id for exposures that come from a nested
subgraph. useAmbientSubgraphPreviews emits immediate-interior ids
instead. Since last_node_id is per-LGraph, ids restart at 1 in every
subgraph, so a nested exposure resolving to leaf id N could collide
with and suppress the host's own interior node N.

Build the exclusion set from previewExposureStore.getExposures(
rootGraphId, hostLocator) instead - those are, by schema, direct
children of the host's own subgraph, so both sides of the dedup are in
the same id space.

Also extract the promoted/ambient merge into a pure
mergeSubgraphPreviews function with unit tests covering no overlap, an
overlapping exposure winning over its ambient duplicate, and the
namespace-collision regression above.
getNodeImageUrls is an unstubbed vi.fn(), reset to undefined by
vi.resetAllMocks(), so `if (!urls?.length) return []` short-circuited
before the isDetached bail, the nested-SubgraphNode skip, or the
hideOutputImages guard ever ran - deleting any of the three still left
every test green. Add mockReturnValue stubs so the detached and
nested-SubgraphNode tests actually reach their guard, and add a test
for the previously uncovered hideOutputImages guard.

Also dedupe the byte-identical "no output" test by differentiating it
into a test for the getNodeImageUrls-returns-nothing case, add a
regression test locking in the nodeOutputs exclusion from the previous
commit, and assert media type via getPreviewMediaType instead of a
hardcoded 'image' literal so a change to that derivation isn't invisible
to the suite.
A prior comment-cleanup pass reworded these it.fails/test.fail markers
to drop the incident name and exact guard line. Without that pointer,
whoever eventually fixes LGraphNode.vue:172's
!lgraphNode?.isSubgraphNode() guard hits a bare "Error: Expect test to
fail" with no context. Add the breadcrumb back.
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all 8 line-level findings from the latest review round:

  1. Id-namespace collision (LGraphNode.vue:728) — the exclusion set is now built from previewExposureStore.getExposures(rootGraphId, hostLocator) instead of promotedPreviews[].sourceNodeId, so both sides of the dedup are in the host's own id space. (d693cd2)
  2. Ambient admitting committed outputs (useAmbientSubgraphPreviews.ts:59) — gate narrowed to nodePreviewImages only; nodeOutputStore.ts now has zero diff vs main. (f604b85)
  3. Media-type derivation (useAmbientSubgraphPreviews.ts:71) — confirmed moot per Configure vite to copy from src to dist #2: ambient now only ever carries b_preview_with_metadata blob frames, which are always images. No code change.
  4. Guard test coverage (useAmbientSubgraphPreviews.test.ts:100) — added mockReturnValue stubs so the isDetached/nested-SubgraphNode tests are mutation-killing, added a hideOutputImages test, deduped the byte-identical test, and switched the hardcoded type: 'image' assertion to getPreviewMediaType. (a356ced)
  5. Docblock accuracy (useAmbientSubgraphPreviews.ts:20) — corrected "collapsed" → "expanded" host and softened the nodeLocationProgressStates analogy to note the depth-1 limitation. (f604b85)
  6. Extract pure merge function (LGraphNode.vue:725) — mergeSubgraphPreviews(promoted, ambient, exposedSourceNodeIds) in src/composables/node/mergeSubgraphPreviews.ts, with unit tests. (d693cd2)
  7. Breadcrumb comments (LGraphNode.test.ts:399, imagePreview.spec.ts:192) — restored the incident-94 / LGraphNode.vue:172 pointer on both markers. (294e3fb)
  8. CI wiring (subgraphConcurrentPreviews.spec.ts:22) — confirmed via playwright test --list --project=chromium that the spec is discovered under the same project/tag filter CI runs; no config change needed.

pnpm typecheck, pnpm lint, and the full touched-file vitest suite are green. Pushed as 4 new commits on top of the existing branch history (no rebase/force-push): f604b85, d693cd2, a356ced, 294e3fb.

Also saw your scope note on classic-canvas parity and the Fixes/Refs correction — nothing further needed there, just acknowledging.


Generated by Claude Code

@christian-byrne

christian-byrne commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Status for whoever picks this up next.

@DrJKL adding you as co-assignee since you own this area (src/core/graph/subgraph/promotionUtils.ts, src/stores/previewExposureStore.ts, and you authored the guard in #12197). All 8 review findings are fixed and CI is green; the PR is conflict-free against main despite being ~212 commits behind. It is blocked only on a human approval — the existing review is COMMENTED, not APPROVED.

Two things worth deciding before this merges, both of which outlive this PR:

Bug 2a is still unowned. The !lgraphNode?.isSubgraphNode() guard at LGraphNode.vue:172 is unchanged on main. This PR carries two .fail()-marked tests documenting it (per your call on 2026-08-02) but does not fix it. It is also not on the incident's bug list, so it is invisible to anyone reading the tracker. Worth noting that app.ts:861 already fans the preview blob to every ancestor execution id including the host's own locator, so deleting that one condition may be the whole fix, renderer-agnostic and depth-agnostic. Happy to red-green it as a separate PR if you want it.

Classic canvas was scoped out on 2026-08-04 and never revisited. getPseudoWidgetPreviewTargets is exposure-only, so LiteGraph-mode users still have the original bug. That may be fine given the Nodes 2.0 rollout momentum, but it should be an explicit call rather than a silent gap.

Also worth linking, both unfiled against this incident: https://linear.app/comfyorg/issue/FE-616 ("Multiple subgraphs on one canvas get same previews from each other", closed as Duplicate with no target) is the same definition-scoped locator bleed that still exists in nodeOutputStore today, and https://linear.app/comfyorg/issue/FE-1529 is a fresh report in the same area.

Comment thread browser_tests/tests/subgraph/subgraphConcurrentPreviews.spec.ts Outdated
Adds e2e coverage for pathways the two existing preview specs don't
reach: an ambient preview nested two subgraph levels deep bubbles to
its immediate host only, not the outermost one; a committed
(non-live) interior output never gets conflated with the ambient
rollup; and un-promoting a still-live sampler's exposed preview falls
back to its ambient preview instead of disappearing. Also fills a
small unit gap: useAmbientSubgraphPreviews derives video/audio media
types the same way the promoted path already does.
@claude

claude Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Per Christian's Slack ask, expanded e2e (+1 unit) coverage for pathways beyond the two original specs. Summary of what I audited and added:

New e2e specs (browser_tests/tests/subgraph/):

  • subgraphNestedAmbientPreviewScope.spec.ts — a live sampler two subgraph levels deep only bubbles to its immediate host, not the outermost one, matching useAmbientSubgraphPreviews's explicit "nested SubgraphNodes derive their own previews independently" behavior. Verifies zero images on the outer host, then one on the middle host after entering. New fixture: subgraph-nested-with-live-sampler.json.
  • subgraphAmbientCommittedOutputIsolation.spec.ts — a committed (executed) output from an unexposed PreviewImage node never leaks into the ambient rollup (only nodePreviewImages-gated streaming frames should), and the live sampler in the same subgraph still shows correctly afterward. This is the exposure-leak bug class end-to-end (WS → store → render), on top of the existing unit-only regression test. New fixture: subgraph-with-live-sampler-and-committed-output.json.
  • Extended subgraphConcurrentPreviews.spec.ts with a case for mergeSubgraphPreviews's actual purpose: un-promoting a still-live sampler's $$canvas-image-preview via the SubgraphEditor doesn't blank it — the ambient rollup immediately takes back over since exclusion is keyed off the host's current exposure set, not baked in at merge time.

Unit: useAmbientSubgraphPreviews.test.ts gained a video/audio previewMediaType case (mirrors the one usePromotedPreviews.test.ts already had) — the ambient path shared getPreviewMediaType but only had image-type coverage.

Audited, not covered (flagging rather than guessing):

  • Multiple sibling instances of the same subgraph definition, each with its own live ambient preview. Tracing useAmbientSubgraphPreviewsnodeOutputStore.getNodeImageUrls/setNodePreviewsByExecutionIdexecutionIdToNodeLocatorId, every instance's per-node preview resolves to the same definition-scoped NodeLocatorId (types/nodeIdentification.ts says this is intentional: "remains the same for all instances"). That would mean two sibling instances of one subgraph type showing the same live image cross-instance — but this looks like a pre-existing property of the whole preview/output store, not something introduced by this PR, and I can't execute against a live backend here to confirm real-world behavior. Flagging for your awareness rather than asserting untested behavior; happy to dig in further if useful.
  • Video-media-type ambient preview at e2e level, and collapsed-subgraph-node interaction: lower value/higher setup cost for what they'd add over the unit-level and generic-collapse coverage that already exists.
  • Didn't touch the two !lgraphNode?.isSubgraphNode()-guard expected-fail pins (incident-94, tracked separately).

pnpm typecheck, typecheck:browser, oxlint, eslint clean; new/changed unit tests pass. New e2e specs weren't runnable in my sandbox (no live backend) — verified by close reading against the actual composable/store code and by matching existing spec conventions; please confirm in CI.

84476ce

@github-actions github-actions Bot added the risk:R2 PR risk grade (advisory shadow check; grader-owned) label Aug 17, 2026
Comment thread src/renderer/extensions/vueNodes/components/LGraphNode.vue
Comment thread src/composables/node/useAmbientSubgraphPreviews.ts Outdated
Comment thread src/composables/node/useAmbientSubgraphPreviews.test.ts
Comment thread src/composables/node/useAmbientSubgraphPreviews.ts
Comment thread src/renderer/extensions/vueNodes/components/LGraphNode.vue Outdated
claude added 2 commits August 17, 2026 21:12
removeExposure had no tombstone, so useAmbientSubgraphPreviews would
re-surface a preview the next frame after a user explicitly demoted it,
as long as the interior node kept producing live output.

Add a suppressedAmbientNodeIds tombstone set to previewExposureStore,
keyed per (rootGraphId, hostNodeLocator): removeExposure adds the
removed source node to it, addExposure clears it, and clearGraph drops
it with the rest of the host's state. useAmbientSubgraphPreviews now
excludes suppressed node ids from its interior-node scan.

Also documents two invariants raised in review: nodePreviewImages is
only ever written by live execution/streaming frames, never static
input data, so the single-branch gate needs no isInputPreviewOutput
guard; and subgraph.nodes is a plain non-reactive array, so structural
add/remove while collapsed isn't tracked until the next preview frame.
… own regression test

b6bc646 added a suppressedAmbientNodeIds tombstone so removeExposure
would permanently hide an interior node's ambient preview. That
directly reverses this PR's stated design ("any interior node
currently producing output shows on the host, whether or not anyone
promoted it") and broke the e2e regression test added earlier in this
branch (subgraphConcurrentPreviews.spec.ts: "un-promoting a still-live
sampler falls back to its ambient preview instead of disappearing"),
which was failing in CI.

Un-promoting a node only removes its explicit exposure (name/ordering
in the promoted slot); it was never meant to blacklist the node from
the ambient rollup while it keeps producing live output. Revert the
tombstone mechanism and its tests, restoring the pre-b6bc646 behavior
that the existing regression test expects.
…mputed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
christian-byrne added a commit that referenced this pull request Aug 23, 2026
Adds e2e coverage for `Convert to Subgraph` with a **partial**
selection.

## The gap

`browser_tests/tests/subgraph/subgraphCrud.spec.ts:68` is the only e2e
test of subgraph creation. It calls `comfyPage.keyboard.selectAll()`
first, so every node is inside the selection, **there are zero boundary
links**, and the entire rewiring block in `_convertToSubgraphImpl`
(`src/lib/litegraph/src/LGraph.ts:1861-1939`) never executes. It then
asserts node counts, never link topology.

Partial selection — what users actually do — had no e2e coverage at all.
That block reconnects boundary links by positional index
(`subgraphNode.inputs[i - 1]`, `subgraphNode.outputs[i - 1]`) against a
slot array built independently in `mapSubgraphInputsAndLinks`, so a
drift there is silent.

## What it does

Packs `KSampler` + `VAE Decode` out of the default workflow and asserts:

- the exact post-conversion link table, with the new subgraph node
rendered as `HOST` (five boundary inputs rewired onto it, one boundary
output to SaveImage, and the two `CheckpointLoaderSimple → CLIP` links
that lie entirely outside the selection left untouched)
- every rewired link lands on a type-compatible slot
- the result survives a serialize/reload round trip

## Status — currently red, cause not yet established

Please do not read the red as a confirmed product bug yet; I do not want
to overstate it.

The first run failed, but **my expected link count was wrong** (I
asserted six root links and forgot the two external-only CLIP links; the
correct total is eight). That error is fixed in `0566c82c5a`, which now
asserts the full topology rather than a count.

What the first run reported that is *not* explained by my arithmetic
error, and is still open:

- the `4:2` VAE boundary link was absent from the links targeting the
host
- one host input slot was left unconnected
- SaveImage's input was not fed by the host
- nine root links, where the corrected expectation is eight

Against that, a faithful unit-level reduction of the same graph shape
(same node/slot/type layout, same selection) **passes**: all five host
inputs connect, SaveImage is fed by the host, and the link count is
eight. So either the trigger is something the reduction lacks (real node
defs, widget-backed inputs, the app's `SubgraphNode` registration path),
or the browser selection was not the two nodes I assumed. The corrected
assertion prints the actual table on failure, which should settle it on
the next run.

I have deliberately **not** written a fix. Test-only PR.

## Related

- Does **not** overlap
#15002 (subgraph
**unpack**, FE-1539 — different action, different code path
`_unpackSubgraphImpl`).
- Does **not** overlap
#15009 /
#15018, which are
based on `feature/ecs-migration` and change `src/stores/linkStore.ts` /
`rerouteStore.ts` — files that do not exist on `main`.
- Does **not** overlap
#14569 (preview/output
display only).

---------

Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:R2 PR risk grade (advisory shadow check; grader-owned) size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants