Upgrade the MSC3381 poll feature from a leaky half-implementation to a complete,
cross-client-correct one:
- End/close a poll (creator or redact-PL mod) via inline confirm → m.poll.end;
locks voting, reveals results, marks winner(s); only pre-end responses count.
- Honor poll kind: undisclosed polls hide counts/percent/bars/total until ended
(creator gets a Show-live-results vs Hidden-until-ended toggle; default live).
Previously every poll was created undisclosed yet the UI leaked live results.
- Enforce max_selections for multi-choice; radiogroup/checkbox a11y with arrow-key
roving and an AT-announced winner.
- Robust, dual-namespace wire handling: parse BOTH stable (m.poll/m.id/m.selections)
and unstable (org.matrix.msc3381.poll.*) by hand — matrix-js-sdk 41.7.0's
PollStart/Response parsers only understand the unstable bodies, so delegating to
them broke every stable poll (caught in agent review). Use the SDK Poll model only
for end validation + before-end filtering.
- Pure tally/visibility/winner/parse logic extracted to utils/poll.ts with 14 tests
incl. a stable/unstable wire-format round-trip.
Reviewed by 3 agents (spec/cross-client, logic, a11y/UI); findings applied.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>