Skip to content

fix(featureFlags): resolve linearToggleEnabled through resolveFlag - #15135

Merged
christian-byrne merged 3 commits into
mainfrom
matt/be-7192-linear-toggle-resolve-flag
Aug 22, 2026
Merged

fix(featureFlags): resolve linearToggleEnabled through resolveFlag#15135
christian-byrne merged 3 commits into
mainfrom
matt/be-7192-linear-toggle-resolve-flag

Conversation

@mattmillerai

Copy link
Copy Markdown
Contributor

ELI-5

Nightly builds always turned the linear toggle on, no matter what. That "always on" check ran before the code that looks at ?ff= URL overrides, ff: localStorage overrides, remote config, and the server flag — so on nightly none of those could ever turn it off. Now nightly is the default value fed into the normal resolution chain, so it stays on unless something explicitly says otherwise.

Summary

linearToggleEnabled short-circuited with if (isNightly) return true above its resolveFlag(...) call, so the session-override and dev-override layers (which live inside resolveFlag) were silently ignored on nightly builds. Passing isNightly as resolveFlag's default instead keeps nightly on by default while letting every override layer work.

Changes

  • What: linearToggleEnabled now resolves through resolveFlag(LINEAR_TOGGLE_ENABLED, remoteConfig.value.linear_toggle_enabled, isNightly) with no short-circuit. Tests updated for the new nightly behavior plus three new cases (remote-config false, server-served false, session override false over an enabled remote config).
  • Breaking: none. Off nightly, isNightly is false, which is byte-identical to the previous false default — production and stable behavior is unchanged.

Review Focus

Two intentional behavior deltas, both nightly-only: (1) ?ff=linear_toggle_enabled:false and the ff: localStorage dev override now change the flag, so an employee can reproduce the non-nightly experience; (2) an explicitly-served false from remote config or the server flag now wins over the built-in nightly on. When nothing is served, getServerFeature(LINEAR_TOGGLE_ENABLED, true) returns the true default, so nightly stays on.

The default is deliberately isNightly alone, not isNightly || import.meta.env.DEV as in the neighbouring nodeLibraryEssentialsEnabled getter — this flag has never defaulted on in dev and that is preserved.

Judgment calls: the first existing test asserted expect(api.getServerFeature).not.toHaveBeenCalled(), which pinned the removed short-circuit; it is rewritten to assert the flag still resolves true and that getServerFeature is called with (LINEAR_TOGGLE_ENABLED, true). isNightly = false was added to the session override precedence block's afterEach so the new nightly case there cannot leak into the auth-gated tests that follow.

Verification: all four new/changed tests were confirmed red against the pre-change getter and green after (41 passed in useFeatureFlags.test.ts, 23 in useWorkflowActionsMenu.test.ts — the only non-test consumer). pnpm typecheck, oxfmt and eslint ran clean via the pre-commit hook.

@mattmillerai mattmillerai added the agent-coded Opened by the agent-work code loop label Aug 12, 2026
@mattmillerai
mattmillerai marked this pull request as ready for review August 12, 2026 07:02
@mattmillerai
mattmillerai requested a review from a team August 12, 2026 07:02
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Aug 12, 2026
@mattmillerai mattmillerai added the cursor-review Trigger multi-model Cursor agent review on this PR label Aug 12, 2026
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 08/17/2026, 11:10:58 PM UTC

Links

🎭 Playwright: ✅ 1812 passed, 0 failed · 7 flaky

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

📦 Bundle: 8.85 MB gzip ⚪ 0 B

Details

Summary

  • Raw size: 37.4 MB baseline 37.4 MB — ⚪ 0 B
  • Gzip: 8.85 MB baseline 8.85 MB — ⚪ 0 B
  • Brotli: 6.19 MB baseline 6.19 MB — ⚪ 0 B
  • Bundles: 438 current • 438 baseline

Category Glance
Vendor & Third-Party ⚪ 0 B (16.8 MB) · Other ⚪ 0 B (14.2 MB) · Data & Services ⚪ 0 B (3.52 MB) · Graph Workspace ⚪ 0 B (1.37 MB) · Panels & Settings ⚪ 0 B (566 kB) · Utilities & Hooks ⚪ 0 B (550 kB) · + 5 more

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

Main entry bundles and manifests

Status: 1 unchanged

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

