UI stress review for vipirc 0.3.1

1. Mouse events crossing a screen boundary

The released transfer-list handler distinguished only the top-level transfer
screen. An Accept click followed by a queued click at the old Reject position
could dispatch the new receive-review Accept action. The offline reproduction
attempted receive and reported that offline DCC receive is disabled.

The handler now compares the exact Settings and transfer subpanel state, the
current conversation, and pending server switches/closures after every mouse
event. It discards the rest of an old-screen batch when any of these changes.
The state helpers are read-only and do not allocate or alter editor contents.

Live loopback regressions verify zero peer connections and no destination
creation before a fresh receive-review action. Larger queued click floods,
field-editor transitions, choice popups, and conversation/server changes are
also covered. Burst overflow may discard mouse events; it must not authorize
an unreviewed receive or change the newly selected draft.

2. Caret attributes splitting a wide character

Minimal reproduction: enter U+4E2D followed by ABC, select all, press Home,
then select all again. The old renderer applied mvchgat with a length of one
cell even when the caret pointed at a two-cell glyph. Its incremental output
then placed ABC at terminal column 2 instead of column 3 and displaced the
explicit caret highlight. Draft storage and byte counts remained intact.

Chat, Settings, and transfer field renderers now highlight the complete
ed_cluster_width, with a one-cell minimum for an empty/newline caret. This
keeps both cells of a wide character under the same attribute operation.
No UTF-8 storage, message splitting, protocol, or connection behavior changed.

The focused regression performs 48 cell/content/caret checks using CJK and
emoji, selection changes, Home/End, and field-editor reopening. The seeded
editor suite additionally checks the hardware caret position and visible
reverse-video caret cell after every modeled operation, including resizing.

3. Poll-array review

The transport agent fixed the separately discovered low-descriptor failure.
The UI loop now compacts actual IRC descriptors and records each server slot's
poll index. Every existing App still contributes its timeout and receives a
service call even without a descriptor. DCC entries follow the compact IRC
portion. Independent review found the slot mapping, capacity and EINTR paths
consistent with the fixed maximum arrays and existing service semantics.

Evidence

ui-stress-source.patch records UI module changes from the 0.3.0 baseline.
ui-wide-caret-repro-before-fix.json/.log retain the failed visual regression
with its original binary SHA256. ui-wide-caret-fixed.json/.log record the
focused private-build fix verification. Final optimized and sanitizer runs
are recorded separately in ui-stress-final-031.json/.log and
ui-stress-sanitize-final-031.json/.log with their own binary hashes.

Limits

These are actual Linux PTY, offline-simulator and local-loopback tests.
They do not establish native BSD or live SSH compatibility, indefinite
uptime, or equivalence to every terminal emulator. No public IRC service or
real user credentials are used. RSS samples verify the child PPid, NSpid and
executable identity; the sampled memory belongs to vipirc, not its harness.
