Files
buzz/desktop/src/features/huddle
5743562896 fix(huddle): stop 20 Hz speaker-level churn from re-rendering the whole app (#5825)
## Problem

With a huddle open, Buzz Desktop becomes extremely slow and laggy
(Tyler, live report, 2026-08-14). Root-caused and runtime-convicted on
the instrumented rig in #buzz-conversational-agents:

- The Rust playout loop emits `huddle-speaker-levels` over Tauri IPC
every 50 ms, unconditionally, for the whole life of a huddle
(`playout.rs` `SPEAKER_LEVEL_TICK_MS = 50`).
- Each event deserializes to a fresh object, so `setRemoteSpeakerLevels`
updates state at 20 Hz even in silence.
- `HuddleProvider` wraps the entire main app and its context value was
an inline object literal — never memoized. Every level tick minted a new
context identity, re-rendering **every** `useHuddle()` consumer,
including `ChannelScreen` and message rows.

**Measured (A/B, silent one-participant huddle, same channel/state):**
~41 sustained ChannelScreen renders/sec unsuppressed vs ~4/sec with only
the speaker-level setState suppressed — the 20 Hz path is ~90% of the
load. Receipts: `driver-render-counter-unsuppressed.jsonl` /
`-suppressed.jsonl` on the rig, verified independently. The same
main-thread churn starves the relay client's 16 ms event-flush timer,
which is the delayed/bursty message hydration and thread-panel stalls
seen alongside the lag.

## Fix (minimal, no behavior change for meters)

1. **Split the high-frequency fields** (`micLevel`, `activeSpeakers`,
`speakerLevels`) out of `HuddleContextValue` into a new
`HuddleLevelsContext`, consumed via `useHuddleLevels()` only by the
three meter components (`HuddleBar`, `HuddleRoomHeader`,
`HuddleProfileControl`).
2. **Memoize the main context value** so provider re-renders no longer
mint a new identity for the ~everything that consumes `useHuddle()`.
3. **Extract the mic-level analyser** into `useMicLevelAnalyser` — the
level pipeline now lives in one place, and `HuddleContext.tsx` stays
under the file-size ratchet (977 lines).

Level meters keep their 20-30 Hz updates. Everything else re-renders
only when a value it actually consumes changes.

## Acceptance bar

With this fix, a silent open huddle should hold `ChannelScreen` at idle
render rates (single digits/sec), and message hydration should stay live
during huddles. The rig's render-counter + four-clock instrumentation
can verify on this branch.

## Validation

- `pnpm typecheck` clean
- `biome check` clean (repo leftovers in sidebar tests are preexisting
on main)
- full desktop suite: **4,775 passed, 0 failed** at the final tree
- file-size ratchet passes (was the reason for the analyser extraction)
- lefthook pre-commit (desktop-fix + signoff) passed on commit

Not yet done: live-local A/B rerun on this branch — the rig (Wren/Max)
has the instrumentation ready and can convict/acquit the fix with the
same probe that convicted the bug.

Base: `068a83b0` (main). Co-developed with runtime evidence from Wren
and instrumentation by Max.

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
2026-08-13 22:26:59 -04:00
..