From 2614e6b92d8adfa932fa10cec0657b182816fe73 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 7 Jul 2026 22:13:23 -0400 Subject: [PATCH] docs(todo): add DP1-DP18 discovery-pass findings (agent-surveyed + TPVR-verified) Three discovery agents swept src/ for correctness/a11y/tech-debt issues beyond the tracked backlog; a separate TPVR pass independently confirmed all 18 (5 refined to partial with count/scope corrections). Filed as DP1-DP18 under Open - Actionable. Co-Authored-By: Claude Opus 4.8 --- LOTUS_TODO.md | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/LOTUS_TODO.md b/LOTUS_TODO.md index 81373970a..eb50cb435 100644 --- a/LOTUS_TODO.md +++ b/LOTUS_TODO.md @@ -63,6 +63,129 @@ Built and gate-green; verify per [LOTUS_TESTING.md](./LOTUS_TESTING.md), then gr ## 🔴 Open — Actionable +### 🔍 Discovery pass (2026-07) — agent-surveyed, TPVR-verified + +Three discovery agents swept the fork's own code (`src/`) for correctness / a11y / +tech-debt items beyond the tracked backlog; every item was then independently +re-verified (TPVR, 2026-07) against the code + installed SDK. **All 18 are real** — +`✅` = confirmed as claimed, `◐` = real but the claim was imprecise (correction inline). +`Sev` = user/maintenance impact, `Eff` = S/M/L. IDs `DP1–DP18`. + +**Correctness (user-facing):** + +- [ ] **DP1 — Silent slash-command failures (Sev High · Eff S–M) · ✅.** `RoomInput.tsx:542` + calls `commandContent.exe(plainText)` (all `exe` are async, several reject) with no + `await`/`.catch`, then unconditionally resets the editor as if it succeeded; no global + `unhandledrejection` handler exists. `/kick` `/ban` `/invite` `/join` `/leave` `/ignore` + `/myroomnick` `/acl` `/delete` etc. fail with **zero** feedback. **TPVR context:** `/kick` + & `/ban` also route through `rateLimitedActions` (`utils/matrix.ts:452`) whose `to()` + swallows all non-429 errors — so a real fix must surface errors **per-command**, not just + await line 542. +- [ ] **DP2 — Pending invites re-notify on every reload (Sev Med · Eff S) · ✅.** + `ClientNonUIFeatures.tsx:202-217` + `usePreviousValue(invites.length, 0)` (ref inits `0`). + **TPVR context:** on warm reload the invite atom is populated synchronously from cached + `mx.getRooms()` while the client is already `SYNCING`, so the sync-state gate (`:203`) + doesn't protect → `notify(N)` + sound fire for pre-existing invites. Fix: seed previous to + `invites.length` and/or a first-render ref. +- [ ] **DP3 — Status cleared on another device is resurrected (Sev Med · Eff S) · ✅.** + `Profile.tsx:370` gates on `presence?.status` truthy, so a remote **clear** (falsy) skips + both the input reset and the `localStorage` write; `usePresenceUpdater.readStatus()` + re-sends the stale `status_msg` on the next heartbeat. Fix: treat `status !== undefined` + as an explicit clear + `localStorage.removeItem(STATUS_MSG_KEY)`. +- [ ] **DP4 — Favourite / Low-priority toggles fail silently (Sev Low–Med · Eff S) · ✅.** + `RoomNavItem.tsx:337-351` — `setRoomTag`/`deleteRoomTag` fire-and-forget with no optimistic + UI (state derives from the account-data echo), so a rejected write leaves the menu closed, + no change, no toast. UX-only, bites on failure. +- [ ] **DP5 — Soundboard pack hooks go stale on room/space change (Sev Low · Eff S) · ✅.** + `useSoundboardPacks.ts:80,103,125` — `useState(() => …)` inits once. **TPVR context:** both + consumers usually remount when the room changes so the stale window is narrow, but it's a + real footgun. Fix: derive via `useMemo`/resync effect keyed on the room list. +- [ ] **DP6 — Call-decline event fire-and-forget (Sev Low · Eff S) · ✅.** + `CallEmbedProvider.tsx:547` — uncaught `mx.sendEvent(RTCDecline)`; UI dismisses + unconditionally (`:553`), so a failed decline looks handled locally while the caller keeps + ringing. Content shape verified spec-correct. Fix: best-effort `.catch` + still dismiss. + +**a11y / UX / mobile:** + +- [ ] **DP7 — Deafen button announces the OPPOSITE action to screen readers (Sev High · Eff S) · ✅.** + `call-status/CallControl.tsx:70` — `aria-label={enabled ? 'Undeafen' : 'Deafen'}` is + inverted; the tooltip (`:58`) is the **correct** one. When sound is ON, pressing deafens → + label should say "Deafen". aria-only fix, no visual risk. +- [ ] **DP8 — Sound/Video/ScreenShare toggles missing `aria-pressed` (Sev Med · Eff S) · ✅.** + Only `MicrophoneButton` (`CallControl.tsx:38`) exposes it; `:52,90,131` omit. **TPVR note:** + also pick a consistent pressed-semantics across all four (mic's `aria-pressed={!enabled}` + = "pressed means muted" is debatable). +- [ ] **DP9 — GifPicker drops focus + fixed width overflow (Sev Med · Eff S/M) · ✅ focus / ◐ width.** + `GifPicker.tsx:106` `returnFocusOnDeactivate:false` (+ `initialFocus:false`) drops focus to + `` on dismiss — confirmed. **Correction:** `PICKER_WIDTH=312` is ~314px total and only + overflows *below* ~314 CSS-px or when PopOut positions near a screen edge (not a flat + "≤320px"). Fix: return focus + `min(312px, calc(100vw - 16px))`. +- [ ] **DP10 — Search-filter "clear" icons: redundant mouse-only affordance (Sev Low–Med · Eff S) · ◐.** + `message-search/SearchFilters.tsx:800,826,850` (+ `DateRangeButton:648`) — `` + inside a `Chip`(`