The real composer state-engine fix. ChatBar subscribed to the full draft string
(`useAuiState(s => s.composer.text)`), so every keystroke re-rendered the whole
~2k-line component even though the contentEditable DOM already owns the text.
Replace that with:
- an imperative composer-runtime subscription (useComposerRuntime().subscribe)
that mirrors text into draftRef, repaints the editor ONLY on external changes
(clear/restore/insert; the focused editor is the source otherwise), and drives
the debounced per-session stash — all without a React render. This folds the
old `[draft]` sync effect and the `[draft]` debounced-stash effect into one
place keyed off the runtime, surviving core rebinds via the effect dep.
- coarse edge selectors (hasText / isHelpHint / isSteerableText, plus
isEmpty / hasHardNewline in useComposerMetrics) for the chrome, which only
re-render when an edge actually flips.
Net: typing within a line does zero ChatBar re-renders / style invalidations;
work happens only on real edges. Behaviour-preserving — draftRef + editor are
already kept current by every mutation path; verified by the composer DOM repro
tests (enter-submit, IME composition, slash-nav) + text-guard.