hermes-agent/apps/desktop/src/app
brooklyn! c856f36459
perf(desktop): kill the layout-thrash cascade on session switch (#66033)
Follow-up to #65890 (router transitions off) and #65898 (structural
compare + first-paint budget): profiling the switch path on real 1000+-
message sessions with a new CDP harness showed the remaining freeze is
NOT markdown rendering — it's a forced-reflow cascade from mount-time
layout reads interleaved with style writes across the transcript's
layout effects, plus the first-paint budget cut landing too late to
stop the full-budget commit.

Measured on the two largest local sessions (996 and 1363 messages),
main-thread longtask totals per switch: warm 2450ms -> 557ms and
1158ms -> 194ms; first paint 1690ms -> 444ms. Harness:
scripts/profile-session-switch.mjs (same CDP family as
profile-real-stream.mjs).

- use-resize-observer: drop the synchronous initial callback and ride
  the observer's spec-guaranteed first delivery instead (same frame,
  after layout, before paint). The sync call ran while the commit's
  layout was dirty, so every size read in a callback forced a full
  reflow — with one instance per user bubble (measureClamp read
  scrollHeight, then WROTE --human-msg-full, re-dirtying layout for the
  next bubble), the switch commit thrashed for over a second. Inside RO
  timing the same reads are free. Composer metrics (2x
  getBoundingClientRect + documentElement style writes) rides the same
  fix.
- Same class, same fix at the remaining call sites profiling surfaced:
  ExpandableBlock and TerminalOutput (dozens per tool-heavy transcript)
  now measure/pin via RO initial delivery; the tool-window and
  thinking-preview pins drop their sync pin() call; the thread
  timeline's initial active-tick compute joins its existing
  scroll-time rAF batching so back-to-back transcript updates coalesce.
- thread/list: cut the render budget in the RENDER phase (state-from-
  props adjustment) instead of the post-commit layout effect. The
  effect-time cut was too late — on a warm switch React first built and
  committed the full 300-part tree, then re-rendered at 60, then bumped
  back to 300, so the expensive commit still happened (and on a cold
  switch the bump rAF usually fired while the transcript was still
  empty, so the prefetched messages rendered at full budget anyway).
  The render-phase cut restarts the component before any child renders;
  a second trigger handles the cold path where messages land later
  under the same sessionKey.
- thread/list: backfill 60 -> 300 inside startTransition so the older
  turns' markdown+shiki render is interruptible background work instead
  of a synchronous freeze one frame after the switch paints. Functional
  Math.max so an urgent "Show earlier" click can't be rebased back down.
- composer focus: skip the rAF/timeout focus retries when the element
  is already focused — focus() runs the full focusing steps (forcing
  layout) even on the active element, ~585ms per switch on a large
  dirty DOM.
- Replace the tautological render-budget test (it re-declared the
  constants locally and asserted 60 < 300) with behavior tests of the
  now-exported buildGroups + firstVisibleGroupIndex.

Verification: apps/desktop `npx tsc --noEmit` clean; full
`npx vitest run` 210 files / 1763 passed; manual CDP check confirms the
deferred backfill commits the full transcript, stays pinned to bottom,
and "Show earlier" still pages.
2026-07-16 22:46:08 -04:00
..
agents refactor(desktop): adopt shared utils + app-wide cleanups 2026-07-03 13:48:44 -05:00
artifacts cleanup(desktop): npm run fix for fmtting 2026-07-08 16:24:16 -07:00
chat perf(desktop): kill the layout-thrash cascade on session switch (#66033) 2026-07-16 22:46:08 -04:00
command-center feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
command-palette fmt(js): npm run fix on merge (#65229) 2026-07-15 21:40:56 +00:00
contrib fix(desktop): drain queued prompts for background sessions (#66001) 2026-07-16 20:39:55 -04:00
cron fmt(js): npm run fix on merge (#65229) 2026-07-15 21:40:56 +00:00
gateway/hooks fmt(js): npm run fix on merge (#65912) 2026-07-16 19:57:39 +00:00
hooks feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
learning refactor(desktop): localize settled TODO(i18n) literals (#57924) 2026-07-03 20:43:50 +00:00
messaging feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
overlays feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
pet-generate style(desktop,tui): fix all lint/type/formatting issues 2026-06-26 01:04:33 -05:00
pet-overlay feat(desktop): TikTok-style vibe hearts on a reusable particle system 2026-07-10 05:42:14 -05:00
profiles feat(desktop): Capabilities foundation — shared utils, master-detail, editors, primitives 2026-07-03 05:08:13 -05:00
right-sidebar feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
session fmt(js): npm run fix on merge (#66013) 2026-07-17 00:58:06 +00:00
settings feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
shell feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
skills feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
starmap feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
floating-hud.ts refactor(desktop): adopt shared utils + app-wide cleanups 2026-07-03 13:48:44 -05:00
index.tsx feat(desktop): routes, nav, and command palette as contributions 2026-07-13 17:57:54 -04:00
layout-constants.ts feat(desktop): cap overlay inner-page width at 75rem 2026-07-02 20:40:57 -05:00
master-detail.tsx feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
model-picker-overlay.tsx Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
model-visibility-overlay.tsx feat(desktop): inline model picker in the status bar 2026-06-02 19:09:41 -05:00
page-search-shell.tsx fix(desktop,gateway,mcp): post-merge — CI contract, review corrections, hub search 2026-07-03 15:22:43 -05:00
routes.ts feat(desktop): routes, nav, and command palette as contributions 2026-07-13 17:57:54 -04:00
session-picker-overlay.tsx desktop: registry-driven slash commands + first-class /resume & /handoff (#42351) 2026-06-11 01:49:24 +00:00
session-switcher.tsx fmt(js): npm run fix on merge (#65229) 2026-07-15 21:40:56 +00:00
types.ts feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
updates-overlay.tsx style(desktop): bring the install & update overlays onto the design system 2026-06-30 14:46:28 -05:00