Skip to content

fix(website): slugify cloud-node pack ids and mock e2e snapshot#12277

Draft
DrJKL wants to merge 7 commits into
mainfrom
glary/website-cloud-nodes-mock-and-slugify
Draft

fix(website): slugify cloud-node pack ids and mock e2e snapshot#12277
DrJKL wants to merge 7 commits into
mainfrom
glary/website-cloud-nodes-mock-and-slugify

Conversation

@DrJKL
Copy link
Copy Markdown
Contributor

@DrJKL DrJKL commented May 14, 2026

PR Created by the Glary-Bot Agent


Summary

/cloud/supported-nodes routes use pack ids as URL segments, but those ids come straight from upstream Python module names which mix PascalCase, snake_case, and kebab-case freely. The most recent Release: Website snapshot refresh (#12271) surfaced packs like ComfyUI-Crystools and basic_data_handling, and the Playwright assertions in cloud-nodes.spec.ts broke on three independent fronts:

  • the slug regex [a-z0-9-]+$ rejects basic_data_handling (underscores) and ComfyQR (uppercase)
  • the hardcoded comfyui-impact-pack assertions assumed the refreshed snapshot would still contain that pack — it didn't
  • the FaceDetailer search assumed Impact Pack nodes would always be present

This PR addresses both the root cause and the test fragility in one change.

Changes

Slugify pack ids at the boundariesslugifyPackId in @comfyorg/object-info-parser normalizes every pack id (lowercase + _-) at the two points where ids enter the website:

  • groupNodesByPack for fresh fetches from the cloud API
  • readSnapshot for the bundled / fallback snapshot

The raw upstream id is preserved as NodePack.rawIds[] and forwarded to fetchRegistryPacks, so registry enrichment continues to hit api.comfy.org/nodes with the exact node_id the API expects (uppercase, underscores, all). 24 underscore-vs-hyphen pairs exist in the live registry today (ComfyUI-QwenVL + ComfyUI_QwenVL, etc.); collisions are merged deterministically into a single static route. When two raw ids collide on the same slug, every alias is queried in one registry batch and the first non-null hit wins, so a merged pack never loses metadata that only one alias would have resolved.

Mock the snapshot in CIWEBSITE_CLOUD_NODES_FIXTURE lets the e2e build read a committed fixture in place of the bundled snapshot. CI sets it to e2e/fixtures/cloud-nodes.fixture.json (a deterministic 5-pack fixture designed to satisfy every assertion in the spec). The override only fires when the env var is set; production builds continue to use the live snapshot and the stale-in-production guard.

Verification

  • 99/99 desktop Playwright tests pass against the fixture-built site (the 4 previously-failing cloud-nodes tests included)
  • 82/82 website Vitest tests pass (+2 build-utility + alias-fallback cases)
  • 49/49 object-info-parser tests pass (+11 new slugifyPackId cases, +5 new groupNodesByPack cases)
  • astro check: 0 errors
  • Local astro build with the fixture env var produces all expected routes (/cloud/supported-nodes/comfyui-impact-pack, /cloud/supported-nodes/comfyui-crystools, /cloud/supported-nodes/alpha-test-pack, /cloud/supported-nodes/rgthree-comfy, /cloud/supported-nodes/was-node-suite-comfyui, plus zh-CN twins)
  • Oracle review: 2 warnings raised, 1 was pre-existing (appModeStore from fix: preserve app builder inputs through graph reconfiguration #11422, out of scope), 1 addressed in this PR (alias loss on slug collision, fixed by rawIds[] + multi-alias query in pickRegistryPack)

Notes for reviewers

  • The committed cloud-nodes.snapshot.json is rewritten so the on-disk ids match what the slugifier produces (ComfyUI-Crystoolscomfyui-crystools, comfyui_ipadapter_pluscomfyui-ipadapter-plus). This breaks any external link to …/cloud/supported-nodes/ComfyUI-Crystools or …/cloud/supported-nodes/comfyui_ipadapter_plus — those URLs were never the documented form, but worth a quick gut-check before merge.

  • PR chore(website): refresh Ashby and cloud nodes snapshots #12271 (the failing auto-refresh) does not need any manual fix once this lands: its broken snapshot data will be regenerated by the next Release: Website run and routed correctly through slugifyPackId.

  • The Pack shape on disk is unchanged. registryId continues to hold the raw upstream id; only id is now guaranteed to be a clean slug.

  • Fixes the website-e2e check failure on chore(website): refresh Ashby and cloud nodes snapshots #12271

┆Issue is synchronized with this Notion page by Unito

Glary-Bot added 2 commits May 14, 2026 19:54
The website's /cloud/supported-nodes routes use pack ids as URL segments,
but pack ids come straight from upstream Python module names which mix
PascalCase, snake_case, and kebab-case freely. After a Release: Website
snapshot refresh that surfaced packs like ComfyUI-Crystools and
basic_data_handling, the Playwright assertions in cloud-nodes.spec.ts
broke because the slug regex requires kebab-case and the hardcoded
comfyui-impact-pack assertions assumed registry contents would never
change.

Two coordinated fixes:

* slugifyPackId in @comfyorg/object-info-parser normalizes every pack
  id (lowercase + _\u2192-) at the boundaries where it enters the website:
  groupNodesByPack for fresh fetches and readSnapshot for the bundled
  fallback. The raw upstream id is preserved as rawId/registryId so
  registry enrichment continues to hit https://api.comfy.org/nodes
  with the exact node_id the API expects. Packs whose raw ids collide
  on the same slug (24 such pairs exist in the live registry today,
  e.g. ComfyUI-QwenVL + ComfyUI_QwenVL) are merged deterministically
  instead of producing duplicate static routes.

* WEBSITE_CLOUD_NODES_FIXTURE lets the e2e build read a committed
  fixture snapshot in place of the bundled one. CI sets it to
  e2e/fixtures/cloud-nodes.fixture.json so Playwright assertions run
  against deterministic pack content; future snapshot refreshes can
  no longer break the test contract by removing the Impact Pack or
  adding underscored ids.

Verification:
* 99/99 desktop Playwright tests pass against the fixture-built site
* 81/81 website Vitest unit tests pass (including new build/fixture
  coverage)
* 48/48 object-info-parser tests pass (11 new slugifyPackId cases,
  4 new groupNodesByPack cases)
* astro check: 0 errors
Addresses Oracle review feedback: when two raw upstream ids slugify to
the same URL slug (e.g. ComfyUI-QwenVL + ComfyUI_QwenVL both -> comfyui-qwenvl)
the previous merge kept only the first rawId and used only that single
alias to fetch registry metadata. If that one alias missed but its twin
would have resolved, the merged pack lost banner/icon/license info.

Now NodePack carries rawIds: string[] holding every raw alias seen for
the slug. parseCloudNodes flattens all aliases into a single registry
batch and pickRegistryPack walks the alias list in insertion order to
find the first non-null hit.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

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: CHILL

Plan: Pro

Run ID: 78d7b5fa-c86e-43c6-9bac-d83eebd02c81

📥 Commits

Reviewing files that changed from the base of the PR and between c753f30 and 669bd5d.

📒 Files selected for processing (1)
  • apps/website/src/utils/cloudNodes.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/website/src/utils/cloudNodes.test.ts

📝 Walkthrough

Walkthrough

Normalize cloud node pack IDs to URL-safe slugs, track raw upstream aliases, merge slug-collided snapshot packs, use an optional on-disk snapshot fixture during website builds (CI e2e), and add tests covering slugification, alias resolution, normalization, and merge semantics.

Changes

Pack ID slugification, grouping, and registry aliasing

Layer / File(s) Summary
Slugify helper
packages/object-info-parser/src/helpers/slugifyPackId.ts, packages/object-info-parser/src/index.ts
Add slugifyPackId(rawId: string) and re-export it from the package entrypoint.
Group nodes by slugged pack id
packages/object-info-parser/src/helpers/groupNodesByPack.ts, packages/object-info-parser/src/__tests__/groupNodesByPack.test.ts, packages/object-info-parser/src/__tests__/slugifyPackId.test.ts
Change grouping to derive id by slugifying rawId; extend NodePack with rawId and rawIds; deduplicate rawIds; add tests for slug rules, duplicate handling, version-suffix stripping, and merging colliding raw ids.
Parser: registry alias handling & snapshot normalization
apps/website/src/utils/cloudNodes.ts, tests in apps/website/src/utils/cloudNodes.test.ts
Update parsing to fetch registry data using union of each pack’s rawIds aliases; add pickRegistryPack to choose registry result per-pack; normalize snapshot pack ids via normalizeSnapshotIds (slugify, dedupe, merge colliding packs); add many tests for registry-enrichment miss/error, alias queries, collision merging, metadata-merge precedence, and snapshot fallback behaviors.

Build-time snapshot override & CI fixture

Layer / File(s) Summary
Build-time fixture URL handling
apps/website/src/utils/cloudNodes.build.ts, apps/website/src/utils/cloudNodes.build.test.ts
Add WEBSITE_PACKAGE_ROOT and fixtureSnapshotUrl() to convert WEBSITE_CLOUD_NODES_FIXTURE into a file: URL when present; pass { snapshotUrl, apiKey: '' } into fetchCloudNodesForBuild when fixture is used; suppress production hard-fail on stale outcomes when fixture override is active; update tests to verify forwarding of fixture path (relative → file: URL, absolute preserved), empty apiKey, and suppressed stale failure.
On-disk fixture and CI wiring
apps/website/e2e/fixtures/cloud-nodes.fixture.json, .github/workflows/ci-website-e2e.yaml, apps/website/src/data/cloud-nodes.snapshot.json
Add cloud-nodes.fixture.json fixture; update CI workflow website-e2e job “Build website” step to set WEBSITE_CLOUD_NODES_FIXTURE; small snapshot JSON normalization changes (id casing, description punctuation).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

size:M

Suggested reviewers

  • Yourz

Poem

🐰 I hopped through ids and stitched each name,
Turned underscores to hyphens for URL fame.
Aliases gathered in a tidy row,
Fixtures on disk so CI tests grow.
Nodes merged softly — the rabbit says: "Bravo!"


Caution

Pre-merge checks failed

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

  • Ignore (reviewers only)

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
End-To-End Regression Coverage For Fixes ❌ Error PR uses bug-fix language ("fix(website)"), changes frontend src/packages files, but no browser_tests/ changes exist. PR description lacks explanation for why no e2e regression test was added. Add a Playwright regression test under browser_tests/ to verify the cloud-node pack ID slugification fix, or add a concrete explanation in the PR description of why an e2e regression test is impractical.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(website): slugify cloud-node pack ids and mock e2e snapshot' clearly and concisely describes the main changes: adding pack id slugification and mocking e2e snapshots. It is specific, follows convention, and accurately reflects the primary intent.
Description check ✅ Passed The PR description comprehensively covers the summary, detailed changes, verification results, and notes for reviewers. It exceeds the template's minimum requirements with thorough explanations of what was changed, why, and how to verify it.
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 Check not applicable. PR modifies website e2e, cloud node pack metadata, and object-info-parser utilities—not litegraph, ECS, or graph entity code under src/lib/litegraph/ or src/ecs/.
✨ Finishing Touches
📝 Generate docstrings
  • ✅ Generated successfully - (🔄 Check to regenerate)
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch glary/website-cloud-nodes-mock-and-slugify

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 05/15/2026, 02:39:58 PM UTC

Links

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

🎭 Playwright: ✅ 1606 passed, 0 failed · 1 flaky

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

🌐 Website E2E

Tip

All tests passed.

Status ✅ Passed
Report View Report

🔗 Website Preview

Website Preview: https://comfy-website-preview-pr-12277.vercel.app

This commit: https://website-frontend-rgkvdx4yr-comfyui.vercel.app

Last updated: 2026-05-15T14:39:39Z for 764977a

@DrJKL DrJKL requested a review from christian-byrne May 14, 2026 20:12
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

📦 Bundle: 5.36 MB gzip 🔴 +197 B

Details

Summary

  • Raw size: 24.7 MB baseline 24.7 MB — ⚪ 0 B
  • Gzip: 5.36 MB baseline 5.36 MB — 🔴 +197 B
  • Brotli: 4.14 MB baseline 4.14 MB — 🟢 -41 B
  • Bundles: 268 current • 268 baseline • 118 added / 118 removed

Category Glance
Vendor & Third-Party ⚪ 0 B (9.94 MB) · Other ⚪ 0 B (9.16 MB) · Data & Services ⚪ 0 B (3.16 MB) · Graph Workspace ⚪ 0 B (1.24 MB) · Panels & Settings ⚪ 0 B (527 kB) · Utilities & Hooks ⚪ 0 B (366 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-3g3HEL2G.js (new) 26.1 kB 🔴 +26.1 kB 🔴 +8.76 kB 🔴 +7.5 kB
assets/index-CV5nSbsN.js (removed) 26.1 kB 🟢 -26.1 kB 🟢 -8.76 kB 🟢 -7.56 kB

Status: 1 added / 1 removed

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

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-BFXzPpvW.js (new) 1.24 MB 🔴 +1.24 MB 🔴 +264 kB 🔴 +199 kB
assets/GraphView-BH_h0BxN.js (removed) 1.24 MB 🟢 -1.24 MB 🟢 -264 kB 🟢 -199 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-C1lLAkBd.js (removed) 19.6 kB 🟢 -19.6 kB 🟢 -5.14 kB 🟢 -4.58 kB
assets/CloudSurveyView-CocQ5WUA.js (new) 19.6 kB 🔴 +19.6 kB 🔴 +5.14 kB 🔴 +4.57 kB
assets/CloudLoginView-BEIK1s_G.js (removed) 12.5 kB 🟢 -12.5 kB 🟢 -3.55 kB 🟢 -3.12 kB
assets/CloudLoginView-gzpCmKPL.js (new) 12.5 kB 🔴 +12.5 kB 🔴 +3.55 kB 🔴 +3.13 kB
assets/CloudSignupView-CLWnhA1T.js (removed) 10.4 kB 🟢 -10.4 kB 🟢 -3.06 kB 🟢 -2.71 kB
assets/CloudSignupView-D_b9WmHo.js (new) 10.4 kB 🔴 +10.4 kB 🔴 +3.06 kB 🔴 +2.7 kB
assets/UserCheckView-DrNU8SGG.js (new) 9.07 kB 🔴 +9.07 kB 🔴 +2.34 kB 🔴 +2.05 kB
assets/UserCheckView-o_0aipFs.js (removed) 9.07 kB 🟢 -9.07 kB 🟢 -2.34 kB 🟢 -2.05 kB
assets/CloudLayoutView-BuUz_NcG.js (removed) 7.81 kB 🟢 -7.81 kB 🟢 -2.48 kB 🟢 -2.17 kB
assets/CloudLayoutView-C5Dfz5oP.js (new) 7.81 kB 🔴 +7.81 kB 🔴 +2.48 kB 🔴 +2.17 kB
assets/CloudForgotPasswordView-Cm1Xf2MB.js (new) 6.22 kB 🔴 +6.22 kB 🔴 +2.21 kB 🔴 +1.94 kB
assets/CloudForgotPasswordView-ZBnO4PXH.js (removed) 6.22 kB 🟢 -6.22 kB 🟢 -2.21 kB 🟢 -1.95 kB
assets/CloudAuthTimeoutView--fwBBr5d.js (removed) 5.58 kB 🟢 -5.58 kB 🟢 -2.05 kB 🟢 -1.8 kB
assets/CloudAuthTimeoutView-B-ItBvd7.js (new) 5.58 kB 🔴 +5.58 kB 🔴 +2.05 kB 🔴 +1.81 kB
assets/CloudSubscriptionRedirectView-B4epFELK.js (removed) 5.36 kB 🟢 -5.36 kB 🟢 -2.03 kB 🟢 -1.8 kB
assets/CloudSubscriptionRedirectView-DW2zqSrA.js (new) 5.36 kB 🔴 +5.36 kB 🔴 +2.03 kB 🔴 +1.8 kB
assets/UserSelectView-Wlij9n9h.js (new) 4.7 kB 🔴 +4.7 kB 🔴 +1.75 kB 🔴 +1.55 kB
assets/UserSelectView-YVyRNCfG.js (removed) 4.7 kB 🟢 -4.7 kB 🟢 -1.75 kB 🟢 -1.55 kB

Status: 9 added / 9 removed / 2 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-BK0dP2_B.js (removed) 47.5 kB 🟢 -47.5 kB 🟢 -9.86 kB 🟢 -8.75 kB
assets/KeybindingPanel-DyeOhLdO.js (new) 47.5 kB 🔴 +47.5 kB 🔴 +9.87 kB 🔴 +8.75 kB
assets/SecretsPanel-mBJ27dsg.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +5.73 kB 🔴 +5.05 kB
assets/SecretsPanel-noDYLbaa.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -5.73 kB 🟢 -5.04 kB
assets/LegacyCreditsPanel-BN5hAT3y.js (new) 21.8 kB 🔴 +21.8 kB 🔴 +5.94 kB 🔴 +5.25 kB
assets/LegacyCreditsPanel-DF-9CnNn.js (removed) 21.8 kB 🟢 -21.8 kB 🟢 -5.94 kB 🟢 -5.25 kB
assets/SubscriptionPanel-BeSWJW71.js (removed) 20.2 kB 🟢 -20.2 kB 🟢 -5.19 kB 🟢 -4.55 kB
assets/SubscriptionPanel-fD-UnASQ.js (new) 20.2 kB 🔴 +20.2 kB 🔴 +5.18 kB 🔴 +4.55 kB
assets/AboutPanel-DfE5Tukv.js (new) 12 kB 🔴 +12 kB 🔴 +3.33 kB 🔴 +2.99 kB
assets/AboutPanel-h4DlAUyi.js (removed) 12 kB 🟢 -12 kB 🟢 -3.33 kB 🟢 -3 kB
assets/ExtensionPanel-Bxy8ddcM.js (removed) 10.1 kB 🟢 -10.1 kB 🟢 -2.94 kB 🟢 -2.61 kB
assets/ExtensionPanel-Cs-8UwKD.js (new) 10.1 kB 🔴 +10.1 kB 🔴 +2.95 kB 🔴 +2.62 kB
assets/ServerConfigPanel-ChHjsFOR.js (new) 7.13 kB 🔴 +7.13 kB 🔴 +2.39 kB 🔴 +2.13 kB
assets/ServerConfigPanel-upL2PWcM.js (removed) 7.13 kB 🟢 -7.13 kB 🟢 -2.39 kB 🟢 -2.13 kB
assets/UserPanel-COQH-sGk.js (removed) 6.84 kB 🟢 -6.84 kB 🟢 -2.27 kB 🟢 -2.01 kB
assets/UserPanel-xfifEMQL.js (new) 6.84 kB 🔴 +6.84 kB 🔴 +2.27 kB 🔴 +2 kB
assets/cloudRemoteConfig-BBTWFyJu.js (new) 2.13 kB 🔴 +2.13 kB 🔴 +1.03 kB 🔴 +883 B
assets/cloudRemoteConfig-DnjrzSiq.js (removed) 2.13 kB 🟢 -2.13 kB 🟢 -1.02 kB 🟢 -884 B
assets/refreshRemoteConfig-CzaVXHP3.js (removed) 1.45 kB 🟢 -1.45 kB 🟢 -650 B 🟢 -554 B
assets/refreshRemoteConfig-Egzl17vi.js (new) 1.45 kB 🔴 +1.45 kB 🔴 +652 B 🔴 +550 B

Status: 10 added / 10 removed / 14 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-CiSWdCdw.js (new) 3.65 kB 🔴 +3.65 kB 🔴 +1.29 kB 🔴 +1.11 kB
assets/auth-Cxu34cLN.js (removed) 3.65 kB 🟢 -3.65 kB 🟢 -1.29 kB 🟢 -1.1 kB
assets/SignUpForm-H9b3-Xtz.js (new) 3.19 kB 🔴 +3.19 kB 🔴 +1.29 kB 🔴 +1.15 kB
assets/SignUpForm-UtQysRdf.js (removed) 3.19 kB 🟢 -3.19 kB 🟢 -1.29 kB 🟢 -1.15 kB
assets/UpdatePasswordContent-BMTRUq2V.js (new) 2.98 kB 🔴 +2.98 kB 🔴 +1.33 kB 🔴 +1.18 kB
assets/UpdatePasswordContent-DDwhNdWJ.js (removed) 2.98 kB 🟢 -2.98 kB 🟢 -1.33 kB 🟢 -1.18 kB
assets/authStore-Dp6GPCMq.js (new) 1.27 kB 🔴 +1.27 kB 🔴 +602 B 🔴 +538 B
assets/authStore-dQOduR2q.js (removed) 1.27 kB 🟢 -1.27 kB 🟢 -600 B 🟢 -539 B
assets/auth-CpT0z4Na.js (new) 348 B 🔴 +348 B 🔴 +216 B 🔴 +210 B
assets/auth-DH-7W4gs.js (removed) 348 B 🟢 -348 B 🟢 -218 B 🟢 -191 B

Status: 5 added / 5 removed / 2 unchanged

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

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyHubPublishDialog-BD1aK6zE.js (new) 85.8 kB 🔴 +85.8 kB 🔴 +18.6 kB 🔴 +15.9 kB
assets/ComfyHubPublishDialog-Ch-oYt2W.js (removed) 85.8 kB 🟢 -85.8 kB 🟢 -18.6 kB 🟢 -15.9 kB
assets/useShareDialog-Bw0B7-CC.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +5.82 kB 🔴 +5.14 kB
assets/useShareDialog-DXJiKCBV.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -5.81 kB 🟢 -5.15 kB
assets/ComfyHubPublishDialog-CG8EMgNj.js (new) 1.43 kB 🔴 +1.43 kB 🔴 +659 B 🔴 +584 B
assets/ComfyHubPublishDialog-Eozo4_Ve.js (removed) 1.43 kB 🟢 -1.43 kB 🟢 -656 B 🟢 -588 B
assets/useSubscriptionDialog-CNYqSkIA.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +591 B 🔴 +519 B
assets/useSubscriptionDialog-Dlxq4RfN.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -589 B 🟢 -523 B

Status: 4 added / 4 removed

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-B5O2ULQC.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.79 kB 🟢 -3.38 kB
assets/ComfyQueueButton-ybkKh_0R.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.79 kB 🔴 +3.38 kB
assets/useTerminalTabs-ClLL12r4.js (new) 11.1 kB 🔴 +11.1 kB 🔴 +3.76 kB 🔴 +3.3 kB
assets/useTerminalTabs-VM2rb-Vm.js (removed) 11.1 kB 🟢 -11.1 kB 🟢 -3.76 kB 🟢 -3.31 kB
assets/SubscribeButton-CXBtj-Yq.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -1.05 kB 🟢 -918 B
assets/SubscribeButton-nPsawnJC.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +1.05 kB 🔴 +930 B
assets/cloudFeedbackTopbarButton-CMln-jw3.js (new) 1.94 kB 🔴 +1.94 kB 🔴 +965 B 🔴 +860 B
assets/cloudFeedbackTopbarButton-D8FCehMo.js (removed) 1.94 kB 🟢 -1.94 kB 🟢 -964 B 🟢 -858 B
assets/ComfyQueueButton-BbcI7_Ij.js (removed) 1.35 kB 🟢 -1.35 kB 🟢 -623 B 🟢 -578 B
assets/ComfyQueueButton-FIppZ6qs.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +626 B 🔴 +573 B

Status: 5 added / 5 removed / 8 unchanged

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

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-DMRiCkdG.js (new) 2.09 MB 🔴 +2.09 MB 🔴 +476 kB 🔴 +361 kB
assets/dialogService-xxDFiCUH.js (removed) 2.09 MB 🟢 -2.09 MB 🟢 -476 kB 🟢 -361 kB
assets/api-C9YWThrQ.js (new) 898 kB 🔴 +898 kB 🔴 +215 kB 🔴 +169 kB
assets/api-uQwhUmAH.js (removed) 898 kB 🟢 -898 kB 🟢 -215 kB 🟢 -169 kB
assets/load3dService-DdPuvc-R.js (removed) 116 kB 🟢 -116 kB 🟢 -25.4 kB 🟢 -21.6 kB
assets/load3dService-DuIF9sYn.js (new) 116 kB 🔴 +116 kB 🔴 +25.4 kB 🔴 +21.6 kB
assets/workflowShareService-DRxyLvP3.js (new) 16.7 kB 🔴 +16.7 kB 🔴 +4.92 kB 🔴 +4.37 kB
assets/workflowShareService-y_1WDuNC.js (removed) 16.7 kB 🟢 -16.7 kB 🟢 -4.92 kB 🟢 -4.36 kB
assets/keybindingService-B1UVf69_.js (removed) 13.8 kB 🟢 -13.8 kB 🟢 -3.67 kB 🟢 -3.21 kB
assets/keybindingService-DfHpXJ1E.js (new) 13.8 kB 🔴 +13.8 kB 🔴 +3.67 kB 🔴 +3.21 kB
assets/releaseStore-1igkS75F.js (removed) 8.12 kB 🟢 -8.12 kB 🟢 -2.28 kB 🟢 -2 kB
assets/releaseStore-CsoZugon.js (new) 8.12 kB 🔴 +8.12 kB 🔴 +2.28 kB 🔴 +2 kB
assets/userStore-ByO-BHwT.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +933 B 🔴 +825 B
assets/userStore-CzRsNFDP.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -932 B 🟢 -818 B
assets/audioService-BTMr1qvO.js (new) 1.8 kB 🔴 +1.8 kB 🔴 +879 B 🔴 +762 B
assets/audioService-BVNW84DV.js (removed) 1.8 kB 🟢 -1.8 kB 🟢 -880 B 🟢 -762 B
assets/releaseStore-BFSPgkFX.js (removed) 1.27 kB 🟢 -1.27 kB 🟢 -593 B 🟢 -531 B
assets/releaseStore-EHVrZ8tD.js (new) 1.27 kB 🔴 +1.27 kB 🔴 +593 B 🔴 +530 B
assets/workflowDraftStore-CwECuTNK.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +590 B 🔴 +522 B
assets/workflowDraftStore-Dvp0_euM.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -588 B 🟢 -525 B
assets/dialogService-BUYulRUx.js (new) 1.24 kB 🔴 +1.24 kB 🔴 +583 B 🔴 +521 B
assets/dialogService-Oryoyk_y.js (removed) 1.24 kB 🟢 -1.24 kB 🟢 -581 B 🟢 -525 B
assets/settingStore-BUu3rg1G.js (removed) 1.23 kB 🟢 -1.23 kB 🟢 -583 B 🟢 -521 B
assets/settingStore-kKYMohqX.js (new) 1.23 kB 🔴 +1.23 kB 🔴 +586 B 🔴 +520 B
assets/assetsStore-DkBN-DMv.js (removed) 1.23 kB 🟢 -1.23 kB 🟢 -583 B 🟢 -519 B
assets/assetsStore-DZt-HPiq.js (new) 1.23 kB 🔴 +1.23 kB 🔴 +586 B 🔴 +518 B

Status: 13 added / 13 removed / 4 unchanged

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-B9bI8HvF.js (removed) 234 kB 🟢 -234 kB 🟢 -52.1 kB 🟢 -42.4 kB
assets/useConflictDetection-oYTBKB_W.js (new) 234 kB 🔴 +234 kB 🔴 +52.1 kB 🔴 +42.4 kB
assets/useLoad3d-B1rXj9U0.js (removed) 22.7 kB 🟢 -22.7 kB 🟢 -5.22 kB 🟢 -4.61 kB
assets/useLoad3d-C4COW2IP.js (new) 22.7 kB 🔴 +22.7 kB 🔴 +5.22 kB 🔴 +4.61 kB
assets/useLoad3dViewer-Bv5jEi6q.js (removed) 21 kB 🟢 -21 kB 🟢 -4.92 kB 🟢 -4.31 kB
assets/useLoad3dViewer-DPhNdRK7.js (new) 21 kB 🔴 +21 kB 🔴 +4.92 kB 🔴 +4.3 kB
assets/useFeatureFlags-BJMHX0P9.js (new) 5.95 kB 🔴 +5.95 kB 🔴 +1.8 kB 🔴 +1.52 kB
assets/useFeatureFlags-CDy92W1Y.js (removed) 5.95 kB 🟢 -5.95 kB 🟢 -1.8 kB 🟢 -1.52 kB
assets/useCopyToClipboard-BblZzlnB.js (removed) 5.29 kB 🟢 -5.29 kB 🟢 -1.86 kB 🟢 -1.57 kB
assets/useCopyToClipboard-UtpxQcz1.js (new) 5.29 kB 🔴 +5.29 kB 🔴 +1.86 kB 🔴 +1.57 kB
assets/useWorkspaceUI-BANyFoRx.js (removed) 3.34 kB 🟢 -3.34 kB 🟢 -982 B 🟢 -813 B
assets/useWorkspaceUI-CwD_KxZY.js (new) 3.34 kB 🔴 +3.34 kB 🔴 +982 B 🔴 +810 B
assets/subscriptionCheckoutUtil-BSobM_2f.js (removed) 3.31 kB 🟢 -3.31 kB 🟢 -1.36 kB 🟢 -1.19 kB
assets/subscriptionCheckoutUtil-ChdMDE7P.js (new) 3.31 kB 🔴 +3.31 kB 🔴 +1.36 kB 🔴 +1.18 kB
assets/assetPreviewUtil-CcDVkIgz.js (new) 2.43 kB 🔴 +2.43 kB 🔴 +1.01 kB 🔴 +879 B
assets/assetPreviewUtil-D81ZJ8Dm.js (removed) 2.43 kB 🟢 -2.43 kB 🟢 -1.01 kB 🟢 -880 B
assets/useUpstreamValue-BEu_WT6A.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +804 B 🔴 +715 B
assets/useUpstreamValue-z654WzV_.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -803 B 🟢 -708 B
assets/useLoad3d-DASuo9_R.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -648 B 🟢 -586 B
assets/useLoad3d-DIEJvPcg.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +654 B 🔴 +583 B
assets/useLoad3dViewer-BOeFhjJb.js (removed) 1.35 kB 🟢 -1.35 kB 🟢 -617 B 🟢 -570 B
assets/useLoad3dViewer-CUSWwfV_.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +620 B 🔴 +570 B
assets/useCurrentUser-BJ9HGltU.js (new) 1.23 kB 🔴 +1.23 kB 🔴 +585 B 🔴 +518 B
assets/useCurrentUser-CCMpxo-k.js (removed) 1.23 kB 🟢 -1.23 kB 🟢 -584 B 🟢 -524 B
assets/useWorkspaceSwitch-9-UiDkzM.js (new) 747 B 🔴 +747 B 🔴 +383 B 🔴 +331 B
assets/useWorkspaceSwitch-Diz7iEBf.js (removed) 747 B 🟢 -747 B 🟢 -383 B 🟢 -331 B

Status: 13 added / 13 removed / 18 unchanged

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

External libraries and shared vendor chunks

Status: 16 unchanged

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

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-BCW_oWNN.js (removed) 78 kB 🟢 -78 kB 🟢 -20.2 kB 🟢 -17.2 kB
assets/core-DcV6pCNT.js (new) 78 kB 🔴 +78 kB 🔴 +20.2 kB 🔴 +17.2 kB
assets/groupNode-ByAO2kp7.js (new) 74.9 kB 🔴 +74.9 kB 🔴 +18.7 kB 🔴 +16.5 kB
assets/groupNode-v1fU_yZP.js (removed) 74.9 kB 🟢 -74.9 kB 🟢 -18.7 kB 🟢 -16.5 kB
assets/WidgetSelect-B-m3aewb.js (new) 67.9 kB 🔴 +67.9 kB 🔴 +14.8 kB 🔴 +12.8 kB
assets/WidgetSelect-It5t8iiY.js (removed) 67.9 kB 🟢 -67.9 kB 🟢 -14.8 kB 🟢 -12.8 kB
assets/SubscriptionRequiredDialogContentWorkspace-BN0OmIr6.js (new) 48.9 kB 🔴 +48.9 kB 🔴 +9.56 kB 🔴 +8.26 kB
assets/SubscriptionRequiredDialogContentWorkspace-s4BRqD8q.js (removed) 48.9 kB 🟢 -48.9 kB 🟢 -9.56 kB 🟢 -8.26 kB
assets/Load3DControls-BRzJzbq6.js (removed) 46.1 kB 🟢 -46.1 kB 🟢 -7.5 kB 🟢 -6.55 kB
assets/Load3DControls-C0oFf4w2.js (new) 46.1 kB 🔴 +46.1 kB 🔴 +7.5 kB 🔴 +6.54 kB
assets/WorkspacePanelContent-C2wJhPd-.js (removed) 34.3 kB 🟢 -34.3 kB 🟢 -7.44 kB 🟢 -6.59 kB
assets/WorkspacePanelContent-Cj3aomhg.js (new) 34.3 kB 🔴 +34.3 kB 🔴 +7.44 kB 🔴 +6.59 kB
assets/WidgetPainter-BIWrXbEV.js (removed) 33.5 kB 🟢 -33.5 kB 🟢 -8.28 kB 🟢 -7.34 kB
assets/WidgetPainter-BYgC4WFI.js (new) 33.5 kB 🔴 +33.5 kB 🔴 +8.29 kB 🔴 +7.35 kB
assets/Load3dViewerContent-BA5_cAVI.js (removed) 30.6 kB 🟢 -30.6 kB 🟢 -6.19 kB 🟢 -5.36 kB
assets/Load3dViewerContent-CSIO1Iz2.js (new) 30.6 kB 🔴 +30.6 kB 🔴 +6.19 kB 🔴 +5.37 kB
assets/SubscriptionRequiredDialogContent-BUuCSyTA.js (removed) 27.6 kB 🟢 -27.6 kB 🟢 -7.02 kB 🟢 -6.19 kB
assets/SubscriptionRequiredDialogContent-Dd3-PyIQ.js (new) 27.6 kB 🔴 +27.6 kB 🔴 +7.01 kB 🔴 +6.22 kB
assets/WidgetImageCrop-Cp0IQFjI.js (new) 24.4 kB 🔴 +24.4 kB 🔴 +6.23 kB 🔴 +5.47 kB
assets/WidgetImageCrop-CTO0_dkt.js (removed) 24.4 kB 🟢 -24.4 kB 🟢 -6.23 kB 🟢 -5.48 kB
assets/SubscriptionPanelContentWorkspace-CFhgthom.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.17 kB 🔴 +4.56 kB
assets/SubscriptionPanelContentWorkspace-DE1pjQse.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.18 kB 🟢 -4.57 kB
assets/SignInContent-CtlTLm30.js (new) 20.9 kB 🔴 +20.9 kB 🔴 +5.47 kB 🔴 +4.79 kB
assets/SignInContent-My5-xHGX.js (removed) 20.9 kB 🟢 -20.9 kB 🟢 -5.47 kB 🟢 -4.78 kB
assets/CurrentUserPopoverWorkspace-CzjCKYl_.js (new) 20.9 kB 🔴 +20.9 kB 🔴 +5 kB 🔴 +4.46 kB
assets/CurrentUserPopoverWorkspace-DMp3aYLQ.js (removed) 20.9 kB 🟢 -20.9 kB 🟢 -4.99 kB 🟢 -4.46 kB
assets/WidgetInputNumber-D-undYvG.js (removed) 19.1 kB 🟢 -19.1 kB 🟢 -4.84 kB 🟢 -4.29 kB
assets/WidgetInputNumber-V3GDUF7U.js (new) 19.1 kB 🔴 +19.1 kB 🔴 +4.84 kB 🔴 +4.29 kB
assets/Load3D-Dm3eOmY5.js (new) 18.5 kB 🔴 +18.5 kB 🔴 +4.39 kB 🔴 +3.83 kB
assets/Load3D-DuKtvXig.js (removed) 18.5 kB 🟢 -18.5 kB 🟢 -4.39 kB 🟢 -3.83 kB
assets/WidgetRecordAudio-6fzkdSCS.js (new) 17.6 kB 🔴 +17.6 kB 🔴 +5.07 kB 🔴 +4.53 kB
assets/WidgetRecordAudio-BNt4SWUx.js (removed) 17.6 kB 🟢 -17.6 kB 🟢 -5.07 kB 🟢 -4.53 kB
assets/WidgetRange-BTfoE89C.js (new) 17.1 kB 🔴 +17.1 kB 🔴 +4.64 kB 🔴 +4.14 kB
assets/WidgetRange-CN93gPVd.js (removed) 17.1 kB 🟢 -17.1 kB 🟢 -4.64 kB 🟢 -4.13 kB
assets/load3d-C2GuSvUQ.js (new) 15.9 kB 🔴 +15.9 kB 🔴 +4.62 kB 🔴 +4.01 kB
assets/load3d-CrUZWdig.js (removed) 15.9 kB 🟢 -15.9 kB 🟢 -4.62 kB 🟢 -4.01 kB
assets/WaveAudioPlayer-B1PeVW9o.js (removed) 13.4 kB 🟢 -13.4 kB 🟢 -3.68 kB 🟢 -3.22 kB
assets/WaveAudioPlayer-CTLYbn7h.js (new) 13.4 kB 🔴 +13.4 kB 🔴 +3.68 kB 🔴 +3.22 kB
assets/WidgetCurve-B3WTro1O.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.96 kB 🟢 -3.59 kB
assets/WidgetCurve-DMQlFjxX.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.96 kB 🔴 +3.58 kB
assets/TeamWorkspacesDialogContent--Dg3WEv9.js (new) 11.4 kB 🔴 +11.4 kB 🔴 +3.45 kB 🔴 +3.07 kB
assets/TeamWorkspacesDialogContent-ChJW2rgt.js (removed) 11.4 kB 🟢 -11.4 kB 🟢 -3.45 kB 🟢 -3.1 kB
assets/nodeTemplates--3RogAvx.js (removed) 9.92 kB 🟢 -9.92 kB 🟢 -3.51 kB 🟢 -3.1 kB
assets/nodeTemplates-W01KQOm3.js (new) 9.92 kB 🔴 +9.92 kB 🔴 +3.52 kB 🔴 +3.12 kB
assets/NightlySurveyController-Bno2kPcm.js (new) 9.05 kB 🔴 +9.05 kB 🔴 +3.18 kB 🔴 +2.81 kB
assets/NightlySurveyController-CEsfLJgF.js (removed) 9.05 kB 🟢 -9.05 kB 🟢 -3.18 kB 🟢 -2.8 kB
assets/Load3DConfiguration-C9GbfRR0.js (removed) 8.77 kB 🟢 -8.77 kB 🟢 -2.61 kB 🟢 -2.29 kB
assets/Load3DConfiguration-DYErV_l4.js (new) 8.77 kB 🔴 +8.77 kB 🔴 +2.61 kB 🔴 +2.3 kB
assets/InviteMemberDialogContent-avVfmJJ4.js (removed) 8.02 kB 🟢 -8.02 kB 🟢 -2.56 kB 🟢 -2.25 kB
assets/InviteMemberDialogContent-D3rcwQ3M.js (new) 8.02 kB 🔴 +8.02 kB 🔴 +2.56 kB 🔴 +2.25 kB
assets/onboardingCloudRoutes-Cwr06iyD.js (new) 6.94 kB 🔴 +6.94 kB 🔴 +2.17 kB 🔴 +1.85 kB
assets/onboardingCloudRoutes-IGNCZ_61.js (removed) 6.94 kB 🟢 -6.94 kB 🟢 -2.17 kB 🟢 -1.86 kB
assets/CreateWorkspaceDialogContent-BdANpMI3.js (removed) 6.23 kB 🟢 -6.23 kB 🟢 -2.27 kB 🟢 -1.99 kB
assets/CreateWorkspaceDialogContent-CJeCns52.js (new) 6.23 kB 🔴 +6.23 kB 🔴 +2.27 kB 🔴 +1.99 kB
assets/WidgetWithControl-BRkT0FsK.js (new) 6.2 kB 🔴 +6.2 kB 🔴 +2.5 kB 🔴 +2.2 kB
assets/WidgetWithControl-D8l0CO-m.js (removed) 6.2 kB 🟢 -6.2 kB 🟢 -2.5 kB 🟢 -2.22 kB
assets/FreeTierDialogContent-BcO1KeHx.js (removed) 6.09 kB 🟢 -6.09 kB 🟢 -2.17 kB 🟢 -1.93 kB
assets/FreeTierDialogContent-BWa3j0-g.js (new) 6.09 kB 🔴 +6.09 kB 🔴 +2.17 kB 🔴 +1.93 kB
assets/EditWorkspaceDialogContent-BPgFxO_Z.js (removed) 6.03 kB 🟢 -6.03 kB 🟢 -2.23 kB 🟢 -1.95 kB
assets/EditWorkspaceDialogContent-BRh21Vsg.js (new) 6.03 kB 🔴 +6.03 kB 🔴 +2.23 kB 🔴 +1.96 kB
assets/WidgetTextarea-CjOPldQN.js (new) 5.84 kB 🔴 +5.84 kB 🔴 +2.31 kB 🔴 +2.03 kB
assets/WidgetTextarea-CNPIQ7Cd.js (removed) 5.84 kB 🟢 -5.84 kB 🟢 -2.3 kB 🟢 -2.03 kB
assets/Preview3d-BrpOCn1o.js (new) 5.81 kB 🔴 +5.81 kB 🔴 +1.96 kB 🔴 +1.72 kB
assets/Preview3d-X-e3BvRZ.js (removed) 5.81 kB 🟢 -5.81 kB 🟢 -1.96 kB 🟢 -1.71 kB
assets/ValueControlPopover-Co7JJaeb.js (removed) 5.61 kB 🟢 -5.61 kB 🟢 -2.04 kB 🟢 -1.83 kB
assets/ValueControlPopover-Cx2JBBIU.js (new) 5.61 kB 🔴 +5.61 kB 🔴 +2.05 kB 🔴 +1.83 kB
assets/CancelSubscriptionDialogContent-BtWNAsZo.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -2.07 kB 🟢 -1.82 kB
assets/CancelSubscriptionDialogContent-LkY7taFM.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +2.07 kB 🔴 +1.82 kB
assets/DeleteWorkspaceDialogContent-5o7kw_VX.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.91 kB 🔴 +1.66 kB
assets/DeleteWorkspaceDialogContent-CMap7o2E.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.91 kB 🟢 -1.66 kB
assets/saveMesh-BvZVNbnj.js (removed) 4.78 kB 🟢 -4.78 kB 🟢 -1.9 kB 🟢 -1.69 kB
assets/saveMesh-p3pN2AbJ.js (new) 4.78 kB 🔴 +4.78 kB 🔴 +1.91 kB 🔴 +1.69 kB
assets/LeaveWorkspaceDialogContent-Cd1Mn3IG.js (new) 4.76 kB 🔴 +4.76 kB 🔴 +1.85 kB 🔴 +1.64 kB
assets/LeaveWorkspaceDialogContent-euZI9c2d.js (removed) 4.76 kB 🟢 -4.76 kB 🟢 -1.85 kB 🟢 -1.61 kB
assets/RemoveMemberDialogContent-BHru4xzJ.js (new) 4.74 kB 🔴 +4.74 kB 🔴 +1.81 kB 🔴 +1.58 kB
assets/RemoveMemberDialogContent-BXsA_26k.js (removed) 4.74 kB 🟢 -4.74 kB 🟢 -1.81 kB 🟢 -1.58 kB
assets/RevokeInviteDialogContent-_aYdN2ld.js (new) 4.65 kB 🔴 +4.65 kB 🔴 +1.82 kB 🔴 +1.59 kB
assets/RevokeInviteDialogContent-BEGv1dLu.js (removed) 4.65 kB 🟢 -4.65 kB 🟢 -1.82 kB 🟢 -1.59 kB
assets/InviteMemberUpsellDialogContent-CKjl9qyM.js (removed) 4.55 kB 🟢 -4.55 kB 🟢 -1.68 kB 🟢 -1.48 kB
assets/InviteMemberUpsellDialogContent-r9qiCt6x.js (new) 4.55 kB 🔴 +4.55 kB 🔴 +1.69 kB 🔴 +1.47 kB
assets/tierBenefits-COih-pZ2.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.58 kB 🔴 +1.36 kB
assets/tierBenefits-Dl5SZJ3W.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.58 kB 🟢 -1.36 kB
assets/Media3DTop-Bkm_ZhCL.js (removed) 4.43 kB 🟢 -4.43 kB 🟢 -1.81 kB 🟢 -1.59 kB
assets/Media3DTop-DQaUua2M.js (new) 4.43 kB 🔴 +4.43 kB 🔴 +1.81 kB 🔴 +1.61 kB
assets/cloudSessionCookie-Cdb1dKUg.js (removed) 4.39 kB 🟢 -4.39 kB 🟢 -1.61 kB 🟢 -1.41 kB
assets/cloudSessionCookie-DgISsdm5.js (new) 4.39 kB 🔴 +4.39 kB 🔴 +1.61 kB 🔴 +1.4 kB
assets/GlobalToast-BCNb2kSz.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.26 kB 🟢 -1.12 kB
assets/GlobalToast-DFSp2r2G.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.26 kB 🔴 +1.07 kB
assets/CloudRunButtonWrapper-Dv0iK3gF.js (new) 2.31 kB 🔴 +2.31 kB 🔴 +1.05 kB 🔴 +940 B
assets/CloudRunButtonWrapper-OY08epsA.js (removed) 2.31 kB 🟢 -2.31 kB 🟢 -1.05 kB 🟢 -939 B
assets/SubscribeToRun-COCIoyOU.js (new) 2.13 kB 🔴 +2.13 kB 🔴 +983 B 🔴 +877 B
assets/SubscribeToRun-DmeD86sb.js (removed) 2.13 kB 🟢 -2.13 kB 🟢 -981 B 🟢 -877 B
assets/MediaAudioTop-dVl5z1LQ.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +1 kB 🔴 +860 B
assets/MediaAudioTop-m7PSx3Y5.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -1 kB 🟢 -894 B
assets/cloudBadges-B5HJoPQI.js (removed) 2.04 kB 🟢 -2.04 kB 🟢 -1.01 kB 🟢 -879 B
assets/cloudBadges-BYofxKYv.js (new) 2.04 kB 🔴 +2.04 kB 🔴 +1.01 kB 🔴 +878 B
assets/cloudSubscription-BtKdSPNy.js (new) 1.96 kB 🔴 +1.96 kB 🔴 +932 B 🔴 +806 B
assets/cloudSubscription-DTMqf2E-.js (removed) 1.96 kB 🟢 -1.96 kB 🟢 -929 B 🟢 -811 B
assets/graphHasMissingNodes-C3ydInTN.js (removed) 1.84 kB 🟢 -1.84 kB 🟢 -860 B 🟢 -764 B
assets/graphHasMissingNodes-M3WwbYvD.js (new) 1.84 kB 🔴 +1.84 kB 🔴 +863 B 🔴 +758 B
assets/Load3D-BJRna8kq.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +744 B 🔴 +663 B
assets/Load3D-sf_fM6iE.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -738 B 🟢 -661 B
assets/nightlyBadges-3UM7iigg.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +779 B 🔴 +689 B
assets/nightlyBadges-BjQli0zA.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -778 B 🟢 -690 B
assets/Load3dViewerContent-AyuB9Pdn.js (new) 1.54 kB 🔴 +1.54 kB 🔴 +697 B 🔴 +621 B
assets/Load3dViewerContent-C9eqjbdT.js (removed) 1.54 kB 🟢 -1.54 kB 🟢 -692 B 🟢 -619 B
assets/previousFullPath-85kSMw5y.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -696 B 🟢 -601 B
assets/previousFullPath-CVsU02HJ.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +696 B 🔴 +600 B
assets/SubscriptionPanelContentWorkspace-ClDbdeS9.js (removed) 1.43 kB 🟢 -1.43 kB 🟢 -646 B 🟢 -582 B
assets/SubscriptionPanelContentWorkspace-DsyZt-dc.js (new) 1.43 kB 🔴 +1.43 kB 🔴 +648 B 🔴 +567 B
assets/WidgetLegacy-9HpHkglN.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -595 B 🟢 -532 B
assets/WidgetLegacy-DiKkGX2J.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +598 B 🔴 +528 B
assets/changeTracker-BS83DOYv.js (removed) 1.23 kB 🟢 -1.23 kB 🟢 -583 B 🟢 -522 B
assets/changeTracker-BVClZ3Z2.js (new) 1.23 kB 🔴 +1.23 kB 🔴 +586 B 🔴 +516 B

Status: 57 added / 57 removed / 86 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.1 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.3 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.9 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.2 MB heap
large-graph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 61.1 MB heap
large-graph-pan: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 113.7 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 102.6 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 104.2 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.8 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.5 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.9 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 158ms TBT · 132.3 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 69.5 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 156.5 MB heap
vue-large-graph-pan: · 56.2 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 41ms TBT · 158.2 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 48.4 MB heap

No regressions detected.

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 6ms 9ms +53% z=-1.8
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 8 9 +13% z=-3.8
canvas-idle: task duration 340ms 389ms +15% z=-0.2
canvas-idle: script duration 18ms 20ms +9% z=-2.4
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 68.0 MB 68.1 MB +0%
canvas-idle: DOM nodes 16 -122 -863% z=-113.4
canvas-idle: event listeners 6 -63 -1142% z=-15.7
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 4ms 3ms -14% z=-1.8
canvas-mouse-sweep: style recalc duration 38ms 33ms -11% z=-2.9
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 75 75 -1% z=-1.8
canvas-mouse-sweep: task duration 777ms 811ms +4% z=-0.9
canvas-mouse-sweep: script duration 110ms 118ms +7% z=-2.6
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 56.5 MB 57.3 MB +1%
canvas-mouse-sweep: DOM nodes -262 -106 -60% z=-64.9
canvas-mouse-sweep: event listeners -131 -64 -52% z=-17.3
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=0.5
canvas-zoom-sweep: p95 frame time 17ms 17ms +0%
canvas-zoom-sweep: layout duration 1ms 1ms -12% z=-1.5
canvas-zoom-sweep: style recalc duration 16ms 17ms +7% z=-1.4
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 32 32 -2% z=0.5
canvas-zoom-sweep: task duration 355ms 282ms -21% z=-2.0
canvas-zoom-sweep: script duration 19ms 17ms -12% z=-3.4
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 43.3 MB 46.9 MB +8%
canvas-zoom-sweep: DOM nodes -211 77 -136% z=-2.8
canvas-zoom-sweep: event listeners -116 20 -117% z=-0.7
dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms +0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 7ms 9ms +20% z=-1.3
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 11 13 +14% z=-1.2
dom-widget-clipping: task duration 307ms 355ms +15% z=-0.6
dom-widget-clipping: script duration 51ms 63ms +24% z=-1.6
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 54.8 MB 58.2 MB +6%
dom-widget-clipping: DOM nodes 18 21 +14% z=-1.2
dom-widget-clipping: event listeners 2 2 +0% variance too high
large-graph-idle: avg frame time 17ms 17ms -0% z=-0.6
large-graph-idle: p95 frame time 17ms 17ms -0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 7ms 8ms +17% z=-4.1
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 9 -6% z=-9.9
large-graph-idle: task duration 519ms 502ms -3% z=-0.7
large-graph-idle: script duration 86ms 85ms -2% z=-1.7
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 58.3 MB 61.1 MB +5%
large-graph-idle: DOM nodes -261 -263 +1% z=-318.3
large-graph-idle: event listeners -129 -129 +0% z=-25.4
large-graph-pan: avg frame time 17ms 17ms +0% z=0.3
large-graph-pan: p95 frame time 17ms 17ms +0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 16ms 16ms -4% z=-2.2
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 68 -1% z=-3.2
large-graph-pan: task duration 1085ms 1069ms -2% z=-0.3
large-graph-pan: script duration 363ms 379ms +4% z=-1.5
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 103.4 MB 113.7 MB +10%
large-graph-pan: DOM nodes -258 -257 -0% z=-167.3
large-graph-pan: event listeners -127 -128 +1% z=-160.5
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms +0%
large-graph-zoom: layout duration 7ms 7ms -2%
large-graph-zoom: style recalc duration 18ms 17ms -4%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 65 66 +1%
large-graph-zoom: task duration 1230ms 1308ms +6%
large-graph-zoom: script duration 434ms 482ms +11%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 66.6 MB 102.6 MB +54%
large-graph-zoom: DOM nodes -267 -128 -52%
large-graph-zoom: event listeners -125 -59 -53%
minimap-idle: avg frame time 17ms 17ms -0% z=-0.4
minimap-idle: p95 frame time 17ms 17ms +0%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 8ms 9ms +14% z=-0.8
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 10 10 +0% z=0.6
minimap-idle: task duration 566ms 561ms -1% z=0.7
minimap-idle: script duration 83ms 92ms +11% z=-0.6
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 95.6 MB 104.2 MB +9%
minimap-idle: DOM nodes -263 -118 -55% z=-100.3
minimap-idle: event listeners -129 -63 -52% z=-101.6
subgraph-dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.4
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 -2% z=-2.3
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 47 47 -1% z=-2.5
subgraph-dom-widget-clipping: task duration 349ms 343ms -2% z=-1.9
subgraph-dom-widget-clipping: script duration 117ms 121ms +3% z=-1.2
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 55.2 MB 55.8 MB +1%
subgraph-dom-widget-clipping: DOM nodes 20 19 -5% z=-2.8
subgraph-dom-widget-clipping: event listeners 8 7 -13% z=-1.6
subgraph-idle: avg frame time 17ms 17ms +0% z=0.4
subgraph-idle: p95 frame time 17ms 17ms -0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 7ms 7ms -6% z=-4.4
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 9 9 -6% z=-3.7
subgraph-idle: task duration 326ms 359ms +10% z=-0.3
subgraph-idle: script duration 15ms 13ms -18% z=-2.8
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 69.6 MB 64.5 MB -7%
subgraph-idle: DOM nodes 18 17 -6% z=-3.2
subgraph-idle: event listeners 6 4 -33% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms -1%
subgraph-mouse-sweep: layout duration 4ms 4ms -2% z=-1.5
subgraph-mouse-sweep: style recalc duration 34ms 39ms +13% z=-1.0
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 75 82 +9% z=0.7
subgraph-mouse-sweep: task duration 726ms 754ms +4% z=-0.2
subgraph-mouse-sweep: script duration 81ms 91ms +12% z=-1.5
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 57.7 MB 60.9 MB +5%
subgraph-mouse-sweep: DOM nodes -260 67 -126% z=-0.2
subgraph-mouse-sweep: event listeners -129 6 -105% 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 11ms 14ms +28%
subgraph-transition-enter: style recalc duration 24ms 28ms +17%
subgraph-transition-enter: layout count 5 5 +0%
subgraph-transition-enter: style recalc count 16 14 -13%
subgraph-transition-enter: task duration 676ms 857ms +27%
subgraph-transition-enter: script duration 28ms 35ms +23%
subgraph-transition-enter: TBT 133ms 158ms +19%
subgraph-transition-enter: heap used 90.7 MB 132.3 MB +46%
subgraph-transition-enter: DOM nodes 13513 12475 -8%
subgraph-transition-enter: event listeners 2527 1288 -49%
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 51ms 49ms -5%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 249 249 +0%
viewport-pan-sweep: task duration 3560ms 3461ms -3%
viewport-pan-sweep: script duration 1155ms 1197ms +4%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 70.4 MB 69.5 MB -1%
viewport-pan-sweep: DOM nodes -261 -261 +0%
viewport-pan-sweep: event listeners -113 -113 +0%
vue-large-graph-idle: avg frame time 17ms 17ms +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 12986ms 10938ms -16%
vue-large-graph-idle: script duration 591ms 547ms -7%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 254.0 MB 156.5 MB -38%
vue-large-graph-idle: DOM nodes -8332 -5821 -30%
vue-large-graph-idle: event listeners -16488 -16470 -0%
vue-large-graph-pan: avg frame time 17ms 18ms +3%
vue-large-graph-pan: p95 frame time 17ms 17ms +0%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 17ms 15ms -8%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 65 67 +2%
vue-large-graph-pan: task duration 12532ms 13861ms +11%
vue-large-graph-pan: script duration 826ms 853ms +3%
vue-large-graph-pan: TBT 3ms 41ms +1267%
vue-large-graph-pan: heap used 169.3 MB 158.2 MB -7%
vue-large-graph-pan: DOM nodes -8329 -8331 +0%
vue-large-graph-pan: event listeners -16464 -16460 -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 2ms +12% z=-0.1
workflow-execution: style recalc duration 22ms 20ms -12% z=-2.1
workflow-execution: layout count 5 6 +10% z=1.0
workflow-execution: style recalc count 17 17 +0% z=-0.4
workflow-execution: task duration 123ms 108ms -12% z=-1.4
workflow-execution: script duration 25ms 22ms -13% z=-2.4
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 52.8 MB 48.4 MB -8%
workflow-execution: DOM nodes 157 169 +8% z=1.2
workflow-execution: event listeners 71 45 -37% z=-1.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-05-15T14:48:39.557Z",
  "gitSha": "412202f553c97c63ef5563dcd4e1a9bb2698f2d3",
  "branch": "glary/website-cloud-nodes-mock-and-slugify",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2063.379999999995,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 8.152,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 417.553,
      "heapDeltaBytes": 19311556,
      "heapUsedBytes": 69430224,
      "domNodes": -264,
      "jsHeapTotalBytes": 18046976,
      "scriptDurationMs": 15.873999999999999,
      "eventListeners": -131,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2013.8499999999908,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 10.328000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 361.002,
      "heapDeltaBytes": 24208760,
      "heapUsedBytes": 73433200,
      "domNodes": 20,
      "jsHeapTotalBytes": 14417920,
      "scriptDurationMs": 24.034,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1704.7370000000228,
      "styleRecalcs": 71,
      "styleRecalcDurationMs": 29.459000000000003,
      "layouts": 12,
      "layoutDurationMs": 3.138,
      "taskDurationMs": 683.932,
      "heapDeltaBytes": 18351144,
      "heapUsedBytes": 68061972,
      "domNodes": 52,
      "jsHeapTotalBytes": 15728640,
      "scriptDurationMs": 116.041,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2020.3669999999647,
      "styleRecalcs": 78,
      "styleRecalcDurationMs": 37.43299999999999,
      "layouts": 12,
      "layoutDurationMs": 3.3680000000000003,
      "taskDurationMs": 938.7630000000001,
      "heapDeltaBytes": 3616064,
      "heapUsedBytes": 52064572,
      "domNodes": -263,
      "jsHeapTotalBytes": 16117760,
      "scriptDurationMs": 120.77899999999998,
      "eventListeners": -131,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1710.470999999984,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 18.333000000000002,
      "layouts": 6,
      "layoutDurationMs": 0.6219999999999999,
      "taskDurationMs": 281.03499999999997,
      "heapDeltaBytes": 512140,
      "heapUsedBytes": 49148772,
      "domNodes": 75,
      "jsHeapTotalBytes": 14942208,
      "scriptDurationMs": 16.881,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1736.1339999999927,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 15.771999999999998,
      "layouts": 6,
      "layoutDurationMs": 0.525,
      "taskDurationMs": 282.69999999999993,
      "heapDeltaBytes": 533016,
      "heapUsedBytes": 49129132,
      "domNodes": 79,
      "jsHeapTotalBytes": 14680064,
      "scriptDurationMs": 17.183999999999997,
      "eventListeners": 21,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 605.7559999999853,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 8.040000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 365.938,
      "heapDeltaBytes": 15303420,
      "heapUsedBytes": 64526260,
      "domNodes": 19,
      "jsHeapTotalBytes": 17039360,
      "scriptDurationMs": 60.515,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 536.687000000029,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 9.662,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 343.418,
      "heapDeltaBytes": 9441176,
      "heapUsedBytes": 57479164,
      "domNodes": 22,
      "jsHeapTotalBytes": 15466496,
      "scriptDurationMs": 64.91199999999999,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2013.9159999999947,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.426,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 502.74299999999994,
      "heapDeltaBytes": 8118224,
      "heapUsedBytes": 66656460,
      "domNodes": -262,
      "jsHeapTotalBytes": 290816,
      "scriptDurationMs": 85.02399999999999,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2026.818999999989,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.393000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 500.707,
      "heapDeltaBytes": 2892264,
      "heapUsedBytes": 61455272,
      "domNodes": -264,
      "jsHeapTotalBytes": 4485120,
      "scriptDurationMs": 84.60099999999998,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2127.346999999986,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 16.773000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1064.7540000000001,
      "heapDeltaBytes": 60631140,
      "heapUsedBytes": 120704380,
      "domNodes": -262,
      "jsHeapTotalBytes": 35360768,
      "scriptDurationMs": 376.206,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2159.694000000002,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 14.226999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1072.74,
      "heapDeltaBytes": 56495260,
      "heapUsedBytes": 117775632,
      "domNodes": -252,
      "jsHeapTotalBytes": 36700160,
      "scriptDurationMs": 380.858,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3134.1810000000123,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 16.901000000000003,
      "layouts": 60,
      "layoutDurationMs": 6.988000000000001,
      "taskDurationMs": 1275.849,
      "heapDeltaBytes": 36702312,
      "heapUsedBytes": 104098628,
      "domNodes": 14,
      "jsHeapTotalBytes": 58339328,
      "scriptDurationMs": 475.14099999999996,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3184.0459999999666,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 16.720000000000002,
      "layouts": 60,
      "layoutDurationMs": 6.816,
      "taskDurationMs": 1340.879,
      "heapDeltaBytes": 49686516,
      "heapUsedBytes": 111035400,
      "domNodes": -269,
      "jsHeapTotalBytes": 38039552,
      "scriptDurationMs": 488.128,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 1993.3689999999729,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.106000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 524.548,
      "heapDeltaBytes": 45086184,
      "heapUsedBytes": 113364416,
      "domNodes": 20,
      "jsHeapTotalBytes": 47853568,
      "scriptDurationMs": 83.231,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2071.8669999999975,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.707,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 597.62,
      "heapDeltaBytes": 45283132,
      "heapUsedBytes": 105145920,
      "domNodes": -256,
      "jsHeapTotalBytes": 32272384,
      "scriptDurationMs": 101.06099999999998,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 519.9220000000082,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 10.865,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 344.003,
      "heapDeltaBytes": 9840420,
      "heapUsedBytes": 59364264,
      "domNodes": 20,
      "jsHeapTotalBytes": 15990784,
      "scriptDurationMs": 121.54100000000001,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 511.4450000000943,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 10.273000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 341.38500000000005,
      "heapDeltaBytes": 8883932,
      "heapUsedBytes": 57740292,
      "domNodes": 18,
      "jsHeapTotalBytes": 15990784,
      "scriptDurationMs": 120.17399999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1994.9060000000145,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 6.111999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 357.35999999999996,
      "heapDeltaBytes": 38971396,
      "heapUsedBytes": 92000372,
      "domNodes": 16,
      "jsHeapTotalBytes": 45875200,
      "scriptDurationMs": 12.604999999999999,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2016.1330000000248,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.820999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 361.282,
      "heapDeltaBytes": -5861468,
      "heapUsedBytes": 43167536,
      "domNodes": 18,
      "jsHeapTotalBytes": 15593472,
      "scriptDurationMs": 12.683000000000007,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1684.759999999983,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 34.8,
      "layouts": 16,
      "layoutDurationMs": 4.14,
      "taskDurationMs": 625.5959999999999,
      "heapDeltaBytes": 15240996,
      "heapUsedBytes": 64646364,
      "domNodes": 62,
      "jsHeapTotalBytes": 15466496,
      "scriptDurationMs": 90.417,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1988.2729999999924,
      "styleRecalcs": 87,
      "styleRecalcDurationMs": 43.258,
      "layouts": 16,
      "layoutDurationMs": 4.264,
      "taskDurationMs": 882.659,
      "heapDeltaBytes": 14426256,
      "heapUsedBytes": 63017344,
      "domNodes": 71,
      "jsHeapTotalBytes": 14680064,
      "scriptDurationMs": 91.061,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1057.7220000000125,
      "styleRecalcs": 14,
      "styleRecalcDurationMs": 27.92,
      "layouts": 5,
      "layoutDurationMs": 13.739,
      "taskDurationMs": 856.9999999999998,
      "heapDeltaBytes": -17104680,
      "heapUsedBytes": 138679708,
      "domNodes": 12475,
      "jsHeapTotalBytes": -11177984,
      "scriptDurationMs": 34.579999999999984,
      "eventListeners": 1288,
      "totalBlockingTimeMs": 158,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8108.627999999953,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 48.300999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3422.307,
      "heapDeltaBytes": 15558080,
      "heapUsedBytes": 74259296,
      "domNodes": -260,
      "jsHeapTotalBytes": 2854912,
      "scriptDurationMs": 1184.485,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.80000000000109
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8142.048999999929,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 49.15,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3499.708,
      "heapDeltaBytes": 13036572,
      "heapUsedBytes": 71488996,
      "domNodes": -262,
      "jsHeapTotalBytes": 2068480,
      "scriptDurationMs": 1209.77,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11172.401000000036,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11159.42,
      "heapDeltaBytes": -28362708,
      "heapUsedBytes": 163383828,
      "domNodes": -3310,
      "jsHeapTotalBytes": 17534976,
      "scriptDurationMs": 549.584,
      "eventListeners": -16472,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 10725.865999999996,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 10717.364,
      "heapDeltaBytes": -33220608,
      "heapUsedBytes": 164894228,
      "domNodes": -8331,
      "jsHeapTotalBytes": 14479360,
      "scriptDurationMs": 543.5799999999999,
      "eventListeners": -16468,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.226666666666762,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13762.086999999952,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 15.189000000000007,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13742.988000000001,
      "heapDeltaBytes": -39834504,
      "heapUsedBytes": 165797828,
      "domNodes": -8331,
      "jsHeapTotalBytes": -3608576,
      "scriptDurationMs": 847.4869999999999,
      "eventListeners": -16460,
      "totalBlockingTimeMs": 82,
      "frameDurationMs": 17.779999999999927,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14006.762999999977,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 15.425000000000022,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13978.495000000003,
      "heapDeltaBytes": -35141516,
      "heapUsedBytes": 166061076,
      "domNodes": -8331,
      "jsHeapTotalBytes": -5595136,
      "scriptDurationMs": 857.966,
      "eventListeners": -16460,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 466.85999999999694,
      "styleRecalcs": 25,
      "styleRecalcDurationMs": 23.801,
      "layouts": 5,
      "layoutDurationMs": 1.5009999999999997,
      "taskDurationMs": 133.42900000000003,
      "heapDeltaBytes": -16889684,
      "heapUsedBytes": 48279156,
      "domNodes": 195,
      "jsHeapTotalBytes": 5505024,
      "scriptDurationMs": 26.497999999999994,
      "eventListeners": 71,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "workflow-execution",
      "durationMs": 118.18500000003951,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 15.539000000000001,
      "layouts": 6,
      "layoutDurationMs": 1.5769999999999997,
      "taskDurationMs": 82.98,
      "heapDeltaBytes": 3078880,
      "heapUsedBytes": 53300268,
      "domNodes": 143,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 17.703,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999727
    }
  ]
}

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 `@apps/website/src/utils/cloudNodes.ts`:
- Around line 373-375: When merging slug-collided snapshot packs (inside the
block that checks `if (existing)`), you currently only append `nodes` and drop
any optional metadata from later `pack`s; change it to preserve existing fields
but fill missing/undefined metadata from `pack`. Specifically, after updating
`existing.nodes = [...existing.nodes, ...pack.nodes]`, copy any other fields
from `pack` into `existing` only when `existing[field]` is null/undefined (do
not overwrite existing values and do not touch `nodes`), e.g., loop over
`Object.keys(pack)` and assign missing properties; this ensures optional fields
from later aliases are retained when the first pack lacked them.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 71ab6d22-50c8-4c25-b05f-aa54381b2c64

📥 Commits

Reviewing files that changed from the base of the PR and between f090ea3 and b58d244.

📒 Files selected for processing (12)
  • .github/workflows/ci-website-e2e.yaml
  • apps/website/e2e/fixtures/cloud-nodes.fixture.json
  • apps/website/src/data/cloud-nodes.snapshot.json
  • apps/website/src/utils/cloudNodes.build.test.ts
  • apps/website/src/utils/cloudNodes.build.ts
  • apps/website/src/utils/cloudNodes.test.ts
  • apps/website/src/utils/cloudNodes.ts
  • packages/object-info-parser/src/__tests__/groupNodesByPack.test.ts
  • packages/object-info-parser/src/__tests__/slugifyPackId.test.ts
  • packages/object-info-parser/src/helpers/groupNodesByPack.ts
  • packages/object-info-parser/src/helpers/slugifyPackId.ts
  • packages/object-info-parser/src/index.ts

Comment thread apps/website/src/utils/cloudNodes.ts
… slug

Addresses CodeRabbit review: when normalizeSnapshotIds merged two snapshot
packs whose ids slugified to the same value, only the nodes were combined
and every other optional field (registryId, description, repoUrl, publisher,
downloads, githubStars, license, ...) was silently dropped from the later
alias. If the first row lacked metadata the second had, those fields were
lost from the rendered detail page.

mergeCollidedPacks now walks every key on the later pack and fills any
undefined or null fields on the merged result, never overwriting metadata
already present on the first row. The merge stays deterministic
(first-wins for filled fields) and the rule covers the full Pack shape
instead of an ad-hoc hand-listed subset.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/website/src/utils/cloudNodes.ts (1)

251-257: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve a raw registryId when registry enrichment misses.

registryId now comes only from registryPack?.id, so any pack whose registry lookup returns null/empty—or any full registry fetch failure—produces a fresh snapshot with no raw upstream id at all. That breaks the new "slugged id + raw registryId" contract and leaves downstream registry lookups without a stable identifier. Please fall back to the pack's canonical raw alias here, e.g. registryPack?.id ?? pack.rawIds[0], and lock it in with a regression test for the no-hit path.

Suggested fix
   const packs = grouped.map((pack) =>
     toDomainPack(
       pack.id,
+      pack.rawIds[0],
       pack.displayName,
       pack.nodes,
       pickRegistryPack(registryMap, pack.rawIds)
     )
   )
@@
 function toDomainPack(
   packId: string,
+  fallbackRegistryId: string | undefined,
   fallbackDisplayName: string,
   nodes: Array<{
@@
   return {
     id: packId,
-    registryId: registryPack?.id,
+    registryId: registryPack?.id ?? fallbackRegistryId,
     displayName: registryPack?.name?.trim() || fallbackDisplayName || packId,

Also applies to: 286-304

🤖 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 `@apps/website/src/utils/cloudNodes.ts` around lines 251 - 257, The pack
creation currently uses only registryPack?.id so when
pickRegistryPack(registryMap, pack.rawIds) returns null you lose the original
raw registry id; change the code that maps grouped packs (the toDomainPack call)
to derive a stable registryId variable like const registryPack =
pickRegistryPack(registryMap, pack.rawIds); const registryId = registryPack?.id
?? pack.rawIds[0]; and pass registryId into toDomainPack (same change for the
other occurrence around the 286-304 block), and add a regression test that
simulates a registry miss (pickRegistryPack returning null) asserting the
resulting domain pack contains the fallback raw registryId.
🤖 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.

Outside diff comments:
In `@apps/website/src/utils/cloudNodes.ts`:
- Around line 251-257: The pack creation currently uses only registryPack?.id so
when pickRegistryPack(registryMap, pack.rawIds) returns null you lose the
original raw registry id; change the code that maps grouped packs (the
toDomainPack call) to derive a stable registryId variable like const
registryPack = pickRegistryPack(registryMap, pack.rawIds); const registryId =
registryPack?.id ?? pack.rawIds[0]; and pass registryId into toDomainPack (same
change for the other occurrence around the 286-304 block), and add a regression
test that simulates a registry miss (pickRegistryPack returning null) asserting
the resulting domain pack contains the fallback raw registryId.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d3bbc268-8e3e-411d-b77b-803740f190a0

📥 Commits

Reviewing files that changed from the base of the PR and between b58d244 and df3c3c7.

📒 Files selected for processing (2)
  • apps/website/src/utils/cloudNodes.test.ts
  • apps/website/src/utils/cloudNodes.ts

…isses

Addresses CodeRabbit review: registryId was sourced purely from
registryPack?.id, so any pack whose registry lookup returned null (or
whose entire fetchRegistryPacks call threw) ended up with registryId
undefined. That breaks the new 'slugged id + raw registryId' contract
and leaves downstream code with no stable upstream identifier.

toDomainPack now takes a fallbackRegistryId derived from pack.rawIds[0]
and uses it when registryPack is null/undefined, so every Pack always
exposes the canonical raw alias even when the registry batch fails.

Two regression tests pin the contract:
* registry-miss path (fetchRegistryPacks returns empty map)
* registry-throw path (fetchRegistryPacks rejects)
@glary-bot
Copy link
Copy Markdown

glary-bot Bot commented May 14, 2026

Addressed the outside-diff finding on cloudNodes.ts 251-257 / 286-304 in 1c5a007.

toDomainPack now takes a fallbackRegistryId derived from pack.rawIds[0], so when pickRegistryPack returns null (registry miss or fetchRegistryPacks throwing), the resulting Pack.registryId still holds the canonical raw alias instead of dropping to undefined. Two regression tests added in cloudNodes.test.ts:

  • falls back to the raw upstream id for registryId when registry lookup missesfetchRegistryPacks returns empty map → registryId === 'ComfyUI_QwenVL'
  • falls back to the raw upstream id for registryId when fetchRegistryPacks throwsfetchRegistryPacks rejects → same assertion

86/86 unit tests pass, 18/18 cloud-nodes e2e pass, astro check: 0 errors.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 `@apps/website/src/utils/cloudNodes.test.ts`:
- Around line 440-586: The fallback-snapshot tests can be affected by
WEBSITE_CLOUD_NODES_FIXTURE; before running the suite that uses withSnapshotDir
and fetchCloudNodesForBuild, save process.env.WEBSITE_CLOUD_NODES_FIXTURE to a
local variable and delete or set it to '' so snapshot reads come from the
provided snapshotUrl, and after the suite restore the original value; add a
beforeAll/afterAll (or beforeEach/afterEach) block in
apps/website/src/utils/cloudNodes.test.ts that captures const originalFixture =
process.env.WEBSITE_CLOUD_NODES_FIXTURE, deletes
process.env.WEBSITE_CLOUD_NODES_FIXTURE (or sets to undefined) in setup, and
resets process.env.WEBSITE_CLOUD_NODES_FIXTURE = originalFixture in teardown so
tests using withSnapshotDir and fetchCloudNodesForBuild are hermetic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 92461a64-3d38-440b-ae53-527dba551881

📥 Commits

Reviewing files that changed from the base of the PR and between df3c3c7 and 1c5a007.

📒 Files selected for processing (2)
  • apps/website/src/utils/cloudNodes.test.ts
  • apps/website/src/utils/cloudNodes.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/website/src/utils/cloudNodes.ts

Comment thread apps/website/src/utils/cloudNodes.test.ts
Defensive hardening per CodeRabbit feedback. WEBSITE_CLOUD_NODES_FIXTURE
is currently read only by loadPacksForBuild (cloudNodes.build.ts), not
by fetchCloudNodesForBuild, so the tests in cloudNodes.test.ts are not
affected today. But clearing the env var in beforeEach and restoring it
in afterEach guards against future refactors that might let the override
bleed into the fetcher, and matches the pattern already used in
cloudNodes.build.test.ts.

Also fixes a latent bug in the existing afterEach: previously,
process.env.WEBSITE_CLOUD_API_KEY = savedCloudApiKey would set the env
var to the literal string 'undefined' when savedCloudApiKey was unset.
Now both env vars are conditionally restored (matching the cloudNodes.build
test convention).
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/website/src/utils/cloudNodes.test.ts (1)

404-449: ⚡ Quick win

“picks the first hit” isn’t fully proven when both aliases resolve.

This case only verifies null -> hit, so it can’t catch a regression that picks the last non-null entry. Add one assertion path where both aliases return metadata and confirm the first alias wins.

Suggested test addition
+  it('prefers the first non-null registry result when multiple aliases resolve', async () => {
+    fetchRegistryPacksMock.mockResolvedValue(
+      new Map<string, unknown>([
+        [
+          'ComfyUI-QwenVL',
+          {
+            id: 'ComfyUI-QwenVL',
+            name: 'Dash Variant',
+            repository: 'https://github.com/example/dash-first'
+          }
+        ],
+        [
+          'ComfyUI_QwenVL',
+          {
+            id: 'ComfyUI_QwenVL',
+            name: 'Underscore Variant',
+            repository: 'https://github.com/example/underscore-second'
+          }
+        ]
+      ])
+    )
+
+    const fetchImpl = vi.fn(async () =>
+      response({
+        QwenDash: validNode({
+          name: 'QwenDash',
+          python_module: 'custom_nodes.ComfyUI-QwenVL.nodes'
+        }),
+        QwenUnder: validNode({
+          name: 'QwenUnder',
+          python_module: 'custom_nodes.ComfyUI_QwenVL.nodes'
+        })
+      })
+    )
+
+    const outcome = await fetchCloudNodesForBuild({
+      apiKey: KEY,
+      baseUrl: BASE_URL,
+      fetchImpl: fetchImpl as typeof fetch
+    })
+
+    expect(outcome.status).toBe('fresh')
+    if (outcome.status !== 'fresh') return
+    expect(outcome.snapshot.packs[0]?.registryId).toBe('ComfyUI-QwenVL')
+    expect(outcome.snapshot.packs[0]?.repoUrl).toBe(
+      'https://github.com/example/dash-first'
+    )
+  })
🤖 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 `@apps/website/src/utils/cloudNodes.test.ts` around lines 404 - 449, The test
currently only covers a null->hit alias resolution so it doesn't prove the code
prefers the first alias when both aliases return metadata; update or add a test
case in the same it block (or a new it) that mocks fetchRegistryPacksMock to
return non-null metadata for both 'ComfyUI-QwenVL' and 'ComfyUI_QwenVL', call
fetchCloudNodesForBuild with the same fetchImpl nodes, and assert that
outcome.status === 'fresh' and outcome.snapshot.packs[0].registryId equals the
first alias ('ComfyUI-QwenVL' or whichever alias appears first in the array),
and that repoUrl/ id correspond to that first-alias metadata; also keep the
existing expectation that fetchRegistryPacksMock was called with both aliases to
ensure both were queried.
🤖 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.

Nitpick comments:
In `@apps/website/src/utils/cloudNodes.test.ts`:
- Around line 404-449: The test currently only covers a null->hit alias
resolution so it doesn't prove the code prefers the first alias when both
aliases return metadata; update or add a test case in the same it block (or a
new it) that mocks fetchRegistryPacksMock to return non-null metadata for both
'ComfyUI-QwenVL' and 'ComfyUI_QwenVL', call fetchCloudNodesForBuild with the
same fetchImpl nodes, and assert that outcome.status === 'fresh' and
outcome.snapshot.packs[0].registryId equals the first alias ('ComfyUI-QwenVL' or
whichever alias appears first in the array), and that repoUrl/ id correspond to
that first-alias metadata; also keep the existing expectation that
fetchRegistryPacksMock was called with both aliases to ensure both were queried.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 06d5fa57-3068-46b7-b448-f298cce1ce31

📥 Commits

Reviewing files that changed from the base of the PR and between 1c5a007 and c753f30.

📒 Files selected for processing (1)
  • apps/website/src/utils/cloudNodes.test.ts

…s resolve

CodeRabbit nitpick: the existing alias-collision test mocked
ComfyUI-QwenVL -> null + ComfyUI_QwenVL -> hit, so the assertion that
the first hit wins was actually proving 'the only non-null hit wins'.
A regression that returns the last non-null entry would still pass.

New test mocks BOTH aliases to non-null metadata with distinct
registryId/repoUrl, and pins registryId === 'ComfyUI-QwenVL' (the first
alias in pack.rawIds) so a 'last wins' or 'arbitrary wins' regression
fails immediately.
@glary-bot
Copy link
Copy Markdown

glary-bot Bot commented May 14, 2026

Good catch — added in 669bd5d. The existing "queries every raw-id alias" test was actually only proving "the only non-null hit wins" because it mocked ComfyUI-QwenVL → null + ComfyUI_QwenVL → hit. A regression that returned the last non-null entry would have still passed.

New test mocks both aliases to non-null metadata with distinct registryId/repository URLs and asserts:

expect(outcome.snapshot.packs[0]?.registryId).toBe('ComfyUI-QwenVL')
expect(outcome.snapshot.packs[0]?.repoUrl).toBe('https://github.com/example/dash-first')

Locks pickRegistryPack to "first alias wins" (where "first" follows the order of NodePack.rawIds, which itself follows insertion order from groupNodesByPack). 87/87 unit tests pass.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

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

Files with missing lines Patch % Lines
...object-info-parser/src/helpers/groupNodesByPack.ts 88.88% 1 Missing ⚠️
@@             Coverage Diff             @@
##             main   #12277       +/-   ##
===========================================
- Coverage   74.49%   59.57%   -14.92%     
===========================================
  Files        1523     1412      -111     
  Lines       92068    71884    -20184     
  Branches    25502    19025     -6477     
===========================================
- Hits        68587    42826    -25761     
- Misses      22629    28585     +5956     
+ Partials      852      473      -379     
Flag Coverage Δ
e2e ?
unit 59.57% <90.90%> (+<0.01%) ⬆️

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

Files with missing lines Coverage Δ
...es/object-info-parser/src/helpers/slugifyPackId.ts 100.00% <100.00%> (ø)
...object-info-parser/src/helpers/groupNodesByPack.ts 90.47% <88.88%> (-3.28%) ⬇️

... and 1016 files with indirect coverage changes

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #12289

coderabbitai Bot added a commit that referenced this pull request May 15, 2026
Docstrings generation was requested by @DrJKL.

* #12277 (comment)

The following files were modified:

* `apps/website/src/utils/cloudNodes.build.ts`
* `apps/website/src/utils/cloudNodes.ts`
* `packages/object-info-parser/src/helpers/groupNodesByPack.ts`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants