Skip to content

fix(billing): resolve terminal promise even if success side effects throw - #14964

Open
christian-byrne wants to merge 4 commits into
mainfrom
test/billing-op-store-coverage
Open

fix(billing): resolve terminal promise even if success side effects throw#14964
christian-byrne wants to merge 4 commits into
mainfrom
test/billing-op-store-coverage

Conversation

@christian-byrne

Copy link
Copy Markdown
Contributor

Summary

  • Wraps the success-path side-effects block (closeDialog, settingsDialog.show, toastStore.add) in a try/finally so resolveTerminal runs unconditionally — even if one of those calls throws.
  • Adds a regression test: throws from the second mockToastAdd call (the success toast) and asserts the terminal promise still resolves to { status: 'succeeded' }.

Root cause

resolveTerminal(opId) was the last line of handleSuccess, after toastStore.add(...). A thrown error in any of the dialog/toast calls skipped resolveTerminal, leaving any caller awaiting startOperation() hanging forever. poll()'s catch block swallowed the exception from outside, masking the hang entirely.

The fix was identified during the review of #14421. That PR's second commit (428c614) fixed exactly this bug in its version of the store — but the bug survived in main because subsequent billing PRs re-introduced the same call structure without carrying the try/finally forward.

Relationship to #14421

PR #14421 (refactor: convert billingOperationStore to discriminated union) can be closed — its implementation work was absorbed by the billing PRs that landed on main between July 30–August 9 (3DS support, cancel op type, workspace-scoping, terminal promise, richer telemetry). This PR backfills the one remaining piece: the try/finally bug fix and its regression test.

Test plan

  • pnpm test:unit src/platform/workspace/stores/billingOperationStore.test.ts — 70 passed (was 69, new test is the regression)
  • New test fails on main before this fix (times out at 5000ms), passes after

🤖 Generated with Claude Code

@christian-byrne
christian-byrne requested a review from a team August 9, 2026 04:37
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 9, 2026
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: f93897e6-1d69-45c9-8e61-7568a39eca63

📥 Commits

Reviewing files that changed from the base of the PR and between 027e785 and 5518a47.

📒 Files selected for processing (1)
  • src/platform/workspace/stores/billingOperationStore.ts

📝 Walkthrough

Walkthrough

The billing success handler now resolves terminal operations even when post-success cleanup, reconciliation, or UI side effects throw. Tests cover top-up toast failures and subscription reconciliation failures.

Changes

Billing success handling

Layer / File(s) Summary
Guarantee terminal success resolution
src/platform/workspace/stores/billingOperationStore.ts, src/platform/workspace/stores/billingOperationStore.test.ts
The success handler resolves the terminal promise in finally. Tests verify status: 'succeeded' when toast rendering or subscription reconciliation throws.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: dante01yoon, wei-hai


Important

Pre-merge checks failed

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

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
End-To-End Regression Coverage For Fixes ❓ Inconclusive The changed files are available, but the PR title and commit subjects are not provided, so the required bug-fix signal cannot be verified. Provide the PR title and commit subjects to determine whether the explicit failure conditions apply.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: resolving the terminal promise when success side effects throw.
Description check ✅ Passed The description explains the root cause, fix, regression test, test results, and relationship to the related pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Adr Compliance For Entity/Litegraph Changes ✅ Passed The changed files are billingOperationStore.ts and its test; none are under litegraph, ecs, or graph-entity paths.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/billing-op-store-coverage

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

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 08/11/2026, 10:34:23 PM UTC

Links

🎭 Playwright: ✅ 1794 passed, 0 failed · 6 flaky

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

📦 Bundle: 8.69 MB gzip 🔴 +64 B

Details

Summary

  • Raw size: 36.7 MB baseline 36.7 MB — 🔴 +71 B
  • Gzip: 8.69 MB baseline 8.69 MB — 🔴 +64 B
  • Brotli: 6.06 MB baseline 6.06 MB — 🔴 +52 B
  • Bundles: 436 current • 436 baseline • 145 added / 145 removed

Category Glance
Data & Services 🔴 +71 B (3.5 MB) · Vendor & Third-Party ⚪ 0 B (16.3 MB) · Other ⚪ 0 B (14 MB) · Graph Workspace ⚪ 0 B (1.36 MB) · Panels & Settings ⚪ 0 B (565 kB) · Utilities & Hooks ⚪ 0 B (550 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CwravgG2.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.84 kB 🔴 +1.59 kB
assets/index-XOO5r9j7.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.84 kB 🟢 -1.59 kB

Status: 1 added / 1 removed

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

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CG1EK1cV.js (new) 1.35 MB 🔴 +1.35 MB 🔴 +294 kB 🔴 +221 kB
assets/GraphView-D3yn5Mn5.js (removed) 1.35 MB 🟢 -1.35 MB 🟢 -294 kB 🟢 -221 kB
assets/WidgetCompositor-CDwnhaC9.js (removed) 8.17 kB 🟢 -8.17 kB 🟢 -2.75 kB 🟢 -2.45 kB
assets/WidgetCompositor-CWi_Cci6.js (new) 8.17 kB 🔴 +8.17 kB 🔴 +2.75 kB 🔴 +2.45 kB

Status: 2 added / 2 removed / 1 unchanged

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-4P8jcDBu.js (new) 25 kB 🔴 +25 kB 🔴 +6.24 kB 🔴 +5.53 kB
assets/CloudSurveyView-CY8r7DJc.js (removed) 25 kB 🟢 -25 kB 🟢 -6.24 kB 🟢 -5.52 kB
assets/CloudLayoutView-BwG0qVA3.js (new) 21.8 kB 🔴 +21.8 kB 🔴 +6.56 kB 🔴 +5.74 kB
assets/CloudLayoutView-iHzQiZCP.js (removed) 21.8 kB 🟢 -21.8 kB 🟢 -6.56 kB 🟢 -5.74 kB
assets/UserCheckView-B1rBdfN9.js (new) 8.75 kB 🔴 +8.75 kB 🔴 +2.19 kB 🔴 +1.9 kB
assets/UserCheckView-D3_s53Wm.js (removed) 8.75 kB 🟢 -8.75 kB 🟢 -2.19 kB 🟢 -1.9 kB
assets/CloudLoginView-Ba_t4Vm6.js (removed) 8.74 kB 🟢 -8.74 kB 🟢 -2.55 kB 🟢 -2.26 kB
assets/CloudLoginView-C5Y-Z0OR.js (new) 8.74 kB 🔴 +8.74 kB 🔴 +2.55 kB 🔴 +2.26 kB
assets/useCloudAuthPage-2l2raJ4a.js (new) 7.08 kB 🔴 +7.08 kB 🔴 +2.51 kB 🔴 +2.21 kB
assets/useCloudAuthPage-CzgDi3Hd.js (removed) 7.08 kB 🟢 -7.08 kB 🟢 -2.51 kB 🟢 -2.2 kB
assets/CloudSignupView-BgcK04uR.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -2.17 kB 🟢 -1.91 kB
assets/CloudSignupView-D17t758M.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +2.17 kB 🔴 +1.9 kB
assets/WidgetTextPreview-BIGStghl.js (removed) 6.07 kB 🟢 -6.07 kB 🟢 -2.13 kB 🟢 -1.88 kB
assets/WidgetTextPreview-CiWm_t0v.js (new) 6.07 kB 🔴 +6.07 kB 🔴 +2.13 kB 🔴 +1.88 kB
assets/CloudSubscriptionRedirectView-9G_mZQ15.js (removed) 6.05 kB 🟢 -6.05 kB 🟢 -2.25 kB 🟢 -1.96 kB
assets/CloudSubscriptionRedirectView-DH13mjsN.js (new) 6.05 kB 🔴 +6.05 kB 🔴 +2.25 kB 🔴 +1.96 kB
assets/UserSelectView-DBwXFkTr.js (removed) 5.49 kB 🟢 -5.49 kB 🟢 -1.95 kB 🟢 -1.71 kB
assets/UserSelectView-Dm4vwwQ1.js (new) 5.49 kB 🔴 +5.49 kB 🔴 +1.95 kB 🔴 +1.71 kB
assets/CloudForgotPasswordView-CZ23-tXW.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.72 kB 🟢 -1.49 kB
assets/CloudForgotPasswordView-mk-IKy8B.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.72 kB 🔴 +1.49 kB
assets/CloudAuthTimeoutView-BKP03nHE.js (removed) 4.43 kB 🟢 -4.43 kB 🟢 -1.54 kB 🟢 -1.33 kB
assets/CloudAuthTimeoutView-Cv4sdxzb.js (new) 4.43 kB 🔴 +4.43 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/OAuthLayoutView-BhitGdmV.js (new) 1.31 kB 🔴 +1.31 kB 🔴 +697 B 🔴 +598 B
assets/OAuthLayoutView-CZH2_cVN.js (removed) 1.31 kB 🟢 -1.31 kB 🟢 -696 B 🟢 -600 B
assets/WidgetTextPreview-BFQIGNM6.js (new) 131 B 🔴 +131 B 🔴 +100 B 🔴 +94 B
assets/WidgetTextPreview-CLz7Xeia.js (removed) 131 B 🟢 -131 B 🟢 -100 B 🟢 -90 B

Status: 13 added / 13 removed / 4 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-Bb0BveK4.js (removed) 49.4 kB 🟢 -49.4 kB 🟢 -9.94 kB 🟢 -8.81 kB
assets/KeybindingPanel-DwJSAL9K.js (new) 49.4 kB 🔴 +49.4 kB 🔴 +9.94 kB 🔴 +8.81 kB
assets/SecretsPanel-Ce1E7eE3.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -7.87 kB 🟢 -6.9 kB
assets/SecretsPanel-DirFdmDW.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +7.86 kB 🔴 +6.9 kB
assets/CreditsPanel-BNHVd2Md.js (new) 11.5 kB 🔴 +11.5 kB 🔴 +3.2 kB 🔴 +2.81 kB
assets/CreditsPanel-CP1ioakN.js (removed) 11.5 kB 🟢 -11.5 kB 🟢 -3.2 kB 🟢 -2.82 kB
assets/AboutPanel-BwjYnm24.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.02 kB 🟢 -2.73 kB
assets/AboutPanel-CAQrfdQ6.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.03 kB 🔴 +2.72 kB
assets/ExtensionPanel-b_48rOHH.js (removed) 9.19 kB 🟢 -9.19 kB 🟢 -2.51 kB 🟢 -2.22 kB
assets/ExtensionPanel-C8nprOLA.js (new) 9.19 kB 🔴 +9.19 kB 🔴 +2.51 kB 🔴 +2.22 kB
assets/ServerConfigPanel-B0QtbrOc.js (new) 6.09 kB 🔴 +6.09 kB 🔴 +1.93 kB 🔴 +1.72 kB
assets/ServerConfigPanel-X09tpH8M.js (removed) 6.09 kB 🟢 -6.09 kB 🟢 -1.93 kB 🟢 -1.72 kB
assets/UserPanel-ClDKUWD7.js (removed) 5.73 kB 🟢 -5.73 kB 🟢 -1.78 kB 🟢 -1.54 kB
assets/UserPanel-DBgkALSs.js (new) 5.73 kB 🔴 +5.73 kB 🔴 +1.78 kB 🔴 +1.54 kB
assets/refreshRemoteConfig-D8EXd-u5.js (removed) 3.44 kB 🟢 -3.44 kB 🟢 -1.33 kB 🟢 -1.17 kB
assets/refreshRemoteConfig-Dt5qNl4w.js (new) 3.44 kB 🔴 +3.44 kB 🔴 +1.33 kB 🔴 +1.17 kB
assets/cloudRemoteConfig-jvNgg9H_.js (new) 951 B 🔴 +951 B 🔴 +514 B 🔴 +429 B
assets/cloudRemoteConfig-oHmgZext.js (removed) 951 B 🟢 -951 B 🟢 -514 B 🟢 -420 B
assets/refreshRemoteConfig-B5UCpeyA.js (removed) 110 B 🟢 -110 B 🟢 -89 B 🟢 -77 B
assets/refreshRemoteConfig-B6EE9HXK.js (new) 110 B 🔴 +110 B 🔴 +89 B 🔴 +89 B

Status: 10 added / 10 removed / 16 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SignUpForm-BOzs0amc.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -4.31 kB 🟢 -3.76 kB
assets/SignUpForm-DxqCu6bs.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +4.31 kB 🔴 +3.76 kB
assets/auth-BokyovlP.js (removed) 3.71 kB 🟢 -3.71 kB 🟢 -1.28 kB 🟢 -1.1 kB
assets/auth-DvRh1Sti.js (new) 3.71 kB 🔴 +3.71 kB 🔴 +1.28 kB 🔴 +1.1 kB
assets/UpdatePasswordContent-1lMjX_u4.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -842 B 🟢 -733 B
assets/UpdatePasswordContent-ByBp-rMe.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +842 B 🔴 +734 B
assets/authStore-Cd8-yMM0.js (removed) 128 B 🟢 -128 B 🟢 -104 B 🟢 -105 B
assets/authStore-cKgnV0sg.js (new) 128 B 🔴 +128 B 🔴 +104 B 🔴 +105 B
assets/workspaceAuthStore-4raWaX-_.js (new) 108 B 🔴 +108 B 🔴 +99 B 🔴 +106 B
assets/workspaceAuthStore-DPLbsuaA.js (removed) 108 B 🟢 -108 B 🟢 -99 B 🟢 -106 B
assets/auth-DxTd3LTI.js (removed) 105 B 🟢 -105 B 🟢 -96 B 🟢 -80 B
assets/auth-I5B09XIx.js (new) 105 B 🔴 +105 B 🔴 +96 B 🔴 +94 B

Status: 6 added / 6 removed / 4 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-BEhDx37A.js (new) 90.1 kB 🔴 +90.1 kB 🔴 +19.3 kB 🔴 +16.5 kB
assets/ComfyHubPublishDialog-iHePV07Q.js (removed) 90.1 kB 🟢 -90.1 kB 🟢 -19.3 kB 🟢 -16.5 kB
assets/useShareDialog-Cp_cD0DK.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +5.69 kB 🔴 +5.03 kB
assets/useShareDialog-n0DdFgM7.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -5.69 kB 🟢 -5.03 kB
assets/feedbackDialog-CG9J8L_R.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.86 kB 🟢 -1.59 kB
assets/feedbackDialog-q3fgIebh.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.87 kB 🔴 +1.59 kB
assets/useRangeEditor-BCIPeND7.js (removed) 3.29 kB 🟢 -3.29 kB 🟢 -1.14 kB 🟢 -1.04 kB
assets/useRangeEditor-ElOFQNwd.js (new) 3.29 kB 🔴 +3.29 kB 🔴 +1.14 kB 🔴 +1.05 kB
assets/useLayerEditor-BOvxNR3T.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -491 B 🟢 -407 B
assets/useLayerEditor-DpqgnmP_.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +489 B 🔴 +406 B
assets/ComfyHubPublishDialog-Cg-I0SF3.js (new) 143 B 🔴 +143 B 🔴 +105 B 🔴 +95 B
assets/ComfyHubPublishDialog-CO2CuIaJ.js (removed) 143 B 🟢 -143 B 🟢 -105 B 🟢 -88 B
assets/useSubscriptionDialog-DSn_VhDE.js (removed) 108 B 🟢 -108 B 🟢 -102 B 🟢 -86 B
assets/useSubscriptionDialog-lCpKlrby.js (new) 108 B 🔴 +108 B 🔴 +102 B 🔴 +100 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-D06o20ss.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.96 kB 🟢 -3.51 kB
assets/ComfyQueueButton-zkHENVP9.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.96 kB 🔴 +3.51 kB
assets/useTerminalTabs-BTmqK4wM.js (new) 11.8 kB 🔴 +11.8 kB 🔴 +3.69 kB 🔴 +3.26 kB
assets/useTerminalTabs-UiXlktCL.js (removed) 11.8 kB 🟢 -11.8 kB 🟢 -3.69 kB 🟢 -3.26 kB
assets/InviteMembersForm-CkBxrXk4.js (removed) 8.2 kB 🟢 -8.2 kB 🟢 -2.72 kB 🟢 -2.44 kB
assets/InviteMembersForm-CV0BTuH6.js (new) 8.2 kB 🔴 +8.2 kB 🔴 +2.72 kB 🔴 +2.44 kB
assets/SubscribeButton-B-AzjpNE.js (removed) 2.15 kB 🟢 -2.15 kB 🟢 -966 B 🟢 -845 B
assets/SubscribeButton-bZm7-9kb.js (new) 2.15 kB 🔴 +2.15 kB 🔴 +966 B 🔴 +848 B
assets/cloudFeedbackTopbarButton-BoTDeLiQ.js (removed) 705 B 🟢 -705 B 🟢 -423 B 🟢 -360 B
assets/cloudFeedbackTopbarButton-DvQVrfCY.js (new) 705 B 🔴 +705 B 🔴 +421 B 🔴 +360 B
assets/ComfyQueueButton-CCtf2JMI.js (new) 128 B 🔴 +128 B 🔴 +99 B 🔴 +89 B
assets/ComfyQueueButton-CWaJOYj3.js (removed) 128 B 🟢 -128 B 🟢 -99 B 🟢 -95 B

Status: 6 added / 6 removed / 8 unchanged

Data & Services — 3.5 MB (baseline 3.5 MB) • 🔴 +71 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settingStore-B-viwOdJ.js (new) 3.22 MB 🔴 +3.22 MB 🔴 +747 kB 🔴 +562 kB
assets/settingStore-C6eSZaMK.js (removed) 3.22 MB 🟢 -3.22 MB 🟢 -747 kB 🟢 -562 kB
assets/load3dService-C2w-Rv8A.js (removed) 132 kB 🟢 -132 kB 🟢 -29.3 kB 🟢 -24.6 kB
assets/load3dService-CoO94sGW.js (new) 132 kB 🔴 +132 kB 🔴 +29.3 kB 🔴 +24.6 kB
assets/api-BmYlOOLb.js (new) 98.3 kB 🔴 +98.3 kB 🔴 +27.2 kB 🔴 +23.4 kB
assets/api-BtSYSJKL.js (removed) 98.3 kB 🟢 -98.3 kB 🟢 -27.2 kB 🟢 -23.4 kB
assets/workflowShareService-BMGV7tny.js (removed) 16.5 kB 🟢 -16.5 kB 🟢 -4.91 kB 🟢 -4.35 kB
assets/workflowShareService-ydFo92vc.js (new) 16.5 kB 🔴 +16.5 kB 🔴 +4.91 kB 🔴 +4.36 kB
assets/keybindingService-BtuMAxfn.js (removed) 6.89 kB 🟢 -6.89 kB 🟢 -1.73 kB 🟢 -1.5 kB
assets/keybindingService-DgfdPQ8u.js (new) 6.89 kB 🔴 +6.89 kB 🔴 +1.73 kB 🔴 +1.5 kB
assets/releaseStore-D2jco2U6.js (new) 6.72 kB 🔴 +6.72 kB 🔴 +2.03 kB 🔴 +1.78 kB
assets/releaseStore-odR82fVp.js (removed) 6.72 kB 🟢 -6.72 kB 🟢 -2.03 kB 🟢 -1.78 kB
assets/systemStatsStore-BMuWp6yw.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.74 kB 🟢 -1.47 kB
assets/systemStatsStore-TH8kDk_x.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.74 kB 🔴 +1.47 kB
assets/userStore-CCco9OUK.js (removed) 2.38 kB 🟢 -2.38 kB 🟢 -898 B 🟢 -791 B
assets/userStore-CQqerbCB.js (new) 2.38 kB 🔴 +2.38 kB 🔴 +897 B 🔴 +791 B
assets/audioService-CQ6kIaoz.js (new) 1.71 kB 🔴 +1.71 kB 🔴 +828 B 🔴 +720 B
assets/audioService-EbeBKLtk.js (removed) 1.71 kB 🟢 -1.71 kB 🟢 -828 B 🟢 -720 B
assets/dialogService-BlttW2R5.js (new) 98 B 🔴 +98 B 🔴 +97 B 🔴 +84 B
assets/dialogService-mxysN6Uy.js (removed) 98 B 🟢 -98 B 🟢 -97 B 🟢 -90 B
assets/releaseStore-8bvpyGIp.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -87 B
assets/releaseStore-HmZDFRyg.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +86 B
assets/settingStore-bDpzPirU.js (removed) 95 B 🟢 -95 B 🟢 -86 B 🟢 -81 B
assets/settingStore-J11IcC9S.js (new) 95 B 🔴 +95 B 🔴 +86 B 🔴 +83 B
assets/assetsStore-B9lwfspg.js (removed) 94 B 🟢 -94 B 🟢 -92 B 🟢 -82 B
assets/assetsStore-DefEuytk.js (new) 94 B 🔴 +94 B 🔴 +92 B 🔴 +84 B
assets/api-CN7ycyF7.js (new) 62 B 🔴 +62 B 🔴 +74 B 🔴 +66 B
assets/api-qf1_O0Bw.js (removed) 62 B 🟢 -62 B 🟢 -74 B 🟢 -66 B

Status: 14 added / 14 removed / 3 unchanged

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-BakqdX_0.js (removed) 236 kB 🟢 -236 kB 🟢 -53 kB 🟢 -43.1 kB
assets/useConflictDetection-BZ1yjG0M.js (new) 236 kB 🔴 +236 kB 🔴 +53 kB 🔴 +43.1 kB
assets/useLayerEditorSession-CrzUOMGJ.js (new) 158 kB 🔴 +158 kB 🔴 +40.8 kB 🔴 +34.3 kB
assets/useLayerEditorSession-D94DHfvX.js (removed) 158 kB 🟢 -158 kB 🟢 -40.8 kB 🟢 -34.3 kB
assets/useLoad3d-BmS0Mdim.js (new) 25.8 kB 🔴 +25.8 kB 🔴 +5.8 kB 🔴 +5.14 kB
assets/useLoad3d-DXAQH_sr.js (removed) 25.8 kB 🟢 -25.8 kB 🟢 -5.8 kB 🟢 -5.16 kB
assets/useLoad3dViewer-B6-QzM-_.js (new) 21.2 kB 🔴 +21.2 kB 🔴 +4.98 kB 🔴 +4.35 kB
assets/useLoad3dViewer-BThKgXOw.js (removed) 21.2 kB 🟢 -21.2 kB 🟢 -4.98 kB 🟢 -4.36 kB
assets/useImageCrop-B-9Af17Y.js (new) 14.9 kB 🔴 +14.9 kB 🔴 +3.42 kB 🔴 +2.99 kB
assets/useImageCrop-Cv3kU56Q.js (removed) 14.9 kB 🟢 -14.9 kB 🟢 -3.42 kB 🟢 -2.98 kB
assets/useDowngradeToPersonal-Beh9ZBhS.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +2.75 kB 🔴 +2.36 kB
assets/useDowngradeToPersonal-DSGiBluc.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -2.75 kB 🟢 -2.37 kB
assets/useFeatureFlags-CBc6yI0b.js (removed) 6.99 kB 🟢 -6.99 kB 🟢 -2 kB 🟢 -1.7 kB
assets/useFeatureFlags-QcYjxd7a.js (new) 6.99 kB 🔴 +6.99 kB 🔴 +2 kB 🔴 +1.7 kB
assets/useCompositorLayers-2ckUZK39.js (removed) 2.94 kB 🟢 -2.94 kB 🟢 -897 B 🟢 -797 B
assets/useCompositorLayers-CrdojUfJ.js (new) 2.94 kB 🔴 +2.94 kB 🔴 +896 B 🔴 +798 B
assets/assetPreviewUtil-ClQG3vka.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +968 B 🔴 +839 B
assets/assetPreviewUtil-nawzfN9J.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -970 B 🟢 -839 B
assets/useUpstreamValue-Byfn4G2W.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +756 B 🔴 +678 B
assets/useUpstreamValue-DHi_08Ey.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -758 B 🟢 -676 B
assets/useWorkspaceTierLabel-CaLlMNgj.js (removed) 1.93 kB 🟢 -1.93 kB 🟢 -812 B 🟢 -698 B
assets/useWorkspaceTierLabel-CkMzP-GQ.js (new) 1.93 kB 🔴 +1.93 kB 🔴 +811 B 🔴 +698 B
assets/subscriptionCheckoutUtil-BarDbjow.js (new) 877 B 🔴 +877 B 🔴 +522 B 🔴 +430 B
assets/subscriptionCheckoutUtil-CUWNcaS9.js (removed) 877 B 🟢 -877 B 🟢 -523 B 🟢 -458 B
assets/useSessionCookie-B74u2K2e.js (new) 652 B 🔴 +652 B 🔴 +336 B 🔴 +293 B
assets/useSessionCookie-CzzAFMkQ.js (removed) 652 B 🟢 -652 B 🟢 -337 B 🟢 -294 B
assets/useLoad3d-_W4Nprvn.js (removed) 311 B 🟢 -311 B 🟢 -165 B 🟢 -152 B
assets/useLoad3d-CMM2FzbY.js (new) 311 B 🔴 +311 B 🔴 +162 B 🔴 +147 B
assets/useSessionCookie-CCii7DlS.js (new) 101 B 🔴 +101 B 🔴 +86 B 🔴 +77 B
assets/useSessionCookie-DwbBTZmM.js (removed) 101 B 🟢 -101 B 🟢 -86 B 🟢 -83 B
assets/useFeatureFlags-CYqPkbIz.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -80 B
assets/useFeatureFlags-XKQMoepP.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +85 B
assets/useLoad3dViewer-3PLuKEg7.js (new) 98 B 🔴 +98 B 🔴 +85 B 🔴 +92 B
assets/useLoad3dViewer-CeRScJaD.js (removed) 98 B 🟢 -98 B 🟢 -85 B 🟢 -86 B
assets/useCurrentUser-C98fKHQs.js (removed) 94 B 🟢 -94 B 🟢 -95 B 🟢 -80 B
assets/useCurrentUser-DV53wTP6.js (new) 94 B 🔴 +94 B 🔴 +95 B 🔴 +95 B

Status: 18 added / 18 removed / 20 unchanged

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

External libraries and shared vendor chunks

Status: 17 unchanged

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

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-BVHPZ0d7.js (new) 115 kB 🔴 +115 kB 🔴 +29.7 kB 🔴 +25.1 kB
assets/core-IfjwmzEB.js (removed) 115 kB 🟢 -115 kB 🟢 -29.7 kB 🟢 -25.1 kB
assets/WidgetSelect-CGP-sVfH.js (removed) 88.8 kB 🟢 -88.8 kB 🟢 -20.1 kB 🟢 -17.2 kB
assets/WidgetSelect-iOd4lSus.js (new) 88.8 kB 🔴 +88.8 kB 🔴 +20.1 kB 🔴 +17.2 kB
assets/SubscriptionPanelContentWorkspace-BJ_KJpwl.js (new) 80 kB 🔴 +80 kB 🔴 +15.8 kB 🔴 +13.6 kB
assets/SubscriptionPanelContentWorkspace-VC791dP6.js (removed) 80 kB 🟢 -80 kB 🟢 -15.8 kB 🟢 -13.6 kB
assets/Load3D-Cmwy29Oz.js (new) 71.3 kB 🔴 +71.3 kB 🔴 +11.7 kB 🔴 +9.96 kB
assets/Load3D-SyLusnyO.js (removed) 71.3 kB 🟢 -71.3 kB 🟢 -11.7 kB 🟢 -9.98 kB
assets/WidgetVideoEdit-0F4NJRFK.js (new) 67.5 kB 🔴 +67.5 kB 🔴 +15.7 kB 🔴 +13.9 kB
assets/WidgetVideoEdit-siTEbM2M.js (removed) 67.5 kB 🟢 -67.5 kB 🟢 -15.7 kB 🟢 -13.9 kB
assets/SubscriptionTransitionPreviewWorkspace-BTX__cuG.js (removed) 66.4 kB 🟢 -66.4 kB 🟢 -13.4 kB 🟢 -11.7 kB
assets/SubscriptionTransitionPreviewWorkspace-DVYQAYrg.js (new) 66.4 kB 🔴 +66.4 kB 🔴 +13.4 kB 🔴 +11.6 kB
assets/WorkspaceSettingsPanelContent-aHE-Ziim.js (new) 61.7 kB 🔴 +61.7 kB 🔴 +13.2 kB 🔴 +11.5 kB
assets/WorkspaceSettingsPanelContent-BpSK5x4J.js (removed) 61.7 kB 🟢 -61.7 kB 🟢 -13.2 kB 🟢 -11.5 kB
assets/Preview3d-CsuS6AoK.js (removed) 50.9 kB 🟢 -50.9 kB 🟢 -8.31 kB 🟢 -7.24 kB
assets/Preview3d-yIXSHXpL.js (new) 50.9 kB 🔴 +50.9 kB 🔴 +8.31 kB 🔴 +7.26 kB
assets/main-BtnR_D1H.js (removed) 45.1 kB 🟢 -45.1 kB 🟢 -13.1 kB 🟢 -11.4 kB
assets/main-CTHf3e9r.js (new) 45.1 kB 🔴 +45.1 kB 🔴 +13.1 kB 🔴 +11.4 kB
assets/SubscriptionRequiredDialogContentUnified-BSj0Uuf-.js (removed) 42.6 kB 🟢 -42.6 kB 🟢 -9.35 kB 🟢 -8.16 kB
assets/SubscriptionRequiredDialogContentUnified-DjF0vORE.js (new) 42.6 kB 🔴 +42.6 kB 🔴 +9.35 kB 🔴 +8.16 kB
assets/LayerEditorContent-DeRAge7Q.js (removed) 42.5 kB 🟢 -42.5 kB 🟢 -9.61 kB 🟢 -8.44 kB
assets/LayerEditorContent-Ds9x1R42.js (new) 42.5 kB 🔴 +42.5 kB 🔴 +9.61 kB 🔴 +8.43 kB
assets/WidgetBoundingBoxes-C4S2dbYA.js (new) 33.7 kB 🔴 +33.7 kB 🔴 +9.16 kB 🔴 +8.13 kB
assets/WidgetBoundingBoxes-zJMzry6i.js (removed) 33.7 kB 🟢 -33.7 kB 🟢 -9.16 kB 🟢 -8.13 kB
assets/WidgetPainter-CHWx7yEr.js (removed) 32.6 kB 🟢 -32.6 kB 🟢 -7.87 kB 🟢 -6.97 kB
assets/WidgetPainter-CZv-2zkS.js (new) 32.6 kB 🔴 +32.6 kB 🔴 +7.87 kB 🔴 +6.95 kB
assets/Load3dViewerContent-BQ6Vc98B.js (new) 30.8 kB 🔴 +30.8 kB 🔴 +6.28 kB 🔴 +5.45 kB
assets/Load3dViewerContent-Cz_E2U6S.js (removed) 30.8 kB 🟢 -30.8 kB 🟢 -6.28 kB 🟢 -5.45 kB
assets/SubscriptionRequiredDialogContent-BrTDIhWR.js (removed) 27 kB 🟢 -27 kB 🟢 -6.37 kB 🟢 -5.61 kB
assets/SubscriptionRequiredDialogContent-DdGv28mL.js (new) 27 kB 🔴 +27 kB 🔴 +6.37 kB 🔴 +5.61 kB
assets/SubscriptionRequiredDialogContentWorkspace--yb2Qt7c.js (removed) 25.1 kB 🟢 -25.1 kB 🟢 -5.79 kB 🟢 -5.1 kB
assets/SubscriptionRequiredDialogContentWorkspace-DlZj3WPr.js (new) 25.1 kB 🔴 +25.1 kB 🔴 +5.79 kB 🔴 +5.1 kB
assets/CreditsTile-Cqtmisr1.js (removed) 24.9 kB 🟢 -24.9 kB 🟢 -6.64 kB 🟢 -5.83 kB
assets/CreditsTile-dafwggwe.js (new) 24.9 kB 🔴 +24.9 kB 🔴 +6.64 kB 🔴 +5.82 kB
assets/load3d-BPUqCOP5.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.4 kB 🟢 -4.67 kB
assets/load3d-qmLdni2y.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.41 kB 🔴 +4.67 kB
assets/CurrentUserPopoverWorkspace-BxrFIAGW.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +4.84 kB 🔴 +4.33 kB
assets/CurrentUserPopoverWorkspace-DHOUrG5t.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -4.84 kB 🟢 -4.32 kB
assets/SignInContent-9ZN04FGo.js (new) 20.2 kB 🔴 +20.2 kB 🔴 +5.09 kB 🔴 +4.45 kB
assets/SignInContent-DbvrRLzs.js (removed) 20.2 kB 🟢 -20.2 kB 🟢 -5.09 kB 🟢 -4.45 kB
assets/WidgetRecordAudio-Bfp2S3nj.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.59 kB 🟢 -4.1 kB
assets/WidgetRecordAudio-DLh0EaOm.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.59 kB 🔴 +4.1 kB
assets/WidgetInputNumber-1WCxBbfw.js (new) 13.9 kB 🔴 +13.9 kB 🔴 +3.63 kB 🔴 +3.21 kB
assets/WidgetInputNumber-CZ4Vn5-Z.js (removed) 13.9 kB 🟢 -13.9 kB 🟢 -3.63 kB 🟢 -3.21 kB
assets/WidgetRange-CuSSDGRt.js (removed) 13.7 kB 🟢 -13.7 kB 🟢 -3.55 kB 🟢 -3.13 kB
assets/WidgetRange-Dl1oYDCF.js (new) 13.7 kB 🔴 +13.7 kB 🔴 +3.55 kB 🔴 +3.12 kB
assets/WaveAudioPlayer-BTRzwbfK.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.46 kB 🔴 +3.05 kB
assets/WaveAudioPlayer-Z2lpyUlE.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.47 kB 🟢 -3.05 kB
assets/WidgetCurve-BYvp7tMs.js (removed) 11.2 kB 🟢 -11.2 kB 🟢 -3.47 kB 🟢 -3.15 kB
assets/WidgetCurve-CAXs1eN2.js (new) 11.2 kB 🔴 +11.2 kB 🔴 +3.47 kB 🔴 +3.15 kB
assets/TeamWorkspacesDialogContent-DgPIfeyE.js (removed) 10.3 kB 🟢 -10.3 kB 🟢 -2.96 kB 🟢 -2.63 kB
assets/TeamWorkspacesDialogContent-vfaT6P0u.js (new) 10.3 kB 🔴 +10.3 kB 🔴 +2.96 kB 🔴 +2.62 kB
assets/onboardingCloudRoutes-BGrOH1MC.js (removed) 9.33 kB 🟢 -9.33 kB 🟢 -2.84 kB 🟢 -2.44 kB
assets/onboardingCloudRoutes-Mcx2EvXD.js (new) 9.33 kB 🔴 +9.33 kB 🔴 +2.84 kB 🔴 +2.44 kB
assets/Load3DConfiguration-D2K2Hhqv.js (new) 8.91 kB 🔴 +8.91 kB 🔴 +2.61 kB 🔴 +2.3 kB
assets/Load3DConfiguration-SyeEznWo.js (removed) 8.91 kB 🟢 -8.91 kB 🟢 -2.61 kB 🟢 -2.29 kB
assets/WidgetImageCrop-BEKm0PZ-.js (new) 8.49 kB 🔴 +8.49 kB 🔴 +2.65 kB 🔴 +2.34 kB
assets/WidgetImageCrop-D5Rutrip.js (removed) 8.49 kB 🟢 -8.49 kB 🟢 -2.65 kB 🟢 -2.34 kB
assets/SetMemberCreditLimitDialogContent-BjobRdXp.js (new) 8.47 kB 🔴 +8.47 kB 🔴 +2.34 kB 🔴 +2.06 kB
assets/SetMemberCreditLimitDialogContent-CCVJ6KhL.js (removed) 8.47 kB 🟢 -8.47 kB 🟢 -2.34 kB 🟢 -2.05 kB
assets/nodeTemplates-ClZdnwT-.js (new) 8.32 kB 🔴 +8.32 kB 🔴 +2.85 kB 🔴 +2.51 kB
assets/nodeTemplates-DRfIdtiu.js (removed) 8.32 kB 🟢 -8.32 kB 🟢 -2.85 kB 🟢 -2.5 kB
assets/NightlySurveyController-5Fu4Q5fn.js (new) 7.5 kB 🔴 +7.5 kB 🔴 +2.55 kB 🔴 +2.24 kB
assets/NightlySurveyController-DggerIr_.js (removed) 7.5 kB 🟢 -7.5 kB 🟢 -2.55 kB 🟢 -2.25 kB
assets/CloudRunButtonWrapper-BwBXlWZX.js (removed) 6.84 kB 🟢 -6.84 kB 🟢 -2.17 kB 🟢 -1.91 kB
assets/CloudRunButtonWrapper-CqDsR4wV.js (new) 6.84 kB 🔴 +6.84 kB 🔴 +2.18 kB 🔴 +1.91 kB
assets/WidgetWithControl-3HwBdJy_.js (removed) 6.41 kB 🟢 -6.41 kB 🟢 -2.61 kB 🟢 -2.31 kB
assets/WidgetWithControl-CjIMPIL4.js (new) 6.41 kB 🔴 +6.41 kB 🔴 +2.61 kB 🔴 +2.31 kB
assets/missingModelMetadata--OsqJpnT.js (removed) 6.17 kB 🟢 -6.17 kB 🟢 -2.13 kB 🟢 -1.86 kB
assets/missingModelMetadata-CA32fUYo.js (new) 6.17 kB 🔴 +6.17 kB 🔴 +2.13 kB 🔴 +1.86 kB
assets/CancelSubscriptionDialogContent-BwUV97Hz.js (removed) 5.97 kB 🟢 -5.97 kB 🟢 -1.98 kB 🟢 -1.75 kB
assets/CancelSubscriptionDialogContent-BXRgaknR.js (new) 5.97 kB 🔴 +5.97 kB 🔴 +1.98 kB 🔴 +1.74 kB
assets/load3dPreviewExtensions-CBvQdXgW.js (new) 5.88 kB 🔴 +5.88 kB 🔴 +1.81 kB 🔴 +1.59 kB
assets/load3dPreviewExtensions-DkjUfR1v.js (removed) 5.88 kB 🟢 -5.88 kB 🟢 -1.81 kB 🟢 -1.59 kB
assets/launchCancellationFlow-BZU9NyEj.js (new) 5.18 kB 🔴 +5.18 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/launchCancellationFlow-DCzGkWLN.js (removed) 5.18 kB 🟢 -5.18 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/CreateWorkspaceDialogContent-CMIbGXJ6.js (new) 5.12 kB 🔴 +5.12 kB 🔴 +1.79 kB 🔴 +1.55 kB
assets/CreateWorkspaceDialogContent-Mf-k7H0E.js (removed) 5.12 kB 🟢 -5.12 kB 🟢 -1.79 kB 🟢 -1.55 kB
assets/ChangeMemberRoleDialogContent-BBcWpfEY.js (new) 4.97 kB 🔴 +4.97 kB 🔴 +1.63 kB 🔴 +1.42 kB
assets/ChangeMemberRoleDialogContent-Cx42NEp_.js (removed) 4.97 kB 🟢 -4.97 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/InviteMemberDialogContent-Cvk_w6XX.js (removed) 4.96 kB 🟢 -4.96 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/InviteMemberDialogContent-D440quVz.js (new) 4.96 kB 🔴 +4.96 kB 🔴 +1.64 kB 🔴 +1.44 kB
assets/EditWorkspaceDialogContent-BmZDJcNU.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.76 kB 🔴 +1.52 kB
assets/EditWorkspaceDialogContent-pyVjw357.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.76 kB 🟢 -1.53 kB
assets/WidgetTextarea-O9ZLI-oR.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.87 kB 🔴 +1.63 kB
assets/WidgetTextarea-OSf793IC.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.87 kB 🟢 -1.63 kB
assets/saveMesh-BQKpZLus.js (removed) 4.76 kB 🟢 -4.76 kB 🟢 -1.52 kB 🟢 -1.34 kB
assets/saveMesh-CYlMk_s3.js (new) 4.76 kB 🔴 +4.76 kB 🔴 +1.52 kB 🔴 +1.35 kB
assets/WorkspacePanelContent-Balei1nU.js (new) 4.74 kB 🔴 +4.74 kB 🔴 +1.62 kB 🔴 +1.43 kB
assets/WorkspacePanelContent-Cz6if3Xe.js (removed) 4.74 kB 🟢 -4.74 kB 🟢 -1.63 kB 🟢 -1.43 kB
assets/ValueControlPopover-C23-RW-t.js (new) 4.49 kB 🔴 +4.49 kB 🔴 +1.55 kB 🔴 +1.38 kB
assets/ValueControlPopover-Vq-K8l7e.js (removed) 4.49 kB 🟢 -4.49 kB 🟢 -1.55 kB 🟢 -1.38 kB
assets/DeleteWorkspaceDialogContent-BBZNgoLf.js (removed) 3.84 kB 🟢 -3.84 kB 🟢 -1.44 kB 🟢 -1.24 kB
assets/DeleteWorkspaceDialogContent-MiVPLJ-z.js (new) 3.84 kB 🔴 +3.84 kB 🔴 +1.44 kB 🔴 +1.23 kB
assets/RemoveMemberDialogContent-C49Ap_NS.js (new) 3.76 kB 🔴 +3.76 kB 🔴 +1.38 kB 🔴 +1.2 kB
assets/RemoveMemberDialogContent-CAlEp2Ek.js (removed) 3.76 kB 🟢 -3.76 kB 🟢 -1.38 kB 🟢 -1.19 kB
assets/RevokeInviteDialogContent-CrDfR0D6.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.39 kB 🟢 -1.21 kB
assets/RevokeInviteDialogContent-D3V9nYkH.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.39 kB 🔴 +1.21 kB
assets/LeaveWorkspaceDialogContent-BdSCJg0D.js (removed) 3.67 kB 🟢 -3.67 kB 🟢 -1.38 kB 🟢 -1.19 kB
assets/LeaveWorkspaceDialogContent-DEiv8ZkH.js (new) 3.67 kB 🔴 +3.67 kB 🔴 +1.38 kB 🔴 +1.19 kB
assets/InviteMemberUpsellDialogContent-BusvtrXU.js (removed) 3.47 kB 🟢 -3.47 kB 🟢 -1.24 kB 🟢 -1.09 kB
assets/InviteMemberUpsellDialogContent-CG1htqAi.js (new) 3.47 kB 🔴 +3.47 kB 🔴 +1.24 kB 🔴 +1.08 kB
assets/workspaceCheckoutTelemetry-3wCBrpZL.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.52 kB 🔴 +1.33 kB
assets/workspaceCheckoutTelemetry-C_ms-dTB.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.52 kB 🟢 -1.33 kB
assets/GlobalToast-BCpqrdh1.js (removed) 3.25 kB 🟢 -3.25 kB 🟢 -1.3 kB 🟢 -1.11 kB
assets/GlobalToast-CgfRz7-U.js (new) 3.25 kB 🔴 +3.25 kB 🔴 +1.3 kB 🔴 +1.11 kB
assets/Media3DTop-C6sxIv0T.js (removed) 3.21 kB 🟢 -3.21 kB 🟢 -1.26 kB 🟢 -1.1 kB
assets/Media3DTop-W_myRE5Z.js (new) 3.21 kB 🔴 +3.21 kB 🔴 +1.26 kB 🔴 +1.1 kB
assets/load3dAdvanced-BUmeV_TL.js (new) 2.82 kB 🔴 +2.82 kB 🔴 +1.09 kB 🔴 +955 B
assets/load3dAdvanced-CvnkN6Gg.js (removed) 2.82 kB 🟢 -2.82 kB 🟢 -1.09 kB 🟢 -950 B
assets/SubscribeToRun-CcMFEBB-.js (removed) 2.39 kB 🟢 -2.39 kB 🟢 -1.03 kB 🟢 -928 B
assets/SubscribeToRun-DgxFM9xV.js (new) 2.39 kB 🔴 +2.39 kB 🔴 +1.03 kB 🔴 +896 B
assets/MediaAudioTop-BYxnQHb-.js (removed) 1.62 kB 🟢 -1.62 kB 🟢 -806 B 🟢 -670 B
assets/MediaAudioTop-D3hhmdFG.js (new) 1.62 kB 🔴 +1.62 kB 🔴 +806 B 🔴 +668 B
assets/cloudSessionCookie-BL5IYFxN.js (new) 933 B 🔴 +933 B 🔴 +432 B 🔴 +376 B
assets/cloudSessionCookie-O88oAbcC.js (removed) 933 B 🟢 -933 B 🟢 -434 B 🟢 -379 B
assets/cloudBadges-B5KcUySW.js (removed) 922 B 🟢 -922 B 🟢 -514 B 🟢 -464 B
assets/cloudBadges-D8ISMtsb.js (new) 922 B 🔴 +922 B 🔴 +513 B 🔴 +440 B
assets/Load3DAdvanced-CMzm_sf8.js (removed) 761 B 🟢 -761 B 🟢 -423 B 🟢 -358 B
assets/Load3DAdvanced-Dc-n8g30.js (new) 761 B 🔴 +761 B 🔴 +424 B 🔴 +360 B
assets/nightlyBadges-D6af9NBA.js (new) 411 B 🔴 +411 B 🔴 +273 B 🔴 +271 B
assets/nightlyBadges-KKnzwogI.js (removed) 411 B 🟢 -411 B 🟢 -273 B 🟢 -268 B
assets/Load3dViewerContent-DdR0dMEO.js (removed) 137 B 🟢 -137 B 🟢 -103 B 🟢 -109 B
assets/Load3dViewerContent-nQ0I-rTW.js (new) 137 B 🔴 +137 B 🔴 +103 B 🔴 +94 B
assets/missingModelMetadata-Dsjobcgg.js (new) 125 B 🔴 +125 B 🔴 +103 B 🔴 +99 B
assets/missingModelMetadata-WvbBZ2Dv.js (removed) 125 B 🟢 -125 B 🟢 -103 B 🟢 -103 B
assets/Load3DAdvanced-Bym4NPd7.js (removed) 122 B 🟢 -122 B 🟢 -97 B 🟢 -97 B
assets/Load3DAdvanced-zy7lU9c4.js (new) 122 B 🔴 +122 B 🔴 +97 B 🔴 +87 B
assets/WidgetLegacy-k4c7QbpV.js (removed) 117 B 🟢 -117 B 🟢 -106 B 🟢 -102 B
assets/WidgetLegacy-pIC68IZQ.js (new) 117 B 🔴 +117 B 🔴 +106 B 🔴 +105 B
assets/workflowDraftStoreV2-Bvss4sTs.js (new) 112 B 🔴 +112 B 🔴 +101 B 🔴 +110 B
assets/workflowDraftStoreV2-Dh-pHubc.js (removed) 112 B 🟢 -112 B 🟢 -101 B 🟢 -109 B
assets/Load3D-CgDE_yoz.js (new) 98 B 🔴 +98 B 🔴 +89 B 🔴 +80 B
assets/Load3D-ktcbRmW8.js (removed) 98 B 🟢 -98 B 🟢 -89 B 🟢 -78 B
assets/changeTracker-D-x_XLtt.js (new) 91 B 🔴 +91 B 🔴 +93 B 🔴 +83 B
assets/changeTracker-Dlp2Fuy8.js (removed) 91 B 🟢 -91 B 🟢 -93 B 🟢 -91 B

Status: 68 added / 68 removed / 217 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.5 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 49.6 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.8 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 50.6 MB heap
large-graph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.2 MB heap
large-graph-pan: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.3 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 71.4 MB heap
minimap-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.3 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 50.5 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.1 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 51.2 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 130ms TBT · 71.2 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.2 MB heap
vue-large-graph-idle: · 57.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 158.6 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 37ms TBT · 147.8 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.5 MB heap

⚠️ 7 regressions detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-idle: task duration 609ms 482ms -21% ⚠️ z=2.8
canvas-zoom-sweep: layout duration 1ms 1ms +11% ⚠️ z=2.4
canvas-zoom-sweep: task duration 456ms 385ms -16% ⚠️ z=2.5
large-graph-idle: task duration 850ms 655ms -23% ⚠️ z=2.1
large-graph-pan: task duration 1406ms 1225ms -13% ⚠️ z=3.3
minimap-idle: task duration 836ms 665ms -20% ⚠️ z=2.9
subgraph-idle: task duration 604ms 479ms -21% ⚠️ z=3.5
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms +0% z=-0.9
canvas-idle: p95 frame time 17ms 17ms +0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 8ms 8ms -4% z=-3.6
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 8 10 +25% z=-2.1
canvas-idle: task duration 609ms 482ms -21% ⚠️ z=2.8
canvas-idle: script duration 25ms 20ms -20% z=-2.4
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 44.6 MB 66.5 MB +49%
canvas-idle: DOM nodes 4 20 +400% z=-2.0
canvas-idle: event listeners -153 4 -103% z=-1.6
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms -0%
canvas-mouse-sweep: layout duration 4ms 4ms -7% z=1.0
canvas-mouse-sweep: style recalc duration 44ms 38ms -13% z=-1.4
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 76 77 +1% z=-0.7
canvas-mouse-sweep: task duration 992ms 886ms -11% z=0.4
canvas-mouse-sweep: script duration 131ms 114ms -14% z=-3.4
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 49.9 MB 49.6 MB -1%
canvas-mouse-sweep: DOM nodes -282 -280 -1% z=-132.3
canvas-mouse-sweep: event listeners -153 -153 +0% z=-38.7
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=0.5
canvas-zoom-sweep: p95 frame time 17ms 17ms -0%
canvas-zoom-sweep: layout duration 1ms 1ms +11% ⚠️ z=2.4
canvas-zoom-sweep: style recalc duration 19ms 16ms -18% z=-2.0
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 31 31 -2% z=-1.7
canvas-zoom-sweep: task duration 456ms 385ms -16% ⚠️ z=2.5
canvas-zoom-sweep: script duration 28ms 22ms -24% z=-1.9
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 69.5 MB 69.8 MB +0%
canvas-zoom-sweep: DOM nodes 77 77 +0% z=-2.8
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.2
dom-widget-clipping: p95 frame time 17ms 17ms +0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 7ms 7ms -5% z=-3.7
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 10 12 +20% z=-2.2
dom-widget-clipping: task duration 399ms 372ms -7% z=0.4
dom-widget-clipping: script duration 60ms 54ms -10% z=-4.2
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 50.7 MB 50.6 MB -0%
dom-widget-clipping: DOM nodes 16 20 +25% z=-1.5
dom-widget-clipping: event listeners 2 0 -100% 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 8ms 6ms -22% z=-6.0
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 8 8 +0% z=-11.5
large-graph-idle: task duration 850ms 655ms -23% ⚠️ z=2.1
large-graph-idle: script duration 126ms 92ms -27% z=-1.0
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 63.5 MB 64.2 MB +1%
large-graph-idle: DOM nodes -283 -283 +0% z=-340.4
large-graph-idle: event listeners -149 -148 -1% z=-28.6
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.8
large-graph-pan: p95 frame time 17ms 17ms -0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 15ms 15ms -2% z=-3.4
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 69 +1% z=-1.7
large-graph-pan: task duration 1406ms 1225ms -13% ⚠️ z=3.3
large-graph-pan: script duration 451ms 392ms -13% z=-0.8
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 62.7 MB 62.3 MB -1%
large-graph-pan: DOM nodes -286 -285 -1% z=-184.0
large-graph-pan: event listeners -151 -148 -2% z=-184.7
large-graph-zoom: avg frame time 17ms 17ms -0%
large-graph-zoom: p95 frame time 17ms 17ms +0%
large-graph-zoom: layout duration 9ms 9ms -2%
large-graph-zoom: style recalc duration 17ms 17ms +2%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 64 66 +3%
large-graph-zoom: task duration 1724ms 1474ms -14%
large-graph-zoom: script duration 601ms 476ms -21%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 68.4 MB 71.4 MB +4%
large-graph-zoom: DOM nodes -290 -137 -53%
large-graph-zoom: event listeners -153 -73 -53%
minimap-idle: avg frame time 17ms 17ms -0% z=-0.9
minimap-idle: p95 frame time 17ms 17ms +0%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 7ms 6ms -8% z=-3.8
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 7 8 +14% z=-2.3
minimap-idle: task duration 836ms 665ms -20% ⚠️ z=2.9
minimap-idle: script duration 129ms 96ms -25% z=-0.2
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 64.2 MB 64.3 MB +0%
minimap-idle: DOM nodes -285 -284 -1% z=-221.3
minimap-idle: event listeners -149 -149 +0% z=-232.6
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms -1%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 11ms 11ms +2% z=-2.0
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 46 48 +3% z=-0.8
subgraph-dom-widget-clipping: task duration 430ms 400ms -7% z=1.2
subgraph-dom-widget-clipping: script duration 129ms 116ms -10% z=-2.0
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 51.3 MB 50.5 MB -1%
subgraph-dom-widget-clipping: DOM nodes 18 21 +17% z=-1.1
subgraph-dom-widget-clipping: event listeners 8 6 -25% z=-1.7
subgraph-idle: avg frame time 17ms 17ms +0% z=0.9
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 9ms 8ms -8% z=-3.1
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 9 11 +22% z=0.2
subgraph-idle: task duration 604ms 479ms -21% ⚠️ z=3.5
subgraph-idle: script duration 22ms 18ms -18% z=-0.9
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 67.2 MB 56.1 MB -17%
subgraph-idle: DOM nodes 18 -128 -811% z=-100.2
subgraph-idle: event listeners 4 -75 -1963% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms -0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms +0%
subgraph-mouse-sweep: layout duration 5ms 5ms +1% z=0.6
subgraph-mouse-sweep: style recalc duration 41ms 36ms -11% z=-1.8
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 78 76 -3% z=-2.1
subgraph-mouse-sweep: task duration 858ms 743ms -13% z=-0.3
subgraph-mouse-sweep: script duration 102ms 89ms -13% z=-1.9
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 57.9 MB 51.2 MB -11%
subgraph-mouse-sweep: DOM nodes 63 -109 -272% z=-78.5
subgraph-mouse-sweep: event listeners 4 -75 -1963% 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 12ms 11ms -11%
subgraph-transition-enter: style recalc duration 31ms 28ms -11%
subgraph-transition-enter: layout count 13 15 +15%
subgraph-transition-enter: style recalc count 17 19 +12%
subgraph-transition-enter: task duration 1091ms 881ms -19%
subgraph-transition-enter: script duration 42ms 34ms -19%
subgraph-transition-enter: TBT 130ms 130ms +0%
subgraph-transition-enter: heap used 95.3 MB 71.2 MB -25%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2375 2375 +0%
viewport-pan-sweep: avg frame time 17ms 17ms -0%
viewport-pan-sweep: p95 frame time 17ms 17ms -1%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 46ms 44ms -4%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 250 -0%
viewport-pan-sweep: task duration 5087ms 4453ms -12%
viewport-pan-sweep: script duration 1502ms 1345ms -10%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 71.3 MB 68.2 MB -4%
viewport-pan-sweep: DOM nodes -283 -284 +0%
viewport-pan-sweep: event listeners -131 -133 +2%
vue-large-graph-idle: avg frame time 18ms 17ms -2%
vue-large-graph-idle: p95 frame time 17ms 17ms -0%
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 18529ms 14481ms -22%
vue-large-graph-idle: script duration 580ms 527ms -9%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 158.0 MB 158.6 MB +0%
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 17ms -6%
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 28ms 18ms -37%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 177 121 -32%
vue-large-graph-pan: task duration 23556ms 17482ms -26%
vue-large-graph-pan: script duration 983ms 880ms -10%
vue-large-graph-pan: TBT 1019ms 37ms -96%
vue-large-graph-pan: heap used 159.0 MB 147.8 MB -7%
vue-large-graph-pan: DOM nodes -8312 -8312 +0%
vue-large-graph-pan: event listeners -16381 -16384 +0%
workflow-execution: avg frame time 17ms 17ms +0% z=0.1
workflow-execution: p95 frame time 17ms 17ms +0%
workflow-execution: layout duration 1ms 1ms +72% z=-2.3
workflow-execution: style recalc duration 21ms 20ms -4% z=-1.9
workflow-execution: layout count 3 3 +0% z=-3.6
workflow-execution: style recalc count 12 13 +8% z=-2.3
workflow-execution: task duration 130ms 119ms -9% z=-0.4
workflow-execution: script duration 11ms 10ms -11% z=-6.4
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 65.3 MB 65.5 MB +0%
workflow-execution: DOM nodes 122 125 +2% z=-5.1
workflow-execution: event listeners 97 98 +1% 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-11T22:52:49.985Z",
  "gitSha": "79cc6153fb556837c2992b33268d8f1122007f84",
  "branch": "test/billing-op-store-coverage",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2051.4840000000163,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.036999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 518.826,
      "heapDeltaBytes": 5759672,
      "heapUsedBytes": 70311324,
      "domNodes": 20,
      "jsHeapTotalBytes": 24379392,
      "scriptDurationMs": 21.648,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-idle",
      "durationMs": 2037.4990000000253,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 7.122999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 445.83199999999994,
      "heapDeltaBytes": 5390824,
      "heapUsedBytes": 69132040,
      "domNodes": 20,
      "jsHeapTotalBytes": 25427968,
      "scriptDurationMs": 18.358000000000004,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1922.1569999999701,
      "styleRecalcs": 79,
      "styleRecalcDurationMs": 40.033,
      "layouts": 12,
      "layoutDurationMs": 3.865,
      "taskDurationMs": 885.005,
      "heapDeltaBytes": -12828816,
      "heapUsedBytes": 51683428,
      "domNodes": -283,
      "jsHeapTotalBytes": 22519808,
      "scriptDurationMs": 112.43900000000001,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1849.62900000005,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 36.443000000000005,
      "layouts": 12,
      "layoutDurationMs": 3.7670000000000003,
      "taskDurationMs": 887.783,
      "heapDeltaBytes": -12000448,
      "heapUsedBytes": 52297544,
      "domNodes": -277,
      "jsHeapTotalBytes": 23306240,
      "scriptDurationMs": 114.77700000000002,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1724.5349999999462,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 15.803999999999998,
      "layouts": 6,
      "layoutDurationMs": 0.8340000000000001,
      "taskDurationMs": 377.512,
      "heapDeltaBytes": 8752136,
      "heapUsedBytes": 73294572,
      "domNodes": 76,
      "jsHeapTotalBytes": 24379392,
      "scriptDurationMs": 20.340999999999998,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1739.465999999993,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 16.244,
      "layouts": 6,
      "layoutDurationMs": 0.665,
      "taskDurationMs": 392.38800000000003,
      "heapDeltaBytes": 8785360,
      "heapUsedBytes": 73177484,
      "domNodes": 78,
      "jsHeapTotalBytes": 24641536,
      "scriptDurationMs": 22.757,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 626.2679999999818,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 6.931000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 385.127,
      "heapDeltaBytes": -11247764,
      "heapUsedBytes": 53128360,
      "domNodes": 20,
      "jsHeapTotalBytes": 25690112,
      "scriptDurationMs": 57.13999999999999,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 563.8890000000174,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 6.956999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 358.188,
      "heapDeltaBytes": -11228308,
      "heapUsedBytes": 53038016,
      "domNodes": 20,
      "jsHeapTotalBytes": 25165824,
      "scriptDurationMs": 51.30500000000001,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2028.9510000000064,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 4.944999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 657.9079999999999,
      "heapDeltaBytes": 7518120,
      "heapUsedBytes": 67341492,
      "domNodes": -284,
      "jsHeapTotalBytes": 3510272,
      "scriptDurationMs": 93.481,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2060.1219999999785,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 6.856000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 652.4540000000001,
      "heapDeltaBytes": 7435836,
      "heapUsedBytes": 67390456,
      "domNodes": -282,
      "jsHeapTotalBytes": 3510272,
      "scriptDurationMs": 91.081,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2150.9190000000444,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 15.109000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1196.746,
      "heapDeltaBytes": 4274880,
      "heapUsedBytes": 64726108,
      "domNodes": -283,
      "jsHeapTotalBytes": 3440640,
      "scriptDurationMs": 374.168,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2138.6759999999185,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 14.111999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1252.3549999999998,
      "heapDeltaBytes": 4653548,
      "heapUsedBytes": 65962532,
      "domNodes": -286,
      "jsHeapTotalBytes": 3440640,
      "scriptDurationMs": 409.696,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3252.301999999986,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 17.403,
      "layouts": 60,
      "layoutDurationMs": 8.765,
      "taskDurationMs": 1502.86,
      "heapDeltaBytes": 249352,
      "heapUsedBytes": 62827472,
      "domNodes": -287,
      "jsHeapTotalBytes": 5607424,
      "scriptDurationMs": 473.65000000000003,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3219.8600000000397,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 17.169000000000004,
      "layouts": 60,
      "layoutDurationMs": 9.037999999999998,
      "taskDurationMs": 1445.1799999999998,
      "heapDeltaBytes": 24277600,
      "heapUsedBytes": 86887044,
      "domNodes": 14,
      "jsHeapTotalBytes": 7340032,
      "scriptDurationMs": 479.21000000000004,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2042.5000000000182,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 6.541999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 656.25,
      "heapDeltaBytes": 6835008,
      "heapUsedBytes": 67504464,
      "domNodes": -285,
      "jsHeapTotalBytes": 2985984,
      "scriptDurationMs": 94.45400000000001,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2033.9389999999185,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 6.402999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 674.604,
      "heapDeltaBytes": 6804372,
      "heapUsedBytes": 67294472,
      "domNodes": -282,
      "jsHeapTotalBytes": 4034560,
      "scriptDurationMs": 97.58,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 599.2750000000342,
      "styleRecalcs": 48,
      "styleRecalcDurationMs": 11.687000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 406.83,
      "heapDeltaBytes": -10702008,
      "heapUsedBytes": 53837924,
      "domNodes": 22,
      "jsHeapTotalBytes": 25690112,
      "scriptDurationMs": 118.723,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 568.7430000000404,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 10.016,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 393.492,
      "heapDeltaBytes": -11599308,
      "heapUsedBytes": 52169764,
      "domNodes": 20,
      "jsHeapTotalBytes": 26214400,
      "scriptDurationMs": 112.486,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2027.2360000000162,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 7.964000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 461.687,
      "heapDeltaBytes": 5904876,
      "heapUsedBytes": 70536112,
      "domNodes": 22,
      "jsHeapTotalBytes": 24379392,
      "scriptDurationMs": 18.31,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2014.6540000000641,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 7.949999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 497.29499999999996,
      "heapDeltaBytes": -17414424,
      "heapUsedBytes": 47071028,
      "domNodes": -278,
      "jsHeapTotalBytes": 22519808,
      "scriptDurationMs": 17.229000000000003,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1693.930000000023,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 37.229,
      "layouts": 16,
      "layoutDurationMs": 5.163,
      "taskDurationMs": 683.1859999999999,
      "heapDeltaBytes": -3856840,
      "heapUsedBytes": 60729680,
      "domNodes": 62,
      "jsHeapTotalBytes": 24903680,
      "scriptDurationMs": 89.05,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1711.6959999999608,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 35.492000000000004,
      "layouts": 16,
      "layoutDurationMs": 4.615,
      "taskDurationMs": 801.9879999999999,
      "heapDeltaBytes": -17726740,
      "heapUsedBytes": 46735032,
      "domNodes": -279,
      "jsHeapTotalBytes": 23306240,
      "scriptDurationMs": 88.245,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1401.927999999998,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 27.804000000000002,
      "layouts": 15,
      "layoutDurationMs": 10.567,
      "taskDurationMs": 880.5920000000001,
      "heapDeltaBytes": 3476984,
      "heapUsedBytes": 74681668,
      "domNodes": 13673,
      "jsHeapTotalBytes": 15990784,
      "scriptDurationMs": 33.594,
      "eventListeners": 2375,
      "totalBlockingTimeMs": 130,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8187.780000000089,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 44.503,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4357.313999999999,
      "heapDeltaBytes": 8729140,
      "heapUsedBytes": 68166836,
      "domNodes": -283,
      "jsHeapTotalBytes": 5799936,
      "scriptDurationMs": 1259.857,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8200.531999999952,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 43.544,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4547.716,
      "heapDeltaBytes": 14656284,
      "heapUsedBytes": 74874048,
      "domNodes": -284,
      "jsHeapTotalBytes": 8945664,
      "scriptDurationMs": 1430.204,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 14428.174000000014,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14412.078999999998,
      "heapDeltaBytes": -31541520,
      "heapUsedBytes": 166520588,
      "domNodes": -8312,
      "jsHeapTotalBytes": -10428416,
      "scriptDurationMs": 520.475,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 14576.70100000007,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14549.262999999999,
      "heapDeltaBytes": -51501236,
      "heapUsedBytes": 166135348,
      "domNodes": -8312,
      "jsHeapTotalBytes": -7540736,
      "scriptDurationMs": 533.1740000000001,
      "eventListeners": -16387,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 17489.65999999996,
      "styleRecalcs": 121,
      "styleRecalcDurationMs": 17.574999999999978,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 17464.413,
      "heapDeltaBytes": -49302624,
      "heapUsedBytes": 156533212,
      "domNodes": -8312,
      "jsHeapTotalBytes": -8855552,
      "scriptDurationMs": 884.055,
      "eventListeners": -16385,
      "totalBlockingTimeMs": 24,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 17530.54599999996,
      "styleRecalcs": 120,
      "styleRecalcDurationMs": 18.062999999999967,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 17499.284,
      "heapDeltaBytes": -72511556,
      "heapUsedBytes": 153471328,
      "domNodes": -8312,
      "jsHeapTotalBytes": -10166272,
      "scriptDurationMs": 876.437,
      "eventListeners": -16383,
      "totalBlockingTimeMs": 49,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 474.6549999999843,
      "styleRecalcs": 14,
      "styleRecalcDurationMs": 21.238999999999997,
      "layouts": 3,
      "layoutDurationMs": 1.6119999999999999,
      "taskDurationMs": 126.72299999999997,
      "heapDeltaBytes": 5063040,
      "heapUsedBytes": 68749036,
      "domNodes": 126,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 11.094,
      "eventListeners": 99,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "workflow-execution",
      "durationMs": 469.9319999999716,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 18.973000000000003,
      "layouts": 3,
      "layoutDurationMs": 0.8059999999999998,
      "taskDurationMs": 110.624,
      "heapDeltaBytes": 5045044,
      "heapUsedBytes": 68532612,
      "domNodes": 123,
      "jsHeapTotalBytes": 4718592,
      "scriptDurationMs": 9.302999999999999,
      "eventListeners": 97,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000728
    }
  ]
}

…hrow

A thrown error in the success-path side-effects block (dialog close,
settings show, or toast add) silently skips resolveTerminal, leaving
any caller awaiting startOperation() hanging forever. poll()'s
catch-all swallowed the exception, masking the hang.

Adds a try/finally so resolveTerminal runs unconditionally after the
success side-effects block. Adds a regression test that throws from
the second mockToastAdd call and asserts the terminal promise still
resolves to succeeded.

Found in the review of #14421.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##             main   #14964      +/-   ##
==========================================
- Coverage   81.30%   81.20%   -0.10%     
==========================================
  Files        1871     1873       +2     
  Lines      106640   107810    +1170     
  Branches    31425    32208     +783     
==========================================
+ Hits        86701    87548     +847     
- Misses      19591    19884     +293     
- Partials      348      378      +30     
Flag Coverage Δ
unit 72.52% <100.00%> (+0.14%) ⬆️

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

Files with missing lines Coverage Δ
...platform/workspace/stores/billingOperationStore.ts 96.09% <100.00%> (+0.33%) ⬆️

... and 59 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 previously approved these changes Aug 10, 2026

@dante01yoon dante01yoon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The change correctly prevents the terminal promise from hanging when the dialog/toast success effects throw. The regression test covers the reported failure path. I left one non-blocking suggestion about broadening the guarantee to the other post-success effects.

useDialogStore().closeDialog({ key: 'top-up-credits' })
useSettingsDialog().show('workspace')
}
try {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion (non-blocking): Could we place this try/finally around all post-success effects after the operation is marked succeeded? As written, a synchronous throw from telemetry, billing reconciliation setup, or the cancel workspace update can still leave the terminal promise unresolved. This patch fixes the reported dialog/toast path, so this does not need to block the PR.

The cancel path's updateActiveWorkspace call and dialog/toast calls are
now all guarded by the same try/finally, so resolveTerminal fires even
if any synchronous side effect throws.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@src/platform/workspace/stores/billingOperationStore.ts`:
- Around line 416-441: Move the existing try/finally boundary in the terminal
operation flow to immediately follow updateOperationStatus, enclosing cleanup,
telemetry, reconciliation, and the current success handling so
resolveTerminal(opId) always executes. Add a regression test that makes a
reconciliation method throw synchronously and verifies the terminal promise
still resolves.
🪄 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: effeceb8-512f-4b0c-b879-0b5803bbb825

📥 Commits

Reviewing files that changed from the base of the PR and between 77fb039 and 46b357d.

📒 Files selected for processing (2)
  • src/platform/workspace/stores/billingOperationStore.test.ts
  • src/platform/workspace/stores/billingOperationStore.ts

Comment on lines +416 to +441
try {
if (operation.type === 'cancel') {
useTeamWorkspaceStore().updateActiveWorkspace({ isSubscribed: false })
return
}

const toastStore = useToastStore()
const messageKey =
operation.type === 'subscription'
? 'billingOperation.subscriptionSuccess'
: 'billingOperation.topupSuccess'
// A subscription checkout shows its own success step in the pricing dialog,
// so leave it open. Top-ups have no such step: close and surface settings.
if (operation.type === 'topup') {
useDialogStore().closeDialog({ key: 'top-up-credits' })
useSettingsDialog().show('workspace')
}

toastStore.add({
severity: 'success',
summary: t(messageKey),
life: 5000
})
const toastStore = useToastStore()
const messageKey =
operation.type === 'subscription'
? 'billingOperation.subscriptionSuccess'
: 'billingOperation.topupSuccess'

resolveTerminal(opId)
toastStore.add({
severity: 'success',
summary: t(messageKey),
life: 5000
})
} finally {
resolveTerminal(opId)

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Expand the terminal-resolution boundary.

cleanup, telemetry, and reconciliation run before this try/finally. If one throws synchronously, resolveTerminal does not run. poll then returns from its catch path because updateOperationStatus replaced the operation object, so the terminal promise remains pending.

Start the try/finally immediately after updateOperationStatus. Include cleanup, telemetry, and reconciliation. Add a regression test that makes a reconciliation method throw synchronously.

🤖 Prompt for 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.

In `@src/platform/workspace/stores/billingOperationStore.ts` around lines 416 -
441, Move the existing try/finally boundary in the terminal operation flow to
immediately follow updateOperationStatus, enclosing cleanup, telemetry,
reconciliation, and the current success handling so resolveTerminal(opId) always
executes. Add a regression test that makes a reconciliation method throw
synchronously and verifies the terminal promise still resolves.

…ciliation

resolveTerminal now fires even if any synchronous side effect in
handleSuccess throws — including cleanup, telemetry dispatches,
billing context reconciliation, or the cancel workspace update.
Adds a regression test verifying the terminal promise resolves when
reconcileSubscriptionSuccess throws synchronously.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Aug 11, 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: 1

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

Inline comments:
In `@src/platform/workspace/stores/billingOperationStore.ts`:
- Around line 408-416: Update the success-side effects around
billingContext.reconcileSubscriptionSuccess, fetchStatus, and fetchBalance to
catch and log any rejected error before preserving the existing propagation or
return behavior. Keep the finally-based resolveTerminal flow unchanged, and use
the store’s existing logging mechanism.
🪄 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: 698f6984-e300-4643-9327-e4f2a7af1e1f

📥 Commits

Reviewing files that changed from the base of the PR and between 46b357d and 027e785.

📒 Files selected for processing (2)
  • src/platform/workspace/stores/billingOperationStore.test.ts
  • src/platform/workspace/stores/billingOperationStore.ts

Comment on lines +408 to +416
const billingContext = useBillingContext()
if (operation.type === 'subscription') {
await Promise.allSettled([billingContext.reconcileSubscriptionSuccess()])
} else {
await Promise.allSettled([
billingContext.fetchStatus(),
billingContext.fetchBalance()
])
}

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.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider logging the swallowed side-effect error.

The finally block guarantees resolveTerminal, but the original error still propagates out of handleSuccess. poll awaits handleSuccess inside its own try, so the rejection reaches the catch at line 258. There, currentOperation !== operation is true because updateOperationStatus replaced the map entry, so poll returns and discards the error.

Result: a reconciliation or telemetry failure leaves no diagnostic signal. Add a catch that logs the error before rethrowing or before returning, so failures in the success path stay observable.

♻️ Proposed observability improvement
     } finally {
       resolveTerminal(opId)
     }
+    } catch (error) {
+      console.error(`Billing operation ${opId} success handling failed`, error)
     } finally {
       resolveTerminal(opId)
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const billingContext = useBillingContext()
if (operation.type === 'subscription') {
await Promise.allSettled([billingContext.reconcileSubscriptionSuccess()])
} else {
await Promise.allSettled([
billingContext.fetchStatus(),
billingContext.fetchBalance()
])
}
const billingContext = useBillingContext()
if (operation.type === 'subscription') {
await Promise.allSettled([billingContext.reconcileSubscriptionSuccess()])
} else {
await Promise.allSettled([
billingContext.fetchStatus(),
billingContext.fetchBalance()
])
}
} catch (error) {
console.error(`Billing operation ${opId} success handling failed`, error)
} finally {
resolveTerminal(opId)
}
🤖 Prompt for 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.

In `@src/platform/workspace/stores/billingOperationStore.ts` around lines 408 -
416, Update the success-side effects around
billingContext.reconcileSubscriptionSuccess, fetchStatus, and fetchBalance to
catch and log any rejected error before preserving the existing propagation or
return behavior. Keep the finally-based resolveTerminal flow unchanged, and use
the store’s existing logging mechanism.

@christian-byrne

christian-byrne commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Handoff: @dante01yoon owns Cloud billing on the frontend now. This one carries changes requested, so it needs work before review, unlike the five straightforward ones I reassigned to him (#14867, #14866, #14856, #14865, #14477).

@christian-byrne

Copy link
Copy Markdown
Contributor Author

Verified the current state — the try/finally boundary now correctly wraps cleanup, telemetry, and reconciliation as CodeRabbit requested, not just the toast/dialog calls from my original narrower fix. resolveTerminal(opId) in the finally guarantees the terminal promise resolves regardless of what throws inside. Both new regression tests (toast throw, reconciliation throw) look correct. No CI failures, no remaining objection from me — looks ready to merge once re-reviewed.

@christian-byrne

Copy link
Copy Markdown
Contributor Author

Heads up — this now has a merge conflict against main in billingOperationStore.ts: your try/finally around resolveTerminal and #15164's isCloud ? 'workspace' : 'credits' settings-dialog destination changed the same block. Not mechanical (needs both kept together correctly), so leaving it for you rather than guessing at the right merge given you own this file now. Should be a quick rebase once you're looking at it.

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

Labels

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