Skip to content

test(assets): e2e coverage for the assets-mode model library sidebar - #13574

Merged
synap5e merged 58 commits into
mainfrom
synap5e/test/assets-sidebar-e2e
Jul 28, 2026
Merged

test(assets): e2e coverage for the assets-mode model library sidebar#13574
synap5e merged 58 commits into
mainfrom
synap5e/test/assets-sidebar-e2e

Conversation

@synap5e

@synap5e synap5e commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

E2E coverage for the assets-backed model library sidebar (#13464), testing the integration seams the unit suites mock away.

Stacked on #13464 (synap5e/assets-mode-sidebar). All assets endpoints are mocked, so the suite passes regardless of whether the CI container backend has the assets API yet.

Changes

  • What:
    • sidebar/modelLibraryRouting.spec.ts: Comfy.ModelLibrary.UseAssetBrowser + Comfy.Assets.UseAssetAPI tab routing (both on → asset browser modal; either off → sidebar tree; @cloud defaults → modal).
    • sidebar/modelLibraryAssetMode.spec.ts: asset-mode tree from a mocked /api/assets walk + /api/experiment/models registration (folder registration order, eager load with no load-all button, extension allowlists verbatim vs match-all default filtering), refresh → POST /api/assets/seed, live tree/search updates on the assets.seed.fast_complete event, ghost placement filling the loader widget with loader_path, bare-tag backend fallback.
    • Fixtures: model_type:/loader_path asset fixtures, AssetHelper seed-endpoint handling, FeatureFlagHelper.setServerFlags (forces api.serverFeatureFlags; the ff: localStorage override is dev-only and tree-shaken from production builds), dispatchApiCustomEvent util for wire-level events outside the typed ApiEventTypes map, getFolderRowByLabel page-object locator (ancestor tree rows contain descendant text, so the existing label locator misclicks nested folders).
    • AssetHelper route pattern narrowed **/assets****/api/assets**: the old pattern intercepted the built frontend's /assets/*.js chunks on any navigation after mock(). No existing consumer is affected (all target /api/assets).
    • graph.spec.ts: mirrors main's branded-LinkId fix (9e5fb67) verbatim; now superseded by main having been merged through the stack (identical content, resolved cleanly).
  • Breaking: none

Review Focus

  • The assets.seed.fast_complete injection dispatches directly on the api singleton (EventTarget.prototype.dispatchEvent), replicating the socket handler's default case; the real WS frame path above that dispatch is not exercised.
  • The bare-tag test forces supports_model_type_tags: false explicitly so the real test backend's feature_flags handshake can't decide which mode is under test.

Test plan

  • pnpm typecheck:browser, eslint, oxlint, knip clean
  • 11/11 chromium tests green against a CI-shaped stack (built OSS dist served by ComfyUI --cpu --multi-user)
  • @cloud routing test green against the built cloud dist
  • Existing sidebar/modelLibrary.spec.ts + assetHelper.spec.ts (34 tests) still green with the shared-fixture changes

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds browser-test infrastructure and coverage for model library asset mode, seed rescans, feature flags, routing, model placement, and bare-tag backends. It also updates a graph regression assertion to use branded link IDs.

Changes

Model library asset and routing coverage

Layer / File(s) Summary
Asset fixtures and test controls
browser_tests/fixtures/data/assetFixtures.ts, browser_tests/fixtures/helpers/*, browser_tests/fixtures/utils/dispatchApiEvent.ts
Adds loader-path-aware model fixtures, scoped asset API mocks, seed-scan responses, server-flag overrides, and API custom-event dispatching.
Asset-mode sidebar behavior
browser_tests/fixtures/components/SidebarTab.ts, browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
Covers folder ordering, eager loading, filtering, rescans, scan-event updates, model placement, and bare-tag behavior.
Model library routing
browser_tests/tests/sidebar/modelLibraryRouting.spec.ts
Verifies whether the model library opens the asset browser modal or sidebar tree under different settings and cloud defaults.

Graph link assertion alignment

Layer / File(s) Summary
Branded link lookup assertion
browser_tests/tests/graph.spec.ts
Passes toLinkId(1) into the evaluated graph-link lookup for the target-slot regression check.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Sidebar
  participant AssetHelper
  participant AppAPI
  Sidebar->>AssetHelper: POST /assets/seed
  AssetHelper-->>Sidebar: status started
  AppAPI-->>Sidebar: assets.seed.fast_complete
  Sidebar-->>Sidebar: refresh tree and active search results
Loading

Possibly related PRs

Suggested reviewers: christian-byrne, AustinMroz, DrJKL, benceruleanlu


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
End-To-End Regression Coverage For Fixes ❓ Inconclusive PR title/commit subjects aren’t provided here, so I can’t verify the required bug-fix signal from PR metadata alone. Please provide the PR title and commit subjects (or full PR metadata) so I can determine whether this regression-test requirement applies.
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Adr Compliance For Entity/Litegraph Changes ✅ Passed PASS: changed files are browser_tests fixtures/tests only; no src/lib/litegraph, src/ecs, or graph entity files, so ADR 0003/0008 is not applicable.
Title check ✅ Passed The title is concise and accurately highlights the main change: E2E coverage for the assets-mode model library sidebar.
Description check ✅ Passed The description follows the template structure and includes summary, changes, review focus, and test plan; screenshots are optional.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch synap5e/test/assets-sidebar-e2e

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

@synap5e synap5e added the cursor-review Trigger multi-model Cursor agent review on this PR label Jul 10, 2026
@synap5e synap5e self-assigned this Jul 10, 2026
@synap5e
synap5e marked this pull request as ready for review July 10, 2026 11:24
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1757 passed, 0 failed

📊 Browser Reports
  • chromium: View Report (✅ 1736 / ❌ 0 / ⚠️ 0 / ⏭️ 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)

📦 Bundle: 8.13 MB gzip 🔴 +345 B

Details

Summary

  • Raw size: 34.1 MB baseline 34.1 MB — 🔴 +1.07 kB
  • Gzip: 8.13 MB baseline 8.13 MB — 🔴 +345 B
  • Brotli: 5.62 MB baseline 5.62 MB — 🟢 -71 B
  • Bundles: 420 current • 420 baseline • 141 added / 141 removed

Category Glance
Data & Services 🔴 +1.07 kB (3.4 MB) · Vendor & Third-Party ⚪ 0 B (15.7 MB) · Other ⚪ 0 B (12.5 MB) · Graph Workspace ⚪ 0 B (1.28 MB) · Panels & Settings ⚪ 0 B (551 kB) · Utilities & Hooks ⚪ 0 B (367 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-ARVGCKZv.js (new) 3.64 kB 🔴 +3.64 kB 🔴 +1.83 kB 🔴 +1.59 kB
assets/index-BNsXBECr.js (removed) 3.64 kB 🟢 -3.64 kB 🟢 -1.82 kB 🟢 -1.59 kB

Status: 1 added / 1 removed

Graph Workspace — 1.28 MB (baseline 1.28 MB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-Bh8W0FQ6.js (removed) 1.28 MB 🟢 -1.28 MB 🟢 -275 kB 🟢 -207 kB
assets/GraphView-Dwsda_YC.js (new) 1.28 MB 🔴 +1.28 MB 🔴 +275 kB 🔴 +207 kB

Status: 1 added / 1 removed / 1 unchanged

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-CNS21-ER.js (new) 25 kB 🔴 +25 kB 🔴 +6.26 kB 🔴 +5.53 kB
assets/CloudSurveyView-Cx7AQRIb.js (removed) 25 kB 🟢 -25 kB 🟢 -6.26 kB 🟢 -5.53 kB
assets/CloudLoginView-Dz4flZ1X.js (removed) 11.6 kB 🟢 -11.6 kB 🟢 -3.14 kB 🟢 -2.76 kB
assets/CloudLoginView-NQn1HTP9.js (new) 11.6 kB 🔴 +11.6 kB 🔴 +3.14 kB 🔴 +2.75 kB
assets/CloudSignupView-CElLY2_i.js (new) 9.96 kB 🔴 +9.96 kB 🔴 +2.81 kB 🔴 +2.47 kB
assets/CloudSignupView-FPwrwOLQ.js (removed) 9.96 kB 🟢 -9.96 kB 🟢 -2.81 kB 🟢 -2.46 kB
assets/CloudLayoutView-CAtynxbo.js (new) 9.54 kB 🔴 +9.54 kB 🔴 +2.34 kB 🔴 +2.02 kB
assets/CloudLayoutView-CYzBP67V.js (removed) 9.54 kB 🟢 -9.54 kB 🟢 -2.35 kB 🟢 -2.02 kB
assets/UserCheckView-C3LHzibQ.js (new) 8.8 kB 🔴 +8.8 kB 🔴 +2.22 kB 🔴 +1.93 kB
assets/UserCheckView-j5TBi-eD.js (removed) 8.8 kB 🟢 -8.8 kB 🟢 -2.22 kB 🟢 -1.92 kB
assets/WidgetTextPreview-hnbetWvA.js (removed) 6.13 kB 🟢 -6.13 kB 🟢 -2.16 kB 🟢 -1.92 kB
assets/WidgetTextPreview-z7q3PUwl.js (new) 6.13 kB 🔴 +6.13 kB 🔴 +2.16 kB 🔴 +1.92 kB
assets/CloudSubscriptionRedirectView-B7TwvORK.js (removed) 6.06 kB 🟢 -6.06 kB 🟢 -2.26 kB 🟢 -1.97 kB
assets/CloudSubscriptionRedirectView-DAAGxhNj.js (new) 6.06 kB 🔴 +6.06 kB 🔴 +2.26 kB 🔴 +1.97 kB
assets/UserSelectView-BX8tCNfk.js (new) 5.54 kB 🔴 +5.54 kB 🔴 +1.99 kB 🔴 +1.74 kB
assets/UserSelectView-Chti9K4v.js (removed) 5.54 kB 🟢 -5.54 kB 🟢 -1.99 kB 🟢 -1.74 kB
assets/CloudForgotPasswordView-idkut2rQ.js (new) 5.15 kB 🔴 +5.15 kB 🔴 +1.76 kB 🔴 +1.53 kB
assets/CloudForgotPasswordView-tjRJNZvD.js (removed) 5.15 kB 🟢 -5.15 kB 🟢 -1.76 kB 🟢 -1.53 kB
assets/CloudAuthTimeoutView-CPqipPjr.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.57 kB 🔴 +1.37 kB
assets/CloudAuthTimeoutView-D9rbeRfw.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.57 kB 🟢 -1.37 kB
assets/OAuthLayoutView-BRWMng8Q.js (new) 1.36 kB 🔴 +1.36 kB 🔴 +734 B 🔴 +621 B
assets/OAuthLayoutView-DthHt31n.js (removed) 1.36 kB 🟢 -1.36 kB 🟢 -733 B 🟢 -620 B
assets/WidgetTextPreview-C16A5RBW.js (removed) 131 B 🟢 -131 B 🟢 -100 B 🟢 -91 B
assets/WidgetTextPreview-C7hBcZTD.js (new) 131 B 🔴 +131 B 🔴 +100 B 🔴 +90 B

Status: 12 added / 12 removed / 4 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-D-Poj4HW.js (removed) 49.5 kB 🟢 -49.5 kB 🟢 -9.97 kB 🟢 -8.82 kB
assets/KeybindingPanel-DsmNGYFb.js (new) 49.5 kB 🔴 +49.5 kB 🔴 +9.97 kB 🔴 +8.83 kB
assets/SecretsPanel-DmbGIqY5.js (removed) 31 kB 🟢 -31 kB 🟢 -7.51 kB 🟢 -6.57 kB
assets/SecretsPanel-S7xRBcXj.js (new) 31 kB 🔴 +31 kB 🔴 +7.51 kB 🔴 +6.58 kB
assets/CreditsPanel-CQNplv2b.js (removed) 16 kB 🟢 -16 kB 🟢 -4.66 kB 🟢 -4.1 kB
assets/CreditsPanel-DRpSwhwk.js (new) 16 kB 🔴 +16 kB 🔴 +4.66 kB 🔴 +4.09 kB
assets/SubscriptionPanel-DLE7e06u.js (new) 11.5 kB 🔴 +11.5 kB 🔴 +3.65 kB 🔴 +3.22 kB
assets/SubscriptionPanel-vHFylB7I.js (removed) 11.5 kB 🟢 -11.5 kB 🟢 -3.65 kB 🟢 -3.21 kB
assets/AboutPanel-Ctrh4hWN.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.06 kB 🟢 -2.74 kB
assets/AboutPanel-D6u6NmL9.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.06 kB 🔴 +2.74 kB
assets/ExtensionPanel-CT-5Icrz.js (removed) 9.24 kB 🟢 -9.24 kB 🟢 -2.54 kB 🟢 -2.24 kB
assets/ExtensionPanel-M2m0W3qO.js (new) 9.24 kB 🔴 +9.24 kB 🔴 +2.54 kB 🔴 +2.25 kB
assets/ServerConfigPanel-NcRRpFaf.js (removed) 6.15 kB 🟢 -6.15 kB 🟢 -1.97 kB 🟢 -1.75 kB
assets/ServerConfigPanel-qLnoGvDl.js (new) 6.15 kB 🔴 +6.15 kB 🔴 +1.97 kB 🔴 +1.75 kB
assets/UserPanel-CSiM4p-C.js (removed) 5.78 kB 🟢 -5.78 kB 🟢 -1.81 kB 🟢 -1.57 kB
assets/UserPanel-D_D3FOZD.js (new) 5.78 kB 🔴 +5.78 kB 🔴 +1.81 kB 🔴 +1.57 kB
assets/refreshRemoteConfig-BhrSY4qF.js (new) 2.97 kB 🔴 +2.97 kB 🔴 +1.27 kB 🔴 +1.11 kB
assets/refreshRemoteConfig-D01L2Ol5.js (removed) 2.97 kB 🟢 -2.97 kB 🟢 -1.27 kB 🟢 -1.11 kB
assets/cloudRemoteConfig-B9Ro8S5l.js (new) 988 B 🔴 +988 B 🔴 +538 B 🔴 +453 B
assets/cloudRemoteConfig-C_qVGTfM.js (removed) 988 B 🟢 -988 B 🟢 -541 B 🟢 -458 B
assets/refreshRemoteConfig-BrUq-WT9.js (new) 110 B 🔴 +110 B 🔴 +89 B 🔴 +83 B
assets/refreshRemoteConfig-BZYIi9pI.js (removed) 110 B 🟢 -110 B 🟢 -89 B 🟢 -83 B

Status: 11 added / 11 removed / 15 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SignUpForm-Ck_rtgHp.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -4.18 kB 🟢 -3.65 kB
assets/SignUpForm-D-6VXIeO.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +4.19 kB 🔴 +3.65 kB
assets/auth-D8d-K-_N.js (removed) 3.69 kB 🟢 -3.69 kB 🟢 -1.3 kB 🟢 -1.14 kB
assets/auth-uJmYJrIW.js (new) 3.69 kB 🔴 +3.69 kB 🔴 +1.3 kB 🔴 +1.12 kB
assets/usePostAuthRedirect-CtRbyxaB.js (removed) 3.33 kB 🟢 -3.33 kB 🟢 -1.27 kB 🟢 -1.11 kB
assets/usePostAuthRedirect-Drt3eqaS.js (new) 3.33 kB 🔴 +3.33 kB 🔴 +1.27 kB 🔴 +1.1 kB
assets/UpdatePasswordContent-Cj-E8aRT.js (removed) 1.91 kB 🟢 -1.91 kB 🟢 -874 B 🟢 -758 B
assets/UpdatePasswordContent-Cm4ATFzx.js (new) 1.91 kB 🔴 +1.91 kB 🔴 +873 B 🔴 +759 B
assets/authStore-C84WupXI.js (new) 128 B 🔴 +128 B 🔴 +104 B 🔴 +105 B
assets/authStore-Ci4NxBK6.js (removed) 128 B 🟢 -128 B 🟢 -104 B 🟢 -107 B
assets/workspaceAuthStore-EBfV3X_i.js (new) 108 B 🔴 +108 B 🔴 +99 B 🔴 +101 B
assets/workspaceAuthStore-OZNW0rZh.js (removed) 108 B 🟢 -108 B 🟢 -99 B 🟢 -102 B
assets/auth-Cj7rtAqk.js (new) 105 B 🔴 +105 B 🔴 +96 B 🔴 +84 B
assets/auth-i0cWK1rj.js (removed) 105 B 🟢 -105 B 🟢 -96 B 🟢 -88 B

Status: 7 added / 7 removed / 3 unchanged

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

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyHubPublishDialog-BAZ4YMaV.js (new) 89.9 kB 🔴 +89.9 kB 🔴 +19.2 kB 🔴 +16.4 kB
assets/ComfyHubPublishDialog-BdJfNE7M.js (removed) 89.9 kB 🟢 -89.9 kB 🟢 -19.2 kB 🟢 -16.5 kB
assets/useShareDialog-7rrNnq6G.js (new) 23.7 kB 🔴 +23.7 kB 🔴 +5.59 kB 🔴 +4.96 kB
assets/useShareDialog-BsPR8JNE.js (removed) 23.7 kB 🟢 -23.7 kB 🟢 -5.58 kB 🟢 -4.95 kB
assets/feedbackDialog-BrFrRrOy.js (removed) 4.5 kB 🟢 -4.5 kB 🟢 -1.89 kB 🟢 -1.62 kB
assets/feedbackDialog-CD630lng.js (new) 4.5 kB 🔴 +4.5 kB 🔴 +1.89 kB 🔴 +1.61 kB
assets/ComfyHubPublishDialog-BfHyWNLh.js (removed) 143 B 🟢 -143 B 🟢 -105 B 🟢 -88 B
assets/ComfyHubPublishDialog-CikOoArM.js (new) 143 B 🔴 +143 B 🔴 +105 B 🔴 +90 B
assets/useSubscriptionDialog-Bnn0vUWv.js (new) 108 B 🔴 +108 B 🔴 +102 B 🔴 +91 B
assets/useSubscriptionDialog-CaEz4_nw.js (removed) 108 B 🟢 -108 B 🟢 -102 B 🟢 -92 B

Status: 5 added / 5 removed / 1 unchanged

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-CPaCubQb.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.77 kB 🔴 +3.34 kB
assets/ComfyQueueButton-DDXvnBDz.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.77 kB 🟢 -3.34 kB
assets/useTerminalTabs-BqlhJwbp.js (new) 11.8 kB 🔴 +11.8 kB 🔴 +3.72 kB 🔴 +3.29 kB
assets/useTerminalTabs-YJi3PIRi.js (removed) 11.8 kB 🟢 -11.8 kB 🟢 -3.72 kB 🟢 -3.29 kB
assets/InviteMembersForm-Bht4xcPZ.js (removed) 7.85 kB 🟢 -7.85 kB 🟢 -2.65 kB 🟢 -2.34 kB
assets/InviteMembersForm-CVNnFc2M.js (new) 7.85 kB 🔴 +7.85 kB 🔴 +2.65 kB 🔴 +2.35 kB
assets/SubscribeButton-BbY6r7ta.js (removed) 2.18 kB 🟢 -2.18 kB 🟢 -987 B 🟢 -863 B
assets/SubscribeButton-CA-lSzE_.js (new) 2.18 kB 🔴 +2.18 kB 🔴 +987 B 🔴 +865 B
assets/cloudFeedbackTopbarButton-DKqVL59t.js (new) 768 B 🔴 +768 B 🔴 +452 B 🔴 +403 B
assets/cloudFeedbackTopbarButton-tXLhqVJ_.js (removed) 768 B 🟢 -768 B 🟢 -452 B 🟢 -376 B
assets/ComfyQueueButton-CnPqG9Gt.js (removed) 128 B 🟢 -128 B 🟢 -99 B 🟢 -91 B
assets/ComfyQueueButton-CnyPUX0_.js (new) 128 B 🔴 +128 B 🔴 +99 B 🔴 +92 B

Status: 6 added / 6 removed / 8 unchanged

Data & Services — 3.4 MB (baseline 3.4 MB) • 🔴 +1.07 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settingStore-DMyPPRCL.js (new) 3.13 MB 🔴 +3.13 MB 🔴 +725 kB 🔴 +547 kB
assets/settingStore-DOFYN80a.js (removed) 3.13 MB 🟢 -3.13 MB 🟢 -725 kB 🟢 -547 kB
assets/load3dService-CofBuzZ5.js (new) 132 kB 🔴 +132 kB 🔴 +29.3 kB 🔴 +24.6 kB
assets/load3dService-CxhlpB9y.js (removed) 132 kB 🟢 -132 kB 🟢 -29.3 kB 🟢 -24.6 kB
assets/api-B07hp_px.js (removed) 91.4 kB 🟢 -91.4 kB 🟢 -25.3 kB 🟢 -21.7 kB
assets/api-Ds0A9bme.js (new) 91.4 kB 🔴 +91.4 kB 🔴 +25.3 kB 🔴 +21.7 kB
assets/workflowShareService-BHYumsqU.js (new) 16.5 kB 🔴 +16.5 kB 🔴 +4.92 kB 🔴 +4.36 kB
assets/workflowShareService-C4_36TxV.js (removed) 16.5 kB 🟢 -16.5 kB 🟢 -4.92 kB 🟢 -4.37 kB
assets/keybindingService-Bq2xPHcw.js (removed) 7.28 kB 🟢 -7.28 kB 🟢 -1.9 kB 🟢 -1.62 kB
assets/keybindingService-DFZ9jp9S.js (new) 7.28 kB 🔴 +7.28 kB 🔴 +1.89 kB 🔴 +1.62 kB
assets/releaseStore-BKewCbRA.js (removed) 6.77 kB 🟢 -6.77 kB 🟢 -2.06 kB 🟢 -1.8 kB
assets/releaseStore-DBZtSDfk.js (new) 6.77 kB 🔴 +6.77 kB 🔴 +2.06 kB 🔴 +1.8 kB
assets/systemStatsStore-CTszlpVQ.js (removed) 4.99 kB 🟢 -4.99 kB 🟢 -1.77 kB 🟢 -1.5 kB
assets/systemStatsStore-Y8Ks5joW.js (new) 4.99 kB 🔴 +4.99 kB 🔴 +1.77 kB 🔴 +1.5 kB
assets/userStore-CZUxgBjg.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -931 B 🟢 -826 B
assets/userStore-DUGPx5ug.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +930 B 🔴 +826 B
assets/audioService-BlzEoGW8.js (removed) 1.76 kB 🟢 -1.76 kB 🟢 -862 B 🟢 -753 B
assets/audioService-CcgGv2tc.js (new) 1.76 kB 🔴 +1.76 kB 🔴 +860 B 🔴 +748 B
assets/dialogService-CVkD8um4.js (removed) 98 B 🟢 -98 B 🟢 -97 B 🟢 -75 B
assets/dialogService-VTI-9lzM.js (new) 98 B 🔴 +98 B 🔴 +97 B 🔴 +83 B
assets/releaseStore-BdB59zWW.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -91 B
assets/releaseStore-YGA5tvqQ.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +84 B
assets/settingStore-BZeQX31J.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -82 B
assets/settingStore-DptU_0O1.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +83 B
assets/assetsStore-CkoDduU5.js (removed) 94 B 🟢 -94 B 🟢 -92 B 🟢 -84 B
assets/assetsStore-v9zDNYnU.js (new) 94 B 🔴 +94 B 🔴 +92 B 🔴 +84 B
assets/api-D3BNOqD1.js (removed) 62 B 🟢 -62 B 🟢 -74 B 🟢 -66 B
assets/api-DMAI8JK3.js (new) 62 B 🔴 +62 B 🔴 +74 B 🔴 +66 B

Status: 14 added / 14 removed / 3 unchanged

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-CB_Q2EE5.js (new) 235 kB 🔴 +235 kB 🔴 +52.5 kB 🔴 +42.7 kB
assets/useConflictDetection-Daf6B4-0.js (removed) 235 kB 🟢 -235 kB 🟢 -52.5 kB 🟢 -42.7 kB
assets/useLoad3d-CJzQGcSy.js (new) 25.8 kB 🔴 +25.8 kB 🔴 +5.82 kB 🔴 +5.16 kB
assets/useLoad3d-DVG-JUkA.js (removed) 25.8 kB 🟢 -25.8 kB 🟢 -5.82 kB 🟢 -5.15 kB
assets/useLoad3dViewer-CgRnP9bP.js (new) 21.3 kB 🔴 +21.3 kB 🔴 +5 kB 🔴 +4.38 kB
assets/useLoad3dViewer-COObVPQx.js (removed) 21.3 kB 🟢 -21.3 kB 🟢 -5 kB 🟢 -4.38 kB
assets/useFeatureFlags-B9WN4_mc.js (new) 7.26 kB 🔴 +7.26 kB 🔴 +2.17 kB 🔴 +1.83 kB
assets/useFeatureFlags-C7bqFfWs.js (removed) 7.26 kB 🟢 -7.26 kB 🟢 -2.17 kB 🟢 -1.83 kB
assets/useDowngradeToPersonal-0kKPA3vO.js (removed) 3.51 kB 🟢 -3.51 kB 🟢 -1.27 kB 🟢 -1.09 kB
assets/useDowngradeToPersonal-D53DpFme.js (new) 3.51 kB 🔴 +3.51 kB 🔴 +1.26 kB 🔴 +1.13 kB
assets/assetPreviewUtil--FlDD58w.js (removed) 2.41 kB 🟢 -2.41 kB 🟢 -1 kB 🟢 -871 B
assets/assetPreviewUtil-CZmJnZYV.js (new) 2.41 kB 🔴 +2.41 kB 🔴 +1 kB 🔴 +871 B
assets/useUpstreamValue-BD4aE6cR.js (new) 2.04 kB 🔴 +2.04 kB 🔴 +790 B 🔴 +704 B
assets/useUpstreamValue-YH4sVL2O.js (removed) 2.04 kB 🟢 -2.04 kB 🟢 -791 B 🟢 -703 B
assets/useWorkspaceTierLabel-BeesRL2b.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +845 B 🔴 +727 B
assets/useWorkspaceTierLabel-CGzyTdGT.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -846 B 🟢 -734 B
assets/subscriptionCheckoutUtil-ByWogGC_.js (new) 903 B 🔴 +903 B 🔴 +534 B 🔴 +450 B
assets/subscriptionCheckoutUtil-kua5WXeR.js (removed) 903 B 🟢 -903 B 🟢 -534 B 🟢 -455 B
assets/useSessionCookie-DytL2pGI.js (removed) 746 B 🟢 -746 B 🟢 -393 B 🟢 -339 B
assets/useSessionCookie-NSxYvc3m.js (new) 746 B 🔴 +746 B 🔴 +391 B 🔴 +342 B
assets/useLoad3d-BuBqW6eF.js (new) 311 B 🔴 +311 B 🔴 +164 B 🔴 +147 B
assets/useLoad3d-CQ1XJmvR.js (removed) 311 B 🟢 -311 B 🟢 -165 B 🟢 -147 B
assets/useSessionCookie-Byo_V44Q.js (removed) 101 B 🟢 -101 B 🟢 -86 B 🟢 -85 B
assets/useSessionCookie-Cb4FxBiL.js (new) 101 B 🔴 +101 B 🔴 +86 B 🔴 +83 B
assets/useFeatureFlags-BO_yEoNg.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +81 B
assets/useFeatureFlags-Cnz_2D41.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -79 B
assets/useLoad3dViewer-B0Fjal5M.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -85 B
assets/useLoad3dViewer-DDFz5v7J.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +86 B
assets/useCurrentUser-BPhtrUVc.js (removed) 94 B 🟢 -94 B 🟢 -95 B 🟢 -85 B
assets/useCurrentUser-CUUau-8K.js (new) 94 B 🔴 +94 B 🔴 +95 B 🔴 +86 B

Status: 15 added / 15 removed / 20 unchanged

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

External libraries and shared vendor chunks

Status: 16 unchanged

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

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-BVPTPz2p.js (removed) 111 kB 🟢 -111 kB 🟢 -28.7 kB 🟢 -24.3 kB
assets/core-Ctm-8cO4.js (new) 111 kB 🔴 +111 kB 🔴 +28.7 kB 🔴 +24.3 kB
assets/WidgetSelect-CbdNiknn.js (removed) 88 kB 🟢 -88 kB 🟢 -20 kB 🟢 -17.1 kB
assets/WidgetSelect-DYEzwl-u.js (new) 88 kB 🔴 +88 kB 🔴 +20 kB 🔴 +17.1 kB
assets/Load3D-4vnZSSYh.js (removed) 71.3 kB 🟢 -71.3 kB 🟢 -11.7 kB 🟢 -10 kB
assets/Load3D-DcMakVdt.js (new) 71.3 kB 🔴 +71.3 kB 🔴 +11.7 kB 🔴 +10 kB
assets/Preview3d-Duljy3Op.js (new) 50.9 kB 🔴 +50.9 kB 🔴 +8.34 kB 🔴 +7.27 kB
assets/Preview3d-sm4jSMV3.js (removed) 50.9 kB 🟢 -50.9 kB 🟢 -8.34 kB 🟢 -7.26 kB
assets/main-pdUPts3t.js (new) 46.7 kB 🔴 +46.7 kB 🔴 +13.8 kB 🔴 +11.9 kB
assets/main-r27Bv5Kl.js (removed) 46.7 kB 🟢 -46.7 kB 🟢 -13.8 kB 🟢 -11.9 kB
assets/SubscriptionTransitionPreviewWorkspace-BO-DqjyT.js (new) 43.5 kB 🔴 +43.5 kB 🔴 +9.36 kB 🔴 +8.22 kB
assets/SubscriptionTransitionPreviewWorkspace-Cb76juPL.js (removed) 43.5 kB 🟢 -43.5 kB 🟢 -9.36 kB 🟢 -8.22 kB
assets/SubscriptionRequiredDialogContentUnified-Be3Rxn3Z.js (new) 42.1 kB 🔴 +42.1 kB 🔴 +9.37 kB 🔴 +8.15 kB
assets/SubscriptionRequiredDialogContentUnified-CZgkP7vD.js (removed) 42.1 kB 🟢 -42.1 kB 🟢 -9.37 kB 🟢 -8.15 kB
assets/MembersPanelContent-CB3wzBW7.js (removed) 41.9 kB 🟢 -41.9 kB 🟢 -8.8 kB 🟢 -7.84 kB
assets/MembersPanelContent-DyfQ38HA.js (new) 41.9 kB 🔴 +41.9 kB 🔴 +8.8 kB 🔴 +7.84 kB
assets/WorkspaceSettingsPanelContent-BNCVQDkW.js (new) 34.6 kB 🔴 +34.6 kB 🔴 +8 kB 🔴 +7.01 kB
assets/WorkspaceSettingsPanelContent-qH-Tnrk2.js (removed) 34.6 kB 🟢 -34.6 kB 🟢 -8 kB 🟢 -7.02 kB
assets/WidgetBoundingBoxes-ac2KvzTu.js (new) 33.8 kB 🔴 +33.8 kB 🔴 +9.19 kB 🔴 +8.16 kB
assets/WidgetBoundingBoxes-BNl1Purq.js (removed) 33.8 kB 🟢 -33.8 kB 🟢 -9.19 kB 🟢 -8.16 kB
assets/WidgetPainter-B-8Ey0Mc.js (new) 32.7 kB 🔴 +32.7 kB 🔴 +7.9 kB 🔴 +7 kB
assets/WidgetPainter-DtcMuwWL.js (removed) 32.7 kB 🟢 -32.7 kB 🟢 -7.9 kB 🟢 -6.99 kB
assets/Load3dViewerContent-2a_OsHdb.js (removed) 30.8 kB 🟢 -30.8 kB 🟢 -6.29 kB 🟢 -5.46 kB
assets/Load3dViewerContent-DfVU7SfY.js (new) 30.8 kB 🔴 +30.8 kB 🔴 +6.3 kB 🔴 +5.47 kB
assets/SubscriptionPanelContentWorkspace-BtQAoanf.js (new) 25.9 kB 🔴 +25.9 kB 🔴 +6.04 kB 🔴 +5.32 kB
assets/SubscriptionPanelContentWorkspace-BvuBJFeG.js (removed) 25.9 kB 🟢 -25.9 kB 🟢 -6.04 kB 🟢 -5.32 kB
assets/SubscriptionRequiredDialogContentWorkspace-DQdZ_I_8.js (removed) 24.9 kB 🟢 -24.9 kB 🟢 -5.77 kB 🟢 -5.06 kB
assets/SubscriptionRequiredDialogContentWorkspace-EfEA0aNT.js (new) 24.9 kB 🔴 +24.9 kB 🔴 +5.76 kB 🔴 +5.07 kB
assets/SubscriptionRequiredDialogContent-6NoVdOvI.js (removed) 24.4 kB 🟢 -24.4 kB 🟢 -6 kB 🟢 -5.29 kB
assets/SubscriptionRequiredDialogContent-CMEWf3JR.js (new) 24.4 kB 🔴 +24.4 kB 🔴 +6 kB 🔴 +5.28 kB
assets/WidgetImageCrop-Cmfx0ZBK.js (removed) 23.3 kB 🟢 -23.3 kB 🟢 -5.75 kB 🟢 -5.04 kB
assets/WidgetImageCrop-CxOAA1k5.js (new) 23.3 kB 🔴 +23.3 kB 🔴 +5.75 kB 🔴 +5.04 kB
assets/load3d-Bu_xL6J5.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.44 kB 🟢 -4.7 kB
assets/load3d-CXRMF9M-.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.43 kB 🔴 +4.69 kB
assets/CurrentUserPopoverWorkspace-DZqy8F-t.js (new) 20.5 kB 🔴 +20.5 kB 🔴 +4.71 kB 🔴 +4.2 kB
assets/CurrentUserPopoverWorkspace-OSKufTTb.js (removed) 20.5 kB 🟢 -20.5 kB 🟢 -4.71 kB 🟢 -4.2 kB
assets/SignInContent-CWpDjfxV.js (removed) 20.3 kB 🟢 -20.3 kB 🟢 -5.13 kB 🟢 -4.48 kB
assets/SignInContent-D-ctfDux.js (new) 20.3 kB 🔴 +20.3 kB 🔴 +5.14 kB 🔴 +4.48 kB
assets/WidgetInputNumber-BKg2B2C2.js (new) 19.1 kB 🔴 +19.1 kB 🔴 +4.83 kB 🔴 +4.28 kB
assets/WidgetInputNumber-CrW9XNOW.js (removed) 19.1 kB 🟢 -19.1 kB 🟢 -4.83 kB 🟢 -4.3 kB
assets/CreditsTile-C6D9ZDWR.js (removed) 17.2 kB 🟢 -17.2 kB 🟢 -4.57 kB 🟢 -4.03 kB
assets/CreditsTile-DdWBnYPu.js (new) 17.2 kB 🔴 +17.2 kB 🔴 +4.57 kB 🔴 +4.02 kB
assets/WidgetRecordAudio-CKKyY3HF.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.63 kB 🟢 -4.13 kB
assets/WidgetRecordAudio-krRSh2Yf.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.63 kB 🔴 +4.13 kB
assets/WidgetRange-BjRfeKkq.js (removed) 16.4 kB 🟢 -16.4 kB 🟢 -4.24 kB 🟢 -3.8 kB
assets/WidgetRange-DPp7rcZG.js (new) 16.4 kB 🔴 +16.4 kB 🔴 +4.24 kB 🔴 +3.8 kB
assets/WaveAudioPlayer-DLYEbjsD.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.5 kB 🟢 -3.07 kB
assets/WaveAudioPlayer-VHNaOH9z.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.5 kB 🔴 +3.06 kB
assets/WidgetCurve-CC_mnyFG.js (removed) 11.3 kB 🟢 -11.3 kB 🟢 -3.51 kB 🟢 -3.16 kB
assets/WidgetCurve-DmTTgti3.js (new) 11.3 kB 🔴 +11.3 kB 🔴 +3.5 kB 🔴 +3.16 kB
assets/TeamWorkspacesDialogContent-BwDee6L4.js (new) 10.3 kB 🔴 +10.3 kB 🔴 +3 kB 🔴 +2.66 kB
assets/TeamWorkspacesDialogContent-CgnnXzgA.js (removed) 10.3 kB 🟢 -10.3 kB 🟢 -3 kB 🟢 -2.66 kB
assets/onboardingCloudRoutes-DULmGhXa.js (removed) 9.03 kB 🟢 -9.03 kB 🟢 -2.77 kB 🟢 -2.38 kB
assets/onboardingCloudRoutes-YgjqBFyD.js (new) 9.03 kB 🔴 +9.03 kB 🔴 +2.77 kB 🔴 +2.38 kB
assets/Load3DConfiguration-DB-3Sd-I.js (new) 8.97 kB 🔴 +8.97 kB 🔴 +2.63 kB 🔴 +2.33 kB
assets/Load3DConfiguration-Dh3TLrZO.js (removed) 8.97 kB 🟢 -8.97 kB 🟢 -2.63 kB 🟢 -2.33 kB
assets/SetMemberCreditLimitDialogContent-BMi48_MD.js (new) 8.54 kB 🔴 +8.54 kB 🔴 +2.37 kB 🔴 +2.08 kB
assets/SetMemberCreditLimitDialogContent-eH2r52BM.js (removed) 8.54 kB 🟢 -8.54 kB 🟢 -2.37 kB 🟢 -2.08 kB
assets/nodeTemplates-5yJtIU5B.js (new) 8.33 kB 🔴 +8.33 kB 🔴 +2.87 kB 🔴 +2.54 kB
assets/nodeTemplates-oplubD2b.js (removed) 8.33 kB 🟢 -8.33 kB 🟢 -2.87 kB 🟢 -2.54 kB
assets/NightlySurveyController-D8CU7SUZ.js (removed) 7.56 kB 🟢 -7.56 kB 🟢 -2.59 kB 🟢 -2.29 kB
assets/NightlySurveyController-DpICSmG4.js (new) 7.56 kB 🔴 +7.56 kB 🔴 +2.59 kB 🔴 +2.28 kB
assets/WidgetWithControl-Bd2oIPaY.js (new) 6.38 kB 🔴 +6.38 kB 🔴 +2.59 kB 🔴 +2.29 kB
assets/WidgetWithControl-BtAu9RJM.js (removed) 6.38 kB 🟢 -6.38 kB 🟢 -2.6 kB 🟢 -2.3 kB
assets/tierBenefits-DhGvm1s1.js (removed) 6.26 kB 🟢 -6.26 kB 🟢 -2 kB 🟢 -1.75 kB
assets/tierBenefits-ZCH0hdaK.js (new) 6.26 kB 🔴 +6.26 kB 🔴 +2 kB 🔴 +1.75 kB
assets/CancelSubscriptionDialogContent-Cbxcq2XL.js (new) 6.01 kB 🔴 +6.01 kB 🔴 +2.04 kB 🔴 +1.8 kB
assets/CancelSubscriptionDialogContent-CDPZtvY4.js (removed) 6.01 kB 🟢 -6.01 kB 🟢 -2.05 kB 🟢 -1.8 kB
assets/load3dPreviewExtensions-CTT083Uf.js (new) 5.94 kB 🔴 +5.94 kB 🔴 +1.84 kB 🔴 +1.63 kB
assets/load3dPreviewExtensions-DAgHp01S.js (removed) 5.94 kB 🟢 -5.94 kB 🟢 -1.85 kB 🟢 -1.62 kB
assets/FreeTierDialogContent-DOYZIz1W.js (new) 5.47 kB 🔴 +5.47 kB 🔴 +1.83 kB 🔴 +1.61 kB
assets/FreeTierDialogContent-DwKQ9e7j.js (removed) 5.47 kB 🟢 -5.47 kB 🟢 -1.83 kB 🟢 -1.61 kB
assets/CreateWorkspaceDialogContent-DA0uRCDs.js (removed) 5.19 kB 🟢 -5.19 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/CreateWorkspaceDialogContent-DDlkzIaz.js (new) 5.19 kB 🔴 +5.19 kB 🔴 +1.83 kB 🔴 +1.58 kB
assets/ChangeMemberRoleDialogContent-DkzIbISG.js (new) 5.04 kB 🔴 +5.04 kB 🔴 +1.67 kB 🔴 +1.46 kB
assets/ChangeMemberRoleDialogContent-yqdEWsMT.js (removed) 5.04 kB 🟢 -5.04 kB 🟢 -1.67 kB 🟢 -1.45 kB
assets/missingModelDownload-RpKjLpiw.js (removed) 5.03 kB 🟢 -5.03 kB 🟢 -1.95 kB 🟢 -1.7 kB
assets/missingModelDownload-x-cqRWiM.js (new) 5.03 kB 🔴 +5.03 kB 🔴 +1.95 kB 🔴 +1.7 kB
assets/EditWorkspaceDialogContent-C_1cYfgS.js (removed) 5 kB 🟢 -5 kB 🟢 -1.79 kB 🟢 -1.56 kB
assets/EditWorkspaceDialogContent-D4lrPqgs.js (new) 5 kB 🔴 +5 kB 🔴 +1.79 kB 🔴 +1.55 kB
assets/WidgetTextarea-BVWCEHYe.js (removed) 4.86 kB 🟢 -4.86 kB 🟢 -1.9 kB 🟢 -1.66 kB
assets/WidgetTextarea-IW6sHn_m.js (new) 4.86 kB 🔴 +4.86 kB 🔴 +1.9 kB 🔴 +1.65 kB
assets/saveMesh-DcfqOE0r.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.55 kB 🔴 +1.37 kB
assets/saveMesh-MQ-6h9hC.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.55 kB 🟢 -1.37 kB
assets/WorkspacePanelContent-Ci7p_Fly.js (new) 4.78 kB 🔴 +4.78 kB 🔴 +1.63 kB 🔴 +1.43 kB
assets/WorkspacePanelContent-CSsklcgF.js (removed) 4.78 kB 🟢 -4.78 kB 🟢 -1.63 kB 🟢 -1.43 kB
assets/InviteMemberDialogContent-Bm372nz9.js (removed) 4.75 kB 🟢 -4.75 kB 🟢 -1.61 kB 🟢 -1.4 kB
assets/InviteMemberDialogContent-BqIaLw3Q.js (new) 4.75 kB 🔴 +4.75 kB 🔴 +1.61 kB 🔴 +1.4 kB
assets/ValueControlPopover-13T90FHv.js (removed) 4.54 kB 🟢 -4.54 kB 🟢 -1.58 kB 🟢 -1.41 kB
assets/ValueControlPopover-BTm6S8-y.js (new) 4.54 kB 🔴 +4.54 kB 🔴 +1.58 kB 🔴 +1.41 kB
assets/DeleteWorkspaceDialogContent-Cjt30udS.js (removed) 3.91 kB 🟢 -3.91 kB 🟢 -1.47 kB 🟢 -1.26 kB
assets/DeleteWorkspaceDialogContent-dgq92ukt.js (new) 3.91 kB 🔴 +3.91 kB 🔴 +1.47 kB 🔴 +1.26 kB
assets/LeaveWorkspaceDialogContent-CmJXJ3zv.js (removed) 3.73 kB 🟢 -3.73 kB 🟢 -1.42 kB 🟢 -1.21 kB
assets/LeaveWorkspaceDialogContent-Cq-1jTP_.js (new) 3.73 kB 🔴 +3.73 kB 🔴 +1.42 kB 🔴 +1.22 kB
assets/RemoveMemberDialogContent-CU4JoIYV.js (removed) 3.71 kB 🟢 -3.71 kB 🟢 -1.37 kB 🟢 -1.18 kB
assets/RemoveMemberDialogContent-DFZ60Zpp.js (new) 3.71 kB 🔴 +3.71 kB 🔴 +1.37 kB 🔴 +1.18 kB
assets/RevokeInviteDialogContent-CaI3kyby.js (new) 3.62 kB 🔴 +3.62 kB 🔴 +1.38 kB 🔴 +1.2 kB
assets/RevokeInviteDialogContent-D5x_9rKJ.js (removed) 3.62 kB 🟢 -3.62 kB 🟢 -1.38 kB 🟢 -1.2 kB
assets/InviteMemberUpsellDialogContent-C7NlLrNY.js (new) 3.51 kB 🔴 +3.51 kB 🔴 +1.26 kB 🔴 +1.1 kB
assets/InviteMemberUpsellDialogContent-Dqs1ek1g.js (removed) 3.51 kB 🟢 -3.51 kB 🟢 -1.26 kB 🟢 -1.09 kB
assets/workspaceCheckoutTelemetry-D4e2atXY.js (new) 3.46 kB 🔴 +3.46 kB 🔴 +1.55 kB 🔴 +1.35 kB
assets/workspaceCheckoutTelemetry-e3HUNTHF.js (removed) 3.46 kB 🟢 -3.46 kB 🟢 -1.56 kB 🟢 -1.35 kB
assets/Media3DTop-B7qMsX7r.js (new) 3.26 kB 🔴 +3.26 kB 🔴 +1.3 kB 🔴 +1.13 kB
assets/Media3DTop-l2wqBC-f.js (removed) 3.26 kB 🟢 -3.26 kB 🟢 -1.29 kB 🟢 -1.13 kB
assets/GlobalToast-Bd_dfjwQ.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.25 kB 🟢 -1.07 kB
assets/GlobalToast-s-Gik2lK.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.25 kB 🔴 +1.11 kB
assets/load3dAdvanced-CArzFqoV.js (new) 2.87 kB 🔴 +2.87 kB 🔴 +1.12 kB 🔴 +975 B
assets/load3dAdvanced-DaZf48q6.js (removed) 2.87 kB 🟢 -2.87 kB 🟢 -1.13 kB 🟢 -980 B
assets/SubscribeToRun-3vmrHxjt.js (removed) 2.45 kB 🟢 -2.45 kB 🟢 -1.06 kB 🟢 -924 B
assets/SubscribeToRun-DPj7Znia.js (new) 2.45 kB 🔴 +2.45 kB 🔴 +1.06 kB 🔴 +927 B
assets/MediaAudioTop-Bva5LdxJ.js (new) 1.67 kB 🔴 +1.67 kB 🔴 +839 B 🔴 +694 B
assets/MediaAudioTop-RjZXjYBW.js (removed) 1.67 kB 🟢 -1.67 kB 🟢 -839 B 🟢 -697 B
assets/CloudRunButtonWrapper-C11LaCaP.js (removed) 1.11 kB 🟢 -1.11 kB 🟢 -545 B 🟢 -482 B
assets/CloudRunButtonWrapper-hT_Z0Zzy.js (new) 1.11 kB 🔴 +1.11 kB 🔴 +543 B 🔴 +479 B
assets/cloudSessionCookie-b6o3qp5K.js (new) 989 B 🔴 +989 B 🔴 +465 B 🔴 +412 B
assets/cloudSessionCookie-Cw_hdGO1.js (removed) 989 B 🟢 -989 B 🟢 -465 B 🟢 -429 B
assets/cloudBadges-8BvbOlN0.js (removed) 971 B 🟢 -971 B 🟢 -544 B 🟢 -457 B
assets/cloudBadges-srx-MabI.js (new) 971 B 🔴 +971 B 🔴 +544 B 🔴 +459 B
assets/Load3DAdvanced-B5IYANd-.js (new) 813 B 🔴 +813 B 🔴 +452 B 🔴 +383 B
assets/Load3DAdvanced-CSEzsI5I.js (removed) 813 B 🟢 -813 B 🟢 -454 B 🟢 -408 B
assets/nightlyBadges-DyjioBFl.js (new) 462 B 🔴 +462 B 🔴 +301 B 🔴 +250 B
assets/nightlyBadges-NMNeYCZy.js (removed) 462 B 🟢 -462 B 🟢 -302 B 🟢 -290 B
assets/missingModelDownload-hudqCwfW.js (removed) 228 B 🟢 -228 B 🟢 -149 B 🟢 -130 B
assets/missingModelDownload-jvLKGxZ4.js (new) 228 B 🔴 +228 B 🔴 +149 B 🔴 +127 B
assets/SubscriptionPanelContentWorkspace-C2uB2QKa.js (new) 179 B 🔴 +179 B 🔴 +117 B 🔴 +92 B
assets/SubscriptionPanelContentWorkspace-Cq8mJVtB.js (removed) 179 B 🟢 -179 B 🟢 -117 B 🟢 -92 B
assets/Load3dViewerContent-BRLogQ8R.js (removed) 137 B 🟢 -137 B 🟢 -103 B 🟢 -108 B
assets/Load3dViewerContent-BwwB9_UU.js (new) 137 B 🔴 +137 B 🔴 +103 B 🔴 +92 B
assets/Load3DAdvanced-CUtNVHxh.js (removed) 122 B 🟢 -122 B 🟢 -97 B 🟢 -88 B
assets/Load3DAdvanced-YCCi4yX5.js (new) 122 B 🔴 +122 B 🔴 +97 B 🔴 +88 B
assets/WidgetLegacy-9y-mWKmZ.js (new) 117 B 🔴 +117 B 🔴 +106 B 🔴 +97 B
assets/WidgetLegacy-ByHSbtTU.js (removed) 117 B 🟢 -117 B 🟢 -106 B 🟢 -105 B
assets/workflowDraftStoreV2-cVq0BfJm.js (removed) 112 B 🟢 -112 B 🟢 -101 B 🟢 -110 B
assets/workflowDraftStoreV2-DOGYdJqe.js (new) 112 B 🔴 +112 B 🔴 +101 B 🔴 +110 B
assets/Load3D-C86v-xH7.js (removed) 98 B 🟢 -98 B 🟢 -89 B 🟢 -82 B
assets/Load3D-QGEDNV0H.js (new) 98 B 🔴 +98 B 🔴 +89 B 🔴 +80 B
assets/changeTracker-CNlbjJxN.js (new) 91 B 🔴 +91 B 🔴 +93 B 🔴 +82 B
assets/changeTracker-UQ7xeIes.js (removed) 91 B 🟢 -91 B 🟢 -93 B 🟢 -84 B

Status: 69 added / 69 removed / 208 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.8 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 49.5 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 71.7 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.1 MB heap
large-graph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.3 MB heap
large-graph-pan: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.5 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.6 MB heap
minimap-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.4 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.6 MB heap
subgraph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.3 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 52.0 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 124ms TBT · 94.8 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.0 MB heap
vue-large-graph-idle: · 56.2 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 166.0 MB heap
vue-large-graph-pan: · 54.6 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 748ms TBT · 153.9 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 48.4 MB heap

⚠️ 11 regressions detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-idle: task duration 499ms 550ms +10% ⚠️ z=5.0
canvas-mouse-sweep: layout duration 3ms 4ms +24% ⚠️ z=2.8
canvas-mouse-sweep: style recalc duration 40ms 50ms +26% ⚠️ z=2.5
canvas-mouse-sweep: task duration 926ms 1027ms +11% ⚠️ z=2.8
canvas-zoom-sweep: task duration 404ms 400ms -1% ⚠️ z=3.2
dom-widget-clipping: task duration 358ms 415ms +16% ⚠️ z=3.1
large-graph-idle: task duration 677ms 705ms +4% ⚠️ z=3.0
large-graph-pan: task duration 1251ms 1389ms +11% ⚠️ z=7.1
minimap-idle: task duration 714ms 640ms -10% ⚠️ z=2.4
subgraph-dom-widget-clipping: task duration 431ms 430ms -0% ⚠️ z=2.8
subgraph-idle: task duration 462ms 523ms +13% ⚠️ z=4.9
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms -0% z=-0.9
canvas-idle: p95 frame time 17ms 17ms +0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 9ms 9ms +1% z=-2.1
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 9 10 +6% z=-2.9
canvas-idle: task duration 499ms 550ms +10% ⚠️ z=5.0
canvas-idle: script duration 19ms 23ms +21% z=-0.9
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 68.0 MB 67.8 MB -0%
canvas-idle: DOM nodes 18 19 +6% z=-2.8
canvas-idle: event listeners 4 4 +0% z=-1.6
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 +24% ⚠️ z=2.8
canvas-mouse-sweep: style recalc duration 40ms 50ms +26% ⚠️ z=2.5
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 77 80 +4% z=0.6
canvas-mouse-sweep: task duration 926ms 1027ms +11% ⚠️ z=2.8
canvas-mouse-sweep: script duration 122ms 137ms +12% z=0.3
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 50.7 MB 49.5 MB -2%
canvas-mouse-sweep: DOM nodes -273 -272 -1% z=-129.1
canvas-mouse-sweep: event listeners -146 -148 +1% z=-37.5
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=-0.3
canvas-zoom-sweep: p95 frame time 17ms 17ms -0%
canvas-zoom-sweep: layout duration 1ms 1ms +2% z=0.5
canvas-zoom-sweep: style recalc duration 19ms 19ms -1% z=-0.3
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 32 32 -2% z=0.5
canvas-zoom-sweep: task duration 404ms 400ms -1% ⚠️ z=3.2
canvas-zoom-sweep: script duration 22ms 22ms -1% z=-1.6
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 71.6 MB 71.7 MB +0%
canvas-zoom-sweep: DOM nodes 77 78 +1% z=-1.6
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms -0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 8ms 9ms +19% z=-0.8
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 11 12 +9% z=-2.2
dom-widget-clipping: task duration 358ms 415ms +16% ⚠️ z=3.1
dom-widget-clipping: script duration 57ms 60ms +5% z=-2.5
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 53.3 MB 53.1 MB -0%
dom-widget-clipping: DOM nodes 18 20 +11% z=-1.5
dom-widget-clipping: event listeners 0 2 variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=0.2
large-graph-idle: p95 frame time 17ms 17ms -0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 8ms 7ms -12% z=-4.9
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 8 8 -6% z=-13.1
large-graph-idle: task duration 677ms 705ms +4% ⚠️ z=3.0
large-graph-idle: script duration 106ms 105ms -1% z=0.3
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 61.9 MB 62.3 MB +1%
large-graph-idle: DOM nodes -277 -276 -0% z=-332.7
large-graph-idle: event listeners -144 -144 +0% z=-27.9
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.2
large-graph-pan: p95 frame time 17ms 17ms +1%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 14ms 17ms +15% z=-0.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 1251ms 1389ms +11% ⚠️ z=7.1
large-graph-pan: script duration 427ms 444ms +4% z=1.8
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 62.4 MB 60.5 MB -3%
large-graph-pan: DOM nodes -278 -279 +0% z=-180.3
large-graph-pan: event listeners -144 -143 -1% z=-178.6
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms +1%
large-graph-zoom: layout duration 7ms 9ms +24%
large-graph-zoom: style recalc duration 16ms 16ms +2%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 65 64 -2%
large-graph-zoom: task duration 1477ms 1670ms +13%
large-graph-zoom: script duration 529ms 578ms +9%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 70.1 MB 63.6 MB -9%
large-graph-zoom: DOM nodes -280 -283 +1%
large-graph-zoom: event listeners -148 -148 +0%
minimap-idle: avg frame time 17ms 17ms -0% z=-0.9
minimap-idle: p95 frame time 17ms 17ms +0%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 6ms 8ms +33% z=-1.7
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 7 9 +21% z=-1.6
minimap-idle: task duration 714ms 640ms -10% ⚠️ z=2.4
minimap-idle: script duration 114ms 105ms -8% z=0.7
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 64.0 MB 63.4 MB -1%
minimap-idle: DOM nodes -279 -276 -1% z=-215.4
minimap-idle: event listeners -144 -144 +0% z=-225.0
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
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 11ms 12ms +13% z=-0.7
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 47 48 +1% z=-0.8
subgraph-dom-widget-clipping: task duration 431ms 430ms -0% ⚠️ z=2.8
subgraph-dom-widget-clipping: script duration 129ms 128ms -1% z=-0.1
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 53.7 MB 53.6 MB -0%
subgraph-dom-widget-clipping: DOM nodes 20 21 +5% z=-1.1
subgraph-dom-widget-clipping: event listeners 8 8 +0% z=-1.4
subgraph-idle: avg frame time 17ms 17ms -0% z=-0.2
subgraph-idle: p95 frame time 17ms 17ms +1%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 8ms 8ms -2% z=-2.9
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 10 9 -15% z=-3.7
subgraph-idle: task duration 462ms 523ms +13% ⚠️ z=4.9
subgraph-idle: script duration 13ms 20ms +49% z=-0.1
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 68.1 MB 68.3 MB +0%
subgraph-idle: DOM nodes 20 17 -15% z=-3.2
subgraph-idle: event listeners 4 4 +0% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=-0.1
subgraph-mouse-sweep: p95 frame time 17ms 17ms +0%
subgraph-mouse-sweep: layout duration 4ms 5ms +12% z=1.0
subgraph-mouse-sweep: style recalc duration 38ms 42ms +11% z=-0.0
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 76 77 +1% z=-1.9
subgraph-mouse-sweep: task duration 827ms 847ms +2% z=1.2
subgraph-mouse-sweep: script duration 92ms 101ms +9% z=-0.0
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 46.2 MB 52.0 MB +12%
subgraph-mouse-sweep: DOM nodes -273 -106 -61% z=-77.4
subgraph-mouse-sweep: event listeners -148 -72 -51% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms +0%
subgraph-transition-enter: p95 frame time 17ms 17ms -1%
subgraph-transition-enter: layout duration 12ms 12ms -4%
subgraph-transition-enter: style recalc duration 30ms 31ms +2%
subgraph-transition-enter: layout count 13 14 +8%
subgraph-transition-enter: style recalc count 17 18 +6%
subgraph-transition-enter: task duration 960ms 1018ms +6%
subgraph-transition-enter: script duration 34ms 39ms +16%
subgraph-transition-enter: TBT 128ms 124ms -3%
subgraph-transition-enter: heap used 95.7 MB 94.8 MB -1%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2371 2371 +0%
viewport-pan-sweep: avg frame time 17ms 17ms +0%
viewport-pan-sweep: p95 frame time 17ms 17ms +0%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 39ms 44ms +13%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 250 -0%
viewport-pan-sweep: task duration 4861ms 4611ms -5%
viewport-pan-sweep: script duration 1476ms 1396ms -5%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 66.1 MB 62.0 MB -6%
viewport-pan-sweep: DOM nodes -275 -278 +1%
viewport-pan-sweep: event listeners -126 -128 +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 17275ms 18474ms +7%
vue-large-graph-idle: script duration 523ms 597ms +14%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 159.8 MB 166.0 MB +4%
vue-large-graph-idle: DOM nodes -8312 -8312 +0%
vue-large-graph-idle: event listeners -16385 -16387 +0%
vue-large-graph-pan: avg frame time 18ms 18ms +3%
vue-large-graph-pan: p95 frame time 17ms 17ms +0%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 16ms 28ms +72%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 140 175 +25%
vue-large-graph-pan: task duration 20479ms 23283ms +14%
vue-large-graph-pan: script duration 840ms 972ms +16%
vue-large-graph-pan: TBT 211ms 748ms +255%
vue-large-graph-pan: heap used 168.4 MB 153.9 MB -9%
vue-large-graph-pan: DOM nodes -8312 -8312 +0%
vue-large-graph-pan: event listeners -16385 -16380 -0%
workflow-execution: avg frame time 17ms 17ms +0% z=0.6
workflow-execution: p95 frame time 17ms 17ms -0%
workflow-execution: layout duration 0ms 1ms +73% z=-5.7
workflow-execution: style recalc duration 19ms 20ms +2% z=-2.0
workflow-execution: layout count 2 3 +50% z=-3.6
workflow-execution: style recalc count 13 13 -4% z=-2.6
workflow-execution: task duration 108ms 119ms +9% z=-0.4
workflow-execution: script duration 9ms 11ms +21% z=-6.3
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 48.6 MB 48.4 MB -0%
workflow-execution: DOM nodes 119 124 +4% z=-5.2
workflow-execution: event listeners 65 66 +2% z=3.2
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-07-28T09:04:30.665Z",
  "gitSha": "63ade8038324b868ed4688f8d3c3a188e0f973eb",
  "branch": "synap5e/test/assets-sidebar-e2e",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2121.4089999999715,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.033000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 586.517,
      "heapDeltaBytes": 3518284,
      "heapUsedBytes": 70749100,
      "domNodes": 20,
      "jsHeapTotalBytes": 20844544,
      "scriptDurationMs": 24.462000000000003,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2037.8670000000056,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.866000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 513.626,
      "heapDeltaBytes": 3459288,
      "heapUsedBytes": 71422916,
      "domNodes": 18,
      "jsHeapTotalBytes": 20844544,
      "scriptDurationMs": 22.203,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2107.797000000005,
      "styleRecalcs": 82,
      "styleRecalcDurationMs": 55.42700000000001,
      "layouts": 12,
      "layoutDurationMs": 4.382000000000001,
      "taskDurationMs": 1084.703,
      "heapDeltaBytes": -16463652,
      "heapUsedBytes": 51487704,
      "domNodes": -271,
      "jsHeapTotalBytes": 21233664,
      "scriptDurationMs": 145.15200000000002,
      "eventListeners": -148,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1942.7239999999983,
      "styleRecalcs": 78,
      "styleRecalcDurationMs": 45.458,
      "layouts": 12,
      "layoutDurationMs": 3.934,
      "taskDurationMs": 969.249,
      "heapDeltaBytes": -15640904,
      "heapUsedBytes": 52315732,
      "domNodes": -272,
      "jsHeapTotalBytes": 20185088,
      "scriptDurationMs": 129.502,
      "eventListeners": -148,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1754.173000000037,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 18.174000000000003,
      "layouts": 6,
      "layoutDurationMs": 0.644,
      "taskDurationMs": 390.388,
      "heapDeltaBytes": 7337264,
      "heapUsedBytes": 75185396,
      "domNodes": 79,
      "jsHeapTotalBytes": 19795968,
      "scriptDurationMs": 20.727999999999998,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1754.0780000000495,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 19.139,
      "layouts": 6,
      "layoutDurationMs": 0.685,
      "taskDurationMs": 408.971,
      "heapDeltaBytes": 7204976,
      "heapUsedBytes": 75125524,
      "domNodes": 77,
      "jsHeapTotalBytes": 20582400,
      "scriptDurationMs": 23.807,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 628.8499999999999,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.266999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 406.065,
      "heapDeltaBytes": -12003740,
      "heapUsedBytes": 55825552,
      "domNodes": 18,
      "jsHeapTotalBytes": 21106688,
      "scriptDurationMs": 59.24199999999999,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 646.9859999999699,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 10.16,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 423.793,
      "heapDeltaBytes": -12605332,
      "heapUsedBytes": 55522992,
      "domNodes": 22,
      "jsHeapTotalBytes": 21630976,
      "scriptDurationMs": 59.952999999999996,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2028.4010000000308,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 6.109999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 662.8810000000001,
      "heapDeltaBytes": 6646256,
      "heapUsedBytes": 66013872,
      "domNodes": -276,
      "jsHeapTotalBytes": 4263936,
      "scriptDurationMs": 93.389,
      "eventListeners": -144,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2023.5440000000153,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.156,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 747.215,
      "heapDeltaBytes": 5734568,
      "heapUsedBytes": 64547216,
      "domNodes": -276,
      "jsHeapTotalBytes": 4526080,
      "scriptDurationMs": 117.49000000000001,
      "eventListeners": -144,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2168.290000000013,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 15.621999999999996,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1335.3139999999999,
      "heapDeltaBytes": 5034332,
      "heapUsedBytes": 65396216,
      "domNodes": -278,
      "jsHeapTotalBytes": 5517312,
      "scriptDurationMs": 434.267,
      "eventListeners": -142,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2251.0019999999713,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 17.531,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1443.362,
      "heapDeltaBytes": 1551296,
      "heapUsedBytes": 61423188,
      "domNodes": -279,
      "jsHeapTotalBytes": 4993024,
      "scriptDurationMs": 454.175,
      "eventListeners": -144,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3259.883000000002,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 15.735000000000003,
      "layouts": 60,
      "layoutDurationMs": 8.683,
      "taskDurationMs": 1607.5140000000001,
      "heapDeltaBytes": 1280688,
      "heapUsedBytes": 63228836,
      "domNodes": -282,
      "jsHeapTotalBytes": 7671808,
      "scriptDurationMs": 556.636,
      "eventListeners": -148,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3411.330000000021,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 16.677000000000003,
      "layouts": 60,
      "layoutDurationMs": 9.199,
      "taskDurationMs": 1731.853,
      "heapDeltaBytes": 8777580,
      "heapUsedBytes": 70201100,
      "domNodes": -283,
      "jsHeapTotalBytes": 7147520,
      "scriptDurationMs": 599.4300000000001,
      "eventListeners": -148,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2023.253000000011,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.240999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 548.43,
      "heapDeltaBytes": 6222072,
      "heapUsedBytes": 66535736,
      "domNodes": -275,
      "jsHeapTotalBytes": 5050368,
      "scriptDurationMs": 95.56800000000001,
      "eventListeners": -144,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2018.2179999999335,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.005000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 731.905,
      "heapDeltaBytes": 5982868,
      "heapUsedBytes": 66449492,
      "domNodes": -276,
      "jsHeapTotalBytes": 5050368,
      "scriptDurationMs": 115.262,
      "eventListeners": -144,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 611.8710000000078,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 11.526000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 418.43500000000006,
      "heapDeltaBytes": -11473124,
      "heapUsedBytes": 56481884,
      "domNodes": 20,
      "jsHeapTotalBytes": 21630976,
      "scriptDurationMs": 126.26599999999999,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 647.4420000000691,
      "styleRecalcs": 48,
      "styleRecalcDurationMs": 12.496,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 441.22299999999996,
      "heapDeltaBytes": -12241680,
      "heapUsedBytes": 55948536,
      "domNodes": 22,
      "jsHeapTotalBytes": 22417408,
      "scriptDurationMs": 129.267,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2007.2789999999827,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.283999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 512.5649999999999,
      "heapDeltaBytes": 3410828,
      "heapUsedBytes": 71455932,
      "domNodes": 16,
      "jsHeapTotalBytes": 21106688,
      "scriptDurationMs": 18.79,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2019.9210000000676,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.943999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 532.645,
      "heapDeltaBytes": 3474200,
      "heapUsedBytes": 71727028,
      "domNodes": 18,
      "jsHeapTotalBytes": 20582400,
      "scriptDurationMs": 21.010000000000005,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1677.3220000000038,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 38.171,
      "layouts": 16,
      "layoutDurationMs": 4.792,
      "taskDurationMs": 779.384,
      "heapDeltaBytes": -5715300,
      "heapUsedBytes": 62261448,
      "domNodes": 63,
      "jsHeapTotalBytes": 20582400,
      "scriptDurationMs": 95.158,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1806.6430000000082,
      "styleRecalcs": 78,
      "styleRecalcDurationMs": 46.650999999999996,
      "layouts": 16,
      "layoutDurationMs": 5.24,
      "taskDurationMs": 913.9900000000001,
      "heapDeltaBytes": -21251344,
      "heapUsedBytes": 46700140,
      "domNodes": -275,
      "jsHeapTotalBytes": 20447232,
      "scriptDurationMs": 106.229,
      "eventListeners": -148,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1403.8140000000112,
      "styleRecalcs": 18,
      "styleRecalcDurationMs": 30.805,
      "layouts": 14,
      "layoutDurationMs": 11.763,
      "taskDurationMs": 1018.2270000000002,
      "heapDeltaBytes": 31427300,
      "heapUsedBytes": 99426244,
      "domNodes": 13673,
      "jsHeapTotalBytes": 13107200,
      "scriptDurationMs": 39.287,
      "eventListeners": 2371,
      "totalBlockingTimeMs": 124,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8176.490000000002,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 42.203,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4438.506,
      "heapDeltaBytes": 9905860,
      "heapUsedBytes": 69317572,
      "domNodes": -277,
      "jsHeapTotalBytes": 7090176,
      "scriptDurationMs": 1340.994,
      "eventListeners": -128,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8373.616999999967,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 45.35499999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4784.123,
      "heapDeltaBytes": 1778172,
      "heapUsedBytes": 60622772,
      "domNodes": -278,
      "jsHeapTotalBytes": 6623232,
      "scriptDurationMs": 1451.461,
      "eventListeners": -128,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 18421.437999999966,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 18403.058,
      "heapDeltaBytes": -30556024,
      "heapUsedBytes": 177831612,
      "domNodes": -8312,
      "jsHeapTotalBytes": -11472896,
      "scriptDurationMs": 581.032,
      "eventListeners": -16385,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 18572.875999999953,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 18545.383,
      "heapDeltaBytes": -32596440,
      "heapUsedBytes": 170383640,
      "domNodes": -8312,
      "jsHeapTotalBytes": -11210752,
      "scriptDurationMs": 612.621,
      "eventListeners": -16389,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 23120.734000000026,
      "styleRecalcs": 171,
      "styleRecalcDurationMs": 25.89199999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 23073.000999999997,
      "heapDeltaBytes": -72377756,
      "heapUsedBytes": 155920000,
      "domNodes": -8312,
      "jsHeapTotalBytes": -15929344,
      "scriptDurationMs": 930.9749999999999,
      "eventListeners": -16379,
      "totalBlockingTimeMs": 542,
      "frameDurationMs": 18.886666666666617,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 23544.035000000007,
      "styleRecalcs": 178,
      "styleRecalcDurationMs": 29.463000000000015,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 23493.977000000003,
      "heapDeltaBytes": -50410412,
      "heapUsedBytes": 166876880,
      "domNodes": -8312,
      "jsHeapTotalBytes": -15142912,
      "scriptDurationMs": 1013.8009999999999,
      "eventListeners": -16381,
      "totalBlockingTimeMs": 954,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 466.72799999998915,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 21.552000000000003,
      "layouts": 3,
      "layoutDurationMs": 0.8409999999999997,
      "taskDurationMs": 126.23200000000001,
      "heapDeltaBytes": -16002404,
      "heapUsedBytes": 50979488,
      "domNodes": 130,
      "jsHeapTotalBytes": 7737344,
      "scriptDurationMs": 11.256,
      "eventListeners": 67,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 460.7099999999491,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 17.968,
      "layouts": 3,
      "layoutDurationMs": 0.596,
      "taskDurationMs": 110.79400000000001,
      "heapDeltaBytes": -16316224,
      "heapUsedBytes": 50559892,
      "domNodes": 117,
      "jsHeapTotalBytes": 7737344,
      "scriptDurationMs": 9.831,
      "eventListeners": 65,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    }
  ]
}

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 07/28/2026, 08:53:50 AM UTC

Links

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 10, 2026
@synap5e
synap5e marked this pull request as draft July 10, 2026 11:25
@synap5e

synap5e commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@synap5e
synap5e marked this pull request as ready for review July 10, 2026 11:28

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Cursor Review — Consolidated panel

Triggered by @synap5e.

Found 1 finding(s).

Severity Count
🟢 Low 1

Panel: 6/8 reviewers contributed findings.

Reviewers that did not contribute: kimi-k2.5:adversarial (empty), kimi-k2.5:edge-case (empty)

Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts`:
- Around line 103-118: Update the “Refresh seeds a backend rescan” test to
validate the POST mutation’s request body in addition to its method and
endpoint. Use AssetHelper’s recorded mutation.body to assert the seed request
contains the exact payload { roots: ['models'] }, ensuring the correct root and
payload shape are sent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7241ae27-81c7-4ce4-abfa-964ae8b03671

📥 Commits

Reviewing files that changed from the base of the PR and between e6916bb and 1b44590.

📒 Files selected for processing (8)
  • browser_tests/fixtures/components/SidebarTab.ts
  • browser_tests/fixtures/data/assetFixtures.ts
  • browser_tests/fixtures/helpers/AssetHelper.ts
  • browser_tests/fixtures/helpers/FeatureFlagHelper.ts
  • browser_tests/fixtures/utils/dispatchApiEvent.ts
  • browser_tests/tests/graph.spec.ts
  • browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
  • browser_tests/tests/sidebar/modelLibraryRouting.spec.ts

Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##             main   #13574      +/-   ##
==========================================
+ Coverage   79.44%   79.47%   +0.02%     
==========================================
  Files        1743     1744       +1     
  Lines       96915    97108     +193     
  Branches    32208    30916    -1292     
==========================================
+ Hits        76997    77172     +175     
- Misses      19556    19566      +10     
- Partials      362      370       +8     
Flag Coverage Δ
unit 68.78% <100.00%> (+0.01%) ⬆️

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

Files with missing lines Coverage Δ
...components/sidebar/tabs/ModelLibrarySidebarTab.vue 93.33% <100.00%> (-0.48%) ⬇️
src/platform/assets/constants/assetEvents.ts 100.00% <100.00%> (ø)
src/platform/assets/services/assetService.ts 82.44% <100.00%> (+0.43%) ⬆️

... and 53 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.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 10, 2026
@synap5e synap5e assigned christian-byrne and unassigned synap5e Jul 10, 2026

@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.

LGTM

@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.

Automated multi-agent review of this PR's delta against its parent branch (concurrent reviewers; B-group tooling and dependency scans skipped since the review checkout has no installed deps). No blocking issues. Findings below, most inline. The route-pattern narrowing (/assets to /api/assets) was verified to regress no existing spec and to fix a latent JS-chunk-intercept bug.

Comment thread browser_tests/fixtures/helpers/FeatureFlagHelper.ts
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated
Comment thread browser_tests/tests/sidebar/modelLibraryRouting.spec.ts
Comment thread browser_tests/tests/sidebar/modelLibraryRouting.spec.ts Outdated
Comment thread browser_tests/fixtures/data/assetFixtures.ts Outdated
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
@christian-byrne

Copy link
Copy Markdown
Contributor

Round 2 review — e2e test completeness

Three findings covering test robustness angles not addressed in round 1:

1. Remaining toBeHidden() calls on v-if elements (nitpick, non-blocking)

browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts:132 — the prior-round fix swapped toBeHidden()toHaveCount(0) in the routing spec, but this file still has three toBeHidden() calls (lines 76, 102, 132). For README and loadAllFoldersButton the vacuous pass is harmless since paired positive assertions guard the test. Line 132 is different: it's the "before" guard in the live-update test — if freshly_scanned were already present in the tree before the event fires, toBeHidden() would still pass (the locator returns no match), and the subsequent toBeVisible() would also pass, leaving the live-update path untested. toHaveCount(0) would catch that case.


2. No unhappy-path test for API error (suggestion, non-blocking)

browser_tests/tests/sidebar/modelLibraryAssetMode.spec.tsAssetHelper.mockError() exists but none of the new specs call it. The sidebar's behavior when /api/assets returns a 500 (error banner, empty tree, retry availability) is completely untested. Even a single test calling assetApi.mockError(500) before comfyPage.setup() and asserting the tree doesn't crash or hang would close the gap.


3. Tree node selectors rely on PrimeVue internal class names (nitpick, non-blocking)

browser_tests/fixtures/components/SidebarTab.tsgetFolderRowByLabel (new in this PR) and the existing getLeafByLabel both match via PrimeVue CSS class names (.p-tree-node-leaf, .p-tree-node:not(.p-tree-node-leaf)). PrimeVue renamed these in v4 → v5; a future upgrade would silently break every locator that uses them. Backing them with data-testid on the tree node elements (analogous to how NodeLibrarySidebarTab uses [data-testid="node-tree-leaf"]) would make them upgrade-proof.

@synap5e

synap5e commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Re the round-2 items:

  1. Remaining toBeHidden() calls: fixed in 0247704. All three are toHaveCount(0) now, including the line-132 before-guard in the live-update test that could previously pass vacuously.
  2. Unhappy-path test: fixed in f96f26d. A new test 500s the eager /api/assets walk via the previously-unused assetApi.mockError and asserts the panel degrades gracefully instead of hanging (refresh available and enabled, search editable, folder list rendered, zero leaves, expand does not crash). Executed against the served-dist stack.
  3. data-testid selectors: agreed in principle, but backing the locators means adding the attributes to the tree components in src, which belongs in the parent PR rather than this test-only one. Your call on if we follow this up further.

Posted by Claude Code on Simon's behalf.

@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.

Thanks for building this out — this is a real improvement over zero e2e coverage on the assets-mode sidebar, and the fixture/helper layer (AssetHelper, assetFixtures, dispatchApiEvent) is reusable well beyond these two specs. The registration-order test and the seed-flow test in particular cover things that were previously only reachable by hand.

Most of what follows is non-blocking. One item is blocking-ish (the flag/WS race, inline on FeatureFlagHelper), and one is a product bug the suite surfaced by omission rather than a problem with the suite itself. I'm leaving this as a comment, not un-approving.


AC3 isn't just untested — the sidebar code violates it

FE-1076's third acceptance criterion:

under flag-on, an asset with no model_type: tag falls back to legacy bare grouping; uncovered assets are handled, not a TODO.

The sidebar path does the opposite of that. src/platform/assets/services/assetService.ts:224 modelFolderFromTag(tag, modelTypeMode) returns undefined for any non-namespaced tag once modelTypeMode is true:

if (modelTypeMode) {
  return tag.startsWith(MODEL_TYPE_TAG_PREFIX)
    ? tag.slice(MODEL_TYPE_TAG_PREFIX.length)
    : undefined
}

buildModelBuckets (assetService.ts:407) then hits the folders.length === 0 branch at assetService.ts:417 and drops the asset with a console.warn. So on a model_type:-capable backend, a user with a legacy bare-tagged model loses it from the sidebar entirely — not "falls back to legacy bare grouping".

The browser path does implement the fallback. src/platform/assets/utils/assetMetadataUtils.ts:279 getAssetCategories returns getBareTagCategories(asset) (filtered for namespace residue) when there are no model_type: values:

if (modelTypeMode) {
  const modelTypes = getModelTypeTagValues(asset)
  if (modelTypes.length > 0) return modelTypes
  return getBareTagCategories(asset).filter(
    (category) => !category.startsWith(MODEL_TYPE_TAG_PREFIX)
  )
}

Two surfaces, two semantics, one flag.

Nothing currently catches it:

  • src/platform/assets/services/assetService.test.ts:483 — the only bare-tag test — flips the flag off (mockSupportsModelTypeTags.value = false), so it exercises the legacy path, not the fallback.
  • assetService.test.ts:500 "drops uncategorized model assets with a warning" uses tags: ['models'] with no bare tag at all, so it asserts the correct behaviour for a genuinely uncovered asset and says nothing about a bare-tagged one.

The missing case is one line: mockSupportsModelTypeTags.value = true with tags: ['models', 'checkpoints'], which currently returns [].

Not asking you to fix the service in a test-only PR — flagging it because it's the AC the e2e suite was meant to cover, and it turns out the code can't satisfy it yet. Happy to take the service fix separately if you'd rather keep this PR scoped to tests.


What the mocks currently hide

(non-blocking — posting top-level because browser_tests/fixtures/helpers/AssetHelper.ts:227-241 is outside this PR's diff hunks, so it won't take an inline anchor.)

Worth writing this down so nobody reads green here as "the asset path is covered".

Cursor pagination is not exercised at all, and the mock's pagination branch is dead code against the real caller. AssetHelper.handleListAssets (browser_tests/fixtures/helpers/AssetHelper.ts:227) slices by offset:

const offset = parseInt(url.searchParams.get('offset') ?? '0', 10)
filtered = filtered.slice(offset, offset + limit)

but getAllAssetsByTag in src/platform/assets/services/assetService.ts never sends offset — it sends limit + after:

const data = await getAssetsPageByTag(tag, includePublic, { limit: pageSize, after, signal })

and the mock always returns has_more: false (AssetHelper.ts:241) and never a next_cursor. So the cursor walk never runs a second iteration, and the non-advancing-cursor backstop (data.next_cursor === after) is never hit. Aligning the mock on after/next_cursor would make the multi-page path real.

Other things green here doesn't cover:

  • Libraries above DEFAULT_LIMIT (500) — single-page mock only.
  • The zod validation failure path — the mock is schema-valid by construction, so a malformed payload never reaches the parser.
  • Whether core's /experiment/models actually emits extensions. The extension-allowlist test rests on that field (modelLibraryAssetMode.spec.ts:24-29 sets extensions: ['.safetensors', '.gguf']). If core omits it, effectiveModelExtensions falls back to DEFAULT_MODEL_EXTENSIONS, which excludes .gguf — the exact model that test asserts is visible. Worth confirming against a real core response once.
  • The real assets.seed.fast_complete WS message. It's synthesised client-side via dispatchApiCustomEvent; the name and payload shape have never been verified against core. The seed 409 "already running" path is also untested.
  • Fixture realism. Every fixture emits only the namespaced tag (tags: ['models', 'model_type:checkpoints']), but assetMetadataUtils.ts:166-170 states core keeps the bare directory-path twin in sync. The realistic dual-tag payload — precisely where a label leak or a double-listing would surface — is never rendered.

Comment thread browser_tests/fixtures/helpers/FeatureFlagHelper.ts
* field that `supports_model_type_tags` backends emit (see
* `src/platform/assets/schemas/assetSchema.ts`).
*/
type CoreModelAsset = Asset & Pick<AssetItem, 'loader_path'>

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.

question — this intersection type is a symptom worth naming, and I think the answer is "not your bug".

type CoreModelAsset = Asset & Pick<AssetItem, 'loader_path'> exists because loader_path has zero hits anywhere in packages/. The generated Asset in packages/ingest-types/src/types.gen.ts carries file_path instead (lines 3057, 3105, 3918). packages/ingest-types is generated from the Cloud Ingest OpenAPI spec, not from core — and core PR #14796 removed file_path and made loader_path authoritative. So the generated types now carry a field core deleted and lack the one core added.

AGENTS.md:229 rule 4 asks for mocks typed from packages/ingest-types; this intersection is the workaround for that not being possible on this field. So: no objection to the type as written.

The consequence worth flagging is that these e2e mocks can't be contract-checked against core at all for the field the whole suite hinges on. The real fix is getting core's OpenAPI into the type-generation pipeline. Worth a ticket — happy to file it.

(This also answers the question I asked you earlier about moving these to generated types: we can't yet, for exactly this field.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, and thanks for tracing it to core #14796 dropping file_path. The intersection is the right local workaround; the real fix is getting core's OpenAPI into the type-generation pipeline so these mocks can be contract-checked on the field the suite hinges on. Please do file that ticket, it's a cross-repo pipeline change that outlives this PR.

Posted by Claude Code on Simon's behalf.

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.

The in-PR intersection type is the right local workaround and I'm not asking to widen it — but per our standard this thread stays open and active rather than being closed on "please file that ticket". The risk it names (the field the whole e2e suite hinges on can't be contract-checked against core at all) outlives this PR precisely because it's cross-repo, which makes losing the thread more likely, not less.

Concrete next step: I'll file the pipeline ticket (get core's OpenAPI into packages/ingest-types generation so loader_path is authoritative) and link it on this thread. Until that link is here with an owner, this is not resolved — keeping it open.

}
})

test.describe('Model library sidebar - asset mode', () => {

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.

suggestion (non-blocking) — coverage gaps measured against the ACs rather than against the code:

  • No negative-membership assertion. Nothing asserts that a model_type:loras asset is absent from checkpoints. Delete the tag matching in modelFolderFromTag and dump every asset into every folder, and the current tests stay green.
  • No assertion that model_type: never appears in a rendered label. grep -rn model_type browser_tests/ only hits fixture tag definitions and the flag name — never a label assertion. Given getAssetModelType's doc warns that a namespaced literal leaking through round-trips into the tag set, a "no visible text contains model_type:" assertion would be cheap insurance.
  • Flag ABSENT (vs. explicitly false) is untested at every level. modelLibraryAssetMode.spec.ts:262 forces supports_model_type_tags: false rather than omitting it, and every unit consumer stubs the getter. Nothing in the suite would fail if the default flipped to true.
  • No e2e orphan asset. loader_path: null is unit-covered only; there's no e2e fixture asserting an orphan is absent from the tree.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good gaps. The negative-membership assertion and the "no visible label contains model_type:" check are cheap insurance; the flag-absent-vs-false and e2e-orphan cases are more involved. I'd prefer to take these as a follow-up on the e2e suite rather than grow this PR further, but the two cheap ones are low-effort if you'd rather they land here now.

Posted by Claude Code on Simon's behalf.

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.

Per our standard, let's not fold the whole set into an unbacked e2e follow-up. The two cheap ones you agree are low-effort should land in this PR now, since this is the PR adding the coverage:

  • Negative-membership assertion: a model_type:loras asset is absent from checkpoints (today, deleting the tag match in modelFolderFromTag keeps the suite green).
  • "No visible label contains model_type:" assertion (cheap insurance against a namespaced literal leaking into a rendered label).

The more involved two — flag ABSENT vs explicit false, and an e2e orphan (loader_path: null absent from the tree) — can be tracked, but only as a linked issue referenced on this thread with an owner, not a verbal follow-up. Keeping open.

'[data-node-id="preview-CheckpointLoaderSimple"]'
)
await expect(ghost).toBeVisible()
expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(0)

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.

suggestion (non-blocking) — snapshot-then-assert.

expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(0) snapshots a value and then asserts on it. browser_tests/FLAKE_PREVENTION_RULES.md §7 lists this as the first entry in the common-flake table:

Pattern Bad Fix
Snapshot-then-assert expect(await evaluate()).toBe(x) await expect.poll(() => evaluate()).toBe(x)

It fails open rather than retrying. Same shape at modelLibraryRouting.spec.ts:71-76 (expect(await comfyPage.settings.getSetting(...)).toBe(true), twice). await expect.poll(...) in all three places.

Separately, at lines 66-67: folderNodes.nth(0) / .nth(1) positional assertions will shift if the fixtures ever gain a folder — folderNodes matches nested non-leaf nodes too, and asset mode hides empty folders, so the index-to-folder mapping isn't stable under fixture growth. Asserting on the ordered text array (or filtering to top-level nodes) would survive that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Valid, these match the FLAKE_PREVENTION_RULES snapshot-then-assert entry and the positional nth() fragility is real given asset mode hides empty folders. The expect.poll swaps are genuinely low-effort; I'm inclined to fold them into the same e2e-suite follow-up as the coverage gaps above so this PR stays put, but happy to do the poll swaps here if you'd prefer them in now.

Posted by Claude Code on Simon's behalf.

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.

You agree the expect.poll swaps are genuinely low-effort, so per our standard let's land them here rather than fold into a follow-up — this is the PR introducing these specs, and FLAKE_PREVENTION_RULES §7 lists snapshot-then-assert as the first common-flake entry.

Concrete fix:

  • Swap the three snapshot-then-assert sites to await expect.poll(...): this file :185, plus modelLibraryRouting.spec.ts:71-76 (twice).
  • Replace the positional folderNodes.nth(0)/.nth(1) at :66-67 with an assertion on the ordered text array (or filter to top-level nodes), since asset mode hides empty folders and the index-to-folder mapping isn't stable under fixture growth.

Keeping this thread open.

synap5e added 7 commits July 24, 2026 09:04
Group the asset-mode Model Library by namespaced model_type:* tags. When an
asset carries model_type:* tags, the stripped values are the authoritative
categories and all other tags are disregarded; otherwise fall back to the
legacy bare-tag top-level grouping. A shared getAssetCategories helper keeps
the "By type" nav and category filtering in agreement.

Resolve node-provider lookup from the same tags via getAssetNodeCategory:
prefer the most specific (deepest parent/child) candidate so a flat
model_type:LLM does not shadow a resolvable hierarchical tag, and strip the
model_type: prefix before the modelNodeMappings lookup.
Drive the model_type: grouping/resolution off the backend-reported
supports_model_type_tags capability (getServerFeature) instead of sniffing
tags per asset. Default false preserves the legacy bare-tag grouping, so a
backend that does not declare the capability is unchanged. When the flag is
true, assets group by their model_type: values and an uncovered asset (no
model_type: tag) still routes by its bare tags.

The thread-through is a modelTypeMode flag on getAssetCategories /
getAssetNodeCategory / filterByCategory (keeping them pure); call sites read
the capability via useFeatureFlags.
Unwrap the if (isCloud) gate in assetsStore getModelState so the asset-mode
Model Library works on non-cloud distributions (it previously returned an
empty no-op store off-cloud, leaving the library blank even with the asset
API enabled). Scoped to the model-asset store only; the rest of the isCloud
forks are out of scope here.
The card type badge derived from the first raw non-models tag, so in
model_type mode it rendered the literal `model_type:checkpoints`. Route it
through a model_type-aware getAssetTypeBadge and key the display cache on the
flag so a late-arriving feature flag re-derives the badge. Also adds
docstrings to the tag helpers to satisfy coverage.
Also realigns the card type badge to the same rule: keep the existing
"first non-models tag" selection and only strip the model_type: namespace
prefix, rather than reordering to prefer the model_type: value. So an asset
like [models, foo, model_type:bar] still shows foo, while
[models, model_type:checkpoints] shows checkpoints. Title (primaryCategoryTag)
strips the same prefix when the flag is on.
…NodeFromAsset

main (#12765) renamed createModelNodeFromAsset -> resolveModelNodeFromAsset.
Re-apply FE-1076's flag-gated node-category resolution there: use
getAssetNodeCategory(asset, flags.supportsModelTypeTags) instead of the inline
first-non-reserved-tag lookup, so a model_type:* tag resolves the loader when
the supports_model_type_tags flag is on.
Importing MODELS_TAG/MISSING_TAG from assetService made this leaf util pull
the assetService -> i18n (createI18n) chain. Test suites that import
assetMetadataUtils (e.g. useAssetFilterOptions, AssetsSidebarListView) with a
minimal vue-i18n mock then failed to load. Define the two reserved-tag
literals locally so the util has no heavy transitive dependency.

@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.

Re-reviewing at b68776b.

Leading with an acknowledgement: the reconnect-safe setServerFlagsPersistent (re-applying the override on each feature_flags handshake, keeping the WS as the source of truth) is the correct fix for the flag-race I raised in round 2 - and my earlier mockServerFeatures pointer was wrong. mockServerFeatures intercepts /api/features, which never populates serverFeatureFlags (only the WS feature_flags message does), so it would have silently dropped these specs into the wrong mode. Thanks for tracing the actual mechanism rather than just taking the JSDoc pointer.

My approval stands. One issue worth considering plus a few nits inline below - all non-blocking.

id: 'mt-checkpoint-001',
name: 'sd_xl_base_1.0.safetensors',
tags: ['models', 'model_type:checkpoints'],
loader_path: 'SDXL/sd_xl_base_1.0.safetensors',

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.

issue (non-blocking) - CI blind spot on the cutover.

Every MODEL_TYPE_* fixture in this block pairs supports_model_type_tags: true (the specs force it on via setServerFlagsPersistent) with a loader_path. There is no fixture for flag-on + no loader_path - which is exactly the cutover-before-cloud#5604 scenario: buildModelBuckets (assetService.ts:428) skips every asset that has no loader_path while the flag is on, so the sidebar tree renders empty. As written, that regression cannot be caught by CI.

Suggest adding a supports_model_type_tags: true + no-loader_path fixture with a spec asserting the skip/empty behaviour - it turns a latent cross-repo BE ordering dependency (BE-4728) into a visible CI gate.

(Adjacent to, but distinct from, the orphan-asset gap in the thread on line 47: that one is a single loader_path: null among otherwise-valid assets; this is the all-assets-lack-it cutover window that empties the whole tree.)

// Expanding a folder re-attempts the failing load without crashing or
// producing leaves, proving the failure path stays contained.
await tab.getFolderRowByLabel('checkpoints').click()
await expect(tab.leafNodes).toHaveCount(0)

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.

nit - this "Degrades gracefully" test asserts tab.leafNodes toHaveCount(0) both before (line 237) and after (this line) expanding checkpoints. The second assertion can pass instantly against the still-empty tree, before an expand-triggered reload would have produced any leaves - so it is weakly synchronized and would not catch a regression where expansion does surface leaves. Consider awaiting a load marker (e.g. the folder's loading state settling) before the final count.

assetApi.configure(
withModels([...WALK_ASSETS, MODEL_TYPE_CHECKPOINT_SCANNED])
)
await dispatchApiCustomEvent(comfyPage.page, 'assets.seed.fast_complete')

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.

nit - the wire string 'assets.seed.fast_complete' is hardcoded here (and again at line 164), duplicating the literal assetService uses in onModelsScanned. If the event name ever changes, these specs will not fail-fast - they will just quietly stop exercising the path. Consider importing the shared constant instead of re-typing the string.

})

function createCoreModelAsset(
overrides: Partial<CoreModelAsset>

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.

nit - createCoreModelAsset(overrides) requires the arg, while its sibling createModelAsset(overrides = {}) (line 11) defaults it. Minor inconsistency in the factory signatures; defaulting to {} here too would match.

- assert negative membership, no model_type: label leak, flag-absent
  default, and orphan (loader_path: null) exclusion
- pin the flag-on/no-loader_path cutover window (BE-4728) with a
  dedicated fixture and empty-tree spec so the cross-repo ordering
  dependency fails visibly in CI
- swap snapshot-then-assert sites to expect.poll and replace positional
  folder assertions with an ordered-text assertion per flake rules
- synchronize the degraded-walk expansion retry on its 500 response
- share the assets.seed.fast_complete wire constant between service and
  specs; default createCoreModelAsset overrides to {}

Specs authored against mocked routes; not fully verified locally (app
boot exceeds the fixture timeout under load). Routing spec passed 3/3;
lint, typecheck, knip, and unit tests pass.

@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.

Approving. Final pass: the commit since my last review closes the e2e coverage gaps I raised. It adds the orphan and pre-cutover (namespaced tag, no loader_path) fixtures so the cutover risk is now CI-visible, a reconnect-safe clearServerFlagsPersistent helper, a negative-membership bucket assertion (a lora leaf must not appear under checkpoints), and ordered-array assertions replacing positional nth() per the flake rules. Clean reparent plus exactly the coverage that was owed. Green.

Base automatically changed from synap5e/assets-mode-sidebar to main July 28, 2026 08:19
@synap5e
synap5e dismissed stale reviews from christian-byrne and coderabbitai[bot] July 28, 2026 08:19

The base branch was changed.

@synap5e
synap5e requested a review from a team July 28, 2026 08:19
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 28, 2026
synap5e added 2 commits July 28, 2026 20:46
…load

Search expansion ran only when the query committed, so a folder whose
first match arrived from a later reload (a scan completing while the
search was active) rendered collapsed and hid the result. Expand result
folders once per key instead: newly appearing folders open, folders the
user collapsed stay collapsed, and an unchanged tree costs no expand
pass.
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Jul 28, 2026
@synap5e

synap5e commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@AustinMroz @christian-byrne — this is the last one of the assets model-library stack; the other four (#12948/#12972/#13302/#13464) have merged. CI is green and the mid-search scan/expand fix is in — #13574 is blocked only on a re-approval, since the fix commits dismissed the prior stamps. Could one of you re-review the delta and approve so it can land? Thanks.

Created by Claude Code.

@synap5e
synap5e added this pull request to the merge queue Jul 28, 2026
Merged via the queue into main with commit 547ce43 Jul 28, 2026
72 checks passed
@synap5e
synap5e deleted the synap5e/test/assets-sidebar-e2e branch July 28, 2026 23:13
pull Bot pushed a commit to Penguinjanator/ComfyUI_frontend that referenced this pull request Aug 12, 2026
…type mode (Comfy-Org#14848)

## Summary

Fixes a bug where a legacy bare-tagged model asset silently disappears
from the model library sidebar once the backend advertises `model_type:`
support, instead of falling back to legacy bare-tag grouping.

_Recreated from Comfy-Org#14217 — same change, opened directly under my own
account for tracking. The High finding from Cursor's panel on that PR is
already folded into this diff._

## Changes

- **What**: `modelFolderFromTag` returned `undefined` for any tag that
didn't carry the `model_type:` prefix as soon as `modelTypeMode` was
`true`. `buildModelBuckets` treats an asset whose tags resolve to no
folder as "uncategorized" and drops it with a `console.warn`, so a model
still carrying a legacy bare tag (e.g. `checkpoints` instead of
`model_type:checkpoints`) vanished from the sidebar entirely on a
`model_type:`-capable backend. Changed in
`src/platform/assets/services/assetService.ts`.
- **Breaking**: none

## How

The fix deletes the local `modelFolderFromTag` helper and buckets via
`getAssetCategories` from `assetMetadataUtils`, which already implements
exactly the intended semantics and is already used by the other asset
surfaces: `model_type:*` values are authoritative when present, and an
asset with no `model_type:` tag still routes by its bare tags (with
namespace residue filtered out). This makes the sidebar consistent with
the rest of the asset code rather than carrying a second, subtly
different grouping rule.

A side effect worth calling out: because `getAssetCategories` returns
`model_type:` values *alone* when an asset has any, an asset covered by
`model_type:` tags can no longer be cross-listed into a second folder by
a leftover bare-tag twin from a partial re-tagging. The e2e suite covers
that case (the "mid-retag twin" scenario).

Added an e2e scenario, `Model library sidebar - asset mode with a legacy
bare tag`, in
`browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts`, plus a
matching fixture (`MODEL_TYPE_CHECKPOINT_LEGACY_TAG` in
`browser_tests/fixtures/data/assetFixtures.ts`): a bare-tagged asset
that still carries a `loader_path`, walked with
`supports_model_type_tags: true`, asserting it still renders in the
`checkpoints` folder rather than being dropped.

## Review Focus

- This targets `main` directly. The stack it was originally written on
top of (Comfy-Org#13574) has since merged, so the diff here is just the three
files.
- Coverage for the regression lives in the e2e spec rather than a unit
test — the unit-level version was dropped as duplicating it. Flagging
that explicitly since it is a judgement call about test placement.
- Verified against `main` that the bug is still live:
`modelFolderFromTag` on `main` still returns `undefined` for bare tags
whenever `modelTypeMode` is true.
- Checked that the existing `assetService.test.ts` cases on `main`
remain valid under the new path: `getBareTagCategories` filters out the
reserved `models` tag, so the "drops uncategorized model assets with a
warning" case still drops its `tags: ['models']` asset; the bare-tag
grouping cases all run with `supports_model_type_tags = false`, an
unchanged path.

## Test plan

- [ ] `pnpm typecheck` — **not run**: no Node/pnpm toolchain provisioned
on the host I authored this on. Relying on CI.
- [ ] `pnpm exec vitest run
src/platform/assets/services/assetService.test.ts` — **not run**, same
reason. Compatibility with the existing cases was verified by reading
them (see Review Focus).
- [x] Static check that the refactor is complete:
`MODEL_TYPE_TAG_PREFIX` import removed with no remaining uses in the
file, `modelFolderFromTag` has zero references repo-wide,
`getAssetCategories` is exported from `assetMetadataUtils` on `main`.
- [x] The identical three-file diff passed a full CI run on Comfy-Org#14217
(Playwright 1759 passed / 0 failed / 1 flaky; Codecov reported all
modified lines covered).

---

**Review coverage note:** no Cursor panel has run on this PR — verified
by querying for the panel review itself rather than inferring from an
empty findings list. That is a *did-not-run*, not a clean result; the
checks API reports success either way. CodeRabbit was rate-limited.
Codex did review it, and its one finding was addressed in `f16560c`.

_(An earlier version of this note blamed an org-wide Cursor outage
running to 2026-08-22. That attribution was wrong and is withdrawn —
panels have since been seen running normally elsewhere. The measured
fact, that none ran here, is unchanged.)_

---------

Co-authored-by: Austin Mroz <austin@comfy.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cursor-review Trigger multi-model Cursor agent review on this PR 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