Graph editor runtime, canvas, workflow orchestration

Status: 3 unchanged

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

Top-level views, pages, and routed surfaces

Status: 17 unchanged

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

Configuration panels, inspectors, and settings screens

Status: 26 unchanged

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

Authentication, profile, and account management bundles

Status: 11 unchanged

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

Modals, dialogs, drawers, and in-app editors

Status: 8 unchanged

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

Reusable component library chunks

Status: 14 unchanged

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

Stores, services, APIs, and repositories

Status: 17 unchanged

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

Helpers, composables, and utility bundles

Status: 38 unchanged

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

External libraries and shared vendor chunks

Status: 18 unchanged

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

Bundles that do not match a named category

Status: 285 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.9 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 59.0 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.4 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.6 MB heap
large-graph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 72.9 MB heap
large-graph-pan: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 74.4 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.4 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.1 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.9 MB heap
subgraph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.4 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.2 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 124ms TBT · 86.3 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 78.2 MB heap
vue-large-graph-idle: · 54.5 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 162.4 MB heap
vue-large-graph-pan: · 55.4 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 159ms TBT · 178.7 MB heap
workflow-execution: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.9 MB heap

⚠️ 4 regressions detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-idle: task duration 408ms 516ms +26% ⚠️ z=3.9
canvas-mouse-sweep: layout duration 3ms 5ms +90% ⚠️ z=6.6
subgraph-idle: task duration 412ms 487ms +18% ⚠️ z=3.7
workflow-execution: event listeners 54 99 +83% ⚠️ z=10.8
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms -0% z=-0.5
canvas-idle: p95 frame time 17ms 17ms +0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 6ms 9ms +42% z=-2.4
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 10 10 -5% z=-2.9
canvas-idle: task duration 408ms 516ms +26% ⚠️ z=3.9
canvas-idle: script duration 6ms 7ms +30% z=-8.0
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 67.5 MB 55.9 MB -17%
canvas-idle: DOM nodes -280 -281 +0% z=-238.0
canvas-idle: event listeners -151 -151 +0% z=-34.4
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 3ms 5ms +90% ⚠️ z=6.6
canvas-mouse-sweep: style recalc duration 29ms 41ms +44% z=-0.5
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 72 75 +4% z=-1.6
canvas-mouse-sweep: task duration 684ms 890ms +30% z=0.4
canvas-mouse-sweep: script duration 79ms 107ms +35% z=-4.4
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 58.7 MB 59.0 MB +0%
canvas-mouse-sweep: DOM nodes -278 -282 +1% z=-132.9
canvas-mouse-sweep: event listeners -151 -152 +1% z=-38.5
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=0.5
canvas-zoom-sweep: p95 frame time 17ms 17ms -1%
canvas-zoom-sweep: layout duration 1ms 1ms +25% z=0.7
canvas-zoom-sweep: style recalc duration 12ms 18ms +48% z=-0.6
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 31 31 +0% z=-0.6
canvas-zoom-sweep: task duration 284ms 356ms +25% z=1.2
canvas-zoom-sweep: script duration 8ms 10ms +30% z=-5.7
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 60.9 MB 60.4 MB -1%
canvas-zoom-sweep: DOM nodes 79 77 -3% z=-2.8
canvas-zoom-sweep: event listeners 19 20 +5% z=-0.7
dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms +0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 6ms 7ms +16% z=-3.9
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 12 11 -13% z=-5.2
dom-widget-clipping: task duration 279ms 367ms +32% z=0.2
dom-widget-clipping: script duration 39ms 53ms +34% z=-4.7
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 67.4 MB 67.6 MB +0%
dom-widget-clipping: DOM nodes 20 17 -15% z=-3.6
dom-widget-clipping: event listeners 0 2 variance too high
large-graph-idle: avg frame time 17ms 17ms -0% z=-0.6
large-graph-idle: p95 frame time 17ms 17ms -0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 6ms 7ms +26% z=-4.9
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 504ms 618ms +23% z=1.4
large-graph-idle: script duration 13ms 17ms +27% z=-8.1
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 60.0 MB 72.9 MB +21%
large-graph-idle: DOM nodes -280 -264 -6% z=-318.8
large-graph-idle: event listeners -179 -149 -17% z=-28.7
large-graph-pan: avg frame time 17ms 17ms +0% z=0.3
large-graph-pan: p95 frame time 17ms 17ms +0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 9ms 13ms +45% z=-5.5
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 67 -2% z=-4.8
large-graph-pan: task duration 851ms 1143ms +34% z=1.4
large-graph-pan: script duration 224ms 317ms +42% z=-4.6
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 72.6 MB 74.4 MB +2%
large-graph-pan: DOM nodes -268 -131 -51% z=-90.6
large-graph-pan: event listeners -149 -71 -53% z=-91.1
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms +1%
large-graph-zoom: layout duration 6ms 8ms +35%
large-graph-zoom: style recalc duration 12ms 15ms +24%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 66 64 -4%
large-graph-zoom: task duration 1002ms 1387ms +39%
large-graph-zoom: script duration 278ms 390ms +40%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 65.2 MB 67.4 MB +3%
large-graph-zoom: DOM nodes 10 -281 -2910%
large-graph-zoom: event listeners 8 -89 -1206%
minimap-idle: avg frame time 17ms 17ms +0% z=0.1
minimap-idle: p95 frame time 17ms 17ms -1%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 6ms 8ms +42% z=-1.5
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 10 9 -15% z=-1.6
minimap-idle: task duration 518ms 612ms +18% z=1.8
minimap-idle: script duration 14ms 15ms +7% z=-8.4
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 64.0 MB 65.1 MB +2%
minimap-idle: DOM nodes -281 -277 -2% z=-216.2
minimap-idle: event listeners -179 -163 -9% z=-253.8
subgraph-dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.4
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms +0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 7ms 10ms +42% z=-3.0
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 47 46 -3% z=-4.2
subgraph-dom-widget-clipping: task duration 282ms 387ms +37% z=0.5
subgraph-dom-widget-clipping: script duration 80ms 119ms +49% z=-1.4
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 69.3 MB 68.9 MB -1%
subgraph-dom-widget-clipping: DOM nodes 20 17 -15% z=-4.6
subgraph-dom-widget-clipping: event listeners 6 8 +33% z=-1.4
subgraph-idle: avg frame time 17ms 17ms +0% z=0.4
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 6ms 11ms +81% z=0.6
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 10 10 -5% z=-2.1
subgraph-idle: task duration 412ms 487ms +18% ⚠️ z=3.7
subgraph-idle: script duration 6ms 7ms +13% z=-5.1
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 69.2 MB 60.4 MB -13%
subgraph-idle: DOM nodes -280 -281 +0% z=-202.2
subgraph-idle: event listeners -151 -149 -1% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms -0%
subgraph-mouse-sweep: layout duration 3ms 5ms +42% z=0.1
subgraph-mouse-sweep: style recalc duration 26ms 39ms +48% z=-1.1
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 637ms 818ms +28% z=0.8
subgraph-mouse-sweep: script duration 58ms 87ms +50% z=-2.1
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 57.2 MB 63.2 MB +11%
subgraph-mouse-sweep: DOM nodes -282 -282 -0% z=-155.9
subgraph-mouse-sweep: event listeners -151 -166 +10% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms +0%
subgraph-transition-enter: p95 frame time 17ms 17ms +1%
subgraph-transition-enter: layout duration 10ms 13ms +41%
subgraph-transition-enter: style recalc duration 24ms 30ms +25%
subgraph-transition-enter: layout count 15 14 -7%
subgraph-transition-enter: style recalc count 20 19 -5%
subgraph-transition-enter: task duration 730ms 905ms +24%
subgraph-transition-enter: script duration 13ms 17ms +30%
subgraph-transition-enter: TBT 112ms 124ms +11%
subgraph-transition-enter: heap used 91.4 MB 86.3 MB -6%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2373 2375 +0%
viewport-pan-sweep: avg frame time 17ms 17ms +0%
viewport-pan-sweep: p95 frame time 17ms 17ms +0%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 27ms 44ms +62%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 250 +0%
viewport-pan-sweep: task duration 3054ms 4135ms +35%
viewport-pan-sweep: script duration 705ms 979ms +39%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 79.5 MB 78.2 MB -2%
viewport-pan-sweep: DOM nodes -262 -262 +0%
viewport-pan-sweep: event listeners -133 -133 +0%
vue-large-graph-idle: avg frame time 17ms 18ms +10%
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 11912ms 17827ms +50%
vue-large-graph-idle: script duration 88ms 128ms +46%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 165.5 MB 162.4 MB -2%
vue-large-graph-idle: DOM nodes -8312 -8312 +0%
vue-large-graph-idle: event listeners -16389 -16385 -0%
vue-large-graph-pan: avg frame time 17ms 18ms +5%
vue-large-graph-pan: p95 frame time 17ms 17ms -0%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 14ms 22ms +59%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 85 177 +108%
vue-large-graph-pan: task duration 14962ms 21645ms +45%
vue-large-graph-pan: script duration 374ms 474ms +27%
vue-large-graph-pan: TBT 11ms 159ms +1341%
vue-large-graph-pan: heap used 181.6 MB 178.7 MB -2%
vue-large-graph-pan: DOM nodes -8312 -8312 +0%
vue-large-graph-pan: event listeners -16387 -16380 -0%
workflow-execution: avg frame time 17ms 17ms -0% z=0.1
workflow-execution: p95 frame time 17ms 17ms -1%
workflow-execution: layout duration 1ms 1ms -15% z=-3.3
workflow-execution: style recalc duration 16ms 21ms +32% z=-1.7
workflow-execution: layout count 3 3 +0% z=-3.6
workflow-execution: style recalc count 8 15 +88% z=-1.4
workflow-execution: task duration 95ms 111ms +17% z=-1.1
workflow-execution: script duration 5ms 9ms +76% z=-6.7
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 61.4 MB 62.9 MB +2%
workflow-execution: DOM nodes 148 136 -8% z=-3.6
workflow-execution: event listeners 54 99 +83% ⚠️ z=10.8
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN MB
canvas-zoom-sweep: DOM nodes ▄▃▁▅█▁▃▆▄▅▅▃▃▄▃ ➡️ 79
canvas-zoom-sweep: event listeners ▁▁▂▅█▂▁▅▁▅▅▄▁▅▁ ➡️ 19
dom-widget-clipping: avg frame time ▂▄▅▅▂▄█▇▅▇▇▅▅▁▇ ➡️ 17ms
dom-widget-clipping: p95 frame time ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-08-17T23:22:03.799Z",
  "gitSha": "5e97777ebf66810a18ae0adaffed3335e03cfc45",
  "branch": "matt/be-7192-linear-toggle-resolve-flag",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2087.9249999999843,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.084000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 543.553,
      "heapDeltaBytes": -2791716,
      "heapUsedBytes": 58399504,
      "domNodes": -281,
      "jsHeapTotalBytes": 4972544,
      "scriptDurationMs": 7.759,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-idle",
      "durationMs": 2039.354000000003,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.206,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 488.42500000000007,
      "heapDeltaBytes": -1652536,
      "heapUsedBytes": 58891868,
      "domNodes": -281,
      "jsHeapTotalBytes": 4448256,
      "scriptDurationMs": 7.2,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1917.250000000024,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 45.211,
      "layouts": 12,
      "layoutDurationMs": 6.135,
      "taskDurationMs": 927.703,
      "heapDeltaBytes": 1698068,
      "heapUsedBytes": 62086796,
      "domNodes": -282,
      "jsHeapTotalBytes": 4710400,
      "scriptDurationMs": 108.631,
      "eventListeners": -153,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1830.9689999999819,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 36.763,
      "layouts": 12,
      "layoutDurationMs": 3.686,
      "taskDurationMs": 853.06,
      "heapDeltaBytes": 595240,
      "heapUsedBytes": 61576588,
      "domNodes": -281,
      "jsHeapTotalBytes": 5234688,
      "scriptDurationMs": 105.52,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1731.1530000000062,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 17.997999999999998,
      "layouts": 6,
      "layoutDurationMs": 0.68,
      "taskDurationMs": 355.7710000000001,
      "heapDeltaBytes": 2807316,
      "heapUsedBytes": 62817912,
      "domNodes": 75,
      "jsHeapTotalBytes": 5242880,
      "scriptDurationMs": 9.898,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1736.799000000019,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 18.576,
      "layouts": 6,
      "layoutDurationMs": 0.672,
      "taskDurationMs": 355.711,
      "heapDeltaBytes": 3102064,
      "heapUsedBytes": 63786020,
      "domNodes": 79,
      "jsHeapTotalBytes": 4456448,
      "scriptDurationMs": 10.122,
      "eventListeners": 21,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 601.6949999999497,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 6.655000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 374.936,
      "heapDeltaBytes": 10698968,
      "heapUsedBytes": 71054288,
      "domNodes": 16,
      "jsHeapTotalBytes": 4980736,
      "scriptDurationMs": 52.638,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 565.5029999999215,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 6.931,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 359.776,
      "heapDeltaBytes": 10434080,
      "heapUsedBytes": 70731344,
      "domNodes": 18,
      "jsHeapTotalBytes": 4980736,
      "scriptDurationMs": 52.56,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2071.8610000000126,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.761999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 635.652,
      "heapDeltaBytes": 2303096,
      "heapUsedBytes": 76376732,
      "domNodes": -260,
      "jsHeapTotalBytes": -1839104,
      "scriptDurationMs": 15.89,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2048.930000000041,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 6.346000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 601.0490000000001,
      "heapDeltaBytes": 2358264,
      "heapUsedBytes": 76526376,
      "domNodes": -267,
      "jsHeapTotalBytes": -1576960,
      "scriptDurationMs": 18.416999999999994,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2153.2440000000292,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 14.206000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1181.7150000000001,
      "heapDeltaBytes": 2435820,
      "heapUsedBytes": 77525192,
      "domNodes": -267,
      "jsHeapTotalBytes": -1089536,
      "scriptDurationMs": 329.418,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2097.3960000000034,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 11.569000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1104.4260000000002,
      "heapDeltaBytes": 17098828,
      "heapUsedBytes": 78437556,
      "domNodes": 6,
      "jsHeapTotalBytes": 225280,
      "scriptDurationMs": 305.00500000000005,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3182.372999999984,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 16.43,
      "layouts": 60,
      "layoutDurationMs": 8.806000000000001,
      "taskDurationMs": 1430.9,
      "heapDeltaBytes": -11376936,
      "heapUsedBytes": 64906168,
      "domNodes": -286,
      "jsHeapTotalBytes": 6025216,
      "scriptDurationMs": 391.571,
      "eventListeners": -183,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3147.950000000037,
      "styleRecalcs": 62,
      "styleRecalcDurationMs": 13.262000000000002,
      "layouts": 60,
      "layoutDurationMs": 8.142999999999999,
      "taskDurationMs": 1344.0639999999999,
      "heapDeltaBytes": 14578016,
      "heapUsedBytes": 76389400,
      "domNodes": -276,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 387.91700000000003,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2024.9169999999594,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.639000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 603.4300000000002,
      "heapDeltaBytes": -13233628,
      "heapUsedBytes": 62045420,
      "domNodes": -281,
      "jsHeapTotalBytes": 2879488,
      "scriptDurationMs": 14.501000000000003,
      "eventListeners": -179,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2076.1099999999715,
      "styleRecalcs": 7,
      "styleRecalcDurationMs": 8.019000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 620.688,
      "heapDeltaBytes": -6189720,
      "heapUsedBytes": 74491308,
      "domNodes": -272,
      "jsHeapTotalBytes": 3997696,
      "scriptDurationMs": 14.584000000000003,
      "eventListeners": -147,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 583.8449999999966,
      "styleRecalcs": 45,
      "styleRecalcDurationMs": 9.693,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 390.022,
      "heapDeltaBytes": 11095060,
      "heapUsedBytes": 71680836,
      "domNodes": 16,
      "jsHeapTotalBytes": 5767168,
      "scriptDurationMs": 120.81299999999999,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 591.6889999999739,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 10.032,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 384.06600000000003,
      "heapDeltaBytes": 11556856,
      "heapUsedBytes": 72746884,
      "domNodes": 18,
      "jsHeapTotalBytes": 4980736,
      "scriptDurationMs": 117.658,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2008.831999999984,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.728,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 486.579,
      "heapDeltaBytes": 4109648,
      "heapUsedBytes": 64276228,
      "domNodes": -281,
      "jsHeapTotalBytes": 4972544,
      "scriptDurationMs": 6.714000000000001,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2046.4040000000523,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 13.094000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 487.46999999999997,
      "heapDeltaBytes": 2087644,
      "heapUsedBytes": 62356108,
      "domNodes": -280,
      "jsHeapTotalBytes": 4710400,
      "scriptDurationMs": 6.795000000000003,
      "eventListeners": -149,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1760.340000000042,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 39.751000000000005,
      "layouts": 16,
      "layoutDurationMs": 4.751,
      "taskDurationMs": 836.484,
      "heapDeltaBytes": -1778528,
      "heapUsedBytes": 58462232,
      "domNodes": -280,
      "jsHeapTotalBytes": 4972544,
      "scriptDurationMs": 87.843,
      "eventListeners": -151,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1719.6539999999914,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 37.69799999999999,
      "layouts": 16,
      "layoutDurationMs": 4.706,
      "taskDurationMs": 800.137,
      "heapDeltaBytes": 13230968,
      "heapUsedBytes": 74096176,
      "domNodes": -283,
      "jsHeapTotalBytes": 5758976,
      "scriptDurationMs": 86.78800000000001,
      "eventListeners": -181,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 1383.8980000000447,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 30.418,
      "layouts": 14,
      "layoutDurationMs": 13.454,
      "taskDurationMs": 904.5609999999997,
      "heapDeltaBytes": -4247292,
      "heapUsedBytes": 90448168,
      "domNodes": 13673,
      "jsHeapTotalBytes": 11272192,
      "scriptDurationMs": 17.051,
      "eventListeners": 2375,
      "totalBlockingTimeMs": 124,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8234.563000000036,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 43.108999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4154.527,
      "heapDeltaBytes": 7777136,
      "heapUsedBytes": 81989176,
      "domNodes": -260,
      "jsHeapTotalBytes": -2138112,
      "scriptDurationMs": 985.446,
      "eventListeners": -135,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8191.927999999962,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 44.509,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4114.728,
      "heapDeltaBytes": 7757628,
      "heapUsedBytes": 81914864,
      "domNodes": -264,
      "jsHeapTotalBytes": -1351680,
      "scriptDurationMs": 971.573,
      "eventListeners": -131,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 18670.61799999999,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 17563.728000000003,
      "heapDeltaBytes": -42159380,
      "heapUsedBytes": 163368496,
      "domNodes": -8312,
      "jsHeapTotalBytes": -9904128,
      "scriptDurationMs": 134.58700000000002,
      "eventListeners": -16385,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 18877.266000000076,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 18089.708000000002,
      "heapDeltaBytes": -28280716,
      "heapUsedBytes": 177182468,
      "domNodes": -8312,
      "jsHeapTotalBytes": -13836288,
      "scriptDurationMs": 121.67599999999999,
      "eventListeners": -16385,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 18.890000000000025,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 22326.571999999942,
      "styleRecalcs": 178,
      "styleRecalcDurationMs": 20.29500000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 21722.051,
      "heapDeltaBytes": -35024300,
      "heapUsedBytes": 183884252,
      "domNodes": -8312,
      "jsHeapTotalBytes": -13115392,
      "scriptDurationMs": 414.401,
      "eventListeners": -16381,
      "totalBlockingTimeMs": 107,
      "frameDurationMs": 18.333333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 22226.504999999976,
      "styleRecalcs": 176,
      "styleRecalcDurationMs": 23.68999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 21568.206,
      "heapDeltaBytes": -15276948,
      "heapUsedBytes": 190912028,
      "domNodes": -8312,
      "jsHeapTotalBytes": -14659584,
      "scriptDurationMs": 532.961,
      "eventListeners": -16379,
      "totalBlockingTimeMs": 210,
      "frameDurationMs": 17.780000000000047,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "workflow-execution",
      "durationMs": 471.339999999941,
      "styleRecalcs": 18,
      "styleRecalcDurationMs": 23.714,
      "layouts": 3,
      "layoutDurationMs": 1.5050000000000001,
      "taskDurationMs": 120.21200000000002,
      "heapDeltaBytes": 5276668,
      "heapUsedBytes": 66015480,
      "domNodes": 150,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 11.380999999999998,
      "eventListeners": 99,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "workflow-execution",
      "durationMs": 450.8820000000924,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 17.308999999999997,
      "layouts": 3,
      "layoutDurationMs": 0.642,
      "taskDurationMs": 100.87800000000001,
      "heapDeltaBytes": 4927856,
      "heapUsedBytes": 65856836,
      "domNodes": 121,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 6.953000000000001,
      "eventListeners": 99,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    }
  ]
}

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9d58ae31-da04-4f14-a68c-352941170f46

