hermes-agent/apps/desktop/scripts
Brooklyn Nicholson 2c867b05ce perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins
Driving HER real instance (real profile, real transcripts, streams live)
via CDP instead of synthetic tiles finally exposed the remaining stall.
The timeline on a real 60-frame sash drag:

  style recalc 2736ms | script 1027ms | layout 89ms
  top callsite: pin @ fallback.tsx — 927ms

Two pin-to-bottom ResizeObservers (the bounded tool window's and the
reasoning preview's) pinned on EVERY resize delivery. A sash drag changes
every message's WIDTH once per frame, so each frame ran scrollTop write ->
scrollHeight read across every tool group: a forced write-read reflow
cascade that the render counters could never see (zero React involvement).

Both pins are now height-gated off the RO entry (reflow-free): only
content GROWTH pins. Width-only deliveries return immediately.

Measured on the live app, same drag, before -> after:
  fps      11.5 -> 59-60
  p95      101ms -> 18ms
  slow>33  60/60 -> 1/60

Also in this batch (each was verified live before the next was attempted):
- thread/list: split messageSignature into STRUCTURAL (ids/roles — keys
  boundaries + row identity) and WEIGHT (part counts — budget only), and
  memoize groups + row JSX. A streamed part-append re-rendered every
  turn's boundary via its resetKey prop; explain() measured 540-865
  wasted Block renders per drag/stream sample, now {}.
- message-render-boundary: document the structural-only resetKey contract.
- tool/fallback: memoize ToolFallback's part object + ToolEntry/ToolTitle/
  ToolGlyph (151 renders each, 100% wasted, on real transcripts).
- use-message-stream: ADAPTIVE flush floor — next flush waits 3x the
  measured cost of the last one (33ms floor, 250ms cap), so multi-stream
  load degrades text update rate instead of input latency.
- tree-split: preview sash drags with inline flex on the two seam
  wrappers, committing the store ONCE on release (fixed-zone sides get
  flexBasis only, so a hidden sidebar can't leave a phantom gap).
- debug/: perf-live LoAF long-frame attribution, explain() cascade walker
  with changed-hook indices, diag-real-loop/key-latency/switch-trace
  probes that drive the real app over CDP.

Typing during 2 live streams: keystroke->paint p50 3.3ms, p95 18.4ms,
zero frames over 33ms. Session switch p50 ~35ms settled; the remaining
~1.3s outlier tail is streaming-session switches (React work-loop, not
style/layout) — next target.
2026-07-27 01:07:48 -05:00
..
perf perf(desktop): baseline multitab + render-churn, leave idle-cost report-only 2026-07-26 19:56:56 -05:00
.gitignore feat(desktop): Memory Graph — playable radial timeline of memories + skills 2026-06-30 00:54:21 -05:00
after-pack.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
assert-dist-built.mjs cleanup(desktop): remove 'use strict' in ts & mjs 2026-07-13 17:22:17 -04:00
assert-dist-built.test.mjs test(desktop): run scripts/ tests in vitest 2026-07-13 17:22:17 -04:00
assert-root-install.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
before-build.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
before-pack.mjs fix(windows): verify rebuilt Hermes.exe integrity before shipping it as an update (#69179) 2026-07-24 19:11:35 -07:00
before-pack.test.mjs fix(windows): verify rebuilt Hermes.exe integrity before shipping it as an update (#69179) 2026-07-24 19:11:35 -07:00
bundle-electron-main.mjs fix(desktop): stop using tsx to boot Electron main in dev 2026-07-08 22:40:51 -05:00
click-session.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
dev-mock.mjs feat(desktop/e2e): Playwright E2E suite with visual regression diffs 2026-07-20 11:44:40 -04:00
dev-no-hmr.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
diag-code-live.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
diag-drag-churn.mjs perf(desktop): stop every zone subscribing to the whole layout tree 2026-07-26 16:53:20 -05:00
diag-drag-trace.mjs perf(desktop): share one ResizeObserver instead of one per consumer 2026-07-26 19:56:55 -05:00
diag-jump.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
diag-key-latency.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
diag-live-state.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
diag-real-loop.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
diag-ro-storm.mjs perf(desktop): share one ResizeObserver instead of one per consumer 2026-07-26 19:56:55 -05:00
diag-scroll-reset.mjs fix(desktop): stop chat scroll jumping by disabling native scroll anchoring 2026-06-02 23:08:01 -05:00
diag-sidebar-dom.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
diag-switch-trace.mjs perf(desktop): 60fps sash drag on real sessions — height-gate the RO pins 2026-07-27 01:07:48 -05:00
eval.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
gen-share-codes.ts feat(desktop): Memory Graph — playable radial timeline of memories + skills 2026-06-30 00:54:21 -05:00
notarize-artifact.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
notarize.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
patch-electron-builder-mac-binary.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
probe-model-picker.mjs perf(desktop): add model-picker open-latency probes 2026-07-26 01:10:22 -05:00
probe-renderer.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
probe-thread.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
profile-model-picker.mjs perf(desktop): add model-picker open-latency probes 2026-07-26 01:10:22 -05:00
profile-typing-lag.md bench(desktop): systematized perf harness; sunset 12 one-off scripts (#67466) 2026-07-19 07:41:00 -04:00
rebuild-native.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
reload-renderer.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
reload.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
run-electron-builder.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
set-exe-identity.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
stage-native-deps.mjs fix(desktop): preserve node-pty helper in packaged app (#65611) 2026-07-16 11:58:50 +00:00
stage-native-deps.test.mjs fix(desktop): preserve node-pty helper in packaged app (#65611) 2026-07-16 11:58:50 +00:00
test-desktop.mjs change(ci/desktop): move desktop app build into check job 2026-07-13 17:22:17 -04:00
utils.mjs feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
write-build-stamp.mjs fix(desktop): stop hard-failing pack on non-git checkouts + fix ZIP-path autocrlf (supersedes #67643) (#67730) 2026-07-19 19:29:36 -04:00
write-build-stamp.test.mjs fix(desktop): stop hard-failing pack on non-git checkouts + fix ZIP-path autocrlf (supersedes #67643) (#67730) 2026-07-19 19:29:36 -04:00