Skip to content

feat(validation): split topology validation from link repair into publishable nx package#11864

Draft
christian-byrne wants to merge 6 commits intomainfrom
glary/workflow-validation-package
Draft

feat(validation): split topology validation from link repair into publishable nx package#11864
christian-byrne wants to merge 6 commits intomainfrom
glary/workflow-validation-package

Conversation

@christian-byrne
Copy link
Copy Markdown
Contributor

@christian-byrne christian-byrne commented May 3, 2026

PR Created by the Glary-Bot Agent


Addresses the broken seedance template thread. Three architectural changes plus a package extraction.

What changed

1. Better linkFixer errors. The four 'Error. Expected node to match patched data.' invariant throws are replaced with LinkRepairAbortedError, which carries a structured TopologyError describing the offending [linkId, src, srcSlot, tgt, tgtSlot]. Next time a template like api_seedance2_0_r2v_real_human.json ships with links pointing into thin air, the message names the link instead of looking like an internal bug.

2. Topology validation split out from repair. A new pure validateLinkTopology(graph): TopologyError[] walks the link table and reports out-of-bounds slots, missing nodes, and endpoint mismatches as a structured union. Catches the seedance breakage (links targeting slots that don't exist on the node) which the schema cannot detect because cross-references aren't expressible in zod tuples. repairLinks() (the renamed fixBadLinks) keeps the existing rgthree-derived auto-repair algorithm; both are independently callable.

3. Topology errors surface in the UI when ValidateWorkflows is on. Today they're swallowed by console.error. Now useWorkflowValidation raises a single warn toast listing up to five offenders (the rest go to the console) when the setting is enabled, plus an error toast on unrepairable workflows. validateWorkflow returns null on abort so the caller falls back to the original graph.

4. New @comfyorg/workflow-validation nx package under packages/. Owns the workflow zod schemas, topology validator, repair, and minimal serialised JSON shapes. Has zero litegraph coupling so a follow-up PR can wire Comfy-Org/workflow_templates CI to consume the published package and validate every template's topology before merge — the second half of Christian's "let me think about how to put this into CI."

Migration uses tsconfig + vite path aliases mirroring the existing @/utils/formatUtil precedent, so the 76 importers of workflowSchema and the lone importer of linkFixer continue to compile without touching any of them.

Verification

  • pnpm typecheck clean
  • pnpm lint clean (1 pre-existing unrelated warning in useWorkspaceBilling.test.ts)
  • pnpm knip clean
  • pnpm test:unit 9890/9890 passing including new validateLinkTopology tests with a seedance-style fixture
  • pnpm --dir packages/workflow-validation run build produces dist/index.js + per-file .d.ts plus a publish-ready dist/package.json

Deferred follow-ups

  • The npm publish workflow YAML (release-npm-workflow-validation.yaml) was authored but had to be dropped from this PR because the bot pushing the branch lacks the GitHub App workflows permission. A maintainer can add it in a follow-up — it's a near-clone of the existing release-npm-types.yaml.
  • Once the package is published, a draft PR on Comfy-Org/workflow_templates to consume it for CI validation will follow.

Architecture notes

Per Oracle review, the package owns the plain serialised workflow contract: SerialisedGraph, SerialisedNode, link tuple/object shapes are defined locally rather than imported from @/lib/litegraph/.... This keeps the package free of frontend coupling, so Node CI scripts and a future backend validator can use the same validator that runs in the UI.

┆Issue is synchronized with this Notion page by Unito

Glary-Bot added 3 commits May 2, 2026 04:41
…lishable nx package

Extract workflow zod schemas, link topology validator, and link repair
into a new `@comfyorg/workflow-validation` package under `packages/`.
The package has zero litegraph coupling — it operates on plain
serialised JSON shapes — so it can be consumed by Node.js CI scripts
and a future backend validator.

Behaviour changes:

- Replace the four `'Error. Expected node to match patched data.'`
  invariant throws in the link fixer with `LinkRepairAbortedError`,
  which carries a structured `TopologyError` describing the offending
  `[linkId, src, srcSlot, tgt, tgtSlot]`.
- Add a pure `validateLinkTopology(graph)` that walks the link table
  and reports out-of-bounds slots, missing nodes, and endpoint
  mismatches as a structured `TopologyError[]`. This catches the
  seedance-style breakage (links targeting slots that don't exist on
  the node) which the schema cannot detect.
- Surface topology errors via toast when `Comfy.Validation.Workflows`
  is enabled, instead of swallowing them with `console.error`.
  Unrepairable workflows raise an `error` toast with structured
  details and `useWorkflowValidation` returns `null` so the caller
  falls back to the original graph.

Migration is via tsconfig + vite path aliases mirroring the existing
`@/utils/formatUtil` precedent, so the 76 importers of
`workflowSchema` and the lone importer of `linkFixer` continue to
compile without changes.

Adds `release-npm-workflow-validation.yaml`, a `workflow_dispatch`
publisher mirroring the existing `release-npm-types` pattern, so a
follow-up PR on Comfy-Org/workflow_templates can pin the published
package for per-template topology CI.
…ublish

Address code review feedback:

- Annotate `zGraphDefinitions.subgraphs`'s lazy resolver with the same
  explicit `z.ZodArray<z.ZodType<SubgraphDefinitionBase<...>>>` shape
  the recursive `zSubgraphDefinition` already uses. This breaks the
  TS7056 'inferred type exceeds maximum length' error when emitting
  declarations for `zComfyWorkflow`.
- Drop `rollupTypes` from the package's `vite-plugin-dts` config.
  Per-file `.d.ts` emit avoids both the api-extractor entry-point
  failure and the recursive-type rollup blowup; `index.d.ts` re-exports
  per-file declarations so consumers still see one entry.
- Restore the full subpath export surface in the published manifest
  (`./linkRepair`, `./linkTopology`, `./workflowSchema`,
  `./serialised`) and resolve catalog versions for runtime deps so the
  published package matches the workspace contract.
- Ignore `*.tsbuildinfo` so package builds don't litter the index.
The workflow file requires `workflows` permission on the GitHub App
posting the PR, which isn't granted today. The release workflow can be
added in a follow-up commit by a maintainer; the package itself is
already buildable via `pnpm --dir packages/workflow-validation run build`.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Warning

Rate limit exceeded

@christian-byrne has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 34 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fe2533f5-4671-402d-9c5d-c690c4a495ed

📥 Commits

Reviewing files that changed from the base of the PR and between 0155a00 and 36df5e2.

📒 Files selected for processing (3)
  • .storybook/main.ts
  • src/locales/en/main.json
  • src/platform/workflow/validation/composables/useWorkflowValidation.ts
📝 Walkthrough

Walkthrough

This PR adds a new @comfyorg/workflow-validation package providing topology validation and link-repair APIs, integrates those APIs into the app workflow validation flow, and wires up build/config, tests, localization, and publishing utilities for the new package.

Changes

Workflow Validation Package Creation & Integration

Layer / File(s) Summary
Package Configuration
packages/workflow-validation/package.json, packages/workflow-validation/tsconfig.json, packages/workflow-validation/vite.config.mts
New @comfyorg/workflow-validation package with ES module exports (., ./linkRepair, ./linkTopology, ./workflowSchema, ./serialised); Vite build + vite-plugin-dts; TypeScript project set to compile srcdist.
Core Type Definitions
packages/workflow-validation/src/serialised.ts, packages/workflow-validation/src/workflowSchema.ts, packages/workflow-validation/src/index.ts
Introduces SerialisedGraph/node/link types, local RendererType, refines zGraphDefinitions. Public entrypoint re-exports serialised types, topology, repair, and schema helpers.
Topology Validation
packages/workflow-validation/src/linkTopology.ts, packages/workflow-validation/src/linkTopology.test.ts
Adds validateLinkTopology(graph): TopologyError[], toLinkContext, describeTopologyError, and tests covering array/object-form links, missing nodes, slot OOB, and mismatched references.
Link Repair Logic
packages/workflow-validation/src/linkRepair.ts
Adds repairLinks(graph, options): RepairResult (replaces prior fixBadLinks), RepairOptions, RepairResult, and LinkRepairAbortedError. Normalizes links, patches slots, supports live vs serialized graphs, collects/deletes stale links, and performs dry-run recheck.
Package Entrypoint & Publish Prep
packages/workflow-validation/src/index.ts, scripts/prepare-workflow-validation.ts
Public re-exports for validation/repair APIs; script generates dist/package.json resolving catalog: versions for publishing.
Project Config & Aliases
.gitignore, eslint.config.ts, tsconfig.json, vite.config.mts, root package.json
Ignore *.tsbuildinfo; ESLint allowDefaultProject updated for package Vite config; TypeScript/Vite/Storybook aliases added for new package paths; root workspace dependency added for @comfyorg/workflow-validation.
Application Integration
src/platform/workflow/validation/composables/useWorkflowValidation.ts, src/utils/linkFixer.test.ts, scripts/generate-json-schema.ts
tryFixLinks() now runs validateLinkTopology() and repairLinks(), reports/top-5-toasts errors, captures repair logs, handles LinkRepairAbortedError by returning aborted: true. Tests and schema-generator import APIs from the new package.
Localization
src/locales/en/main.json
Adds validation.topology.* keys for invalid link counts, overflow, aborted summary, and link-fix summaries/details.
sequenceDiagram
    participant UI as useWorkflowValidation
    participant V as validateLinkTopology
    participant R as repairLinks
    participant E as LinkRepairAbortedError

    UI->>V: validateLinkTopology(graph)
    V-->>UI: TopologyError[]
    alt Validation errors present
        UI->>UI: warn + toast top N errors
    end

    UI->>R: repairLinks(graph, { fix: true })
    alt Repair succeeds
        R->>R: patch slots, collect deleted links
        R-->>UI: RepairResult { fixed, patched, deleted }
        UI->>UI: show success toast with summary
    else Unreconcilable divergence
        R-->>E: throw LinkRepairAbortedError(topologyError)
        E-->>UI: structured topology error
        UI->>UI: show abort toast, return { aborted: true }
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through links, both broken and bent,
Built a small package to mend what was rent,
Topology checked, repairs tidy and neat,
Warnings and toasts make the outcome complete,
Hooray — workflows leap forward on nimble feet!

🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main objective: extracting workflow validation into a publishable nx package and reorganizing topology validation/repair functionality.
Description check ✅ Passed The description provides comprehensive context: architectural changes, specific error handling improvements, topology validation details, UI integration, package structure, verification steps, and deferred follow-ups. However, it deviates from the template structure by using custom sections instead of the required template format.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
End-To-End Regression Coverage For Fixes ✅ Passed PR title uses 'feat' prefix and describes architectural refactoring, not bug-fix. Commit subject lacks bug-fix language. No files changed under browser_tests/.
Adr Compliance For Entity/Litegraph Changes ✅ Passed PR does not modify files under src/lib/litegraph/ or src/ecs/. New packages/workflow-validation/ package contains plain serialization types and pure validation functions with zero litegraph coupling, maintaining ADR compliance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch glary/workflow-validation-package

Review rate limit: 0/5 reviews remaining, refill in 7 minutes and 34 seconds.

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

🌐 Website E2E

Tip

All tests passed.

Status ✅ Passed
Report View Report

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

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

📊 Browser Reports
  • chromium: View Report (✅ 1446 / ❌ 0 / ⚠️ 1 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 16 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 05/03/2026, 06:57:26 AM UTC

Links

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 3, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

📦 Bundle: 5.26 MB gzip 🔴 +2.03 kB

Details

Summary

  • Raw size: 24.2 MB baseline 24.2 MB — 🔴 +8.38 kB
  • Gzip: 5.26 MB baseline 5.25 MB — 🔴 +2.03 kB
  • Brotli: 4.07 MB baseline 4.07 MB — 🔴 +1.51 kB
  • Bundles: 258 current • 258 baseline • 126 added / 126 removed

Category Glance
Data & Services 🔴 +7.05 kB (3.05 MB) · Other 🔴 +1.33 kB (8.84 MB) · Vendor & Third-Party ⚪ 0 B (9.94 MB) · Graph Workspace ⚪ 0 B (1.24 MB) · Panels & Settings ⚪ 0 B (489 kB) · Utilities & Hooks ⚪ 0 B (365 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CUEqsTN-.js (removed) 22.6 kB 🟢 -22.6 kB 🟢 -8.01 kB 🟢 -6.89 kB
assets/index-CvnEMJIq.js (new) 22.6 kB 🔴 +22.6 kB 🔴 +8 kB 🔴 +6.85 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-B539dQZX.js (removed) 1.24 MB 🟢 -1.24 MB 🟢 -265 kB 🟢 -199 kB
assets/GraphView-BbabUxDx.js (new) 1.24 MB 🔴 +1.24 MB 🔴 +265 kB 🔴 +199 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-BjD9z7tW.js (new) 19.6 kB 🔴 +19.6 kB 🔴 +5.15 kB 🔴 +4.58 kB
assets/CloudSurveyView-DEVOi6J9.js (removed) 19.6 kB 🟢 -19.6 kB 🟢 -5.15 kB 🟢 -4.57 kB
assets/CloudLoginView-C0IF3LYW.js (new) 12.2 kB 🔴 +12.2 kB 🔴 +3.45 kB 🔴 +3.06 kB
assets/CloudLoginView-C5ckSsL-.js (removed) 12.2 kB 🟢 -12.2 kB 🟢 -3.45 kB 🟢 -3.06 kB
assets/CloudSignupView-C4CYGKqQ.js (new) 9.97 kB 🔴 +9.97 kB 🔴 +2.95 kB 🔴 +2.59 kB
assets/CloudSignupView-Dngr26OH.js (removed) 9.97 kB 🟢 -9.97 kB 🟢 -2.94 kB 🟢 -2.6 kB
assets/UserCheckView-B6odfFa4.js (removed) 9.07 kB 🟢 -9.07 kB 🟢 -2.33 kB 🟢 -2.04 kB
assets/UserCheckView-CS_TcMjm.js (new) 9.07 kB 🔴 +9.07 kB 🔴 +2.34 kB 🔴 +2.04 kB
assets/CloudLayoutView-DeaSdFqX.js (removed) 7.73 kB 🟢 -7.73 kB 🟢 -2.45 kB 🟢 -2.15 kB
assets/CloudLayoutView-DpE5RKaf.js (new) 7.73 kB 🔴 +7.73 kB 🔴 +2.45 kB 🔴 +2.15 kB
assets/CloudForgotPasswordView-BbF70f_b.js (removed) 6.14 kB 🟢 -6.14 kB 🟢 -2.19 kB 🟢 -1.91 kB
assets/CloudForgotPasswordView-BdHRc_zt.js (new) 6.14 kB 🔴 +6.14 kB 🔴 +2.19 kB 🔴 +1.92 kB
assets/CloudAuthTimeoutView-BZAOYhIj.js (removed) 5.5 kB 🟢 -5.5 kB 🟢 -2.02 kB 🟢 -1.77 kB
assets/CloudAuthTimeoutView-BzJbn7Hr.js (new) 5.5 kB 🔴 +5.5 kB 🔴 +2.02 kB 🔴 +1.77 kB
assets/CloudSubscriptionRedirectView-Dpuu2zvS.js (removed) 5.28 kB 🟢 -5.28 kB 🟢 -2 kB 🟢 -1.78 kB
assets/CloudSubscriptionRedirectView-eqQk4uRS.js (new) 5.28 kB 🔴 +5.28 kB 🔴 +2 kB 🔴 +1.78 kB
assets/UserSelectView-D4mftg42.js (new) 4.73 kB 🔴 +4.73 kB 🔴 +1.75 kB 🔴 +1.55 kB
assets/UserSelectView-DTwcJ8GV.js (removed) 4.73 kB 🟢 -4.73 kB 🟢 -1.76 kB 🟢 -1.56 kB

Status: 9 added / 9 removed / 2 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-D9SsbI3y.js (removed) 46.7 kB 🟢 -46.7 kB 🟢 -9.62 kB 🟢 -8.54 kB
assets/KeybindingPanel-DpGOLI13.js (new) 46.7 kB 🔴 +46.7 kB 🔴 +9.62 kB 🔴 +8.55 kB
assets/SecretsPanel-DAc6hUbg.js (removed) 22.9 kB 🟢 -22.9 kB 🟢 -5.55 kB 🟢 -4.87 kB
assets/SecretsPanel-DacjU33s.js (new) 22.9 kB 🔴 +22.9 kB 🔴 +5.55 kB 🔴 +4.87 kB
assets/LegacyCreditsPanel-CwggeDup.js (removed) 21.7 kB 🟢 -21.7 kB 🟢 -5.91 kB 🟢 -5.21 kB
assets/LegacyCreditsPanel-UmkKXupz.js (new) 21.7 kB 🔴 +21.7 kB 🔴 +5.91 kB 🔴 +5.21 kB
assets/SubscriptionPanel-DE3wVrKA.js (new) 19.9 kB 🔴 +19.9 kB 🔴 +5.08 kB 🔴 +4.48 kB
assets/SubscriptionPanel-sa_wXnmW.js (removed) 19.9 kB 🟢 -19.9 kB 🟢 -5.09 kB 🟢 -4.5 kB
assets/AboutPanel-BgV4yMuW.js (removed) 12 kB 🟢 -12 kB 🟢 -3.33 kB 🟢 -2.98 kB
assets/AboutPanel-BybbkuFK.js (new) 12 kB 🔴 +12 kB 🔴 +3.33 kB 🔴 +2.99 kB
assets/ExtensionPanel-DiaIVZMo.js (removed) 9.97 kB 🟢 -9.97 kB 🟢 -2.91 kB 🟢 -2.58 kB
assets/ExtensionPanel-dIvBdJTM.js (new) 9.97 kB 🔴 +9.97 kB 🔴 +2.91 kB 🔴 +2.59 kB
assets/ServerConfigPanel-Bq9dzjcw.js (new) 7.05 kB 🔴 +7.05 kB 🔴 +2.36 kB 🔴 +2.13 kB
assets/ServerConfigPanel-D7-rhx0w.js (removed) 7.05 kB 🟢 -7.05 kB 🟢 -2.36 kB 🟢 -2.12 kB
assets/UserPanel-BfsNNSl6.js (new) 6.75 kB 🔴 +6.75 kB 🔴 +2.25 kB 🔴 +1.98 kB
assets/UserPanel-CSei9Bdo.js (removed) 6.75 kB 🟢 -6.75 kB 🟢 -2.24 kB 🟢 -1.97 kB
assets/cloudRemoteConfig-C-hq9mgw.js (new) 2.05 kB 🔴 +2.05 kB 🔴 +988 B 🔴 +854 B
assets/cloudRemoteConfig-UN2EXqAO.js (removed) 2.05 kB 🟢 -2.05 kB 🟢 -991 B 🟢 -852 B
assets/refreshRemoteConfig-Cxl8oX6k.js (new) 1.45 kB 🔴 +1.45 kB 🔴 +649 B 🔴 +551 B
assets/refreshRemoteConfig-Dy0Msv7L.js (removed) 1.45 kB 🟢 -1.45 kB 🟢 -650 B 🟢 -555 B

Status: 10 added / 10 removed / 11 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-AEdDB0B6.js (new) 3.57 kB 🔴 +3.57 kB 🔴 +1.26 kB 🔴 +1.08 kB
assets/auth-ClQ84zgI.js (removed) 3.57 kB 🟢 -3.57 kB 🟢 -1.26 kB 🟢 -1.08 kB
assets/SignUpForm-B_foPHjM.js (new) 3.19 kB 🔴 +3.19 kB 🔴 +1.29 kB 🔴 +1.15 kB
assets/SignUpForm-DVA32rjx.js (removed) 3.19 kB 🟢 -3.19 kB 🟢 -1.29 kB 🟢 -1.15 kB
assets/UpdatePasswordContent-BygW7x96.js (removed) 2.9 kB 🟢 -2.9 kB 🟢 -1.3 kB 🟢 -1.16 kB
assets/UpdatePasswordContent-CZr1HLeQ.js (new) 2.9 kB 🔴 +2.9 kB 🔴 +1.3 kB 🔴 +1.16 kB
assets/authStore-C3SupBbA.js (removed) 1.19 kB 🟢 -1.19 kB 🟢 -569 B 🟢 -504 B
assets/authStore-PE1311Qp.js (new) 1.19 kB 🔴 +1.19 kB 🔴 +567 B 🔴 +507 B
assets/auth-De-GCU07.js (removed) 348 B 🟢 -348 B 🟢 -218 B 🟢 -187 B
assets/auth-I16H7sRY.js (new) 348 B 🔴 +348 B 🔴 +219 B 🔴 +186 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-Dgu3akc_.js (removed) 85.8 kB 🟢 -85.8 kB 🟢 -18.6 kB 🟢 -15.9 kB
assets/ComfyHubPublishDialog-DZ3E8l_o.js (new) 85.8 kB 🔴 +85.8 kB 🔴 +18.6 kB 🔴 +15.9 kB
assets/useShareDialog-D44Qs113.js (new) 23.8 kB 🔴 +23.8 kB 🔴 +5.78 kB 🔴 +5.12 kB
assets/useShareDialog-DfdYoxUH.js (removed) 23.8 kB 🟢 -23.8 kB 🟢 -5.78 kB 🟢 -5.12 kB
assets/ComfyHubPublishDialog-Cmy5S3Pb.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +629 B 🔴 +556 B
assets/ComfyHubPublishDialog-TdayRYcQ.js (removed) 1.35 kB 🟢 -1.35 kB 🟢 -629 B 🟢 -561 B
assets/useSubscriptionDialog-BHmLveNA.js (new) 1.17 kB 🔴 +1.17 kB 🔴 +560 B 🔴 +488 B
assets/useSubscriptionDialog-CxU2_C3m.js (removed) 1.17 kB 🟢 -1.17 kB 🟢 -560 B 🟢 -485 B

Status: 4 added / 4 removed

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-BvbYkV6D.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.79 kB 🟢 -3.39 kB
assets/ComfyQueueButton-VQPo_edE.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.79 kB 🔴 +3.38 kB
assets/useTerminalTabs-CTZosskJ.js (removed) 11 kB 🟢 -11 kB 🟢 -3.73 kB 🟢 -3.29 kB
assets/useTerminalTabs-dggnfHHI.js (new) 11 kB 🔴 +11 kB 🔴 +3.73 kB 🔴 +3.28 kB
assets/SubscribeButton-B4pI2rjL.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -1.05 kB 🟢 -945 B
assets/SubscribeButton-DBI0Ikj4.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +1.05 kB 🔴 +946 B
assets/cloudFeedbackTopbarButton-BDwvhXNr.js (new) 1.83 kB 🔴 +1.83 kB 🔴 +946 B 🔴 +831 B
assets/cloudFeedbackTopbarButton-MLg6OTgX.js (removed) 1.83 kB 🟢 -1.83 kB 🟢 -946 B 🟢 -825 B
assets/ComfyQueueButton-B54rtp9T.js (new) 1.27 kB 🔴 +1.27 kB 🔴 +595 B 🔴 +528 B
assets/ComfyQueueButton-RswHVYku.js (removed) 1.27 kB 🟢 -1.27 kB 🟢 -595 B 🟢 -528 B

Status: 5 added / 5 removed / 9 unchanged

Data & Services — 3.05 MB (baseline 3.04 MB) • 🔴 +7.05 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-CA2SgcjN.js (new) 1.99 MB 🔴 +1.99 MB 🔴 +457 kB 🔴 +346 kB
assets/dialogService-BemmE-sw.js (removed) 1.98 MB 🟢 -1.98 MB 🟢 -456 kB 🟢 -345 kB
assets/api-TQ6MHyC5.js (removed) 887 kB 🟢 -887 kB 🟢 -212 kB 🟢 -167 kB
assets/api-DEkuDu5T.js (new) 887 kB 🔴 +887 kB 🔴 +212 kB 🔴 +167 kB
assets/load3dService-CPSIugH_.js (new) 115 kB 🔴 +115 kB 🔴 +25 kB 🔴 +21.3 kB
assets/load3dService-lxXsxCyX.js (removed) 115 kB 🟢 -115 kB 🟢 -25 kB 🟢 -21.3 kB
assets/workflowShareService-1XCDUJdq.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.89 kB 🔴 +4.33 kB
assets/workflowShareService-C6OJMD3U.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.89 kB 🟢 -4.33 kB
assets/keybindingService-C04hHkoJ.js (removed) 13.8 kB 🟢 -13.8 kB 🟢 -3.67 kB 🟢 -3.22 kB
assets/keybindingService-CP5W7LZN.js (new) 13.8 kB 🔴 +13.8 kB 🔴 +3.67 kB 🔴 +3.22 kB
assets/releaseStore-B_BwEyoj.js (removed) 8.12 kB 🟢 -8.12 kB 🟢 -2.28 kB 🟢 -2 kB
assets/releaseStore-ByQMhQC0.js (new) 8.12 kB 🔴 +8.12 kB 🔴 +2.28 kB 🔴 +2 kB
assets/userStore-Ba2ar1sA.js (new) 2.24 kB 🔴 +2.24 kB 🔴 +868 B 🔴 +761 B
assets/userStore-BId6eebM.js (removed) 2.24 kB 🟢 -2.24 kB 🟢 -870 B 🟢 -761 B
assets/audioService-Ce4O39CR.js (removed) 1.8 kB 🟢 -1.8 kB 🟢 -881 B 🟢 -761 B
assets/audioService-DGRMWj2E.js (new) 1.8 kB 🔴 +1.8 kB 🔴 +879 B 🔴 +759 B
assets/releaseStore-5vI1ZqVT.js (removed) 1.19 kB 🟢 -1.19 kB 🟢 -565 B 🟢 -495 B
assets/releaseStore-DrjLM0vG.js (new) 1.19 kB 🔴 +1.19 kB 🔴 +565 B 🔴 +495 B
assets/workflowDraftStore-BXxhDx6U.js (new) 1.17 kB 🔴 +1.17 kB 🔴 +558 B 🔴 +493 B
assets/workflowDraftStore-CMWeW5-d.js (removed) 1.17 kB 🟢 -1.17 kB 🟢 -558 B 🟢 -494 B
assets/dialogService-BwINNxtn.js (removed) 1.16 kB 🟢 -1.16 kB 🟢 -551 B 🟢 -487 B
assets/dialogService-CuoB7y3r.js (new) 1.16 kB 🔴 +1.16 kB 🔴 +550 B 🔴 +487 B
assets/settingStore-DCfULqiH.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +554 B 🔴 +486 B
assets/settingStore-DuAHwax3.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -554 B 🟢 -485 B
assets/assetsStore-CBBgWbBi.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +553 B 🔴 +488 B
assets/assetsStore-DaBxr8rj.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -554 B 🟢 -487 B

Status: 13 added / 13 removed / 4 unchanged

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-cpgrhKCU.js (new) 233 kB 🔴 +233 kB 🔴 +51.8 kB 🔴 +42.3 kB
assets/useConflictDetection-Dcuj8JHc.js (removed) 233 kB 🟢 -233 kB 🟢 -51.8 kB 🟢 -42.2 kB
assets/useLoad3d-BstEhs5h.js (new) 22.3 kB 🔴 +22.3 kB 🔴 +5.09 kB 🔴 +4.49 kB
assets/useLoad3d-VInYKuSI.js (removed) 22.3 kB 🟢 -22.3 kB 🟢 -5.09 kB 🟢 -4.49 kB
assets/useLoad3dViewer-BjGQcV4y.js (removed) 20.8 kB 🟢 -20.8 kB 🟢 -4.91 kB 🟢 -4.29 kB
assets/useLoad3dViewer-DTYVBX8t.js (new) 20.8 kB 🔴 +20.8 kB 🔴 +4.91 kB 🔴 +4.29 kB
assets/useFeatureFlags-DyInWKFh.js (new) 5.95 kB 🔴 +5.95 kB 🔴 +1.79 kB 🔴 +1.52 kB
assets/useFeatureFlags-xaGH8w1K.js (removed) 5.95 kB 🟢 -5.95 kB 🟢 -1.8 kB 🟢 -1.53 kB
assets/useCopyToClipboard-Ddz0OQ40.js (removed) 5.29 kB 🟢 -5.29 kB 🟢 -1.86 kB 🟢 -1.58 kB
assets/useCopyToClipboard-LU01xeN-.js (new) 5.29 kB 🔴 +5.29 kB 🔴 +1.86 kB 🔴 +1.57 kB
assets/downloadUtil-B6b18NP4.js (new) 4.68 kB 🔴 +4.68 kB 🔴 +1.85 kB 🔴 +1.54 kB
assets/downloadUtil-ChbjxAzX.js (removed) 4.68 kB 🟢 -4.68 kB 🟢 -1.85 kB 🟢 -1.54 kB
assets/useWorkspaceUI-Ab3EdbfB.js (removed) 3.34 kB 🟢 -3.34 kB 🟢 -980 B 🟢 -808 B
assets/useWorkspaceUI-BRpvqSYm.js (new) 3.34 kB 🔴 +3.34 kB 🔴 +982 B 🔴 +808 B
assets/subscriptionCheckoutUtil-97wr-x5P.js (new) 3.31 kB 🔴 +3.31 kB 🔴 +1.36 kB 🔴 +1.19 kB
assets/subscriptionCheckoutUtil-CihIAoWB.js (removed) 3.31 kB 🟢 -3.31 kB 🟢 -1.36 kB 🟢 -1.18 kB
assets/useExternalLink-CkBkAUu9.js (removed) 3.03 kB 🟢 -3.03 kB 🟢 -1.16 kB 🟢 -1.03 kB
assets/useExternalLink-D7CpLErS.js (new) 3.03 kB 🔴 +3.03 kB 🔴 +1.16 kB 🔴 +1.03 kB
assets/assetPreviewUtil-CGpH3SBg.js (removed) 2.27 kB 🟢 -2.27 kB 🟢 -958 B 🟢 -834 B
assets/assetPreviewUtil-HibRzRTQ.js (new) 2.27 kB 🔴 +2.27 kB 🔴 +959 B 🔴 +835 B
assets/useUpstreamValue-BJ46hu7r.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -805 B 🟢 -721 B
assets/useUpstreamValue-DlTJH7gQ.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +806 B 🔴 +710 B
assets/useErrorHandling-Cgi-gzTj.js (new) 1.54 kB 🔴 +1.54 kB 🔴 +647 B 🔴 +548 B
assets/useErrorHandling-LQcAA_SX.js (removed) 1.54 kB 🟢 -1.54 kB 🟢 -648 B 🟢 -552 B
assets/useLoad3d-7_Q89Egh.js (removed) 1.33 kB 🟢 -1.33 kB 🟢 -622 B 🟢 -564 B
assets/useLoad3d-D_sRxRY3.js (new) 1.33 kB 🔴 +1.33 kB 🔴 +624 B 🔴 +552 B
assets/useLoad3dViewer-CR1CwDtq.js (removed) 1.27 kB 🟢 -1.27 kB 🟢 -587 B 🟢 -524 B
assets/useLoad3dViewer-DN7MmiST.js (new) 1.27 kB 🔴 +1.27 kB 🔴 +588 B 🔴 +525 B
assets/useCurrentUser-BCAqTYmV.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +554 B 🔴 +488 B
assets/useCurrentUser-CrgEw2QG.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -555 B 🟢 -486 B
assets/useWorkspaceSwitch-BqraGoDm.js (new) 747 B 🔴 +747 B 🔴 +385 B 🔴 +328 B
assets/useWorkspaceSwitch-CHLxbStF.js (removed) 747 B 🟢 -747 B 🟢 -381 B 🟢 -332 B

Status: 16 added / 16 removed / 15 unchanged

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

External libraries and shared vendor chunks

Status: 16 unchanged

Other — 8.84 MB (baseline 8.84 MB) • 🔴 +1.33 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-CTwHGqqU.js (new) 592 kB 🔴 +592 kB 🔴 +116 kB 🔴 +90.6 kB
assets/i18n-DZr9fSQ0.js (removed) 591 kB 🟢 -591 kB 🟢 -115 kB 🟢 -90.2 kB
assets/core-BrjJENMi.js (new) 76.6 kB 🔴 +76.6 kB 🔴 +19.8 kB 🔴 +16.9 kB
assets/core-G3P-dXEi.js (removed) 76.6 kB 🟢 -76.6 kB 🟢 -19.8 kB 🟢 -16.9 kB
assets/groupNode-BapHHj5M.js (new) 74.9 kB 🔴 +74.9 kB 🔴 +18.7 kB 🔴 +16.5 kB
assets/groupNode-DO5H1bGB.js (removed) 74.9 kB 🟢 -74.9 kB 🟢 -18.7 kB 🟢 -16.5 kB
assets/WidgetSelect-BsQE7UXo.js (new) 67.2 kB 🔴 +67.2 kB 🔴 +14.6 kB 🔴 +12.6 kB
assets/WidgetSelect-CE_Ro0_u.js (removed) 67.2 kB 🟢 -67.2 kB 🟢 -14.6 kB 🟢 -12.7 kB
assets/SubscriptionRequiredDialogContentWorkspace-CIQsC6Nj.js (removed) 48.8 kB 🟢 -48.8 kB 🟢 -9.52 kB 🟢 -8.21 kB
assets/SubscriptionRequiredDialogContentWorkspace-Cj_w1SKa.js (new) 48.8 kB 🔴 +48.8 kB 🔴 +9.53 kB 🔴 +8.22 kB
assets/Load3DControls-CCG9loGy.js (removed) 46.1 kB 🟢 -46.1 kB 🟢 -7.51 kB 🟢 -6.55 kB
assets/Load3DControls-yxBL3KGy.js (new) 46.1 kB 🔴 +46.1 kB 🔴 +7.51 kB 🔴 +6.55 kB
assets/WidgetPainter-DXuVnBDj.js (new) 34 kB 🔴 +34 kB 🔴 +8.3 kB 🔴 +7.35 kB
assets/WidgetPainter-X_jWIjEl.js (removed) 34 kB 🟢 -34 kB 🟢 -8.3 kB 🟢 -7.37 kB
assets/WorkspacePanelContent-BbmFVBea.js (removed) 32.8 kB 🟢 -32.8 kB 🟢 -7.01 kB 🟢 -6.2 kB
assets/WorkspacePanelContent-rVmwPoi8.js (new) 32.8 kB 🔴 +32.8 kB 🔴 +7.01 kB 🔴 +6.2 kB
assets/Load3dViewerContent-D-GJXC09.js (new) 28 kB 🔴 +28 kB 🔴 +5.85 kB 🔴 +5.07 kB
assets/Load3dViewerContent-dBek541Y.js (removed) 28 kB 🟢 -28 kB 🟢 -5.85 kB 🟢 -5.07 kB
assets/SubscriptionRequiredDialogContent-CGOg9eOJ.js (new) 27.5 kB 🔴 +27.5 kB 🔴 +6.98 kB 🔴 +6.16 kB
assets/SubscriptionRequiredDialogContent-DvvjJlId.js (removed) 27.5 kB 🟢 -27.5 kB 🟢 -6.98 kB 🟢 -6.18 kB
assets/WidgetImageCrop-40d-CNvN.js (removed) 24.3 kB 🟢 -24.3 kB 🟢 -6.2 kB 🟢 -5.46 kB
assets/WidgetImageCrop-C_idLwXd.js (new) 24.3 kB 🔴 +24.3 kB 🔴 +6.2 kB 🔴 +5.46 kB
assets/SubscriptionPanelContentWorkspace-BTDp_OAr.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.17 kB 🟢 -4.58 kB
assets/SubscriptionPanelContentWorkspace-CxBlTqp3.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.17 kB 🔴 +4.56 kB
assets/SignInContent-_hLN7O91.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.37 kB 🔴 +4.68 kB
assets/SignInContent-2be5Om84.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.37 kB 🟢 -4.72 kB
assets/CurrentUserPopoverWorkspace-b85zQXRa.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -4.91 kB 🟢 -4.4 kB
assets/CurrentUserPopoverWorkspace-df74Pg2z.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +4.91 kB 🔴 +4.4 kB
assets/WidgetInputNumber-Bw9ahUPH.js (new) 19.1 kB 🔴 +19.1 kB 🔴 +4.84 kB 🔴 +4.29 kB
assets/WidgetInputNumber-pu0T03-1.js (removed) 19.1 kB 🟢 -19.1 kB 🟢 -4.84 kB 🟢 -4.3 kB
assets/Load3D-B0xVRlP7.js (removed) 18.5 kB 🟢 -18.5 kB 🟢 -4.39 kB 🟢 -3.83 kB
assets/Load3D-DRXoRZvV.js (new) 18.5 kB 🔴 +18.5 kB 🔴 +4.39 kB 🔴 +3.83 kB
assets/WidgetRecordAudio-CzCXjZ9Z.js (removed) 17.4 kB 🟢 -17.4 kB 🟢 -5.02 kB 🟢 -4.48 kB
assets/WidgetRecordAudio-Dae3BeH7.js (new) 17.4 kB 🔴 +17.4 kB 🔴 +5.02 kB 🔴 +4.48 kB
assets/WidgetRange-DnVZHKs3.js (new) 17.1 kB 🔴 +17.1 kB 🔴 +4.61 kB 🔴 +4.12 kB
assets/WidgetRange-TspUbmjn.js (removed) 17.1 kB 🟢 -17.1 kB 🟢 -4.61 kB 🟢 -4.12 kB
assets/load3d-Btai9y69.js (new) 15.8 kB 🔴 +15.8 kB 🔴 +4.6 kB 🔴 +3.97 kB
assets/load3d-C6TrhyfU.js (removed) 15.8 kB 🟢 -15.8 kB 🟢 -4.59 kB 🟢 -3.98 kB
assets/WaveAudioPlayer-B9QrwwsE.js (new) 13.4 kB 🔴 +13.4 kB 🔴 +3.69 kB 🔴 +3.23 kB
assets/WaveAudioPlayer-f9UVoPwl.js (removed) 13.4 kB 🟢 -13.4 kB 🟢 -3.69 kB 🟢 -3.23 kB
assets/WidgetCurve-e8xjnJ18.js (removed) 12.2 kB 🟢 -12.2 kB 🟢 -3.94 kB 🟢 -3.56 kB
assets/WidgetCurve-gtWI1TuO.js (new) 12.2 kB 🔴 +12.2 kB 🔴 +3.93 kB 🔴 +3.56 kB
assets/TeamWorkspacesDialogContent-Dlv5wM6c.js (removed) 11.3 kB 🟢 -11.3 kB 🟢 -3.43 kB 🟢 -3.05 kB
assets/TeamWorkspacesDialogContent-DwsDUe_T.js (new) 11.3 kB 🔴 +11.3 kB 🔴 +3.42 kB 🔴 +3.04 kB
assets/AudioPreviewPlayer-By76-XR1.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -3.13 kB 🟢 -2.81 kB
assets/AudioPreviewPlayer-C6hJ8LAj.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +3.14 kB 🔴 +2.81 kB
assets/nodeTemplates-Bd7eg70l.js (new) 9.84 kB 🔴 +9.84 kB 🔴 +3.48 kB 🔴 +3.06 kB
assets/nodeTemplates-CXEWfRdO.js (removed) 9.84 kB 🟢 -9.84 kB 🟢 -3.48 kB 🟢 -3.08 kB
assets/NightlySurveyController-aNFbFI1Q.js (removed) 9.02 kB 🟢 -9.02 kB 🟢 -3.16 kB 🟢 -2.8 kB
assets/NightlySurveyController-BUIhLvlC.js (new) 9.02 kB 🔴 +9.02 kB 🔴 +3.16 kB 🔴 +2.79 kB
assets/Load3DConfiguration-AehTYCB6.js (removed) 8.03 kB 🟢 -8.03 kB 🟢 -2.37 kB 🟢 -2.06 kB
assets/Load3DConfiguration-BwT1ISDB.js (new) 8.03 kB 🔴 +8.03 kB 🔴 +2.36 kB 🔴 +2.07 kB
assets/InviteMemberDialogContent-BDDwicUA.js (new) 7.94 kB 🔴 +7.94 kB 🔴 +2.53 kB 🔴 +2.23 kB
assets/InviteMemberDialogContent-EQkJS_TD.js (removed) 7.94 kB 🟢 -7.94 kB 🟢 -2.53 kB 🟢 -2.22 kB
assets/onboardingCloudRoutes-CxmfcHNl.js (new) 6.59 kB 🔴 +6.59 kB 🔴 +2.05 kB 🔴 +1.75 kB
assets/onboardingCloudRoutes-Do2msHYT.js (removed) 6.59 kB 🟢 -6.59 kB 🟢 -2.06 kB 🟢 -1.76 kB
assets/CreateWorkspaceDialogContent-BZkFbbDj.js (new) 6.15 kB 🔴 +6.15 kB 🔴 +2.24 kB 🔴 +1.96 kB
assets/CreateWorkspaceDialogContent-ZlhNKt-o.js (removed) 6.15 kB 🟢 -6.15 kB 🟢 -2.24 kB 🟢 -1.95 kB
assets/WidgetWithControl-BPy4vCDS.js (removed) 6.05 kB 🟢 -6.05 kB 🟢 -2.42 kB 🟢 -2.16 kB
assets/WidgetWithControl-BsCGIEBg.js (new) 6.05 kB 🔴 +6.05 kB 🔴 +2.42 kB 🔴 +2.16 kB
assets/FreeTierDialogContent-Bqr3s1kV.js (new) 6.01 kB 🔴 +6.01 kB 🔴 +2.13 kB 🔴 +1.88 kB
assets/FreeTierDialogContent-HDCTaUBf.js (removed) 6.01 kB 🟢 -6.01 kB 🟢 -2.14 kB 🟢 -1.88 kB
assets/EditWorkspaceDialogContent-CxCfNHgA.js (removed) 5.95 kB 🟢 -5.95 kB 🟢 -2.2 kB 🟢 -1.94 kB
assets/EditWorkspaceDialogContent-Dw0f9kSc.js (new) 5.95 kB 🔴 +5.95 kB 🔴 +2.2 kB 🔴 +1.94 kB
assets/WidgetTextarea-BcZxbQAj.js (new) 5.76 kB 🔴 +5.76 kB 🔴 +2.27 kB 🔴 +2.02 kB
assets/WidgetTextarea-BoAkX6p4.js (removed) 5.76 kB 🟢 -5.76 kB 🟢 -2.27 kB 🟢 -2.02 kB
assets/Preview3d-B_zuqCbz.js (new) 5.73 kB 🔴 +5.73 kB 🔴 +1.93 kB 🔴 +1.69 kB
assets/Preview3d-Dj3XUi84.js (removed) 5.73 kB 🟢 -5.73 kB 🟢 -1.93 kB 🟢 -1.68 kB
assets/ValueControlPopover-CYbcpcbY.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -2.02 kB 🟢 -1.79 kB
assets/ValueControlPopover-DzbNI0uW.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +2.02 kB 🔴 +1.79 kB
assets/CancelSubscriptionDialogContent-BZEjswfw.js (new) 5.49 kB 🔴 +5.49 kB 🔴 +2.06 kB 🔴 +1.8 kB
assets/CancelSubscriptionDialogContent-D9YkBd27.js (removed) 5.49 kB 🟢 -5.49 kB 🟢 -2.06 kB 🟢 -1.81 kB
assets/DeleteWorkspaceDialogContent-BsC2poF_.js (new) 4.85 kB 🔴 +4.85 kB 🔴 +1.88 kB 🔴 +1.64 kB
assets/DeleteWorkspaceDialogContent-C2i09E9m.js (removed) 4.85 kB 🟢 -4.85 kB 🟢 -1.88 kB 🟢 -1.63 kB
assets/LeaveWorkspaceDialogContent-BeNZfhpY.js (removed) 4.68 kB 🟢 -4.68 kB 🟢 -1.82 kB 🟢 -1.58 kB
assets/LeaveWorkspaceDialogContent-DGjO65HM.js (new) 4.68 kB 🔴 +4.68 kB 🔴 +1.82 kB 🔴 +1.58 kB
assets/RemoveMemberDialogContent-BFCDvk5Y.js (removed) 4.66 kB 🟢 -4.66 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/RemoveMemberDialogContent-Dqxnffpe.js (new) 4.66 kB 🔴 +4.66 kB 🔴 +1.77 kB 🔴 +1.56 kB
assets/RevokeInviteDialogContent-9ADz8bRr.js (new) 4.57 kB 🔴 +4.57 kB 🔴 +1.79 kB 🔴 +1.57 kB
assets/RevokeInviteDialogContent-Unvei2ml.js (removed) 4.57 kB 🟢 -4.57 kB 🟢 -1.79 kB 🟢 -1.56 kB
assets/InviteMemberUpsellDialogContent-BHAodLkE.js (new) 4.47 kB 🔴 +4.47 kB 🔴 +1.65 kB 🔴 +1.45 kB
assets/InviteMemberUpsellDialogContent-DMuRASAI.js (removed) 4.47 kB 🟢 -4.47 kB 🟢 -1.65 kB 🟢 -1.44 kB
assets/tierBenefits-C3pLxwFJ.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.57 kB 🔴 +1.36 kB
assets/tierBenefits-CWpzOY05.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.57 kB 🟢 -1.36 kB
assets/cloudSessionCookie-B-zd9JaA.js (removed) 4.31 kB 🟢 -4.31 kB 🟢 -1.58 kB 🟢 -1.38 kB
assets/cloudSessionCookie-CutpWdyd.js (new) 4.31 kB 🔴 +4.31 kB 🔴 +1.58 kB 🔴 +1.38 kB
assets/ApiNodesSignInContent-CN6kZMYX.js (new) 4.26 kB 🔴 +4.26 kB 🔴 +1.4 kB 🔴 +1.23 kB
assets/ApiNodesSignInContent-uny2DsxT.js (removed) 4.26 kB 🟢 -4.26 kB 🟢 -1.39 kB 🟢 -1.23 kB
assets/Media3DTop-BBu6Ukr3.js (new) 4.04 kB 🔴 +4.04 kB 🔴 +1.71 kB 🔴 +1.51 kB
assets/Media3DTop-DHhD0vRC.js (removed) 4.04 kB 🟢 -4.04 kB 🟢 -1.71 kB 🟢 -1.51 kB
assets/saveMesh-B0CcZWmf.js (new) 4.03 kB 🔴 +4.03 kB 🔴 +1.76 kB 🔴 +1.56 kB
assets/saveMesh-bQoL-pML.js (removed) 4.03 kB 🟢 -4.03 kB 🟢 -1.76 kB 🟢 -1.56 kB
assets/GlobalToast-B-jjIrrD.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.26 kB 🔴 +1.08 kB
assets/GlobalToast-wCNdjUDO.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.26 kB 🟢 -1.07 kB
assets/CloudRunButtonWrapper-OqY7iSHP.js (new) 2.23 kB 🔴 +2.23 kB 🔴 +1.02 kB 🔴 +911 B
assets/CloudRunButtonWrapper-zEB8aa7R.js (removed) 2.23 kB 🟢 -2.23 kB 🟢 -1.02 kB 🟢 -905 B
assets/SubscribeToRun-ajY8nHBg.js (removed) 2.13 kB 🟢 -2.13 kB 🟢 -979 B 🟢 -865 B
assets/SubscribeToRun-HapF3ybh.js (new) 2.13 kB 🔴 +2.13 kB 🔴 +982 B 🔴 +861 B
assets/MediaAudioTop-AJqrfmAP.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +1.01 kB 🔴 +868 B
assets/MediaAudioTop-DGWXaEo0.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -1.01 kB 🟢 -864 B
assets/cloudBadges-BKDoKA6I.js (removed) 1.96 kB 🟢 -1.96 kB 🟢 -980 B 🟢 -851 B
assets/cloudBadges-D9WEHY83.js (new) 1.96 kB 🔴 +1.96 kB 🔴 +980 B 🔴 +849 B
assets/cloudSubscription-BV4lDp2j.js (new) 1.88 kB 🔴 +1.88 kB 🔴 +900 B 🔴 +777 B
assets/cloudSubscription-CR5M6f4f.js (removed) 1.88 kB 🟢 -1.88 kB 🟢 -901 B 🟢 -777 B
assets/graphHasMissingNodes-Cm_0Qp6b.js (new) 1.83 kB 🔴 +1.83 kB 🔴 +860 B 🔴 +762 B
assets/graphHasMissingNodes-DRhoG1u3.js (removed) 1.83 kB 🟢 -1.83 kB 🟢 -860 B 🟢 -770 B
assets/signInSchema-CxzeUUey.js (new) 1.6 kB 🔴 +1.6 kB 🔴 +586 B 🔴 +548 B
assets/signInSchema-Y8sLcDr_.js (removed) 1.6 kB 🟢 -1.6 kB 🟢 -585 B 🟢 -518 B
assets/Load3D-C75QroVn.js (removed) 1.58 kB 🟢 -1.58 kB 🟢 -709 B 🟢 -632 B
assets/Load3D-CWRpoT6u.js (new) 1.58 kB 🔴 +1.58 kB 🔴 +712 B 🔴 +632 B
assets/previousFullPath-Bp3Akw8q.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -693 B 🟢 -596 B
assets/previousFullPath-QYBsZesL.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +694 B 🔴 +614 B
assets/nightlyBadges-BaX8RCN2.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -749 B 🟢 -684 B
assets/nightlyBadges-Cb6VsLPN.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +746 B 🔴 +654 B
assets/Load3dViewerContent-Dh2kcovI.js (new) 1.46 kB 🔴 +1.46 kB 🔴 +664 B 🔴 +602 B
assets/Load3dViewerContent-eUUjZ92J.js (removed) 1.46 kB 🟢 -1.46 kB 🟢 -663 B 🟢 -601 B
assets/SubscriptionPanelContentWorkspace-C-SXs6mW.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +618 B 🔴 +534 B
assets/SubscriptionPanelContentWorkspace-D8wc1KrD.js (removed) 1.35 kB 🟢 -1.35 kB 🟢 -619 B 🟢 -540 B
assets/WidgetLegacy-geJMsiyE.js (removed) 1.18 kB 🟢 -1.18 kB 🟢 -566 B 🟢 -493 B
assets/WidgetLegacy-lxcZIiiO.js (new) 1.18 kB 🔴 +1.18 kB 🔴 +566 B 🔴 +497 B
assets/changeTracker-Crpuvm-K.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -554 B 🟢 -485 B
assets/changeTracker-CsFk9NMq.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +554 B 🔴 +482 B
assets/i18n-azwffK6r.js (new) 137 B 🔴 +137 B 🔴 +122 B 🔴 +112 B
assets/i18n-DwJZZTtZ.js (removed) 137 B 🟢 -137 B 🟢 -122 B 🟢 -108 B

Status: 62 added / 62 removed / 73 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.8 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 45.6 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.6 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 54.8 MB heap
large-graph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.7 MB heap
large-graph-pan: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.8 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.0 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 61.2 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.0 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 41.3 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 44.9 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 66.6 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 151.2 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 56ms TBT · 166.5 MB heap
workflow-execution: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 52.9 MB heap

No regressions detected.

All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms +0% z=-0.1
canvas-idle: p95 frame time 17ms 17ms +0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 11ms 8ms -29% z=-3.7
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 11 9 -18% z=-3.8
canvas-idle: task duration 343ms 337ms -2% z=-1.8
canvas-idle: script duration 15ms 15ms +0% z=-4.4
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 68.7 MB 67.8 MB -1%
canvas-idle: DOM nodes 22 17 -23% z=-4.4
canvas-idle: event listeners 4 4 +0% z=-1.6
canvas-mouse-sweep: avg frame time 17ms 17ms +0% z=-0.4
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 4ms 3ms -11% z=-1.4
canvas-mouse-sweep: style recalc duration 39ms 35ms -9% z=-2.4
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 73 72 -1% z=-2.8
canvas-mouse-sweep: task duration 812ms 770ms -5% z=-1.6
canvas-mouse-sweep: script duration 126ms 122ms -4% z=-2.1
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 45.6 MB 45.6 MB +0%
canvas-mouse-sweep: DOM nodes -266 -265 -0% z=-126.5
canvas-mouse-sweep: event listeners -133 -133 +0% z=-33.9
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 +1% z=-0.2
canvas-zoom-sweep: style recalc duration 18ms 17ms -2% z=-1.2
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 30 31 +3% z=-0.6
canvas-zoom-sweep: task duration 289ms 285ms -2% z=-1.8
canvas-zoom-sweep: script duration 18ms 18ms -3% z=-3.1
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 46.6 MB 46.6 MB -0%
canvas-zoom-sweep: DOM nodes 75 76 +1% z=-4.1
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms -1%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 6ms 8ms +27% z=-2.2
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 10 11 +10% z=-4.2
dom-widget-clipping: task duration 322ms 325ms +1% z=-2.4
dom-widget-clipping: script duration 59ms 57ms -3% z=-3.2
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 54.7 MB 54.8 MB +0%
dom-widget-clipping: DOM nodes 16 18 +13% z=-2.9
dom-widget-clipping: event listeners 0 0 +0% variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=-0.2
large-graph-idle: p95 frame time 17ms 17ms +1%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 9ms 8ms -16% z=-4.1
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 8 -11% z=-11.5
large-graph-idle: task duration 586ms 522ms -11% z=-0.4
large-graph-idle: script duration 101ms 85ms -17% z=-1.7
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 58.2 MB 64.7 MB +11%
large-graph-idle: DOM nodes -263 -265 +1% z=-320.5
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 -1%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 18ms 18ms -1% z=0.9
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 69 69 +0% z=-0.9
large-graph-pan: task duration 1125ms 1067ms -5% z=-0.3
large-graph-pan: script duration 395ms 391ms -1% z=-0.9
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 64.1 MB 65.8 MB +3%
large-graph-pan: DOM nodes -264 -264 +0% z=-171.5
large-graph-pan: event listeners -127 -127 +0% z=-159.3
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms -1%
large-graph-zoom: layout duration 8ms 7ms -6%
large-graph-zoom: style recalc duration 18ms 18ms -3%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 65 65 +0%
large-graph-zoom: task duration 1393ms 1322ms -5%
large-graph-zoom: script duration 509ms 487ms -4%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 66.1 MB 66.0 MB -0%
large-graph-zoom: DOM nodes -266 -268 +1%
large-graph-zoom: event listeners -125 -125 +0%
minimap-idle: avg frame time 17ms 17ms +0% z=0.1
minimap-idle: p95 frame time 17ms 17ms -0%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 11ms 7ms -30% z=-2.5
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 10 8 -20% z=-2.3
minimap-idle: task duration 531ms 511ms -4% z=-0.4
minimap-idle: script duration 96ms 84ms -12% z=-1.4
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 64.1 MB 61.2 MB -5%
minimap-idle: DOM nodes -262 -266 +2% z=-208.5
minimap-idle: event listeners -129 -129 +0% z=-202.3
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms +0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 12ms 11ms -10% z=-1.9
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 47 46 -2% z=-3.3
subgraph-dom-widget-clipping: task duration 353ms 354ms +0% z=-1.3
subgraph-dom-widget-clipping: script duration 121ms 120ms -1% z=-1.4
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 54.8 MB 55.0 MB +0%
subgraph-dom-widget-clipping: DOM nodes 20 18 -10% z=-3.7
subgraph-dom-widget-clipping: event listeners 6 6 +0% z=-1.7
subgraph-idle: avg frame time 17ms 17ms +0% z=-0.7
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 8ms 8ms +10% z=-2.5
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 9 9 +0% z=-2.9
subgraph-idle: task duration 341ms 359ms +5% z=-0.3
subgraph-idle: script duration 14ms 13ms -1% z=-2.6
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 67.6 MB 41.3 MB -39%
subgraph-idle: DOM nodes 18 18 +0% z=-2.5
subgraph-idle: event listeners 4 4 +0% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=-0.5
subgraph-mouse-sweep: p95 frame time 17ms 17ms +1%
subgraph-mouse-sweep: layout duration 4ms 4ms -4% z=-1.4
subgraph-mouse-sweep: style recalc duration 37ms 36ms -2% z=-1.9
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 75 75 +0% z=-2.7
subgraph-mouse-sweep: task duration 661ms 683ms +3% z=-1.2
subgraph-mouse-sweep: script duration 94ms 92ms -2% z=-1.3
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 59.7 MB 44.9 MB -25%
subgraph-mouse-sweep: DOM nodes 61 -261 -528% z=-146.8
subgraph-mouse-sweep: event listeners 4 -133 -3425% variance too high
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 51ms +0%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 249 250 +0%
viewport-pan-sweep: task duration 3805ms 3691ms -3%
viewport-pan-sweep: script duration 1281ms 1309ms +2%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 69.3 MB 66.6 MB -4%
viewport-pan-sweep: DOM nodes -262 -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 +0%
vue-large-graph-idle: layout duration 0ms 0ms +0%
vue-large-graph-idle: style recalc duration 0ms 0ms +0%
vue-large-graph-idle: layout count 0 0 +0%
vue-large-graph-idle: style recalc count 0 0 +0%
vue-large-graph-idle: task duration 12431ms 12018ms -3%
vue-large-graph-idle: script duration 650ms 577ms -11%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 165.0 MB 151.2 MB -8%
vue-large-graph-idle: DOM nodes -8331 -8331 +0%
vue-large-graph-idle: event listeners -16464 -16464 +0%
vue-large-graph-pan: avg frame time 17ms 17ms -0%
vue-large-graph-pan: p95 frame time 17ms 17ms -1%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 16ms 17ms +5%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 67 67 +0%
vue-large-graph-pan: task duration 14457ms 14468ms +0%
vue-large-graph-pan: script duration 898ms 885ms -1%
vue-large-graph-pan: TBT 0ms 56ms
vue-large-graph-pan: heap used 157.8 MB 166.5 MB +6%
vue-large-graph-pan: DOM nodes -8331 -8331 +0%
vue-large-graph-pan: event listeners -16460 -16488 +0%
workflow-execution: avg frame time 17ms 17ms -0% z=-0.4
workflow-execution: p95 frame time 17ms 17ms +1%
workflow-execution: layout duration 1ms 1ms +2% z=-1.7
workflow-execution: style recalc duration 26ms 22ms -14% z=-1.0
workflow-execution: layout count 5 5 +0% z=0.1
workflow-execution: style recalc count 19 16 -16% z=-0.9
workflow-execution: task duration 124ms 118ms -5% z=-0.5
workflow-execution: script duration 25ms 25ms -3% z=-1.5
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 52.6 MB 52.9 MB +1%
workflow-execution: DOM nodes 157 155 -1% z=-0.8
workflow-execution: event listeners 69 69 +0% z=3.9
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN MB
canvas-zoom-sweep: DOM nodes ▄▃▁▅█▁▃▆▄▅▅▃▃▄▃ ➡️ 79
canvas-zoom-sweep: event listeners ▁▁▂▅█▂▁▅▁▅▅▄▁▅▁ ➡️ 19
dom-widget-clipping: avg frame time ▂▄▅▅▂▄█▇▅▇▇▅▅▁▇ ➡️ 17ms
dom-widget-clipping: p95 frame time ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-05-03T07:15:40.166Z",
  "gitSha": "f371e934e210d91dbccb0fb5ffac6b7c2f171b8c",
  "branch": "glary/workflow-validation-package",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2033.693999999997,
      "styleRecalcs": 5,
      "styleRecalcDurationMs": 4.375999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 382.50700000000006,
      "heapDeltaBytes": -2036996,
      "heapUsedBytes": 45802792,
      "domNodes": -270,
      "jsHeapTotalBytes": 14282752,
      "scriptDurationMs": 15.474000000000002,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-idle",
      "durationMs": 2013.6029999999892,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.044,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 337.199,
      "heapDeltaBytes": 22727148,
      "heapUsedBytes": 71085264,
      "domNodes": 17,
      "jsHeapTotalBytes": 15204352,
      "scriptDurationMs": 14.925,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2018.6619999999493,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.573999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 326.09900000000005,
      "heapDeltaBytes": 23059736,
      "heapUsedBytes": 71714268,
      "domNodes": 18,
      "jsHeapTotalBytes": 14680064,
      "scriptDurationMs": 16.039,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1818.3129999999892,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 35.752,
      "layouts": 12,
      "layoutDurationMs": 3.333,
      "taskDurationMs": 773.424,
      "heapDeltaBytes": 1073556,
      "heapUsedBytes": 49428864,
      "domNodes": -265,
      "jsHeapTotalBytes": 15069184,
      "scriptDurationMs": 128.233,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1779.8699999999599,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 35.125,
      "layouts": 12,
      "layoutDurationMs": 3.013,
      "taskDurationMs": 749.966,
      "heapDeltaBytes": -801068,
      "heapUsedBytes": 47786552,
      "domNodes": -265,
      "jsHeapTotalBytes": 16379904,
      "scriptDurationMs": 120.46300000000001,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1819.613000000004,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 34.92000000000001,
      "layouts": 12,
      "layoutDurationMs": 3.409,
      "taskDurationMs": 769.506,
      "heapDeltaBytes": -815740,
      "heapUsedBytes": 47811876,
      "domNodes": -264,
      "jsHeapTotalBytes": 16642048,
      "scriptDurationMs": 121.95100000000001,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1732.9829999999902,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 16.814000000000004,
      "layouts": 6,
      "layoutDurationMs": 0.5239999999999999,
      "taskDurationMs": 284.75,
      "heapDeltaBytes": 128228,
      "heapUsedBytes": 48499048,
      "domNodes": 76,
      "jsHeapTotalBytes": 14680064,
      "scriptDurationMs": 17.423000000000002,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1717.525999999964,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 17.217999999999996,
      "layouts": 6,
      "layoutDurationMs": 0.6619999999999998,
      "taskDurationMs": 280.37899999999996,
      "heapDeltaBytes": 211220,
      "heapUsedBytes": 48885860,
      "domNodes": 75,
      "jsHeapTotalBytes": 14942208,
      "scriptDurationMs": 17.845,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1736.9529999999713,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 17.468,
      "layouts": 6,
      "layoutDurationMs": 0.6330000000000001,
      "taskDurationMs": 291.432,
      "heapDeltaBytes": 238044,
      "heapUsedBytes": 48861804,
      "domNodes": 77,
      "jsHeapTotalBytes": 14942208,
      "scriptDurationMs": 18.009999999999998,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 592.316000000011,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 7.278000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 370.20400000000006,
      "heapDeltaBytes": 9316648,
      "heapUsedBytes": 58037008,
      "domNodes": 18,
      "jsHeapTotalBytes": 15728640,
      "scriptDurationMs": 65.661,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 509.6080000000143,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.206999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 324.573,
      "heapDeltaBytes": 9101436,
      "heapUsedBytes": 57409308,
      "domNodes": 18,
      "jsHeapTotalBytes": 14942208,
      "scriptDurationMs": 57.28199999999999,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 518.6019999999871,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.105,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 323.299,
      "heapDeltaBytes": 8760856,
      "heapUsedBytes": 57414692,
      "domNodes": 18,
      "jsHeapTotalBytes": 15466496,
      "scriptDurationMs": 57.235,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2058.349000000021,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.9,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 541.015,
      "heapDeltaBytes": 13611968,
      "heapUsedBytes": 71996000,
      "domNodes": -265,
      "jsHeapTotalBytes": 290816,
      "scriptDurationMs": 92.472,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2008.4140000000161,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.909999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 522.466,
      "heapDeltaBytes": 9533924,
      "heapUsedBytes": 67791636,
      "domNodes": -265,
      "jsHeapTotalBytes": 815104,
      "scriptDurationMs": 83.195,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2010.6319999999869,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.813999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 508.71200000000005,
      "heapDeltaBytes": 6748628,
      "heapUsedBytes": 65294832,
      "domNodes": -264,
      "jsHeapTotalBytes": 290816,
      "scriptDurationMs": 84.51299999999999,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2138.0809999999997,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 17.266999999999996,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1067.404,
      "heapDeltaBytes": -1013928,
      "heapUsedBytes": 58524480,
      "domNodes": -267,
      "jsHeapTotalBytes": 1282048,
      "scriptDurationMs": 389.173,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2135.3320000000053,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 17.976999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1100.7659999999998,
      "heapDeltaBytes": 9490524,
      "heapUsedBytes": 68945252,
      "domNodes": -260,
      "jsHeapTotalBytes": 495616,
      "scriptDurationMs": 398.714,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2130.4179999999633,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 18.495,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1058.095,
      "heapDeltaBytes": 23309048,
      "heapUsedBytes": 82672092,
      "domNodes": -264,
      "jsHeapTotalBytes": 5738496,
      "scriptDurationMs": 390.779,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3181.5460000000257,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 17.835,
      "layouts": 60,
      "layoutDurationMs": 7.444999999999999,
      "taskDurationMs": 1342.0939999999998,
      "heapDeltaBytes": 9080588,
      "heapUsedBytes": 69749848,
      "domNodes": -268,
      "jsHeapTotalBytes": 552960,
      "scriptDurationMs": 490.28399999999993,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3135.264999999947,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 17.996,
      "layouts": 60,
      "layoutDurationMs": 7.194000000000001,
      "taskDurationMs": 1321.764,
      "heapDeltaBytes": -6614280,
      "heapUsedBytes": 54112604,
      "domNodes": -269,
      "jsHeapTotalBytes": 552960,
      "scriptDurationMs": 487.08699999999993,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3134.3009999999367,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 18.027,
      "layouts": 60,
      "layoutDurationMs": 6.952,
      "taskDurationMs": 1282.054,
      "heapDeltaBytes": 8327504,
      "heapUsedBytes": 69233740,
      "domNodes": -266,
      "jsHeapTotalBytes": 4747264,
      "scriptDurationMs": 472.35699999999997,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2011.000000000024,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.841000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 515.355,
      "heapDeltaBytes": 3812836,
      "heapUsedBytes": 64158816,
      "domNodes": -264,
      "jsHeapTotalBytes": 552960,
      "scriptDurationMs": 86.714,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "minimap-idle",
      "durationMs": 2012.8290000000106,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.4719999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 510.72700000000003,
      "heapDeltaBytes": 3549720,
      "heapUsedBytes": 63248160,
      "domNodes": -266,
      "jsHeapTotalBytes": 552960,
      "scriptDurationMs": 84.44399999999999,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2020.748000000026,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 6.0440000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 496.2199999999999,
      "heapDeltaBytes": 6088064,
      "heapUsedBytes": 66551016,
      "domNodes": -267,
      "jsHeapTotalBytes": 1077248,
      "scriptDurationMs": 83.148,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 530.5890000000204,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 10.92,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 349.46099999999996,
      "heapDeltaBytes": 8861292,
      "heapUsedBytes": 57533488,
      "domNodes": 18,
      "jsHeapTotalBytes": 15466496,
      "scriptDurationMs": 119.36099999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 513.1980000000453,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 11.306000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 354.042,
      "heapDeltaBytes": 9548396,
      "heapUsedBytes": 58053444,
      "domNodes": 19,
      "jsHeapTotalBytes": 15728640,
      "scriptDurationMs": 119.60200000000002,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 566.2740000000213,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 10.153999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 363.88800000000003,
      "heapDeltaBytes": 9014028,
      "heapUsedBytes": 57716724,
      "domNodes": 16,
      "jsHeapTotalBytes": 15728640,
      "scriptDurationMs": 128.99699999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1999.7869999999978,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.562,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 364.043,
      "heapDeltaBytes": -5216616,
      "heapUsedBytes": 43326624,
      "domNodes": 18,
      "jsHeapTotalBytes": 14544896,
      "scriptDurationMs": 13.492999999999999,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2000.7509999999797,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.461,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 359.182,
      "heapDeltaBytes": -5215612,
      "heapUsedBytes": 43347496,
      "domNodes": 18,
      "jsHeapTotalBytes": 15331328,
      "scriptDurationMs": 13.423999999999998,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1989.4299999999703,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.826,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 317.455,
      "heapDeltaBytes": 22531752,
      "heapUsedBytes": 71252420,
      "domNodes": 18,
      "jsHeapTotalBytes": 14942208,
      "scriptDurationMs": 13.019000000000002,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1707.4029999999993,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 36.189,
      "layouts": 16,
      "layoutDurationMs": 4.252000000000001,
      "taskDurationMs": 657.497,
      "heapDeltaBytes": 14876660,
      "heapUsedBytes": 63029448,
      "domNodes": 60,
      "jsHeapTotalBytes": 14680064,
      "scriptDurationMs": 93.10300000000001,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1691.10500000005,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 35.458999999999996,
      "layouts": 16,
      "layoutDurationMs": 3.7819999999999996,
      "taskDurationMs": 682.5269999999999,
      "heapDeltaBytes": -1592524,
      "heapUsedBytes": 47042040,
      "domNodes": -261,
      "jsHeapTotalBytes": 15069184,
      "scriptDurationMs": 90.12799999999999,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1738.301999999976,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 36.790000000000006,
      "layouts": 16,
      "layoutDurationMs": 4.26,
      "taskDurationMs": 685.263,
      "heapDeltaBytes": -2491776,
      "heapUsedBytes": 46350928,
      "domNodes": -262,
      "jsHeapTotalBytes": 14807040,
      "scriptDurationMs": 92.308,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8199.689999999975,
      "styleRecalcs": 251,
      "styleRecalcDurationMs": 51.471000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3894.0550000000003,
      "heapDeltaBytes": 16679640,
      "heapUsedBytes": 73806180,
      "domNodes": -261,
      "jsHeapTotalBytes": 8884224,
      "scriptDurationMs": 1450.5140000000001,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8164.13,
      "styleRecalcs": 249,
      "styleRecalcDurationMs": 50.358000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3648.6749999999997,
      "heapDeltaBytes": 10526848,
      "heapUsedBytes": 68858916,
      "domNodes": -263,
      "jsHeapTotalBytes": 7311360,
      "scriptDurationMs": 1243.3939999999998,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8147.922999999992,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 50.932,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3690.5909999999994,
      "heapDeltaBytes": 13997232,
      "heapUsedBytes": 69856528,
      "domNodes": -259,
      "jsHeapTotalBytes": 8097792,
      "scriptDurationMs": 1308.7949999999998,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.80000000000109
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12284.96100000001,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12265.722999999998,
      "heapDeltaBytes": -31206548,
      "heapUsedBytes": 172713524,
      "domNodes": -8331,
      "jsHeapTotalBytes": 25751552,
      "scriptDurationMs": 617.283,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11825.895999999942,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11810.464,
      "heapDeltaBytes": -47163360,
      "heapUsedBytes": 151366816,
      "domNodes": -8331,
      "jsHeapTotalBytes": 14741504,
      "scriptDurationMs": 568.875,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12027.885999999966,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12018.012000000002,
      "heapDeltaBytes": -52742704,
      "heapUsedBytes": 158591680,
      "domNodes": -8331,
      "jsHeapTotalBytes": -17502208,
      "scriptDurationMs": 577.458,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14491.194000000007,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 17.22900000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14468.146,
      "heapDeltaBytes": -42491232,
      "heapUsedBytes": 152438448,
      "domNodes": -8335,
      "jsHeapTotalBytes": 61440,
      "scriptDurationMs": 910.4340000000001,
      "eventListeners": -16488,
      "totalBlockingTimeMs": 66,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14607.94599999997,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 19.181999999999977,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14587.408,
      "heapDeltaBytes": -21037952,
      "heapUsedBytes": 174619312,
      "domNodes": -8331,
      "jsHeapTotalBytes": -3170304,
      "scriptDurationMs": 885.288,
      "eventListeners": -16488,
      "totalBlockingTimeMs": 56,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14097.100999999951,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 15.514000000000028,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14074.882999999998,
      "heapDeltaBytes": -18392152,
      "heapUsedBytes": 191307336,
      "domNodes": -8331,
      "jsHeapTotalBytes": 25927680,
      "scriptDurationMs": 854.9830000000001,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "workflow-execution",
      "durationMs": 456.3089999999761,
      "styleRecalcs": 17,
      "styleRecalcDurationMs": 25.498000000000005,
      "layouts": 5,
      "layoutDurationMs": 1.4150000000000003,
      "taskDurationMs": 119.13099999999999,
      "heapDeltaBytes": 5244648,
      "heapUsedBytes": 55442008,
      "domNodes": 164,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 24.586,
      "eventListeners": 69,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "workflow-execution",
      "durationMs": 447.4969999999985,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 21.753,
      "layouts": 5,
      "layoutDurationMs": 1.302,
      "taskDurationMs": 111.34700000000001,
      "heapDeltaBytes": 5014492,
      "heapUsedBytes": 55304568,
      "domNodes": 153,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 22.47199999999999,
      "eventListeners": 69,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "workflow-execution",
      "durationMs": 463.8809999999012,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 21.935,
      "layouts": 5,
      "layoutDurationMs": 1.2489999999999999,
      "taskDurationMs": 117.61100000000002,
      "heapDeltaBytes": 5045664,
      "heapUsedBytes": 56144996,
      "domNodes": 155,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 24.728,
      "eventListeners": 69,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "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: 7

Caution

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

⚠️ Outside diff range comments (1)
scripts/prepare-workflow-validation.js (1)

1-82: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Convert this new build helper to TypeScript to satisfy repo policy.

This PR adds a new .js file under scripts/, but this repository’s rules
disallow introducing JavaScript files.

As per coding guidelines **/*.js: Use TypeScript exclusively, no new JavaScript files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/prepare-workflow-validation.js` around lines 1 - 82, The new script
scripts/prepare-workflow-validation.js must be converted to TypeScript to comply
with the repo policy: create scripts/prepare-workflow-validation.ts (remove the
.js file), keep the same logic and identifiers (__dirname, repoRoot, packageDir,
distDir, workspaceCatalog, resolveCatalog, distPackage), convert CommonJS-ish
patterns to valid TS module code (import fs and path with proper types, type the
resolveCatalog function signature and return values where useful), ensure
JSON.parse and regex usages have correct typings, and update tsconfig.json (or
project build includes) so scripts/*.ts is compiled or allowed; run the script
build/path changes if any CI references the .js path.
🧹 Nitpick comments (1)
packages/workflow-validation/src/linkTopology.test.ts (1)

10-74: ⚡ Quick win

Cover the object-form link contract in this suite.

The new package surface includes both tuple and object link shapes, but every validateLinkTopology() case here exercises only tuple links. Adding one object-form happy-path and one object-form failure case would keep that published branch from drifting untested.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/workflow-validation/src/linkTopology.test.ts` around lines 10 - 74,
Tests only exercise tuple-form links; add two cases using object-form links to
cover the new contract: (1) a happy-path where makeGraph receives links as
objects (e.g., { id, originId, originSlot, targetId, targetSlot, type }) and
assert validateLinkTopology(graph) returns [] and describeTopologyError works as
expected; (2) a failure case (e.g., target-slot-out-of-bounds or
missing-origin-node) constructed with an object-form link and assert the same
error kind and payload shape as the tuple tests. Update linkTopology.test.ts to
include these two new it(...) cases alongside the existing tuple tests,
referencing validateLinkTopology, makeGraph, and describeTopologyError so the
object-shape code paths are exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/workflow-validation/src/linkRepair.ts`:
- Around line 492-496: The code is calling splice with idx even when findIndex
returned -1, which removes the last element; update the block around idx (in
linkRepair.ts where you reference data.deletedLinks[i], idx, and graph.links) to
bail out when idx === -1: log the not-found condition (using logger.log or
logger.error) and skip the splice (e.g., continue or return) so you do not call
(graph.links as Array<unknown>).splice(idx, 1) with a negative index.
- Around line 113-116: The exported repairLinks function currently only accepts
SerialisedGraph but its body still branches on isLiveGraph() and handles
record-shaped graph.links, breaking callers that pass live graphs at compile
time; update the public signature to accept both SerialisedGraph and the live
graph type (e.g., SerialisedGraph | LiveGraph or the shared Graph union used
elsewhere) so callers of repairLinks and fixBadLinks compile, and ensure any
type narrowing inside the function still uses isLiveGraph(graph) before
accessing record-shaped graph.links.

In `@packages/workflow-validation/src/linkTopology.ts`:
- Around line 121-136: The origin-slot bounds check in validateLinkTopology()
bails out with continue after pushing an 'origin-slot-out-of-bounds' error,
which prevents also reporting 'target-slot-out-of-bounds' when both
link.originSlot and link.targetSlot are invalid; update the logic around the
checks that reference link.originSlot, outputs, target.inputs and
link.targetSlot to evaluate both bounds before bailing: test origin bounds and
push the origin-slot-out-of-bounds error if needed, test target bounds and push
the target-slot-out-of-bounds error if needed, then only continue if either
error was emitted so both errors can be recorded for the same link.

In `@scripts/generate-json-schema.ts`:
- Line 57: The final success message in scripts/generate-json-schema.ts
currently uses console.warn('JSON Schemas generated successfully!') which emits
to stderr; change that call to console.log('JSON Schemas generated
successfully!') so successful runs print to stdout instead of appearing as a
warning to CI and callers—update the lone logging statement in the script
accordingly.

In `@scripts/prepare-workflow-validation.js`:
- Around line 13-17: The regex that extracts the catalog into workspaceCatalog
fails when "catalog:" is the last top-level YAML block; update the match used in
scripts/prepare-workflow-validation.js so the capture for workspaceCatalog
allows the block to end at EOF as well as before the next top-level key (e.g.,
use a terminating condition that matches either a following non-indented key or
end-of-file). Change the match expression that assigns workspaceCatalog (the
.match(...) call) to use a pattern that accepts end-of-file (for example by
replacing the final `\n\S` requirement with a non-capturing group that allows
`\n\S` OR end-of-input) so resolveCatalog(...) receives the actual block
content.

In `@src/platform/workflow/validation/composables/useWorkflowValidation.ts`:
- Around line 82-96: The catch block in useWorkflowValidation (handling
repairLinks) currently swallows all exceptions and returns { graph: graphData,
aborted: true }; change it so only LinkRepairAbortedError is handled/converted
to an aborted result (with the existing toastStore and console.error behavior),
while any other unexpected error is re-thrown to propagate the failure to
callers (do not return aborted for non-LinkRepairAbortedError). Ensure you
reference the same symbols (LinkRepairAbortedError, toastStore, graphData,
useWorkflowValidation) and preserve existing logging for the known abort case
before re-throwing other errors.
- Around line 22-29: Replace all hard-coded user-facing strings in
useWorkflowValidation.ts with vue-i18n keys: call useI18n() in the composable
and use t('...') for the overflow text in summariseTopologyErrors (currently
using TOPOLOGY_TOAST_LIMIT), the error count message in reportTopology, and the
toast summary/detail strings used around reportTopology and
describeTopologyError; add corresponding keys and English text to
src/locales/en/main.json (e.g. topology.toast.overflow,
topology.toast.errorCount, topology.toast.summary.*, topology.toast.detail.*) so
the messages are routed through i18n rather than embedded literals.

---

Outside diff comments:
In `@scripts/prepare-workflow-validation.js`:
- Around line 1-82: The new script scripts/prepare-workflow-validation.js must
be converted to TypeScript to comply with the repo policy: create
scripts/prepare-workflow-validation.ts (remove the .js file), keep the same
logic and identifiers (__dirname, repoRoot, packageDir, distDir,
workspaceCatalog, resolveCatalog, distPackage), convert CommonJS-ish patterns to
valid TS module code (import fs and path with proper types, type the
resolveCatalog function signature and return values where useful), ensure
JSON.parse and regex usages have correct typings, and update tsconfig.json (or
project build includes) so scripts/*.ts is compiled or allowed; run the script
build/path changes if any CI references the .js path.

---

Nitpick comments:
In `@packages/workflow-validation/src/linkTopology.test.ts`:
- Around line 10-74: Tests only exercise tuple-form links; add two cases using
object-form links to cover the new contract: (1) a happy-path where makeGraph
receives links as objects (e.g., { id, originId, originSlot, targetId,
targetSlot, type }) and assert validateLinkTopology(graph) returns [] and
describeTopologyError works as expected; (2) a failure case (e.g.,
target-slot-out-of-bounds or missing-origin-node) constructed with an
object-form link and assert the same error kind and payload shape as the tuple
tests. Update linkTopology.test.ts to include these two new it(...) cases
alongside the existing tuple tests, referencing validateLinkTopology, makeGraph,
and describeTopologyError so the object-shape code paths are exercised.
🪄 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: 3ac522b9-cb22-4d81-ad6f-0b40672d8379

📥 Commits

Reviewing files that changed from the base of the PR and between 7abd9d1 and 0eeddb6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (18)
  • .gitignore
  • eslint.config.ts
  • package.json
  • packages/workflow-validation/package.json
  • packages/workflow-validation/src/index.ts
  • packages/workflow-validation/src/linkRepair.ts
  • packages/workflow-validation/src/linkTopology.test.ts
  • packages/workflow-validation/src/linkTopology.ts
  • packages/workflow-validation/src/serialised.ts
  • packages/workflow-validation/src/workflowSchema.ts
  • packages/workflow-validation/tsconfig.json
  • packages/workflow-validation/vite.config.mts
  • scripts/generate-json-schema.ts
  • scripts/prepare-workflow-validation.js
  • src/platform/workflow/validation/composables/useWorkflowValidation.ts
  • src/utils/linkFixer.test.ts
  • tsconfig.json
  • vite.config.mts

Comment thread packages/workflow-validation/src/linkRepair.ts
Comment thread packages/workflow-validation/src/linkRepair.ts
Comment thread packages/workflow-validation/src/linkTopology.ts Outdated
Comment thread scripts/generate-json-schema.ts
Comment thread scripts/prepare-workflow-validation.js Outdated
Comment thread src/platform/workflow/validation/composables/useWorkflowValidation.ts Outdated
Comment thread src/platform/workflow/validation/composables/useWorkflowValidation.ts Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented May 3, 2026

Codecov Report

❌ Patch coverage is 53.37079% with 83 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ow/validation/composables/useWorkflowValidation.ts 1.85% 53 Missing ⚠️
packages/workflow-validation/src/linkRepair.ts 64.61% 23 Missing ⚠️
packages/workflow-validation/src/linkTopology.ts 89.65% 6 Missing ⚠️
packages/workflow-validation/src/workflowSchema.ts 0.00% 1 Missing ⚠️
@@             Coverage Diff             @@
##             main   #11864       +/-   ##
===========================================
- Coverage   71.13%   55.94%   -15.19%     
===========================================
  Files        1490     1384      -106     
  Lines       86009    70722    -15287     
  Branches    23344    19702     -3642     
===========================================
- Hits        61182    39566    -21616     
- Misses      23677    30629     +6952     
+ Partials     1150      527      -623     
Flag Coverage Δ
e2e ?
unit 55.94% <53.37%> (+0.72%) ⬆️

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

Files with missing lines Coverage Δ
packages/workflow-validation/src/workflowSchema.ts 94.87% <0.00%> (ø)
packages/workflow-validation/src/linkTopology.ts 89.65% <89.65%> (ø)
packages/workflow-validation/src/linkRepair.ts 80.08% <64.61%> (ø)
...ow/validation/composables/useWorkflowValidation.ts 1.53% <1.85%> (-73.47%) ⬇️

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

- linkRepair: `continue` on `idx === -1` so we don't `splice(-1, 1)`
  and clobber the last unrelated link.
- linkTopology: report origin- and target-slot-out-of-bounds errors
  independently for the same link instead of bailing after the first.
- useWorkflowValidation: re-throw non-`LinkRepairAbortedError` failures
  so unrelated bugs don't get silently downgraded to an aborted load.
- useWorkflowValidation: route every toast string through
  `vue-i18n` (`validation.topology.*` keys in
  `src/locales/en/main.json`).
- Convert `scripts/prepare-workflow-validation.js` to TypeScript per
  repo policy and run it via `tsx`. Make the catalog regex robust by
  appending a synthetic terminator instead of changing the existing
  `\\n\\S` semantics, which broke for the multiline catalog block.
- Add object-form link tests covering the both-shapes contract.
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

♻️ Duplicate comments (1)
src/platform/workflow/validation/composables/useWorkflowValidation.ts (1)

27-38: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Localize the topology detail text too.

Line 30 feeds describeTopologyError() directly into the toast body, and Line 99 surfaces err.message from the shared package. That means non-English locales will still get English detail text even though the surrounding toast chrome now goes through vue-i18n. Map TopologyError.kind and the abort case to local keys in this composable instead of rendering library strings directly.

As per coding guidelines, "Use vue-i18n for ALL user-facing strings" and "Provide user-friendly and actionable error messages".

Also applies to: 96-100

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/workflow/validation/composables/useWorkflowValidation.ts`:
- Around line 63-70: The code calls repairLinks(graphData as SerialisedGraph,
...) which can mutate its input, but validateWorkflow() later treats that same
graph as the untouched fallback; to fix, create a clone of the serialised graph
(e.g., via a deep-clone utility or structuredClone/JSON deep copy) and pass the
clone into repairLinks so the original graphData remains intact for the
abort/fallback path; update the call site in useWorkflowValidation.ts (the
repairLinks invocation) to use the cloned SerialisedGraph.
🪄 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: 2a78249c-84a5-42f2-a83e-4209aca47099

📥 Commits

Reviewing files that changed from the base of the PR and between 0eeddb6 and 1f795c7.

📒 Files selected for processing (7)
  • packages/workflow-validation/package.json
  • packages/workflow-validation/src/linkRepair.ts
  • packages/workflow-validation/src/linkTopology.test.ts
  • packages/workflow-validation/src/linkTopology.ts
  • scripts/prepare-workflow-validation.ts
  • src/locales/en/main.json
  • src/platform/workflow/validation/composables/useWorkflowValidation.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/workflow-validation/src/linkTopology.test.ts
  • packages/workflow-validation/src/linkTopology.ts
  • packages/workflow-validation/src/linkRepair.ts

christian-byrne added a commit that referenced this pull request May 3, 2026
…lback

repairLinks() mutates its input as it patches links, and can throw
LinkRepairAbortedError after partial mutation. The caller relies on the
original graphData being untouched as the fallback when validateWorkflow()
returns null on abort. Clone via structuredClone before passing to
repairLinks so the fallback contract holds.

Addresses review feedback:
#11864 (comment)
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 3, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 3, 2026
…il strings

- Clone the validated graph before passing it to `repairLinks`. Repair
  is mutating, and after the new re-throw path, an aborted repair would
  leave the caller's graph half-mutated even though
  `validateWorkflow` returns `null` to signal fallback.
- Render every `TopologyError` via `vue-i18n` keys
  (`validation.topology.tuple` plus per-kind templates) in the
  composable, including the abort toast detail and the per-link summary
  lines. The package keeps `describeTopologyError` as the structured
  English form for console logs, CI scripts, and the future backend
  validator.
@glary-bot glary-bot Bot force-pushed the glary/workflow-validation-package branch from 0155a00 to ea2e0fe Compare May 3, 2026 06:55
…ok config

Storybook's vite config does not inherit aliases from vite.config.mts. Add
the @/utils/linkFixer and @/platform/workflow/validation/schemas/workflowSchema
redirects that the package extraction relies on, matching the pattern already
used for shared-frontend-utils.

Fixes the storybook-build CI failure on this branch:
https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/25272069987/job/74096058783
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.

3 participants