Skip to content

Commit f954e2f

Browse files
committed
docs(react-components): multi-perspective review issue list
37 confirmed findings (11 major / 18 minor) from the adversarial component review; the 3 CI-red blockers are fixed, the rest are open follow-ups.
1 parent 88e56be commit f954e2f

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Code-Review: Uncommittete React-Änderungen (`components/react`)
2+
3+
> Multi-Perspektiven-Adversarial-Review (47 Agents: 8 Lenses → Skeptiker pro Finding → Synthese) der 73
4+
> uncommitteten Working-Tree-Änderungen (50 modifiziert + 23 neu). 37/38 Findings bestätigt, 1 verworfen.
5+
> Status: ❌ offen · ✅ behoben · ⁉️ kein echtes Issue. **Diese Änderungen gehören dir (WIP) — der Review ist
6+
> die Bewertung, das Beheben ist deine Entscheidung.**
7+
8+
## Verdict
9+
10+
Funktional weit gediehen, aber **noch nicht commit-reif**. **11 eindeutige MAJOR-Root-Causes** (13 Einträge),
11+
davon drei färben Tooling/CI sofort rot und blockieren/gefährden den `yalc push` an die 7 Konsumenten:
12+
13+
- **TS-1** (`coreActions.ts`): `tsc -p tsconfig.lib.json --noEmit` → 2× `TS2345` (verifiziert). `pnpm build` läuft
14+
durch (`noEmitOnError:false`), aber das typecheck-Gate ist rot.
15+
- **SLOP-1** (`behaviourEntryIntegrity.test.ts`): committeter Harness-Test rot — 30 Failures, davon 7 Map + 12
16+
EmojiPicker aus diesem Changeset (verifiziert).
17+
- **CONV-1** (`iconBadge/Patterns.tsx`): `pnpm lint` rot (verbotene `text-stone-800`).
18+
19+
Zwei echte Laufzeit-/Korrektheitsdefekte: **SLOP-2** (Suche im HistoryPanel für alle übersetzten Actions kaputt),
20+
**SLOP-3** (Undo-Stack-Korruption bei Teilgruppen-Undo → State-Korruption). Dazu A11y-/i18n-Lücken in neuen, an
21+
7 Apps ausgelieferten Komponenten (A11Y-1/-2/-4/-5), Test-Lücken (QA-1/-2/-3) und eine Drag-Perf-Regression (PERF-1).
22+
Keine CRITICAL. Vor dem Commit sollten mindestens alle MAJOR (v. a. die Tooling-Roten) behoben sein.
23+
24+
| Severity | Anzahl |
25+
|----------|--------|
26+
| Critical | 0 |
27+
| Major | 11 |
28+
| Minor | 18 |
29+
30+
---
31+
32+
## Major
33+
34+
### [TS-1] — lib/lib/mowsContext/coreActions.ts:364,374,386,392
35+
`REPLACE_SETTINGS_BLOB` ruft `parseBlobPayload(payload, "...")` ohne Typargument; `P``{}` → an
36+
`replaceBlob(next: SettingsBlob)`. `tsc --noEmit``TS2345` (374,66)/(392,66). **Fix:** `import type { SettingsBlob }`
37+
+ `parseBlobPayload<SettingsBlob>(...)`; mit `tsc -p tsconfig.lib.json --noEmit` verifizieren.
38+
39+
### [SLOP-1] — src/examples/map/MapDocPage.tsx:101-107 + src/examples/emojiPicker/EmojiPickerDocPage.tsx:119-130
40+
`Map.test.tsx`/`EmojiPicker.test.tsx` geändert, aber `<BehaviourList>`-`testLine`-Felder nicht nachgezogen →
41+
`behaviourEntryIntegrity.test.ts` rot. **Fix:** testLine neu ableiten — Map `215→264,220→269,227→276,239→288,254→303,272→321,294→343`;
42+
EmojiPicker alle 12 um +6. (Die 11 `sidebar`-Failures sind pre-existing Drift, nicht dieses Changeset.)
43+
44+
### [CONV-1] — src/examples/iconBadge/Patterns.tsx:45-46
45+
`text-stone-800` (verbotene Neutral-Palette) → `eslint` rot. **Fix:** Farb-Klasse entfernen, einmalig per
46+
Inline-Style (`color:'#1c1917'`) auf dem Wrapper-Div (Lucide erbt `currentColor`); **nicht** `text-foreground`.
47+
48+
### [SLOP-2] — lib/components/appShell/historyPanel/HistoryPanel.tsx:150-157 vs 226-231
49+
Suchfilter matched Roh-`actionId`, angezeigt wird übersetztes `formatActionLabel(...)` → Suche nach sichtbarem Text
50+
findet für alle realen Core-Actions nichts. **Fix:** aufgelöstes Label einmal berechnen, für Suche+Render nutzen;
51+
Regressionstest mit echtem Übersetzungsschlüssel.
52+
53+
### [SLOP-3] — lib/lib/mowsContext/ActionManager.tsx:813-866 (`runInverts`)
54+
Bei Undo einer Transaktionsgruppe: trifft ein Entry ohne registrierten Handler → früher `return`, aber bereits
55+
invertierte Entries werden NICHT vom Stack gepoppt → Undo-Stack inkonsistent → nächstes Ctrl+Z invertiert erneut →
56+
**Dokument-State-Korruption**. **Fix:** Gruppen-Inversion stackseitig atomar machen (invertierte sammeln, vor jedem
57+
frühen `return` poppen + auf Redo schieben); Regressionstests.
58+
59+
### [A11Y-1] — lib/components/map/weatherExpandable/WeatherExpandable.tsx:212-217
60+
`role="region" aria-label` liegt INNERHALB des `<CollapsibleTrigger>`-Buttons → ungültiges ARIA, Screenreader prunen
61+
den einzigen accessible Name. **Fix:** role/aria-label vom Header-Div weg; `regionLabel?`-Passthrough zu
62+
`ExpandableSection`, auf dem äußeren Collapsible-Div setzen.
63+
64+
### [A11Y-2] — lib/components/chat/Chat/Composer.tsx:145-178,270,391-392
65+
Voice/Attachment geben AT keine Rückmeldung: Fehlerzeile (270) ohne `role="alert"`, Recording-Toggle ohne
66+
`aria-live`. WCAG 4.1.3. **Fix:** `role="alert" aria-live="assertive"` auf die Fehlerzeile; `role="status"`-Live-Region
67+
für Recording-State; Strings in beide Locales.
68+
69+
### [A11Y-4] — lib/components/map/Map.tsx:487,539-694
70+
Neuer 3D-Buildings-Toggle + gesamter Control-Stack + `Map failed to load` sind hartkodiertes Englisch; `Map` liest
71+
`context.t` nicht. **Fix:** Übersetzungen via `MowsContext.t` durchreichen (`map`-Sektion in beide Locales);
72+
mindestens die zwei neuen 3D-Labels.
73+
74+
### [A11Y-5] — lib/components/dateTime/scheduler/TimeGridView.tsx:157-220,359-392
75+
Drag-to-Reschedule ist pointer-only — kein Tastatur-Pfad, keine `aria-live`-Ansage. **Fix:** `onKeyDown`
76+
(Arrow nudgt um ±slotMinutes / ±1 Tag, ruft `onItemMove`), Live-Region für neue Zeit; Tests.
77+
78+
### [QA-1] — lib/components/chat/Chat/Composer.tsx:357-383 (Chat.media.test.tsx fehlt)
79+
`enableEmojiPicker` komplett ungetestet (Caret-Insert, `maxBodyLength`-Guard, Focus-Restore). **Fix:** Tests im
80+
`Chat — composer opt-ins`-Block.
81+
82+
### [QA-2] — lib/components/chat/Chat/Chat.tsx:205-294,462-475 (Chat.test.tsx)
83+
Die 3 jüngsten Scroll/Paging-Bugfixes haben keine Regressionstests (`handleScroll``maybeLoadOlder`, `stickyBottom`,
84+
`pendingNewCount`-Pill, `scrollToBottom`-Handle). **Fix:** Tests gegen den realen Outer-Node (AutoSizer gemockt).
85+
86+
### [QA-3] — lib/components/settings/settingsPanel/SettingsPanel.tsx:435-455 (SettingsPanel.test.tsx)
87+
Neue Temperatureinheit-Select treibt `setTemperatureUnit` — kein Test rendert die Zeile/asserted den Aufruf.
88+
**Fix:** Select öffnen+wählen, `setTemperatureUnit`-Aufruf asserten; `WeatherExpandable` Context-Fallback testen.
89+
90+
### [PERF-1] — lib/components/dateTime/scheduler/TimeGridView.tsx:176-220,320-456
91+
Drag rendert die ganze View pro `pointermove` (~60-120Hz): `layoutDayEvents` für alle 7 Spalten + `new
92+
Intl.DateTimeFormat` pro Event pro Frame. **Fix:** Formatter `useMemo([locale])`, `dayLayouts` memoisieren,
93+
`onMove` per rAF-Latch throtteln.
94+
95+
---
96+
97+
## Minor
98+
- **[REACT-1]** Chat.tsx:176-203 — `setMeasured` re-ankert rein positional → async Media-Höhen reißen Nutzer nach unten. Gesten-Latch.
99+
- **[REACT-2]** MowsContext.tsx:597-614 — `setLanguage`/`setTheme` `setState` nach `await` ohne Unmount-Guard.
100+
- **[REACT-3/SLOP-4]** useScheduler.ts:45-67 — `useCallback`-Deps auf Inline-`opts`-Objekt → tote Memoisierung.
101+
- **[REACT-4]** TimeGridView.tsx:176-220 — Pointer-Drag-Effekt re-attached Window-Listener pro Frame.
102+
- **[REACT-5]** Chat.tsx:243 — Auto-Scroll-`requestAnimationFrame` ohne Cleanup/cancel.
103+
- **[REACT-6]** Composer.tsx:100-109 — `useImperativeHandle` ohne Dep-Array.
104+
- **[TS-2]** MowsContext.tsx:73-85 — `adapterToAuthContext` Doppel-Cast `as unknown as AuthContextProps` (5/17 Member) → besiegte Typgarantie. Surface verengen.
105+
- **[TS-3]** EmojiPicker.tsx:120-126 — `readJson<T> as T` ohne Runtime-Check; korrupte `recents` (Nicht-Array) → `.map`-Crash. Validieren.
106+
- **[A11Y-3]** coreActions.ts UNDO/REDO — hartkodiertes `Nothing to undo/redo` (+LOGIN/LOGOUT) im Tooltip.
107+
- **[A11Y-6]** Composer.tsx:286-291 — gestagtes `<video>`/`<audio>` ohne aria-label/Dateiname.
108+
- **[A11Y-7]** WeatherExpandable.tsx:326 — Forecast-Strip ohne `tabIndex`/fokussierbare Kinder → kein Keyboard-Scroll.
109+
- **[A11Y-8]** CoordinateLinks.tsx:98,126 — `Open in`/`default map app` hartkodiertes Englisch im einzigen accessible Name.
110+
- **[QA-4]** ActionManager.tsx:697-725 — Audit-Log-Quota-Eviction-Pfad ungetestet.
111+
- **[QA-5]** scheduler/eventLayout.ts — reine Geometrie (Packing/Clipping/Snap) ohne `eventLayout.test.ts`.
112+
- **[QA-6]** openingHours/OpeningHours.tsx:237-246 — `locale`-aus-Context-Fallback ungetestet.
113+
- **[QA-7]** weatherExpandable/icons.tsx:34-65 — `resolveWeatherLucideIcon` nur 1/12 Mappings getestet (Emoji hat Parity-Test).
114+
- **[PERF-2..7]** Diverse: Intl-Formatter in Render-Loops (calendarMath/Views), O(days×events)-Filter ohne Bucketing/`React.memo`, `MessageRow` nicht memoisiert + inline `itemKey`, `searchEmojis` allokiert Heuhaufen pro Keystroke, `getRecentCommands` sortiert in-place beim Read, `OpeningHours` `week`-useMemo rebaut pro Minute.
115+
116+
## Geprüft & verworfen
117+
- **SEC-1** (CoordinateLinks `buildUrl`): kein Sicherheitsproblem — App-Code im eigenen Trust-Boundary, lat/lng streng validiert, `_blank`+`rel=noopener` neutralisiert `javascript:`. Severity none.
118+
- **SEC-2** (Attachment-URLs in media.tsx/MessageRow): out-of-scope — unverändert ggü. HEAD (bereits in 2c643d07 committet); uncommittete Chat-Änderungen sind XSS-sicher (escaped React-Text).

0 commit comments

Comments
 (0)