📥 Commits

Reviewing files that changed from the base of the PR and between 38b07da and 98d77dc.

📒 Files selected for processing (2)
  • src/composables/useFeatureFlags.test.ts
  • src/composables/useFeatureFlags.ts

Included review availability: 0 reviews are currently available. Based on recent review activity, included reviews refill at 1 per hour.


📝 Walkthrough

Walkthrough

The Linear nightly flag now uses resolveFlag with isNightly as its fallback. Tests cover server and remote disabling, session override precedence, API calls, and nightly state cleanup.

Changes

Linear nightly toggle

Layer / File(s) Summary
Resolve nightly Linear defaults
src/composables/useFeatureFlags.ts
linearToggleEnabled now passes isNightly to resolveFlag instead of forcing nightly builds to enabled.
Validate override precedence
src/composables/useFeatureFlags.test.ts
Tests cover server API calls, remote and server disabling, false session overrides, and nightly state cleanup.

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

Merge Risk: ⚪ Minimal · up to 98d77

This localized change preserves nightly behavior by default while allowing explicit overrides to disable the linear toggle; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: dante01yoon


Important

Pre-merge checks failed

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

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
End-To-End Regression Coverage For Fixes ❓ Inconclusive The review context lists changed src files and the description, but it does not provide the PR title or commit subjects required to verify the bug-fix signal. Provide the PR title and commit subjects, then reassess the end-to-end regression coverage criteria.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change to resolve linearToggleEnabled through resolveFlag.
Description check ✅ Passed The description includes the required summary, changes, review focus, behavior details, testing, and validation information.
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.
Website End-To-End Regression Coverage ✅ Passed The PR changes only src/composables/useFeatureFlags.ts and its test; no apps/website/src/ or apps/website/public/ runtime file changed.
Adr Compliance For Entity/Litegraph Changes ✅ Passed The changed files are under src/composables and do not modify src/lib/litegraph/, src/ecs/, or graph entity files.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-7192-linear-toggle-resolve-flag

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

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

Found 4 finding(s).

Severity Count
🟢 Low 3
⚪ Nit 1

Panel: 8/8 reviewers contributed findings.

Comment thread src/composables/useFeatureFlags.test.ts
Comment thread src/composables/useFeatureFlags.test.ts
Comment thread src/composables/useFeatureFlags.ts
Comment thread src/composables/useFeatureFlags.test.ts
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##             main   #15135      +/-   ##
==========================================
+ Coverage   78.97%   80.87%   +1.90%     
==========================================
  Files        2209     1882     -327     
  Lines      111780   109943    -1837     
  Branches    33649    34539     +890     
==========================================
+ Hits        88275    88919     +644     
+ Misses      23057    20625    -2432     
+ Partials      448      399      -49     
Flag Coverage Δ
unit 72.89% <ø> (-0.01%) ⬇️
website-unit ?

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

Files with missing lines Coverage Δ
src/composables/useFeatureFlags.ts 83.33% <ø> (-3.80%) ⬇️

... and 412 files with indirect coverage changes

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

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 12, 2026
@christian-byrne
christian-byrne added this pull request to the merge queue Aug 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Aug 16, 2026

@christian-byrne christian-byrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you fix the merge conflicts?

…oggle-resolve-flag

# Conflicts:
#	src/composables/useFeatureFlags.test.ts
@mattmillerai

Copy link
Copy Markdown
Contributor Author

Merged main and resolved the conflict in useFeatureFlags.test.ts (kept both this PR's linearToggleEnabled tests and main's newer nodeLibraryEssentialsEnabled tests). Typecheck, lint, and useFeatureFlags.test.ts all pass locally. Re-requesting review since the push dismissed the prior approval.

@github-actions github-actions Bot added the risk:R2 PR risk grade (advisory shadow check; grader-owned) label Aug 17, 2026
@christian-byrne christian-byrne removed their assignment Aug 22, 2026
@christian-byrne
christian-byrne added this pull request to the merge queue Aug 22, 2026
Merged via the queue into main with commit 795292d Aug 22, 2026
69 of 70 checks passed
@christian-byrne
christian-byrne deleted the matt/be-7192-linear-toggle-resolve-flag branch August 22, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded Opened by the agent-work code loop cursor-review Trigger multi-model Cursor agent review on this PR risk:R2 PR risk grade (advisory shadow check; grader-owned) size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants