Skip to content

feat(workspace): enable local credit workspace switching FE-1584 - #15164

Merged
dante01yoon merged 13 commits into
mainfrom
dante01yoon/fe-1584-local-workspace-switcher
Aug 21, 2026
Merged

feat(workspace): enable local credit workspace switching FE-1584#15164
dante01yoon merged 13 commits into
mainfrom
dante01yoon/fe-1584-local-workspace-switcher

Conversation

@dante01yoon

@dante01yoon dante01yoon commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Why

Local/Desktop users cannot select the workspace that owns their subscription or credits. The existing workspace and billing clients also resolve through api.apiURL(), which points at the local ComfyUI server off Cloud, so simply exposing the Cloud switcher leaves workspace hydration dormant and returns 404s.

Root cause

The Cloud-only UI guard hid the switcher, but the deeper boundary was also Cloud-only:

  • workspace token exchange, workspace listing, and /billing/* used same-origin URLs
  • generic auth helpers mixed Firebase user identity with workspace-scoped identity
  • Cloud workspace switching reloads the app and changes workflow-persistence namespaces, which is incorrect for Local/Desktop where workspaces are credit wallets only

Change

  • Expose the existing workspace switcher in Local/Desktop after Firebase auth hydrates; keep workspace creation Cloud-only.
  • Route workspace auth, listing, and billing requests to the build's Firebase-paired Cloud gateway (cloud.comfy.org in production, testcloud.comfy.org in non-production) while Cloud remains same-origin.
  • Separate Firebase-authenticated /customers/* calls from workspace-authenticated billing and partner-node execution.
  • Switch the active local credit context without reloading or moving local workflow persistence; persist the selected wallet per device.
  • Keep Add credits permission-aware and return completed/pending top-ups to Settings → Credits on Local/Desktop.

Implementation scope and rationale

Area Change Why it is required
Workspace API routing Resolve workspace and billing requests through the Firebase-paired Cloud gateway outside the Cloud distribution. Local /api targets the local ComfyUI server, while workspace and billing state is owned by Cloud ingest.
Authentication boundary Separate Firebase user authentication from workspace-scoped authentication, including partner-node queue execution. A Firebase token identifies the user; the workspace token deterministically identifies the wallet that owns credits and receives usage charges.
Workspace bootstrap Share and await the in-flight Local workspace initialization, and fail closed when no active workspace can be established. Prompt submission during bootstrap must not run without credentials or silently fall back to the personal workspace.
Local switch lifecycle Switch the active credit workspace without reloading the document. Cloud reload semantics are unnecessary for Local and would interrupt the current local workflow.
Workflow persistence Keep Local workflow storage in the personal namespace when the credit workspace changes. Local workspace selection changes the billing wallet only; it must not move, clear, or split locally stored workflows.
Billing routing Use workspace billing after Local workspace hydration. Balances, plans, billing events, and top-ups must follow the selected credit workspace rather than the personal account.
Billing permissions Keep Credits visible while hiding Add credits for members who cannot top up. Backend top-up operations are owner-only, so the UI must not offer an action the selected workspace role cannot perform.
Top-up completion Return completed or pending Local top-ups to Settings → Credits. Local does not expose the Cloud workspace-management destination used by the existing Cloud flow.
Cloud customer endpoints Explicitly retain Firebase authentication for user-scoped customer and subscription calls. Changing generic auth precedence must not send a workspace token to endpoints whose contract is user-scoped.
Feature-flag isolation Disable unified_cloud_auth outside the Cloud distribution. Unified Cloud JWT minting is not available in Local/Desktop; accepting that flag there would break workspace discovery and execution authentication.
Regression coverage Add focused unit tests and a Local Playwright workspace-switching flow. The tests protect workspace attribution, Cloud-gateway routing, no-reload switching, workflow retention, permissions, and bootstrap race handling.

Backend dependency: cloud#6635 is required and merged. Its Local/Desktop CORS scope covers POST /api/auth/token, GET /api/workspaces, and GET/POST /api/billing/*; Local keeps workspace creation hidden. The backend PR is merged into main, and its production manifest contains the loopback origins. A live preflight currently passes on testcloud.comfy.org, while cloud.comfy.org still omits Access-Control-Allow-Origin for loopback origins. No additional backend code change is currently identified; the remaining release check is to confirm the merged configuration has rolled out to the production runtime and repeat the preflight. #15151 independently fixes the existing Settings → Credits activity spinner and billing-portal rail.

Plan / QA

  1. Review the auth and persistence boundaries in this PR.
  2. Land fix(billing): make the Credits panel follow the active billing rail #15151 so activity and Invoice History follow the selected billing rail.
  3. Confirm the merged cloud#6635 configuration has rolled out to the production runtime and repeat the live preflight.
  4. Verify on a Desktop build against the deployed gateway: switch/relaunch, popover and Settings balances, top-up attribution, partner-node debit and allowlist, member permissions, and zero-credit local runs.

Regression audit added a focused Local Playwright flow. It caught and fixed two release blockers: Local rendered the legacy profile popover even after workspace hydration, and unified_cloud_auth=true incorrectly selected an unavailable Cloud JWT outside the Cloud distribution. The E2E verifies workspace/role rendering, workspace token exchange, Cloud-gateway billing routing, and that switching neither reloads the document nor loses the open workflow tab.

A second auth/accounting audit found two queue-time races: a prompt could be submitted without a workspace token while Local workspace bootstrap was in flight, or fall back to the personal Firebase identity after bootstrap failed. Queue authentication now shares and awaits the in-flight workspace initialization and fails closed if no active workspace can be established. Identity-generation guards prevent a previous user's initialization from overwriting the next user's state.

Design of record: MVP before/after · popover and switcher

The implementation references those prototype states: the profile popover gains the workspace row, the selector opens to the left, and the selected workspace is highlighted with a check while roles remain visible. Local-specific adaptations are the compact single-line trigger and the retained Credits entry, because this scope adds wallet switching without exposing Cloud workspace management.

AS IS — Local profile menu TO BE — Local workspace selector
AS IS Local profile menu TO BE Local workspace selector

Captured from the actual Local frontend at 1920×1200 with deterministic auth/workspace/billing API fixtures; no Figma image is substituted for the implementation capture.

Validation

  • Focused Local workspace Playwright E2E: 1/1 passed on Chromium before the final auth-race patch; final local rerun was blocked during fixture setup because the 8188 ComfyUI test backend was unavailable, before any product assertion ran
  • Final focused workspace/auth/queue unit suites: 316/316 passed when run in their stable focused groups
  • Earlier affected unit/component suites: 650/650 passed before rebase; 594/594 passed after rebase
  • pnpm typecheck
  • targeted ESLint and oxfmt checks
  • pnpm knip reports only existing repository-wide unused dependency/export findings
  • Real-app screenshot Playwright run: 2/2 passed (AS IS without a workspace roster; TO BE with the selector open)
  • Live CORS preflight: staging passes; production runtime rollout/sync verification remains the release blocker

Linear: FE-1584

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 13ab1d53-4ec6-45bb-b07f-802beadbdb5c

📥 Commits

Reviewing files that changed from the base of the PR and between 8070e42 and 8537d1c.

📒 Files selected for processing (1)
  • src/platform/workflow/persistence/composables/useWorkflowPersistenceV2.test.ts

Included review availability: Your plan includes up to 4 reviews per rolling hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The PR adds workspace-specific authentication and API routing, enables background workspace initialization outside cloud deployments, supports local workspace switching without reloads, and updates billing and top-bar workspace controls for cloud and non-cloud distributions.

Changes

Workspace-aware platform behavior

Layer / File(s) Summary
Authentication and workspace API boundaries
src/stores/authStore.ts, src/platform/workspace/api/*, src/config/comfyApi.ts, src/platform/cloud/subscription/*, src/scripts/app.ts, src/services/customerEventsService.ts
Authentication helpers distinguish Firebase and workspace credentials. Workspace APIs use distribution-specific URLs and workspace authentication.
Non-cloud workspace initialization and transitions
src/platform/workspace/auth/*, src/platform/workspace/stores/*, src/platform/workflow/persistence/base/*, src/stores/__tests__/authTokenPriority.test.ts
Non-cloud deployments initialize workspace context in the background. Workspace switching and revoked-workspace fallback update local state without reloads or workflow cleanup.
Workspace-aware billing and distribution behavior
src/composables/billing/*, src/platform/workspace/components/*, src/platform/workspace/stores/billingOperationStore.*, src/composables/useFeatureFlags.ts
Billing routing uses workspace readiness and billing rails. Local top-ups open Credits settings. Workspace creation and unified cloud authentication remain cloud-only.
Workspace controls in the top bar
src/components/topbar/*
The top bar displays active workspace identity, provides workspace selection, and applies workspace permissions to credits and plan controls.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to 8537d

This PR enables Local workspace-based credit switching without reloading workflows, but unresolved state-management and account-lifecycle issues could leave workspace data inconsistent or allow stale initialization to affect a later session; merge should wait for these risks to be fixed or explicitly accepted.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant WorkspaceAuthGate
  participant teamWorkspaceStore
  participant workspaceAuthStore
  participant workspaceApi
  User->>WorkspaceAuthGate: sign in
  WorkspaceAuthGate->>teamWorkspaceStore: initialize workspace context
  teamWorkspaceStore->>workspaceAuthStore: authenticate active workspace
  workspaceAuthStore->>workspaceApi: request workspace token
  workspaceApi-->>workspaceAuthStore: return workspace credentials
  workspaceAuthStore-->>teamWorkspaceStore: confirm workspace
  teamWorkspaceStore-->>User: update workspace UI without reload
Loading
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 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.
End-To-End Regression Coverage For Fixes ✅ Passed The PR changes browser_tests/ files, so it does not meet the check's second failure condition. The description also documents the end-to-end regression coverage.
Adr Compliance For Entity/Litegraph Changes ✅ Passed The changed-file list contains no src/lib/litegraph/, src/ecs/, or graph-entity files, so this ADR check is not applicable.
Title check ✅ Passed The title clearly and concisely identifies the primary change: enabling local credit workspace switching.
Description check ✅ Passed The description is comprehensive, on-topic, and covers the change, rationale, review focus, screenshots, dependencies, and validation.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch dante01yoon/fe-1584-local-workspace-switcher
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dante01yoon/fe-1584-local-workspace-switcher

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

…orkspace-switcher

# Conflicts:
#	src/platform/workspace/stores/billingOperationStore.test.ts
#	src/platform/workspace/stores/teamWorkspaceStore.test.ts
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1841 passed, 0 failed

📊 Browser Reports
  • chromium: View Report (✅ 1820 / ❌ 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)
  • New-test walkthrough (chromium, recorded video): View Report

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 08/20/2026, 05:31:10 PM UTC

Links

📦 Bundle: 9.13 MB gzip 🔴 +2.9 kB

Details

Summary

  • Raw size: 38.7 MB baseline 38.7 MB — 🔴 +10.9 kB
  • Gzip: 9.13 MB baseline 9.12 MB — 🔴 +2.9 kB
  • Brotli: 6.38 MB baseline 6.38 MB — 🔴 +2.55 kB
  • Bundles: 440 current • 439 baseline • 157 added / 156 removed

Category Glance
Other 🔴 +4.23 kB (14.2 MB) · Graph Workspace 🔴 +3.43 kB (1.37 MB) · Data & Services 🔴 +3.3 kB (3.53 MB) · Utilities & Hooks 🟢 -74 B (549 kB) · Vendor & Third-Party ⚪ 0 B (18.1 MB) · Panels & Settings ⚪ 0 B (566 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-Cx43wSVD.js (new) 3.71 kB 🔴 +3.71 kB 🔴 +1.86 kB 🔴 +1.6 kB
assets/index-DhI90Xg8.js (removed) 3.71 kB 🟢 -3.71 kB 🟢 -1.86 kB 🟢 -1.59 kB

Status: 1 added / 1 removed

Graph Workspace — 1.37 MB (baseline 1.37 MB) • 🔴 +3.43 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-BvtH-g7q.js (new) 1.37 MB 🔴 +1.37 MB 🔴 +298 kB 🔴 +224 kB
assets/GraphView-B8MV0U1Z.js (removed) 1.36 MB 🟢 -1.36 MB 🟢 -297 kB 🟢 -223 kB
assets/WidgetCompositor-BR05Qh6x.js (new) 8.17 kB 🔴 +8.17 kB 🔴 +2.76 kB 🔴 +2.46 kB
assets/WidgetCompositor-D5B0sZa1.js (removed) 8.17 kB 🟢 -8.17 kB 🟢 -2.76 kB 🟢 -2.46 kB

Status: 2 added / 2 removed / 1 unchanged

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-Bq29BBfF.js (new) 25 kB 🔴 +25 kB 🔴 +6.25 kB 🔴 +5.53 kB
assets/CloudSurveyView-DUt5EnbQ.js (removed) 25 kB 🟢 -25 kB 🟢 -6.25 kB 🟢 -5.52 kB
assets/CloudLayoutView-BPuqF2QV.js (new) 21.8 kB 🔴 +21.8 kB 🔴 +6.56 kB 🔴 +5.74 kB
assets/CloudLayoutView-BwS0bzYJ.js (removed) 21.8 kB 🟢 -21.8 kB 🟢 -6.57 kB 🟢 -5.74 kB
assets/UserCheckView-BpibgHdB.js (new) 8.75 kB 🔴 +8.75 kB 🔴 +2.19 kB 🔴 +1.9 kB
assets/UserCheckView-CpSZGdXV.js (removed) 8.75 kB 🟢 -8.75 kB 🟢 -2.19 kB 🟢 -1.91 kB
assets/CloudLoginView-BHzBnmfV.js (new) 8.74 kB 🔴 +8.74 kB 🔴 +2.55 kB 🔴 +2.26 kB
assets/CloudLoginView-BRBIT9ov.js (removed) 8.74 kB 🟢 -8.74 kB 🟢 -2.56 kB 🟢 -2.28 kB
assets/useCloudAuthPage-0S1R00wH.js (new) 7.08 kB 🔴 +7.08 kB 🔴 +2.52 kB 🔴 +2.21 kB
assets/useCloudAuthPage-ChBBDGAD.js (removed) 7.08 kB 🟢 -7.08 kB 🟢 -2.52 kB 🟢 -2.2 kB
assets/CloudSignupView-5tXeGFBl.js (removed) 6.96 kB 🟢 -6.96 kB 🟢 -2.28 kB 🟢 -2.01 kB
assets/CloudSignupView-RnaItWt9.js (new) 6.96 kB 🔴 +6.96 kB 🔴 +2.28 kB 🔴 +2 kB
assets/WidgetTextPreview-Bh2VP5M4.js (new) 6.07 kB 🔴 +6.07 kB 🔴 +2.13 kB 🔴 +1.9 kB
assets/WidgetTextPreview-dd_rnLid.js (removed) 6.07 kB 🟢 -6.07 kB 🟢 -2.13 kB 🟢 -1.9 kB
assets/CloudSubscriptionRedirectView-AaCO_-1x.js (removed) 6.05 kB 🟢 -6.05 kB 🟢 -2.25 kB 🟢 -1.96 kB
assets/CloudSubscriptionRedirectView-DVtP44vO.js (new) 6.05 kB 🔴 +6.05 kB 🔴 +2.25 kB 🔴 +1.97 kB
assets/UserSelectView-cSMoSBxJ.js (removed) 5.49 kB 🟢 -5.49 kB 🟢 -1.96 kB 🟢 -1.72 kB
assets/UserSelectView-MSejSVBT.js (new) 5.49 kB 🔴 +5.49 kB 🔴 +1.96 kB 🔴 +1.71 kB
assets/CloudForgotPasswordView-_PIsImEK.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.72 kB 🔴 +1.49 kB
assets/CloudForgotPasswordView-BNaUsRSV.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.72 kB 🟢 -1.49 kB
assets/CloudAuthTimeoutView-BSrr0R9i.js (new) 4.43 kB 🔴 +4.43 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/CloudAuthTimeoutView-fghaAq6N.js (removed) 4.43 kB 🟢 -4.43 kB 🟢 -1.54 kB 🟢 -1.33 kB
assets/OAuthLayoutView-BzUbkzyX.js (removed) 1.31 kB 🟢 -1.31 kB 🟢 -700 B 🟢 -588 B
assets/OAuthLayoutView-Cju5qkY_.js (new) 1.31 kB 🔴 +1.31 kB 🔴 +700 B 🔴 +587 B
assets/WidgetTextPreview-Bm-2E3lN.js (new) 131 B 🔴 +131 B 🔴 +100 B 🔴 +92 B
assets/WidgetTextPreview-yxjYxxbo.js (removed) 131 B 🟢 -131 B 🟢 -100 B 🟢 -95 B

Status: 13 added / 13 removed / 4 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-Bt1FPUpl.js (new) 49.4 kB 🔴 +49.4 kB 🔴 +9.94 kB 🔴 +8.79 kB
assets/KeybindingPanel-CkRkJ-Oi.js (removed) 49.4 kB 🟢 -49.4 kB 🟢 -9.95 kB 🟢 -8.79 kB
assets/SecretsPanel-C37UAZU9.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -7.88 kB 🟢 -6.91 kB
assets/SecretsPanel-hg_Iy_Km.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +7.88 kB 🔴 +6.91 kB
assets/CreditsPanel-DdZTaMHM.js (removed) 11.5 kB 🟢 -11.5 kB 🟢 -3.21 kB 🟢 -2.82 kB
assets/CreditsPanel-DtiEccQ1.js (new) 11.5 kB 🔴 +11.5 kB 🔴 +3.21 kB 🔴 +2.81 kB
assets/AboutPanel-BNCSqTTV.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.12 kB 🔴 +2.79 kB
assets/AboutPanel-tJ5RgKVT.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.12 kB 🟢 -2.8 kB
assets/ExtensionPanel-DFPhyzCS.js (new) 9.19 kB 🔴 +9.19 kB 🔴 +2.51 kB 🔴 +2.23 kB
assets/ExtensionPanel-nLkblog5.js (removed) 9.19 kB 🟢 -9.19 kB 🟢 -2.51 kB 🟢 -2.23 kB
assets/ServerConfigPanel-Bkm1wRuN.js (new) 6.09 kB 🔴 +6.09 kB 🔴 +1.94 kB 🔴 +1.73 kB
assets/ServerConfigPanel-P9BkAcL2.js (removed) 6.09 kB 🟢 -6.09 kB 🟢 -1.94 kB 🟢 -1.72 kB
assets/UserPanel-Ci1tBmWq.js (removed) 5.73 kB 🟢 -5.73 kB 🟢 -1.79 kB 🟢 -1.54 kB
assets/UserPanel-px5Z8aaX.js (new) 5.73 kB 🔴 +5.73 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/refreshRemoteConfig-6jOhroFL.js (new) 4.24 kB 🔴 +4.24 kB 🔴 +1.51 kB 🔴 +1.34 kB
assets/refreshRemoteConfig-DRUgxOA_.js (removed) 4.24 kB 🟢 -4.24 kB 🟢 -1.51 kB 🟢 -1.34 kB
assets/cloudRemoteConfig-Cu2Gg6je.js (removed) 951 B 🟢 -951 B 🟢 -515 B 🟢 -421 B
assets/cloudRemoteConfig-ZKvIU2_A.js (new) 951 B 🔴 +951 B 🔴 +514 B 🔴 +420 B
assets/refreshRemoteConfig-BBIXgNEA.js (removed) 110 B 🟢 -110 B 🟢 -89 B 🟢 -86 B
assets/refreshRemoteConfig-C4lUwB2g.js (new) 110 B 🔴 +110 B 🔴 +89 B 🔴 +82 B

Status: 10 added / 10 removed / 16 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SignUpForm-BWNWETRj.js (removed) 13.3 kB 🟢 -13.3 kB 🟢 -4.53 kB 🟢 -3.94 kB
assets/SignUpForm-C8SjZzeR.js (new) 13.3 kB 🔴 +13.3 kB 🔴 +4.53 kB 🔴 +3.93 kB
assets/auth-DV1r7ghm.js (new) 3.48 kB 🔴 +3.48 kB 🔴 +1.21 kB 🔴 +1.01 kB
assets/auth-ok7NLPIO.js (removed) 3.48 kB 🟢 -3.48 kB 🟢 -1.21 kB 🟢 -1.01 kB
assets/UpdatePasswordContent-D5kJv4ZJ.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -843 B 🟢 -740 B
assets/UpdatePasswordContent-eCJxQImL.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +843 B 🔴 +734 B
assets/authStore-4WpqIhMf.js (new) 128 B 🔴 +128 B 🔴 +104 B 🔴 +105 B
assets/authStore-CNWRbYxF.js (removed) 128 B 🟢 -128 B 🟢 -104 B 🟢 -104 B
assets/workspaceAuthStore-DnGnxRow.js (new) 108 B 🔴 +108 B 🔴 +99 B 🔴 +108 B
assets/workspaceAuthStore-DoMQ3BIB.js (removed) 108 B 🟢 -108 B 🟢 -99 B 🟢 -107 B
assets/auth-CC_j4aYy.js (new) 105 B 🔴 +105 B 🔴 +96 B 🔴 +84 B
assets/auth-jwzecDVv.js (removed) 105 B 🟢 -105 B 🟢 -96 B 🟢 -84 B

Status: 6 added / 6 removed / 5 unchanged

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

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyHubPublishDialog-BfecVdcj.js (new) 90.1 kB 🔴 +90.1 kB 🔴 +19.3 kB 🔴 +16.5 kB
assets/ComfyHubPublishDialog-IFpVILHe.js (removed) 90.1 kB 🟢 -90.1 kB 🟢 -19.3 kB 🟢 -16.5 kB
assets/useShareDialog-B5ws9iY8.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -5.7 kB 🟢 -5.04 kB
assets/useShareDialog-DcaxVlwm.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +5.7 kB 🔴 +5.04 kB
assets/feedbackDialog-F5RVLwJ-.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.87 kB 🟢 -1.59 kB
assets/feedbackDialog-rV1Yhpdf.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.87 kB 🔴 +1.59 kB
assets/useRangeEditor-CfQGLMMx.js (removed) 3.29 kB 🟢 -3.29 kB 🟢 -1.14 kB 🟢 -1.03 kB
assets/useRangeEditor-CUil5RqF.js (new) 3.29 kB 🔴 +3.29 kB 🔴 +1.14 kB 🔴 +1.03 kB
assets/useLayerEditor-CQZ8m-Hm.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +490 B 🔴 +405 B
assets/useLayerEditor-DcgE5tn4.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -490 B 🟢 -405 B
assets/ComfyHubPublishDialog-4rZW1mm1.js (removed) 143 B 🟢 -143 B 🟢 -105 B 🟢 -91 B
assets/ComfyHubPublishDialog-DVccZdWm.js (new) 143 B 🔴 +143 B 🔴 +105 B 🔴 +91 B
assets/useSubscriptionDialog-Dd9MiHBd.js (removed) 108 B 🟢 -108 B 🟢 -102 B 🟢 -91 B
assets/useSubscriptionDialog-DyTtJY4A.js (new) 108 B 🔴 +108 B 🔴 +102 B 🔴 +87 B

Status: 7 added / 7 removed / 1 unchanged

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-BBLDARXJ.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.97 kB 🔴 +3.53 kB
assets/ComfyQueueButton-wk6hbVzm.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.97 kB 🟢 -3.53 kB
assets/useTerminalTabs-Bkq7L9xw.js (new) 11.8 kB 🔴 +11.8 kB 🔴 +3.69 kB 🔴 +3.28 kB
assets/useTerminalTabs-t_Czh6em.js (removed) 11.8 kB 🟢 -11.8 kB 🟢 -3.69 kB 🟢 -3.28 kB
assets/InviteMembersForm-C6prfxin.js (removed) 8.23 kB 🟢 -8.23 kB 🟢 -2.74 kB 🟢 -2.43 kB
assets/InviteMembersForm-C8CERied.js (new) 8.23 kB 🔴 +8.23 kB 🔴 +2.74 kB 🔴 +2.43 kB
assets/SubscribeButton-BNjC8SoQ.js (removed) 2.15 kB 🟢 -2.15 kB 🟢 -970 B 🟢 -850 B
assets/SubscribeButton-CXsoMQgb.js (new) 2.15 kB 🔴 +2.15 kB 🔴 +970 B 🔴 +850 B
assets/cloudFeedbackTopbarButton-BmJobzGv.js (new) 705 B 🔴 +705 B 🔴 +421 B 🔴 +361 B
assets/cloudFeedbackTopbarButton-CcNSdYaY.js (removed) 705 B 🟢 -705 B 🟢 -420 B 🟢 -360 B
assets/ComfyQueueButton-DHu_al7Y.js (removed) 128 B 🟢 -128 B 🟢 -99 B 🟢 -89 B
assets/ComfyQueueButton-P-sItyeq.js (new) 128 B 🔴 +128 B 🔴 +99 B 🔴 +96 B

Status: 6 added / 6 removed / 8 unchanged

Data & Services — 3.53 MB (baseline 3.53 MB) • 🔴 +3.3 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settingStore-Dan43T87.js (new) 3.16 MB 🔴 +3.16 MB 🔴 +742 kB 🔴 +558 kB
assets/settingStore-CGzrLIJj.js (removed) 3.16 MB 🟢 -3.16 MB 🟢 -742 kB 🟢 -558 kB
assets/api-aS7Vc2yz.js (new) 186 kB 🔴 +186 kB 🔴 +39.8 kB 🔴 +33.4 kB
assets/api-uWfJ2q5S.js (removed) 186 kB 🟢 -186 kB 🟢 -39.8 kB 🟢 -33.3 kB
assets/load3dService-DcZq334v.js (new) 132 kB 🔴 +132 kB 🔴 +29.3 kB 🔴 +24.7 kB
assets/load3dService-hmQVBkMN.js (removed) 132 kB 🟢 -132 kB 🟢 -29.3 kB 🟢 -24.7 kB
assets/workflowShareService-C4XThT5S.js (removed) 16.5 kB 🟢 -16.5 kB 🟢 -4.92 kB 🟢 -4.34 kB
assets/workflowShareService-DLfSCWwc.js (new) 16.5 kB 🔴 +16.5 kB 🔴 +4.91 kB 🔴 +4.34 kB
assets/keybindingService-CwIjDZZf.js (new) 6.95 kB 🔴 +6.95 kB 🔴 +1.74 kB 🔴 +1.51 kB
assets/keybindingService-DdgJ6x7j.js (removed) 6.95 kB 🟢 -6.95 kB 🟢 -1.74 kB 🟢 -1.51 kB
assets/releaseStore-BB5zkunj.js (removed) 6.72 kB 🟢 -6.72 kB 🟢 -2.03 kB 🟢 -1.77 kB
assets/releaseStore-bLtQqEji.js (new) 6.72 kB 🔴 +6.72 kB 🔴 +2.03 kB 🔴 +1.77 kB
assets/systemStatsStore-BenBB442.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.74 kB 🟢 -1.47 kB
assets/systemStatsStore-VE3ltMSQ.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.74 kB 🔴 +1.47 kB
assets/userStore-DL1_w_i3.js (removed) 2.38 kB 🟢 -2.38 kB 🟢 -899 B 🟢 -795 B
assets/userStore-xgfKXBip.js (new) 2.38 kB 🔴 +2.38 kB 🔴 +898 B 🔴 +795 B
assets/audioService-CLTVgXK2.js (removed) 1.71 kB 🟢 -1.71 kB 🟢 -830 B 🟢 -722 B
assets/audioService-DwPyMyGd.js (new) 1.71 kB 🔴 +1.71 kB 🔴 +829 B 🔴 +732 B
assets/dialogService-eOh1igI5.js (removed) 98 B 🟢 -98 B 🟢 -97 B 🟢 -83 B
assets/dialogService-glnFqEMc.js (new) 98 B 🔴 +98 B 🔴 +97 B 🔴 +84 B
assets/releaseStore-BvtX67pT.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +85 B
assets/releaseStore-DiTG14eT.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -82 B
assets/settingStore-CRZ4hK3m.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -90 B
assets/settingStore-DlcjXbXY.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +88 B
assets/assetsStore-CD74mz6B.js (new) 94 B 🔴 +94 B 🔴 +92 B 🔴 +85 B
assets/assetsStore-jYpcXRdZ.js (removed) 94 B 🟢 -94 B 🟢 -92 B 🟢 -84 B
assets/api-9RNt8YuK.js (new) 62 B 🔴 +62 B 🔴 +74 B 🔴 +66 B
assets/api-Dpq229qW.js (removed) 62 B 🟢 -62 B 🟢 -74 B 🟢 -66 B

Status: 14 added / 14 removed / 3 unchanged

Utilities & Hooks — 549 kB (baseline 549 kB) • 🟢 -74 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-CPisTXvC.js (new) 236 kB 🔴 +236 kB 🔴 +53.1 kB 🔴 +43.2 kB
assets/useConflictDetection-Dhk8jJ-T.js (removed) 236 kB 🟢 -236 kB 🟢 -53.1 kB 🟢 -43.2 kB
assets/useLayerEditorSession-BEDefOsY.js (new) 158 kB 🔴 +158 kB 🔴 +40.8 kB 🔴 +34.3 kB
assets/useLayerEditorSession-Ca6Wr2A2.js (removed) 158 kB 🟢 -158 kB 🟢 -40.8 kB 🟢 -34.3 kB
assets/useLoad3d-B3I4PcsI.js (new) 25.8 kB 🔴 +25.8 kB 🔴 +5.8 kB 🔴 +5.15 kB
assets/useLoad3d-XBlpEQlh.js (removed) 25.8 kB 🟢 -25.8 kB 🟢 -5.8 kB 🟢 -5.15 kB
assets/useLoad3dViewer-BdG3EADJ.js (new) 21.2 kB 🔴 +21.2 kB 🔴 +4.98 kB 🔴 +4.36 kB
assets/useLoad3dViewer-CLIgAyKd.js (removed) 21.2 kB 🟢 -21.2 kB 🟢 -4.98 kB 🟢 -4.36 kB
assets/useImageCrop-ECPLBnku.js (new) 14.9 kB 🔴 +14.9 kB 🔴 +3.42 kB 🔴 +2.98 kB
assets/useImageCrop-pHWsXol-.js (removed) 14.9 kB 🟢 -14.9 kB 🟢 -3.42 kB 🟢 -2.99 kB
assets/useDowngradeToPersonal-ClpGhM8G.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +2.74 kB 🔴 +2.35 kB
assets/useDowngradeToPersonal-CTOjOudd.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -2.73 kB 🟢 -2.35 kB
assets/useFeatureFlags-DGTg09GD.js (removed) 7.32 kB 🟢 -7.32 kB 🟢 -2.06 kB 🟢 -1.74 kB
assets/useFeatureFlags-Ba-fPkXK.js (new) 7.25 kB 🔴 +7.25 kB 🔴 +2.05 kB 🔴 +1.74 kB
assets/useCompositorLayers-CUYJhM1w.js (new) 2.94 kB 🔴 +2.94 kB 🔴 +899 B 🔴 +804 B
assets/useCompositorLayers-uV8zlrM_.js (removed) 2.94 kB 🟢 -2.94 kB 🟢 -898 B 🟢 -804 B
assets/useExternalLink-KQhi_zOI.js (new) 2.85 kB 🔴 +2.85 kB 🔴 +1.07 kB 🔴 +923 B
assets/useExternalLink-vLTS5Any.js (removed) 2.85 kB 🟢 -2.85 kB 🟢 -1.06 kB 🟢 -922 B
assets/assetPreviewUtil-9rqegOj3.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -970 B 🟢 -847 B
assets/assetPreviewUtil-DRIuMYOU.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +969 B 🔴 +846 B
assets/downloadUtil-B7TLEo9-.js (removed) 2.04 kB 🟢 -2.04 kB 🟢 -906 B 🟢 -724 B
assets/downloadUtil-D3R_4_YM.js (new) 2.04 kB 🔴 +2.04 kB 🔴 +907 B 🔴 +728 B
assets/useUpstreamValue-Btnokvia.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -758 B 🟢 -671 B
assets/useUpstreamValue-DVWA0kY_.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +759 B 🔴 +684 B
assets/useWorkspaceTierLabel-DElV5ZeU.js (new) 1.93 kB 🔴 +1.93 kB 🔴 +815 B 🔴 +697 B
assets/useWorkspaceTierLabel-EFmJM87t.js (removed) 1.93 kB 🟢 -1.93 kB 🟢 -814 B 🟢 -697 B
assets/useErrorHandling-BD71jpNZ.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +614 B 🔴 +520 B
assets/useErrorHandling-VHP-cpqL.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -613 B 🟢 -521 B
assets/subscriptionCheckoutUtil-BIqMx3xc.js (new) 877 B 🔴 +877 B 🔴 +523 B 🔴 +453 B
assets/subscriptionCheckoutUtil-kkwwii9_.js (removed) 877 B 🟢 -877 B 🟢 -521 B 🟢 -435 B
assets/useSessionCookie-C8lc3M5F.js (new) 652 B 🔴 +652 B 🔴 +336 B 🔴 +290 B
assets/useSessionCookie-Dxr-DT1i.js (removed) 652 B 🟢 -652 B 🟢 -337 B 🟢 -290 B
assets/useLoad3d-DsxkIWxt.js (removed) 311 B 🟢 -311 B 🟢 -164 B 🟢 -150 B
assets/useLoad3d-Oh2Wg2Sj.js (new) 311 B 🔴 +311 B 🔴 +164 B 🔴 +147 B
assets/useSessionCookie-BgXvPBzt.js (removed) 101 B 🟢 -101 B 🟢 -86 B 🟢 -78 B
assets/useSessionCookie-tHCwfJ66.js (new) 101 B 🔴 +101 B 🔴 +86 B 🔴 +83 B
assets/useFeatureFlags-DKjh51b8.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -80 B
assets/useFeatureFlags-Fuo9WgWW.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +80 B
assets/useLoad3dViewer-B9TdOAwh.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +85 B
assets/useLoad3dViewer-BqKGiv7A.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -93 B
assets/useCurrentUser-0PjAzXKj.js (new) 94 B 🔴 +94 B 🔴 +95 B 🔴 +86 B
assets/useCurrentUser-BKjEBYsC.js (removed) 94 B 🟢 -94 B 🟢 -95 B 🟢 -85 B

Status: 21 added / 21 removed / 16 unchanged

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

External libraries and shared vendor chunks

Status: 18 unchanged

Other — 14.2 MB (baseline 14.2 MB) • 🔴 +4.23 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/main-B4VP8h3c.js (new) 207 kB 🔴 +207 kB 🔴 +60.2 kB 🔴 +50.5 kB
assets/main-C2VbHNI1.js (removed) 207 kB 🟢 -207 kB 🟢 -60.1 kB 🟢 -50.4 kB
assets/core-7MelGzY8.js (removed) 115 kB 🟢 -115 kB 🟢 -30 kB 🟢 -25.3 kB
assets/core-BTPCPti_.js (new) 115 kB 🔴 +115 kB 🔴 +30 kB 🔴 +25.3 kB
assets/WidgetSelect-3J8gkIxW.js (removed) 88.8 kB 🟢 -88.8 kB 🟢 -20.1 kB 🟢 -17.2 kB
assets/WidgetSelect-DsENSHkS.js (new) 88.8 kB 🔴 +88.8 kB 🔴 +20.1 kB 🔴 +17.2 kB
assets/SubscriptionPanelContentWorkspace-Be4x2US2.js (new) 81.2 kB 🔴 +81.2 kB 🔴 +16.1 kB 🔴 +13.8 kB
assets/SubscriptionPanelContentWorkspace-BUckNZxv.js (removed) 81.2 kB 🟢 -81.2 kB 🟢 -16.1 kB 🟢 -13.9 kB
assets/Load3D-Dr9Nwm91.js (removed) 73.3 kB 🟢 -73.3 kB 🟢 -12.1 kB 🟢 -10.3 kB
assets/Load3D-DtSUBL3S.js (new) 73.3 kB 🔴 +73.3 kB 🔴 +12.1 kB 🔴 +10.3 kB
assets/WidgetVideoEdit-Br5ovtVl.js (removed) 71.2 kB 🟢 -71.2 kB 🟢 -17 kB 🟢 -14.9 kB
assets/WidgetVideoEdit-CJf4qiIK.js (new) 71.2 kB 🔴 +71.2 kB 🔴 +17 kB 🔴 +14.9 kB
assets/SubscriptionTransitionPreviewWorkspace-BRCznFab.js (removed) 66.6 kB 🟢 -66.6 kB 🟢 -13.4 kB 🟢 -11.7 kB
assets/SubscriptionTransitionPreviewWorkspace-BUrykXA2.js (new) 66.6 kB 🔴 +66.6 kB 🔴 +13.5 kB 🔴 +11.7 kB
assets/WorkspaceSettingsPanelContent-C5uBwfmi.js (removed) 58.2 kB 🟢 -58.2 kB 🟢 -12.4 kB 🟢 -10.8 kB
assets/WorkspaceSettingsPanelContent-DxoUnRH_.js (new) 58.2 kB 🔴 +58.2 kB 🔴 +12.4 kB 🔴 +10.8 kB
assets/Preview3d-Cu0ag9jH.js (new) 50.9 kB 🔴 +50.9 kB 🔴 +8.31 kB 🔴 +7.24 kB
assets/Preview3d-hUEc_-Ny.js (removed) 50.9 kB 🟢 -50.9 kB 🟢 -8.32 kB 🟢 -7.24 kB
assets/main-BYSCai7U.js (new) 47.4 kB 🔴 +47.4 kB 🔴 +13.7 kB 🔴 +11.9 kB
assets/main-Ce8blh71.js (removed) 45.4 kB 🟢 -45.4 kB 🟢 -13.2 kB 🟢 -11.5 kB
assets/SubscriptionRequiredDialogContentUnified-BruIpReD.js (new) 42.7 kB 🔴 +42.7 kB 🔴 +9.39 kB 🔴 +8.19 kB
assets/SubscriptionRequiredDialogContentUnified-DjfoPi8p.js (removed) 42.7 kB 🟢 -42.7 kB 🟢 -9.39 kB 🟢 -8.19 kB
assets/LayerEditorContent-CfafkEq4.js (new) 42.5 kB 🔴 +42.5 kB 🔴 +9.62 kB 🔴 +8.45 kB
assets/LayerEditorContent-eg-EAnYG.js (removed) 42.5 kB 🟢 -42.5 kB 🟢 -9.62 kB 🟢 -8.43 kB
assets/WidgetBoundingBoxes-ByZeI6v4.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -9.16 kB 🟢 -8.12 kB
assets/WidgetBoundingBoxes-DbvhaCAA.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +9.16 kB 🔴 +8.12 kB
assets/WidgetPainter-B3vlslkg.js (new) 32.6 kB 🔴 +32.6 kB 🔴 +7.87 kB 🔴 +6.98 kB
assets/WidgetPainter-B7O2UjIR.js (removed) 32.6 kB 🟢 -32.6 kB 🟢 -7.87 kB 🟢 -6.95 kB
assets/Load3dViewerContent-ivt5IA8y.js (new) 30.8 kB 🔴 +30.8 kB 🔴 +6.28 kB 🔴 +5.45 kB
assets/Load3dViewerContent-ZE4aQYEo.js (removed) 30.8 kB 🟢 -30.8 kB 🟢 -6.28 kB 🟢 -5.45 kB
assets/HdrViewerContent-B5ZFcVjw.js (new) 29.8 kB 🔴 +29.8 kB 🔴 +8.25 kB 🔴 +7.28 kB
assets/HdrViewerContent-EoBiIwDW.js (removed) 29.8 kB 🟢 -29.8 kB 🟢 -8.25 kB 🟢 -7.27 kB
assets/SubscriptionRequiredDialogContent-D8kZmPxj.js (new) 26.9 kB 🔴 +26.9 kB 🔴 +6.36 kB 🔴 +5.6 kB
assets/SubscriptionRequiredDialogContent-DOPsNJrq.js (removed) 26.9 kB 🟢 -26.9 kB 🟢 -6.36 kB 🟢 -5.6 kB
assets/SubscriptionRequiredDialogContentWorkspace-Cx9EM52a.js (new) 25.1 kB 🔴 +25.1 kB 🔴 +5.81 kB 🔴 +5.12 kB
assets/SubscriptionRequiredDialogContentWorkspace-DFnDXXiT.js (removed) 25.1 kB 🟢 -25.1 kB 🟢 -5.81 kB 🟢 -5.12 kB
assets/CreditsTile-Qb2Ua5vD.js (new) 24.9 kB 🔴 +24.9 kB 🔴 +6.66 kB 🔴 +5.85 kB
assets/CreditsTile-CqiB76c7.js (removed) 24.9 kB 🟢 -24.9 kB 🟢 -6.65 kB 🟢 -5.84 kB
assets/load3d-B7bsQW-U.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.41 kB 🔴 +4.68 kB
assets/load3d-n9n5VdxJ.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.41 kB 🟢 -4.67 kB
assets/CurrentUserPopoverWorkspace-Bm597eeb.js (removed) 21.9 kB 🟢 -21.9 kB 🟢 -5 kB 🟢 -4.43 kB
assets/SignInContent-B3-zvfb7.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.18 kB 🟢 -4.53 kB
assets/SignInContent-B3UCBvNc.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.18 kB 🔴 +4.54 kB
assets/i18n-CKcspdJI.js (removed) 16.7 kB 🟢 -16.7 kB 🟢 -4.55 kB 🟢 -3.82 kB
assets/i18n-DXl9dHuW.js (new) 16.7 kB 🔴 +16.7 kB 🔴 +4.55 kB 🔴 +3.82 kB
assets/WidgetRecordAudio-ciLoKsC0.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.6 kB 🟢 -4.1 kB
assets/WidgetRecordAudio-DEoeOHr6.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.6 kB 🔴 +4.1 kB
assets/CurrentUserPopoverWorkspace-D1tnYDTd.js (new) 15.8 kB 🔴 +15.8 kB 🔴 +3.86 kB 🔴 +3.42 kB
assets/WidgetInputNumber-Bll73aIj.js (new) 13.9 kB 🔴 +13.9 kB 🔴 +3.63 kB 🔴 +3.21 kB
assets/WidgetInputNumber-KHaZYIIi.js (removed) 13.9 kB 🟢 -13.9 kB 🟢 -3.63 kB 🟢 -3.21 kB
assets/WidgetRange-D_1xlQuP.js (removed) 13.7 kB 🟢 -13.7 kB 🟢 -3.55 kB 🟢 -3.12 kB
assets/WidgetRange-DzVc_Q3J.js (new) 13.7 kB 🔴 +13.7 kB 🔴 +3.55 kB 🔴 +3.13 kB
assets/WaveAudioPlayer-Btz3MFBP.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.46 kB 🟢 -3.03 kB
assets/WaveAudioPlayer-DQm9mDwZ.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.46 kB 🔴 +3.04 kB
assets/WidgetCurve-C9Bv2xs8.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.48 kB 🔴 +3.15 kB
assets/WidgetCurve-CIEPjo2-.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.47 kB 🟢 -3.15 kB
assets/AudioPreviewPlayer-C2CVwXNm.js (new) 10.6 kB 🔴 +10.6 kB 🔴 +3.05 kB 🔴 +2.72 kB
assets/AudioPreviewPlayer-CBRLHZXW.js (removed) 10.6 kB 🟢 -10.6 kB 🟢 -3.05 kB 🟢 -2.74 kB
assets/TeamWorkspacesDialogContent-Bj6xP7Bx.js (removed) 10.3 kB 🟢 -10.3 kB 🟢 -2.97 kB 🟢 -2.63 kB
assets/TeamWorkspacesDialogContent-CuviOjZB.js (new) 10.3 kB 🔴 +10.3 kB 🔴 +2.97 kB 🔴 +2.63 kB
assets/onboardingCloudRoutes-CeFOutEJ.js (removed) 9.49 kB 🟢 -9.49 kB 🟢 -2.85 kB 🟢 -2.44 kB
assets/onboardingCloudRoutes-wQxzZE8L.js (new) 9.49 kB 🔴 +9.49 kB 🔴 +2.85 kB 🔴 +2.44 kB
assets/Load3DConfiguration-BlE92Jxy.js (removed) 8.91 kB 🟢 -8.91 kB 🟢 -2.61 kB 🟢 -2.3 kB
assets/Load3DConfiguration-PGLJ1Kh9.js (new) 8.91 kB 🔴 +8.91 kB 🔴 +2.61 kB 🔴 +2.31 kB
assets/WidgetImageCrop-73pH1Mhk.js (new) 8.49 kB 🔴 +8.49 kB 🔴 +2.66 kB 🔴 +2.34 kB
assets/WidgetImageCrop-DwJjekeh.js (removed) 8.49 kB 🟢 -8.49 kB 🟢 -2.65 kB 🟢 -2.34 kB
assets/SetMemberCreditLimitDialogContent-BvL7pTPM.js (removed) 8.47 kB 🟢 -8.47 kB 🟢 -2.34 kB 🟢 -2.06 kB
assets/SetMemberCreditLimitDialogContent-D24bD7Sz.js (new) 8.47 kB 🔴 +8.47 kB 🔴 +2.34 kB 🔴 +2.05 kB
assets/nodeTemplates-DauWUvPf.js (new) 8.32 kB 🔴 +8.32 kB 🔴 +2.85 kB 🔴 +2.5 kB
assets/nodeTemplates-qrroFxB9.js (removed) 8.32 kB 🟢 -8.32 kB 🟢 -2.86 kB 🟢 -2.51 kB
assets/WorkspaceSwitcherPopover-CmTZ4Br4.js (new) 8.01 kB 🔴 +8.01 kB 🔴 +2.38 kB 🔴 +2.12 kB
assets/NightlySurveyController-DdeHEyo0.js (removed) 7.5 kB 🟢 -7.5 kB 🟢 -2.56 kB 🟢 -2.25 kB
assets/NightlySurveyController-QqEHSHQr.js (new) 7.5 kB 🔴 +7.5 kB 🔴 +2.55 kB 🔴 +2.25 kB
assets/CloudRunButtonWrapper-DWk1yodi.js (new) 7.29 kB 🔴 +7.29 kB 🔴 +2.29 kB 🔴 +2.01 kB
assets/CloudRunButtonWrapper-fvAoIE5C.js (removed) 7.29 kB 🟢 -7.29 kB 🟢 -2.29 kB 🟢 -2.01 kB
assets/WidgetWithControl-AESg2mqL.js (removed) 6.51 kB 🟢 -6.51 kB 🟢 -2.67 kB 🟢 -2.35 kB
assets/WidgetWithControl-CK9K-jKI.js (new) 6.51 kB 🔴 +6.51 kB 🔴 +2.66 kB 🔴 +2.32 kB
assets/missingModelMetadata-CpmCxEZf.js (removed) 6.45 kB 🟢 -6.45 kB 🟢 -2.21 kB 🟢 -1.93 kB
assets/missingModelMetadata-wfrBvJ4b.js (new) 6.45 kB 🔴 +6.45 kB 🔴 +2.21 kB 🔴 +1.93 kB
assets/CancelSubscriptionDialogContent-CKFTVqjj.js (removed) 5.97 kB 🟢 -5.97 kB 🟢 -1.98 kB 🟢 -1.75 kB
assets/CancelSubscriptionDialogContent-Cz6yB_5x.js (new) 5.97 kB 🔴 +5.97 kB 🔴 +1.98 kB 🔴 +1.75 kB
assets/main-CEUpmmm4.js (removed) 5.92 kB 🟢 -5.92 kB 🟢 -1.91 kB 🟢 -1.59 kB
assets/main-n11Ll7sq.js (new) 5.92 kB 🔴 +5.92 kB 🔴 +1.91 kB 🔴 +1.59 kB
assets/load3dPreviewExtensions-B9YZ5852.js (removed) 5.88 kB 🟢 -5.88 kB 🟢 -1.81 kB 🟢 -1.6 kB
assets/load3dPreviewExtensions-DluQep2e.js (new) 5.88 kB 🔴 +5.88 kB 🔴 +1.81 kB 🔴 +1.6 kB
assets/launchCancellationFlow-Bh84GRp8.js (removed) 5.18 kB 🟢 -5.18 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/launchCancellationFlow-CLtaDZLj.js (new) 5.18 kB 🔴 +5.18 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CreateWorkspaceDialogContent-B56N9L91.js (removed) 5.12 kB 🟢 -5.12 kB 🟢 -1.8 kB 🟢 -1.55 kB
assets/CreateWorkspaceDialogContent-yrKbC_D0.js (new) 5.12 kB 🔴 +5.12 kB 🔴 +1.79 kB 🔴 +1.55 kB
assets/ChangeMemberRoleDialogContent-BVCb7T3T.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.64 kB 🔴 +1.43 kB
assets/ChangeMemberRoleDialogContent-DGwi_Onx.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/InviteMemberDialogContent-Dj1NNsSS.js (removed) 4.96 kB 🟢 -4.96 kB 🟢 -1.65 kB 🟢 -1.44 kB
assets/InviteMemberDialogContent-oaJlpgjD.js (new) 4.96 kB 🔴 +4.96 kB 🔴 +1.65 kB 🔴 +1.43 kB
assets/EditWorkspaceDialogContent-Bu33qmPJ.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.76 kB 🟢 -1.52 kB
assets/EditWorkspaceDialogContent-D8mUdiv7.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.76 kB 🔴 +1.53 kB
assets/WidgetTextarea-C8xER7Ba.js (removed) 4.83 kB 🟢 -4.83 kB 🟢 -1.88 kB 🟢 -1.64 kB
assets/WidgetTextarea-M0Jl4TIe.js (new) 4.83 kB 🔴 +4.83 kB 🔴 +1.88 kB 🔴 +1.65 kB
assets/saveMesh-D6r4qtql.js (new) 4.76 kB 🔴 +4.76 kB 🔴 +1.52 kB 🔴 +1.36 kB
assets/saveMesh-DdAbG_v3.js (removed) 4.76 kB 🟢 -4.76 kB 🟢 -1.52 kB 🟢 -1.34 kB
assets/WorkspacePanelContent-B70A3bKd.js (removed) 4.74 kB 🟢 -4.74 kB 🟢 -1.63 kB 🟢 -1.44 kB
assets/WorkspacePanelContent-BzLH5cuw.js (new) 4.74 kB 🔴 +4.74 kB 🔴 +1.62 kB 🔴 +1.44 kB
assets/ValueControlPopover-BfbDxav8.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.55 kB 🔴 +1.38 kB
assets/ValueControlPopover-V8LZqv0M.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.55 kB 🟢 -1.38 kB
assets/ApiNodesSignInContent-D0CA2Ia7.js (new) 4.08 kB 🔴 +4.08 kB 🔴 +1.31 kB 🔴 +1.16 kB
assets/ApiNodesSignInContent-SERbGLjv.js (removed) 4.08 kB 🟢 -4.08 kB 🟢 -1.31 kB 🟢 -1.15 kB
assets/DeleteWorkspaceDialogContent-XvCluFfv.js (removed) 3.84 kB 🟢 -3.84 kB 🟢 -1.44 kB 🟢 -1.24 kB
assets/DeleteWorkspaceDialogContent-YpHAsTqb.js (new) 3.84 kB 🔴 +3.84 kB 🔴 +1.44 kB 🔴 +1.24 kB
assets/RemoveMemberDialogContent-D51L0JAN.js (removed) 3.76 kB 🟢 -3.76 kB 🟢 -1.39 kB 🟢 -1.2 kB
assets/RemoveMemberDialogContent-njciLym2.js (new) 3.76 kB 🔴 +3.76 kB 🔴 +1.39 kB 🔴 +1.2 kB
assets/RevokeInviteDialogContent-B9nKUBXT.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.39 kB 🔴 +1.21 kB
assets/RevokeInviteDialogContent-CdUc4fZQ.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.39 kB 🟢 -1.21 kB
assets/LeaveWorkspaceDialogContent-Bx3hoHFb.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.39 kB 🔴 +1.19 kB
assets/LeaveWorkspaceDialogContent-tk77JW7Y.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.39 kB 🟢 -1.19 kB
assets/InviteMemberUpsellDialogContent--53p20Uh.js (new) 3.47 kB 🔴 +3.47 kB 🔴 +1.24 kB 🔴 +1.09 kB
assets/InviteMemberUpsellDialogContent-D2qAE3zv.js (removed) 3.47 kB 🟢 -3.47 kB 🟢 -1.24 kB 🟢 -1.09 kB
assets/workspaceCheckoutTelemetry-AxmjLFp_.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.52 kB 🔴 +1.32 kB
assets/workspaceCheckoutTelemetry-w91fTtMT.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.52 kB 🟢 -1.32 kB
assets/GlobalToast-C8nzWYiX.js (removed) 3.25 kB 🟢 -3.25 kB 🟢 -1.3 kB 🟢 -1.11 kB
assets/GlobalToast-COwHsDhc.js (new) 3.25 kB 🔴 +3.25 kB 🔴 +1.3 kB 🔴 +1.11 kB
assets/Media3DTop-DkO7i1Uu.js (removed) 3.21 kB 🟢 -3.21 kB 🟢 -1.26 kB 🟢 -1.11 kB
assets/Media3DTop-DLTg15C0.js (new) 3.21 kB 🔴 +3.21 kB 🔴 +1.27 kB 🔴 +1.11 kB
assets/load3dAdvanced-BgOQ4Okv.js (removed) 2.82 kB 🟢 -2.82 kB 🟢 -1.09 kB 🟢 -954 B
assets/load3dAdvanced-CoZe2h4G.js (new) 2.82 kB 🔴 +2.82 kB 🔴 +1.1 kB 🔴 +956 B
assets/SubscribeToRun-2BmxA3bZ.js (removed) 2.39 kB 🟢 -2.39 kB 🟢 -1.04 kB 🟢 -911 B
assets/SubscribeToRun-DDVo4g7e.js (new) 2.39 kB 🔴 +2.39 kB 🔴 +1.04 kB 🔴 +910 B
assets/MediaAudioTop-BvX4NGDm.js (removed) 1.62 kB 🟢 -1.62 kB 🟢 -807 B 🟢 -672 B
assets/MediaAudioTop-Dgrap9yg.js (new) 1.62 kB 🔴 +1.62 kB 🔴 +808 B 🔴 +668 B
assets/signInSchema-0LYBQf_B.js (new) 1.55 kB 🔴 +1.55 kB 🔴 +554 B 🔴 +515 B
assets/signInSchema-CkrGCURU.js (removed) 1.55 kB 🟢 -1.55 kB 🟢 -553 B 🟢 -490 B
assets/cloudSessionCookie-CZoApUqN.js (removed) 933 B 🟢 -933 B 🟢 -430 B 🟢 -393 B
assets/cloudSessionCookie-DVZ4PWEU.js (new) 933 B 🔴 +933 B 🔴 +433 B 🔴 +377 B
assets/cloudBadges-BwvwhGjB.js (removed) 922 B 🟢 -922 B 🟢 -513 B 🟢 -470 B
assets/cloudBadges-CmIjhXW7.js (new) 922 B 🔴 +922 B 🔴 +514 B 🔴 +441 B
assets/Load3DAdvanced-BzFeozx-.js (removed) 761 B 🟢 -761 B 🟢 -423 B 🟢 -361 B
assets/Load3DAdvanced-DdhylK3f.js (new) 761 B 🔴 +761 B 🔴 +423 B 🔴 +359 B
assets/nightlyBadges-B9-ACv8L.js (new) 411 B 🔴 +411 B 🔴 +273 B 🔴 +264 B
assets/nightlyBadges-VaNsuaxP.js (removed) 411 B 🟢 -411 B 🟢 -270 B 🟢 -231 B
assets/Load3dViewerContent-Bt7z16Nw.js (new) 137 B 🔴 +137 B 🔴 +103 B 🔴 +94 B
assets/Load3dViewerContent-DEsJIzdh.js (removed) 137 B 🟢 -137 B 🟢 -103 B 🟢 -106 B
assets/missingModelMetadata-BaHlLjad.js (removed) 125 B 🟢 -125 B 🟢 -103 B 🟢 -103 B
assets/missingModelMetadata-mPAAVZM_.js (new) 125 B 🔴 +125 B 🔴 +103 B 🔴 +103 B
assets/Load3DAdvanced-__pdFxIj.js (removed) 122 B 🟢 -122 B 🟢 -97 B 🟢 -90 B
assets/Load3DAdvanced-CNDAMN_K.js (new) 122 B 🔴 +122 B 🔴 +97 B 🔴 +89 B
assets/WidgetLegacy-DSI69ZKg.js (removed) 117 B 🟢 -117 B 🟢 -106 B 🟢 -104 B
assets/WidgetLegacy-SlYlIcFY.js (new) 117 B 🔴 +117 B 🔴 +106 B 🔴 +103 B
assets/workflowDraftStoreV2-Bqd8cgTg.js (new) 112 B 🔴 +112 B 🔴 +101 B 🔴 +107 B
assets/workflowDraftStoreV2-DxtUL_Vj.js (removed) 112 B 🟢 -112 B 🟢 -101 B 🟢 -110 B
assets/Load3D-Bt_bngRg.js (new) 98 B 🔴 +98 B 🔴 +89 B 🔴 +81 B
assets/Load3D-Ck9fwZW_.js (removed) 98 B 🟢 -98 B 🟢 -89 B 🟢 -88 B
assets/i18n-CncTt5YL.js (removed) 97 B 🟢 -97 B 🟢 -92 B 🟢 -84 B
assets/i18n-DcZHqANb.js (new) 97 B 🔴 +97 B 🔴 +92 B 🔴 +101 B
assets/changeTracker-9i7024OD.js (removed) 91 B 🟢 -91 B 🟢 -93 B 🟢 -85 B
assets/changeTracker-Dp0w4NRP.js (new) 91 B 🔴 +91 B 🔴 +93 B 🔴 +85 B

Status: 77 added / 76 removed / 211 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.3 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.2 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 61.1 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.8 MB heap
large-graph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.0 MB heap
large-graph-pan: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.4 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 73.8 MB heap
legacy-node-drag: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 87.3 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.0 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.3 MB heap
subgraph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.6 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 74.7 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 150ms TBT · 100.9 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 75.4 MB heap
vue-large-graph-idle: · 56.3 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 168.4 MB heap
vue-large-graph-pan: · 56.2 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 306ms TBT · 184.4 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.1 MB heap

⚠️ 12 regressions detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-idle: task duration 578ms 566ms -2% ⚠️ z=5.5
canvas-mouse-sweep: layout duration 4ms 4ms +9% ⚠️ z=3.2
canvas-mouse-sweep: style recalc duration 41ms 49ms +19% ⚠️ z=2.1
canvas-mouse-sweep: task duration 940ms 1051ms +12% ⚠️ z=3.2
canvas-zoom-sweep: layout duration 1ms 1ms +24% ⚠️ z=3.2
canvas-zoom-sweep: task duration 380ms 400ms +5% ⚠️ z=3.2
large-graph-idle: task duration 688ms 724ms +5% ⚠️ z=3.4
large-graph-pan: task duration 1291ms 1318ms +2% ⚠️ z=5.5
minimap-idle: task duration 660ms 711ms +8% ⚠️ z=3.9
subgraph-dom-widget-clipping: task duration 401ms 424ms +6% ⚠️ z=2.5
subgraph-idle: task duration 558ms 591ms +6% ⚠️ z=7.0
workflow-execution: event listeners 49 98 +100% ⚠️ z=10.6
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms +0% z=0.4
canvas-idle: p95 frame time 17ms 17ms -0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 9ms 8ms -8% z=-3.2
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 8 9 +6% z=-4.7
canvas-idle: task duration 578ms 566ms -2% ⚠️ z=5.5
canvas-idle: script duration 12ms 11ms -9% z=-6.4
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 68.3 MB 66.3 MB -3%
canvas-idle: DOM nodes -283 -282 -1% z=-238.4
canvas-idle: event listeners -151 -166 +10% z=-37.5
canvas-mouse-sweep: avg frame time 17ms 17ms +0% z=-0.4
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 4ms 4ms +9% ⚠️ z=3.2
canvas-mouse-sweep: style recalc duration 41ms 49ms +19% ⚠️ z=2.1
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 75 77 +3% z=-0.7
canvas-mouse-sweep: task duration 940ms 1051ms +12% ⚠️ z=3.2
canvas-mouse-sweep: script duration 124ms 122ms -2% z=-2.1
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 68.1 MB 65.2 MB -4%
canvas-mouse-sweep: DOM nodes -281 -281 -0% z=-132.5
canvas-mouse-sweep: event listeners -181 -182 +1% z=-45.7
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 +24% ⚠️ z=3.2
canvas-zoom-sweep: style recalc duration 19ms 19ms -2% z=-0.1
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 32 33 +2% z=2.7
canvas-zoom-sweep: task duration 380ms 400ms +5% ⚠️ z=3.2
canvas-zoom-sweep: script duration 12ms 13ms +6% z=-4.8
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 60.8 MB 61.1 MB +0%
canvas-zoom-sweep: DOM nodes 76 77 +1% z=-3.5
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.2
dom-widget-clipping: p95 frame time 17ms 17ms -0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 8ms 8ms -4% z=-2.9
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 10 11 +5% z=-5.2
dom-widget-clipping: task duration 382ms 386ms +1% z=1.3
dom-widget-clipping: script duration 58ms 58ms -0% z=-3.1
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 68.2 MB 68.8 MB +1%
dom-widget-clipping: DOM nodes 16 17 +6% z=-3.6
dom-widget-clipping: event listeners 2 1 -50% variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=-0.2
large-graph-idle: p95 frame time 17ms 17ms -1%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 9ms 9ms +3% z=-2.7
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 10 +6% z=-6.7
large-graph-idle: task duration 688ms 724ms +5% ⚠️ z=3.4
large-graph-idle: script duration 17ms 18ms +4% z=-8.0
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 66.2 MB 65.0 MB -2%
large-graph-idle: DOM nodes -280 -282 +1% z=-338.8
large-graph-idle: event listeners -149 -165 +11% z=-31.3
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.2
large-graph-pan: p95 frame time 17ms 17ms +0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 15ms 18ms +20% z=0.4
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 70 +2% z=-0.1
large-graph-pan: task duration 1291ms 1318ms +2% ⚠️ z=5.5
large-graph-pan: script duration 352ms 344ms -2% z=-3.2
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 84.4 MB 63.4 MB -25%
large-graph-pan: DOM nodes -282 -280 -1% z=-180.9
large-graph-pan: event listeners -181 -147 -19% z=-183.5
large-graph-zoom: avg frame time 17ms 17ms -0%
large-graph-zoom: p95 frame time 17ms 17ms +0%
large-graph-zoom: layout duration 8ms 9ms +13%
large-graph-zoom: style recalc duration 16ms 17ms +10%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 65 65 +0%
large-graph-zoom: task duration 1469ms 1557ms +6%
large-graph-zoom: script duration 405ms 424ms +5%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 69.9 MB 73.8 MB +6%
large-graph-zoom: DOM nodes -287 -288 +0%
large-graph-zoom: event listeners -181 -169 -7%
legacy-node-drag: avg frame time 17ms 17ms +0%
legacy-node-drag: p95 frame time 17ms 17ms -0%
legacy-node-drag: layout duration 0ms 0ms +0%
legacy-node-drag: style recalc duration 10ms 11ms +5%
legacy-node-drag: layout count 0 0 +0%
legacy-node-drag: style recalc count 45 45 +0%
legacy-node-drag: task duration 1569ms 1544ms -2%
legacy-node-drag: script duration 499ms 491ms -2%
legacy-node-drag: TBT 0ms 0ms +0%
legacy-node-drag: heap used 86.5 MB 87.3 MB +1%
legacy-node-drag: DOM nodes 10 10 +0%
legacy-node-drag: event listeners 186 185 -1%
minimap-idle: avg frame time 17ms 17ms -0% z=-0.4
minimap-idle: p95 frame time 17ms 17ms -1%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 8ms 8ms +1% z=-1.6
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 8 9 +13% z=-0.8
minimap-idle: task duration 660ms 711ms +8% ⚠️ z=3.9
minimap-idle: script duration 20ms 18ms -13% z=-8.1
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 68.4 MB 63.0 MB -8%
minimap-idle: DOM nodes -278 -279 +0% z=-218.0
minimap-idle: event listeners -149 -163 +9% z=-253.8
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.7
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms +0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 11ms 11ms +1% z=-2.3
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 46 46 -1% z=-4.2
subgraph-dom-widget-clipping: task duration 401ms 424ms +6% ⚠️ z=2.5
subgraph-dom-widget-clipping: script duration 119ms 126ms +6% z=-0.3
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 69.6 MB 69.3 MB -0%
subgraph-dom-widget-clipping: DOM nodes 18 17 -6% z=-4.6
subgraph-dom-widget-clipping: event listeners 6 7 +17% z=-1.6
subgraph-idle: avg frame time 17ms 17ms -0% z=-0.2
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 10ms 9ms -11% z=-2.4
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 9 9 -6% z=-3.7
subgraph-idle: task duration 558ms 591ms +6% ⚠️ z=7.0
subgraph-idle: script duration 10ms 10ms +5% z=-3.8
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 59.5 MB 58.6 MB -2%
subgraph-idle: DOM nodes -280 -282 +1% z=-203.2
subgraph-idle: event listeners -151 -166 +10% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.8
subgraph-mouse-sweep: p95 frame time 17ms 17ms +0%
subgraph-mouse-sweep: layout duration 5ms 5ms +3% z=1.0
subgraph-mouse-sweep: style recalc duration 39ms 41ms +5% z=-0.6
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 75 76 +1% z=-2.4
subgraph-mouse-sweep: task duration 865ms 876ms +1% z=1.6
subgraph-mouse-sweep: script duration 99ms 93ms -5% z=-1.2
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 64.1 MB 74.7 MB +17%
subgraph-mouse-sweep: DOM nodes -283 -282 -1% z=-155.9
subgraph-mouse-sweep: event listeners -183 -151 -17% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms +0%
subgraph-transition-enter: p95 frame time 17ms 17ms +0%
subgraph-transition-enter: layout duration 16ms 15ms -7%
subgraph-transition-enter: style recalc duration 34ms 33ms -3%
subgraph-transition-enter: layout count 16 12 -25%
subgraph-transition-enter: style recalc count 21 17 -19%
subgraph-transition-enter: task duration 1002ms 1063ms +6%
subgraph-transition-enter: script duration 18ms 23ms +27%
subgraph-transition-enter: TBT 151ms 150ms -1%
subgraph-transition-enter: heap used 83.8 MB 100.9 MB +20%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2375 2373 -0%
viewport-pan-sweep: avg frame time 17ms 17ms +0%
viewport-pan-sweep: p95 frame time 17ms 17ms +0%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 41ms 46ms +13%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 249 -1%
viewport-pan-sweep: task duration 4514ms 4608ms +2%
viewport-pan-sweep: script duration 1101ms 1062ms -4%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 68.7 MB 75.4 MB +10%
viewport-pan-sweep: DOM nodes -277 -264 -5%
viewport-pan-sweep: event listeners -135 -132 -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 17155ms 18148ms +6%
vue-large-graph-idle: script duration 131ms 136ms +4%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 170.8 MB 168.4 MB -1%
vue-large-graph-idle: DOM nodes -8312 -8312 +0%
vue-large-graph-idle: event listeners -16387 -16387 +0%
vue-large-graph-pan: avg frame time 18ms 18ms +0%
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 20ms 27ms +30%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 173 181 +5%
vue-large-graph-pan: task duration 20765ms 23381ms +13%
vue-large-graph-pan: script duration 446ms 493ms +11%
vue-large-graph-pan: TBT 103ms 306ms +197%
vue-large-graph-pan: heap used 177.6 MB 184.4 MB +4%
vue-large-graph-pan: DOM nodes -8312 -8314 +0%
vue-large-graph-pan: event listeners -16383 -16381 -0%
workflow-execution: avg frame time 17ms 17ms +0% z=0.6
workflow-execution: p95 frame time 17ms 17ms -0%
workflow-execution: layout duration 1ms 1ms -3% z=-2.6
workflow-execution: style recalc duration 21ms 22ms +2% z=-1.2
workflow-execution: layout count 2 4 +75% z=-2.7
workflow-execution: style recalc count 10 14 +35% z=-2.1
workflow-execution: task duration 107ms 115ms +8% z=-0.7
workflow-execution: script duration 7ms 9ms +28% z=-6.9
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 61.7 MB 63.1 MB +2%
workflow-execution: DOM nodes 132 134 +1% z=-3.8
workflow-execution: event listeners 49 98 +100% ⚠️ z=10.6
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN MB
canvas-zoom-sweep: DOM nodes ▄▃▁▅█▁▃▆▄▅▅▃▃▄▃ ➡️ 79
canvas-zoom-sweep: event listeners ▁▁▂▅█▂▁▅▁▅▅▄▁▅▁ ➡️ 19
dom-widget-clipping: avg frame time ▂▄▅▅▂▄█▇▅▇▇▅▅▁▇ ➡️ 17ms
dom-widget-clipping: p95 frame time ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-08-20T17:42:35.749Z",
  "gitSha": "42b3ecbb17159bd9449f082abdc38c55ebc3b72e",
  "branch": "dante01yoon/fe-1584-local-workspace-switcher",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2058.4240000000023,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.496000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 540.653,
      "heapDeltaBytes": -1072440,
      "heapUsedBytes": 60951752,
      "domNodes": -281,
      "jsHeapTotalBytes": 4448256,
      "scriptDurationMs": 8.683,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2090.787999999975,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.528,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 590.409,
      "heapDeltaBytes": 16690652,
      "heapUsedBytes": 78092720,
      "domNodes": -282,
      "jsHeapTotalBytes": 3661824,
      "scriptDurationMs": 13.499999999999998,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2144.672000000014,
      "styleRecalcs": 79,
      "styleRecalcDurationMs": 54.039,
      "layouts": 12,
      "layoutDurationMs": 4.3309999999999995,
      "taskDurationMs": 1101.875,
      "heapDeltaBytes": 6694228,
      "heapUsedBytes": 68776048,
      "domNodes": -281,
      "jsHeapTotalBytes": 6545408,
      "scriptDurationMs": 127.53799999999998,
      "eventListeners": -183,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1945.1340000000528,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 44.612,
      "layouts": 12,
      "layoutDurationMs": 4.138999999999999,
      "taskDurationMs": 1000.4660000000001,
      "heapDeltaBytes": 7337040,
      "heapUsedBytes": 68032848,
      "domNodes": -280,
      "jsHeapTotalBytes": 6283264,
      "scriptDurationMs": 115.74099999999999,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1726.9039999999904,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 18.317999999999998,
      "layouts": 6,
      "layoutDurationMs": 0.753,
      "taskDurationMs": 373.328,
      "heapDeltaBytes": 2463904,
      "heapUsedBytes": 63799608,
      "domNodes": 76,
      "jsHeapTotalBytes": 4718592,
      "scriptDurationMs": 11.406,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1740.9860000000208,
      "styleRecalcs": 33,
      "styleRecalcDurationMs": 19.569000000000003,
      "layouts": 6,
      "layoutDurationMs": 0.8210000000000001,
      "taskDurationMs": 427.29200000000003,
      "heapDeltaBytes": 3143196,
      "heapUsedBytes": 64245288,
      "domNodes": 77,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 13.804,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 588.5820000000308,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.085,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 381.14699999999993,
      "heapDeltaBytes": 10386360,
      "heapUsedBytes": 72087296,
      "domNodes": 18,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 57.074,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 610.6969999999592,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 7.069000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 391.19200000000006,
      "heapDeltaBytes": 10778500,
      "heapUsedBytes": 72139640,
      "domNodes": 16,
      "jsHeapTotalBytes": 4718592,
      "scriptDurationMs": 58.555,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2037.8429999999526,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.293,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 652.899,
      "heapDeltaBytes": -8024832,
      "heapUsedBytes": 67758720,
      "domNodes": -282,
      "jsHeapTotalBytes": -528384,
      "scriptDurationMs": 16.637,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2058.854999999994,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 9.418,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 794.66,
      "heapDeltaBytes": -7335292,
      "heapUsedBytes": 68497628,
      "domNodes": -281,
      "jsHeapTotalBytes": -1839104,
      "scriptDurationMs": 19.496,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2150.3809999999817,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 17.751999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1210.8,
      "heapDeltaBytes": -13027676,
      "heapUsedBytes": 63451496,
      "domNodes": -281,
      "jsHeapTotalBytes": 2093056,
      "scriptDurationMs": 320.69499999999994,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2537.992000000031,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 17.461000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1425.367,
      "heapDeltaBytes": -7124820,
      "heapUsedBytes": 69519132,
      "domNodes": -278,
      "jsHeapTotalBytes": -303104,
      "scriptDurationMs": 367.348,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3180.2959999999985,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 17.137999999999998,
      "layouts": 60,
      "layoutDurationMs": 8.886000000000001,
      "taskDurationMs": 1418.779,
      "heapDeltaBytes": -11924128,
      "heapUsedBytes": 66105392,
      "domNodes": -287,
      "jsHeapTotalBytes": 5500928,
      "scriptDurationMs": 402.804,
      "eventListeners": -185,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3719.600000000014,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 17.146,
      "layouts": 60,
      "layoutDurationMs": 9.269,
      "taskDurationMs": 1695.8489999999997,
      "heapDeltaBytes": 10616832,
      "heapUsedBytes": 88687640,
      "domNodes": -288,
      "jsHeapTotalBytes": 4976640,
      "scriptDurationMs": 446.099,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333338,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "legacy-node-drag",
      "durationMs": 2189.9740000000065,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 9.850999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1433.403,
      "heapDeltaBytes": 11357372,
      "heapUsedBytes": 91032124,
      "domNodes": 10,
      "jsHeapTotalBytes": 7532544,
      "scriptDurationMs": 460.71599999999995,
      "eventListeners": 184,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "legacy-node-drag",
      "durationMs": 2809.6719999999777,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 11.242000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1653.601,
      "heapDeltaBytes": 13351316,
      "heapUsedBytes": 92105716,
      "domNodes": 10,
      "jsHeapTotalBytes": 7270400,
      "scriptDurationMs": 520.432,
      "eventListeners": 186,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2037.17800000004,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.758000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 619.6189999999999,
      "heapDeltaBytes": -12910020,
      "heapUsedBytes": 68919132,
      "domNodes": -278,
      "jsHeapTotalBytes": 4190208,
      "scriptDurationMs": 15.53,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2039.4619999999577,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.805,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 802.816,
      "heapDeltaBytes": -13446352,
      "heapUsedBytes": 63279212,
      "domNodes": -280,
      "jsHeapTotalBytes": 3403776,
      "scriptDurationMs": 20.005,
      "eventListeners": -179,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 607.3450000000093,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 9.644,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 408.6360000000001,
      "heapDeltaBytes": 10802980,
      "heapUsedBytes": 72298468,
      "domNodes": 16,
      "jsHeapTotalBytes": 4718592,
      "scriptDurationMs": 123.399,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 646.3380000000143,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 11.523000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 440.341,
      "heapDeltaBytes": 11709208,
      "heapUsedBytes": 73091252,
      "domNodes": 18,
      "jsHeapTotalBytes": 6029312,
      "scriptDurationMs": 128.96,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2045.4110000000014,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.055,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 542.7850000000001,
      "heapDeltaBytes": 5293424,
      "heapUsedBytes": 66812100,
      "domNodes": -282,
      "jsHeapTotalBytes": 4186112,
      "scriptDurationMs": 8.245000000000003,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2036.6510000000062,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 9.054,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 639.744,
      "heapDeltaBytes": -5222308,
      "heapUsedBytes": 56111052,
      "domNodes": -282,
      "jsHeapTotalBytes": 4186112,
      "scriptDurationMs": 11.899,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1728.1639999999925,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 37.962999999999994,
      "layouts": 16,
      "layoutDurationMs": 4.887,
      "taskDurationMs": 814.5769999999999,
      "heapDeltaBytes": 19770300,
      "heapUsedBytes": 80860212,
      "domNodes": -281,
      "jsHeapTotalBytes": 4710400,
      "scriptDurationMs": 87.727,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1810.0470000000541,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 43.189,
      "layouts": 16,
      "layoutDurationMs": 5.180000000000001,
      "taskDurationMs": 936.5159999999998,
      "heapDeltaBytes": 14220860,
      "heapUsedBytes": 75843308,
      "domNodes": -282,
      "jsHeapTotalBytes": 5496832,
      "scriptDurationMs": 98.552,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1466.6220000000294,
      "styleRecalcs": 17,
      "styleRecalcDurationMs": 33.11300000000001,
      "layouts": 12,
      "layoutDurationMs": 14.804999999999998,
      "taskDurationMs": 1062.8950000000002,
      "heapDeltaBytes": 22139092,
      "heapUsedBytes": 105780260,
      "domNodes": 13673,
      "jsHeapTotalBytes": 11534336,
      "scriptDurationMs": 23.25399999999999,
      "eventListeners": 2373,
      "totalBlockingTimeMs": 150,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8274.954999999976,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 44.403999999999996,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4275.621,
      "heapDeltaBytes": 70184,
      "heapUsedBytes": 75763636,
      "domNodes": -280,
      "jsHeapTotalBytes": -827392,
      "scriptDurationMs": 996.9820000000001,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 9093.507000000045,
      "styleRecalcs": 248,
      "styleRecalcDurationMs": 47.86399999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4941.05,
      "heapDeltaBytes": 6466504,
      "heapUsedBytes": 82344404,
      "domNodes": -247,
      "jsHeapTotalBytes": 188416,
      "scriptDurationMs": 1126.1889999999999,
      "eventListeners": -131,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 18716.218000000026,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 17785.894,
      "heapDeltaBytes": -30985792,
      "heapUsedBytes": 178540060,
      "domNodes": -8312,
      "jsHeapTotalBytes": -17240064,
      "scriptDurationMs": 129.386,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.779999999999927,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 19051.71100000007,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 18510.806000000004,
      "heapDeltaBytes": -34786364,
      "heapUsedBytes": 174561584,
      "domNodes": -8312,
      "jsHeapTotalBytes": -22220800,
      "scriptDurationMs": 143.36100000000002,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.77333333333336,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 23548.78500000001,
      "styleRecalcs": 180,
      "styleRecalcDurationMs": 24.638000000000048,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 23058.184,
      "heapDeltaBytes": -14783352,
      "heapUsedBytes": 193641496,
      "domNodes": -8316,
      "jsHeapTotalBytes": -15179776,
      "scriptDurationMs": 479.34299999999996,
      "eventListeners": -16381,
      "totalBlockingTimeMs": 358,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 24228.174999999967,
      "styleRecalcs": 182,
      "styleRecalcDurationMs": 28.577999999999992,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 23703.579999999998,
      "heapDeltaBytes": -42965380,
      "heapUsedBytes": 193021148,
      "domNodes": -8312,
      "jsHeapTotalBytes": -12558336,
      "scriptDurationMs": 507.15600000000006,
      "eventListeners": -16381,
      "totalBlockingTimeMs": 253,
      "frameDurationMs": 17.77666666666652,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 487.83800000001065,
      "styleRecalcs": 15,
      "styleRecalcDurationMs": 23.806,
      "layouts": 4,
      "layoutDurationMs": 1.7089999999999999,
      "taskDurationMs": 123.77500000000002,
      "heapDeltaBytes": 5135972,
      "heapUsedBytes": 66233812,
      "domNodes": 146,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 9.829,
      "eventListeners": 99,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 479.07999999995354,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 19.548,
      "layouts": 3,
      "layoutDurationMs": 0.637,
      "taskDurationMs": 106.57900000000001,
      "heapDeltaBytes": 4932668,
      "heapUsedBytes": 66140436,
      "domNodes": 121,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 7.488999999999999,
      "eventListeners": 97,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    }
  ]
}

@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: 2

🤖 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 `@src/platform/workspace/api/workspaceApi.ts`:
- Line 181: Ensure unified cloud authentication completes token minting before
workspace discovery initializes. Update the login flow around mintAtLogin() to
await the mint before WorkspaceAuthGate initializes the workspace store, or make
getWorkspaceAuthHeaderOrThrow() wait for the in-flight mint before returning a
header; preserve the legacy Firebase path for Local/Desktop users.

In `@src/platform/workspace/stores/teamWorkspaceStore.ts`:
- Around line 418-428: Replace the direct workspace removal, active-workspace
assignment, and last-workspace persistence in the local fallback and switch
paths of the workspace store with serializable, deterministic, idempotent
command batches. Validate and execute those batches through the existing command
executor so entity updates and authentication/persistence effects are
replayable, undoable, and CRDT-transmittable, while preserving the current
personal-workspace fallback behavior.
🪄 Autofix

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: b5972cb4-dd27-49a9-b156-d0d048e2dcc4

📥 Commits

Reviewing files that changed from the base of the PR and between b72bdea and 82d7f23.

📒 Files selected for processing (39)
  • src/components/topbar/CurrentUserButton.test.ts
  • src/components/topbar/CurrentUserButton.vue
  • src/components/topbar/CurrentUserPopoverLegacy.test.ts
  • src/components/topbar/CurrentUserPopoverLegacy.vue
  • src/composables/billing/useBillingRouting.test.ts
  • src/composables/billing/useBillingRouting.ts
  • src/config/comfyApi.test.ts
  • src/config/comfyApi.ts
  • src/platform/cloud/subscription/components/PricingTable.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.test.ts
  • src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.ts
  • src/platform/workflow/persistence/base/storageKeys.test.ts
  • src/platform/workflow/persistence/base/storageKeys.ts
  • src/platform/workspace/api/workspaceApi.test.ts
  • src/platform/workspace/api/workspaceApi.ts
  • src/platform/workspace/api/workspaceApiUrl.test.ts
  • src/platform/workspace/api/workspaceApiUrl.ts
  • src/platform/workspace/auth/WorkspaceAuthGate.test.ts
  • src/platform/workspace/auth/WorkspaceAuthGate.vue
  • src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts
  • src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
  • src/platform/workspace/components/WorkspaceSwitcherPopover.test.ts
  • src/platform/workspace/components/WorkspaceSwitcherPopover.vue
  • src/platform/workspace/stores/billingOperationStore.test.ts
  • src/platform/workspace/stores/billingOperationStore.ts
  • src/platform/workspace/stores/teamWorkspaceStore.test.ts
  • src/platform/workspace/stores/teamWorkspaceStore.ts
  • src/platform/workspace/stores/useWorkspaceAuth.test.ts
  • src/platform/workspace/stores/workspaceAuthStore.ts
  • src/scripts/app.test.ts
  • src/scripts/app.ts
  • src/services/customerEventsService.test.ts
  • src/services/customerEventsService.ts
  • src/stores/__tests__/authTokenPriority.test.ts
  • src/stores/authStore.test.ts
  • src/stores/authStore.ts
  • src/vite-env.d.ts
💤 Files with no reviewable changes (1)
  • src/composables/billing/useBillingRouting.ts

Comment thread src/platform/workspace/api/workspaceApi.ts
Comment thread src/platform/workspace/stores/teamWorkspaceStore.ts
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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: 2

🤖 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 `@src/platform/workspace/auth/WorkspaceAuthGate.vue`:
- Around line 103-107: The non-cloud initialization flow in initialize and
initializeWorkspacesInBackground must be cancellable and deduplicated per
authenticated user. Track the single in-flight operation with the existing
initializationGeneration or an abort signal, invalidate it on logout,
currentUser changes, and component unmount, and validate ownership before
initializeWorkspaceMode mutates state. Ensure the mount path and currentUser
watcher reuse the same operation, and add coverage for cancellation during
unmount/logout and auth hydration triggering both entry points.

In `@src/stores/__tests__/authTokenPriority.test.ts`:
- Around line 280-289: Update the “uses Firebase before workspace
initialization” test setup to set mockTeamWorkspaceInitState to “uninitialized”
before calling store.getWorkspaceAuthHeader() and store.getWorkspaceAuthToken().
Keep the existing Firebase-token assertions so the test exercises the
uninitialized workspace behavior rather than the inherited ready state.
🪄 Autofix

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: d55f66f1-274a-44f2-81c0-82bcb03d520a

📥 Commits

Reviewing files that changed from the base of the PR and between b72bdea and f027006.

📒 Files selected for processing (39)
  • src/components/topbar/CurrentUserButton.test.ts
  • src/components/topbar/CurrentUserButton.vue
  • src/components/topbar/CurrentUserPopoverLegacy.test.ts
  • src/components/topbar/CurrentUserPopoverLegacy.vue
  • src/composables/billing/useBillingRouting.test.ts
  • src/composables/billing/useBillingRouting.ts
  • src/config/comfyApi.test.ts
  • src/config/comfyApi.ts
  • src/platform/cloud/subscription/components/PricingTable.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.test.ts
  • src/platform/cloud/subscription/utils/subscriptionCheckoutUtil.ts
  • src/platform/workflow/persistence/base/storageKeys.test.ts
  • src/platform/workflow/persistence/base/storageKeys.ts
  • src/platform/workspace/api/workspaceApi.test.ts
  • src/platform/workspace/api/workspaceApi.ts
  • src/platform/workspace/api/workspaceApiUrl.test.ts
  • src/platform/workspace/api/workspaceApiUrl.ts
  • src/platform/workspace/auth/WorkspaceAuthGate.test.ts
  • src/platform/workspace/auth/WorkspaceAuthGate.vue
  • src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts
  • src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue
  • src/platform/workspace/components/WorkspaceSwitcherPopover.test.ts
  • src/platform/workspace/components/WorkspaceSwitcherPopover.vue
  • src/platform/workspace/stores/billingOperationStore.test.ts
  • src/platform/workspace/stores/billingOperationStore.ts
  • src/platform/workspace/stores/teamWorkspaceStore.test.ts
  • src/platform/workspace/stores/teamWorkspaceStore.ts
  • src/platform/workspace/stores/useWorkspaceAuth.test.ts
  • src/platform/workspace/stores/workspaceAuthStore.ts
  • src/scripts/app.test.ts
  • src/scripts/app.ts
  • src/services/customerEventsService.test.ts
  • src/services/customerEventsService.ts
  • src/stores/__tests__/authTokenPriority.test.ts
  • src/stores/authStore.test.ts
  • src/stores/authStore.ts
  • src/vite-env.d.ts
💤 Files with no reviewable changes (1)
  • src/composables/billing/useBillingRouting.ts

Comment thread src/platform/workspace/auth/WorkspaceAuthGate.vue
Comment thread src/stores/__tests__/authTokenPriority.test.ts Outdated
@github-actions github-actions Bot added the risk:R3 PR risk grade (advisory shadow check; grader-owned) label Aug 13, 2026

@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: 2

🤖 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 `@src/platform/workspace/stores/teamWorkspaceStore.test.ts`:
- Around line 314-330: Update the test around
useTeamWorkspaceStore().initialize() so it waits until mockWorkspaceApi.list has
been called and resolveList has been assigned before invoking the deferred
resolver. Then await both initialization promises and retain the existing
single-call and ready-state assertions.

In `@src/stores/__tests__/authTokenPriority.test.ts`:
- Around line 317-323: Update the test covering workspace initialization errors
to start with mockTeamWorkspaceInitState set to 'uninitialized' and configure
mockInitializeWorkspaces to reject. Assert getWorkspaceAuthToken() resolves to
undefined and neither mockUser.getIdToken nor mockEnsureWorkspaceToken is
called, ensuring the rejected initialize() path and its catch handling are
exercised.
🪄 Autofix

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: 3ad84c9c-5800-4f89-a12c-c2fce50b32f2

📥 Commits

Reviewing files that changed from the base of the PR and between 12e926b and 8070e42.

📒 Files selected for processing (5)
  • src/platform/workspace/stores/teamWorkspaceStore.test.ts
  • src/platform/workspace/stores/teamWorkspaceStore.ts
  • src/scripts/app.test.ts
  • src/stores/__tests__/authTokenPriority.test.ts
  • src/stores/authStore.ts

Comment thread src/platform/workspace/stores/teamWorkspaceStore.test.ts
Comment thread src/stores/__tests__/authTokenPriority.test.ts
@dante01yoon
dante01yoon marked this pull request as ready for review August 13, 2026 17:33
@dante01yoon
dante01yoon requested a review from a team August 13, 2026 17:33
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Aug 13, 2026
@dante01yoon dante01yoon added needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch core/1.50 Backport PRs for core 1.50 cloud/1.50 Backport PRs for cloud 1.50 labels Aug 13, 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.

Unit tests are failing

@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.81633% with 18 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/stores/authStore.ts 83.33% 8 Missing ⚠️
src/platform/workspace/auth/WorkspaceAuthGate.vue 89.47% 4 Missing ⚠️
...rc/platform/workspace/stores/teamWorkspaceStore.ts 91.89% 3 Missing ⚠️
...rc/platform/workspace/stores/workspaceAuthStore.ts 85.71% 2 Missing ⚠️
src/config/comfyApi.ts 85.71% 1 Missing ⚠️
@@            Coverage Diff             @@
##             main   #15164      +/-   ##
==========================================
+ Coverage   80.01%   81.08%   +1.06%     
==========================================
  Files        2213     1887     -326     
  Lines      130727   123117    -7610     
  Branches    42189    37955    -4234     
==========================================
- Hits       104606    99833    -4773     
+ Misses      25476    22787    -2689     
+ Partials      645      497     -148     
Flag Coverage Δ
unit 73.30% <90.81%> (+0.03%) ⬆️
website-unit ?

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

Files with missing lines Coverage Δ
src/components/topbar/CurrentUserButton.vue 66.07% <100.00%> (-27.55%) ⬇️
src/components/topbar/CurrentUserPopoverLegacy.vue 51.51% <100.00%> (-0.28%) ⬇️
src/composables/billing/useBillingRouting.ts 92.59% <ø> (-7.41%) ⬇️
src/composables/useFeatureFlags.ts 79.53% <100.00%> (+3.50%) ⬆️
.../cloud/subscription/composables/useSubscription.ts 82.62% <100.00%> (-6.79%) ⬇️
...oud/subscription/utils/subscriptionCheckoutUtil.ts 91.66% <100.00%> (ø)
.../platform/workflow/persistence/base/storageKeys.ts 100.00% <100.00%> (+6.45%) ⬆️
src/platform/workspace/api/workspaceApi.ts 45.51% <100.00%> (-12.91%) ⬇️
src/platform/workspace/api/workspaceApiUrl.ts 100.00% <100.00%> (ø)
...rkspace/components/CurrentUserPopoverWorkspace.vue 81.20% <100.00%> (+1.64%) ⬆️
... and 10 more

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

@dante01yoon

dante01yoon commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

AS IS → TO BE: local workspace switcher

These screenshots were captured from the actual running local ComfyUI app with the same authenticated user and workspace data on both branches.

This PR is the functional baseline for local workspace switching. Alex's stacked PR, #15438, keeps this switching behavior unchanged and adds only the local-specific scope explanation from DES-787.

AS IS — #15164 running app

AS IS — #15164 in the running local ComfyUI app

  • Local reuses the Cloud workspace rows and selection interaction.
  • Switching selects the workspace whose credits are used.
  • The menu does not yet explain that local workflows, settings, and output location remain unchanged.

TO BE — #15438 running app

TO BE — #15438 in the running local ComfyUI app

  • Keeps the same rows and switching behavior from this PR.
  • Adds the local-only caption: “Workspaces only affect which credits you use.”
  • Adds an info tooltip explaining that partner-node runs spend credits from the selected workspace, while local output continues to use the usual output folder.
  • Does not add a new auth layer or change the Cloud switcher.

Review split: review this PR for the switching implementation; review #15438 separately for the focused design/copy delta.

comfydesigner and others added 3 commits August 20, 2026 10:53
## Summary

Stacked on #15164. Adds the local-only scope framing to the workspace
switcher menu, per
[DES-787](https://linear.app/comfyorg/issue/DES-787/local-workspace-switcher-menu-credits-source-rows-one-workspace-state)
/
[FE-1584](https://linear.app/comfyorg/issue/FE-1584/add-workspace-switcher-to-localdesktop-credits-only-no-settings).
Design: [Menu States
(6245-41540)](https://www.figma.com/design/CkFTD4c20PyRGpNVAJgpfV/Team-Plan---Workspaces?node-id=6245-41540).

## Behavioral spec

1. On local, the workspace switcher picks whose credits you spend —
nothing else (shipped by #15164; unchanged here).
2. Workspace rows are identical to cloud: name, role, check on the
active row.
3. The scope explainer, off cloud only: the "Workspaces only affect
which credits you use." caption, whose info icon carries the full
tooltip ("Runs that use partner nodes spend credits from this workspace.
Unlike on Cloud, every workspace saves to your usual output folder."),
positioned left so the rows stay visible during hover.
4. No "manage workspaces" entry on local (already gated `isCloud` by
#15164; unchanged here).

## Deferred: per-row credit balances

Earlier commits on this branch built the designed per-row balances
(read-only token mint + balance fetch per workspace, 60s cache) and then
removed them — deferred post-V1 so local rows stay in parity with
cloud's switcher. Deferring also drops this PR's interim fetch pattern
and its two open dependencies: confirming the balance endpoint applies
the member min-rule per identity, and the eventual balance field on the
workspace list response. The implementation is intact in this branch's
history for the follow-up.

## Verification

- `pnpm test:unit` — popover suite 10 passed (scope framing off-cloud,
rows/roles, cloud unaffected).
- Cloud behavior unchanged: caption/tooltip are `!isCloud` only; no
balance fetches on any distribution; create-workspace button untouched.
@dante01yoon

Copy link
Copy Markdown
Collaborator Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

@dante01yoon
dante01yoon added this pull request to the merge queue Aug 21, 2026
@dante01yoon dante01yoon added core/1.50 Backport PRs for core 1.50 cloud/1.50 Backport PRs for cloud 1.50 labels Aug 21, 2026
Merged via the queue into main with commit 848cd39 Aug 21, 2026
94 of 96 checks passed
@dante01yoon
dante01yoon deleted the dante01yoon/fe-1584-local-workspace-switcher branch August 21, 2026 01:49
@github-actions

Copy link
Copy Markdown

⚠️ Backport to core/1.50 failed

Reason: Merge conflicts detected during cherry-pick of 848cd39

The auto-backport could not be completed automatically. Please backport
manually onto branch backport-15164-to-core-1.50 (from origin/core/1.50) and
open a PR to core/1.50.

This may be a stacking conflict rather than a real one. #15513, #15511, #15340 are still open against core/1.50. If this PR sits on top of any of them, the conflict will disappear once they merge — wait for that, then remove and re-add the needs-backport label to re-run this workflow.

📄 Conflicting files
src/components/topbar/CurrentUserPopoverLegacy.test.ts
src/components/topbar/CurrentUserPopoverLegacy.vue
src/composables/billing/useBillingRouting.ts
src/platform/workspace/api/workspaceApi.test.ts
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts
src/platform/workspace/stores/billingOperationStore.test.ts
src/platform/workspace/stores/teamWorkspaceStore.test.ts
src/platform/workspace/stores/teamWorkspaceStore.ts
src/platform/workspace/stores/useWorkspaceAuth.test.ts
src/scripts/app.test.ts
src/services/customerEventsService.test.ts
🤖 Prompt for AI Agents
Backport PR #15164 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/15164) to core/1.50.
Cherry-pick merge commit 848cd39ed06a2da6fea389305cf7210a0a18c5ee onto new branch
backport-15164-to-core-1.50 from origin/core/1.50.
Resolve conflicts in: src/components/topbar/CurrentUserPopoverLegacy.test.ts src/components/topbar/CurrentUserPopoverLegacy.vue src/composables/billing/useBillingRouting.ts src/platform/workspace/api/workspaceApi.test.ts src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts src/platform/workspace/stores/billingOperationStore.test.ts src/platform/workspace/stores/teamWorkspaceStore.test.ts src/platform/workspace/stores/teamWorkspaceStore.ts src/platform/workspace/stores/useWorkspaceAuth.test.ts src/scripts/app.test.ts src/services/customerEventsService.test.ts .

> **This may be a stacking conflict rather than a real one.** #15513, #15511, #15340 are still open against `core/1.50`. If this PR sits on top of any of them, the conflict will disappear once they merge — wait for that, then remove and re-add the `needs-backport` label to re-run this workflow.

For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport core/1.50] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @dante01yoon

@github-actions

Copy link
Copy Markdown

⚠️ Backport to cloud/1.50 failed

Reason: Merge conflicts detected during cherry-pick of 848cd39

The auto-backport could not be completed automatically. Please backport
manually onto branch backport-15164-to-cloud-1.50 (from origin/cloud/1.50) and
open a PR to cloud/1.50.

This may be a stacking conflict rather than a real one. #15514, #15512, #15341 are still open against cloud/1.50. If this PR sits on top of any of them, the conflict will disappear once they merge — wait for that, then remove and re-add the needs-backport label to re-run this workflow.

📄 Conflicting files
src/components/topbar/CurrentUserPopoverLegacy.test.ts
src/components/topbar/CurrentUserPopoverLegacy.vue
src/composables/billing/useBillingRouting.ts
src/platform/workspace/api/workspaceApi.test.ts
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts
src/platform/workspace/stores/billingOperationStore.test.ts
src/platform/workspace/stores/teamWorkspaceStore.test.ts
src/platform/workspace/stores/teamWorkspaceStore.ts
src/platform/workspace/stores/useWorkspaceAuth.test.ts
src/scripts/app.test.ts
src/services/customerEventsService.test.ts
🤖 Prompt for AI Agents
Backport PR #15164 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/15164) to cloud/1.50.
Cherry-pick merge commit 848cd39ed06a2da6fea389305cf7210a0a18c5ee onto new branch
backport-15164-to-cloud-1.50 from origin/cloud/1.50.
Resolve conflicts in: src/components/topbar/CurrentUserPopoverLegacy.test.ts src/components/topbar/CurrentUserPopoverLegacy.vue src/composables/billing/useBillingRouting.ts src/platform/workspace/api/workspaceApi.test.ts src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts src/platform/workspace/stores/billingOperationStore.test.ts src/platform/workspace/stores/teamWorkspaceStore.test.ts src/platform/workspace/stores/teamWorkspaceStore.ts src/platform/workspace/stores/useWorkspaceAuth.test.ts src/scripts/app.test.ts src/services/customerEventsService.test.ts .

> **This may be a stacking conflict rather than a real one.** #15514, #15512, #15341 are still open against `cloud/1.50`. If this PR sits on top of any of them, the conflict will disappear once they merge — wait for that, then remove and re-add the `needs-backport` label to re-run this workflow.

For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport cloud/1.50] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @dante01yoon

comfy-pr-bot pushed a commit that referenced this pull request Aug 21, 2026
…witching FE-1584 (#15558)

## Summary

Manual backport of #15164 to `core/1.51`, preserving the original
local/Desktop credit-workspace switching behavior and regression
coverage.

## Changes

- **What**: Cherry-picks squash commit
`848cd39ed06a2da6fea389305cf7210a0a18c5ee` onto the current `core/1.51`
tip.
- **Conflict resolution**: The commit applied cleanly; no semantic
conflict edits were required. The resulting stable patch ID exactly
matches the original commit
(`d4910c5a0c7422e75a8e878248822032be6ab222`).

## Verification

- `pnpm test:unit <24 changed workspace
switcher/auth/billing/persistence test files>`
  - 24 test files passed
  - 756 tests passed
- Push hook: `knip --cache` passed.

## Review Focus

Confirm local credit-workspace switching, workspace-auth routing,
billing attribution, and local workflow persistence remain equivalent to
#15164 on the 1.51 release line.

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: comfydesigner <alextov@comfy.org>
comfy-pr-bot pushed a commit that referenced this pull request Aug 21, 2026
…switching FE-1584 (#15557)

## Summary

Manual backport of #15164 to `cloud/1.51`, preserving the original
local/Desktop credit-workspace switching behavior and regression
coverage.

## Changes

- **What**: Cherry-picks squash commit
`848cd39ed06a2da6fea389305cf7210a0a18c5ee` onto the current `cloud/1.51`
tip.
- **Conflict resolution**: The commit applied cleanly; no semantic
conflict edits were required. The resulting stable patch ID exactly
matches the original commit
(`d4910c5a0c7422e75a8e878248822032be6ab222`).

## Verification

- `pnpm test:unit <24 changed workspace
switcher/auth/billing/persistence test files>`
  - 24 test files passed
  - 756 tests passed
- Push hook: `knip --cache` passed.

## Review Focus

Confirm local credit-workspace switching, workspace-auth routing,
billing attribution, and local workflow persistence remain equivalent to
#15164 on the 1.51 release line.

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: comfydesigner <alextov@comfy.org>
zeus-onl pushed a commit to zeus-onl/ComfyUI_frontend that referenced this pull request Aug 21, 2026
## Summary

Fixes [FE-1739](https://linear.app/comfyorg/issue/FE-1739/): the
workspace selector in the profile popover inherited native browser
button styling after PR Comfy-Org#15164 changed it from a `<div>` to a semantic
`<button>`.

## Changes

- **What**: Reset the selector's native appearance with
`appearance-none`, `border-0`, `bg-transparent`, and `text-left` while
preserving its button semantics and existing interactions.
- **Regression coverage**: Add a focused Playwright screenshot for the
selector's neutral menu-row appearance.
- **Backports**: Required for `core/1.51` and `cloud/1.51`; staging is
currently on the affected `cloud/v1.51.9` (`ad9f651`).

## Review Focus

Confirm the selector remains a full-width semantic button without
Chromium's native gray fill or border.

## Testing

- `pnpm test:unit
src/platform/workspace/components/CurrentUserPopoverWorkspace.test.ts`
(17/17 passed)
- Focused Cloud Playwright screenshot test
- `pnpm typecheck`
- `pnpm typecheck:browser`
- Lint, stylelint, oxlint, and oxfmt via the commit hook

## Screenshot

![Neutral workspace
selector](https://raw.githubusercontent.com/Comfy-Org/ComfyUI_frontend/4b84db664a/browser_tests/tests/currentUserPopoverCredits.spec.ts-snapshots/workspace-selector-menu-item-cloud-linux.png)

Co-authored-by: Amp <amp@ampcode.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cloud/1.50 Backport PRs for cloud 1.50 cloud/1.51 Backport PRs for cloud 1.51 core/1.50 Backport PRs for core 1.50 core/1.51 Backport PRs for core 1.51 needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch risk:R3 PR risk grade (advisory shadow check; grader-owned) size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants