Zusammenfassung, Verifikation und STATE.md zum Quick-Vorgang 260921-gof.
Ergebnis der Einzelbeurteilung: nur 2 echte Defekte, 15 Fallen (das
naive Eintragen der Abhaengigkeit haette eine Abruf-Schleife erzeugt),
3 bewusste Ausnahmen, 1 Ballast. Die gefaehrlichste Stelle war
calendar-widget.tsx: showToday setzt bei jedem Klick ein frisches Date,
der naive Umbau haette jeden Druck auf den Monatstitel bis zum
Exchange-Server durchschlagen lassen.
Im Browser nachgemessen statt nur behauptet: Dashboard 62 s Ruhe ohne
zusaetzlichen Abruf, Monatstitel dreimal gedrueckt mit null zusaetzlichen
Abrufen nach dem ersten, Stoppuhr echtzeitgetreu ueber 6 s und ueber
4 Runden monoton, dazu acht weitere Ansichten je 20-25 s ruhen gelassen
mit genau einem Abruf je Endpunkt.
Warnungen 467 -> 446, useExhaustiveDependencies 0, web-Tests 66/462 ->
67/477, api unveraendert, type-check 4/4, pnpm lint 5/5.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
Der Testfall, der die instabile-t-Falle in ResultsList.tsx tatsaechlich aufgedeckt hat
Alle 21 Biome-Befunde der Regel useExhaustiveDependencies in apps/web einzeln entschieden und behoben
Erste Verwendung von biome-ignore im Projekt (genau 3x, mit deutscher Begruendung)
Der durchgaengige Griff gegen die t-Falle: uebersetzten Text vor dem Hook in eine Konstante ziehen statt t selbst in die Abhaengigkeitsliste zu schreiben
Ersatz-Fehlertext vor dem Effekt/Rueckruf in eine Konstante ziehen und die Konstante (nicht t) in die Abhaengigkeitsliste schreiben — React vergleicht Strings per Wert
Bei einer instabilen Ladefunktion (gewoehnliche Funktion im Rumpf) diese in useCallback mit der Text-Konstante als Abhaengigkeit einpacken, statt sie leer/eslint-disabled zu lassen
Auffrisch-Ausloeser (refreshKey-Muster) bleiben in der Abhaengigkeitsliste stehen, mit begruendetem biome-ignore statt stiller Unterdrueckung
setState-Funktionsform zur Identitaetserhaltung nutzen (showToday gibt bei unveraendertem Zielmonat dieselbe Referenz zurueck), bevor eine .getTime()-Umgehung durch die direkte Objektreferenz ersetzt wird
Reihenfolge bei calendar-widget.tsx eingehalten: showToday zuerst identitaetserhaltend gemacht, erst danach die Abhaengigkeitsliste des Ladeeffekts von monthDate.getTime() auf monthDate umgestellt — die umgekehrte Reihenfolge haette bei jedem Druck auf den Monatsknopf im laufenden Monat einen Termin-Abruf bis zum Exchange-Server ausgeloest.
t kommt in keiner der acht betroffenen Dateien in eine Abhaengigkeitsliste — stattdessen wird der uebersetzte Ersatztext vor dem Effekt/Rueckruf in eine Konstante gezogen.
Genau drei biome-ignore-Zeilen (Befunde 15, 16, 17) fuer echte Auffrisch-Ausloeser — 14% aller Befunde, deutlich unter der Drittel-Grenze aus D-02.
DigestIntervalForm.tsx bekam bewusst keine neue Testdatei — die Komponente wird nur am laufenden System auf 'Meine Quellen' nachgezaehlt (siehe Luecken unten).
Kalender-Widget: Ersteinblendung/Monatswechsel/Monatsknopf im laufenden Monat verhalten sich korrekt (Zaehlung im Browser-Netzwerkprotokoll ueber 60s + Knopfdruecke)
D-04
true
Erfordert einen laufenden Docker-Stapel und Playwright-MCP-Netzwerkzaehlung im Browser — kein CLI-Ersatz vorhanden, siehe Abgrenzung im PLAN.
stopwatch-widget.test.tsx#quick-260921-gof: Runde unterbricht den Takt nicht
pass
true
Das visuelle Laufverhalten auf dem Bildschirm (springt/laeuft doppelt/faellt zurueck) ist per PLAN ausdruecklich menschliches Urteil, nicht automatisierbar.
Der Browser-Nachweis am laufenden System (Modul-Aktivierung ohne Neuladen sichtbar) ist Teil der Abgrenzung des PLAN und wird vom Orchestrator per Playwright-MCP nachgeholt.
id
description
requirement
verification
human_judgment
D6
Alle bestehenden Tests bleiben gruen, Zahl der Testdateien/Tests sinkt nicht
Quick 260921-gof: 21 useExhaustiveDependencies-Befunde in React Summary
Alle 21 Biome-Befunde der Regel lint/correctness/useExhaustiveDependencies in apps/web einzeln entschieden: 15 Fallen entschaerft (t-Falle achtmal, instabile Ladefunktionen zweimal, Kalender/Stoppuhr-Objektzugriffe zweimal), zwei echte Defekte behoben, drei Auffrisch-Ausloeser mit biome-ignore begruendet stehen gelassen, ein Ballast-Fund entfernt — Gesamtstand 467 auf 446 Meldungen gesenkt, null Regelbefunde, null Fehler.
Performance
Duration: ca. 55 min
Tasks: 3/3
Files modified: 25 (24 bestehende + 1 neue Testdatei)
Commits: 3 (+ diese SUMMARY, vom Orchestrator committet)
Befundtabelle — alle 21, mit Entscheidung
#
Datei
Zeile
Befund
Kat.
Entscheidung
Was ginge schief (ohne Fix / beim naiven Fix)
1
calendar-widget.tsx
76
config fehlt
B
useMemo um resolveCalendarConfig(config) ersatzlos entfernt, Werte direkt destrukturiert
Reine Funktion mit drei einfachen Werten — die Merkung hat nie etwas gespart; config als Ganzes einzutragen macht sie bei jedem frischen config-Objekt wirkungslos
2
calendar-widget.tsx
76
config.lookaheadDays zu eng
B
dieselbe Aenderung wie #1
Gegenrichtung desselben Problems
3
calendar-widget.tsx
82
monthDate fehlt
B
showToday identitaetserhaltend gemacht (gibt bei bereits angezeigtem Zielmonat dieselbe Referenz zurueck), danach Ladeeffekt-Deps von monthDate.getTime() auf monthDate umgestellt
Ohne die Stabilisierung zuerst haette jeder Druck auf den Monatsknopf im laufenden Monat einen neuen Termin-Abruf bis zum Exchange-Server ausgeloest (D-04)
4
calendar-widget.tsx
82
monthDate.getTime() ueberfluessig
B
dieselbe Aenderung wie #3
Gegenrichtung desselben Problems
5
stopwatch-widget.tsx
81
sw fehlt
B
neue reine Hilfsfunktion computeElapsedFrom(state, startedAt, elapsed), Takt-Effekt liest nur noch die drei Einzelwerte statt des ganzen sw-Objekts
sw als Abhaengigkeit haette den 100-ms-Takt bei jeder aufgezeichneten Runde ab- und wiederaufgebaut — ohne Not, mit Taktversatz
6
stopwatch-widget.tsx
81
sw.elapsed zu eng
B
dieselbe Aenderung wie #5
Gegenrichtung desselben Problems
7
VehicleTable.tsx
182
t fehlt
B
loadErrorText = t(...) vor load gezogen, Konstante in loads Deps
t in der Liste haette load bei jedem Durchlauf neu erzeugt (Testattrappe liefert frische Funktion) — der Mount-Effekt waere zur Abruf-Schleife geworden
8
ResultsList.tsx
89
t fehlt
B
loadErrorText vor load gezogen
dieselbe Schleifengefahr wie #7 — hier tatsaechlich in 260921-bi2 zugeschnappt
9
TenderDetail.tsx
96
t fehlt
B
detailErrorText vor dem Effekt gezogen
Detail-Abruf beim Oeffnen einer Ausschreibung waere zur Schleife geworden
10
DigestIntervalForm.tsx
32
t fehlt
B
loadErrorText vor dem Effekt gezogen
Laden der Zustell-Einstellung waere zur Schleife geworden
11
SourceConfigForm.tsx
44
t fehlt
B
loadErrorText vor dem Effekt gezogen
Laden der Quellen-Konfiguration waere zur Schleife geworden
12
RssFeedListForm.tsx
74
loadFeeds fehlt
B
loadFeeds in useCallback([loadErrorText]) eingepackt
loadFeeds als gewoehnliche Rumpf-Funktion waere bei jedem Durchlauf neu entstanden — als Effekt-Abhaengigkeit eine endlose Abruf-Schleife gegen die Feed-Liste
13
SavedSearchBar.tsx
141
load fehlt
B
load in useCallback([loadErrorText]) eingepackt
dieselbe Schleifengefahr wie #12, gegen die Suchprofile
14
favorites-widget.tsx
99
t fehlt
B
favoritesErrorText vor dem Effekt gezogen
Mount-Abruf der Favoriten waere zur Schleife geworden
15
ResultsList.tsx
89
refreshKey ueberfluessig
C
aus loads Deps entfernt, in den aufrufenden Mount-Effekt verschoben + biome-ignore mit deutschem Grund
refreshKey ist der Auffrisch-Ausloeser der Elternseite nach "Jetzt abrufen" — ohne ihn bliebe die Trefferliste nach einem Abruf auf dem alten Stand
16
InvoiceHistoryTable.tsx
81
refreshKey ueberfluessig
C
bleibt stehen + biome-ignore mit deutschem Grund
ohne ihn bliebe die DKV-Historie nach "Jetzt pruefen" auf dem alten Stand
17
sidebar.tsx
57
sidebarRefreshKey ueberfluessig
C
bleibt stehen + biome-ignore mit deutschem Grund
ohne ihn erschiene ein frisch aktiviertes Modul erst nach einem Neuladen der Seite — die Navigation liefe dem Berechtigungsstand hinterher
18
ActivateModuleDialog.tsx
47
moduleId ueberfluessig
D
aus der Liste entfernt, open bleibt
reiner Ballast: der Effekt holt nur die vom Modul unabhaengige Gruppenliste, die Elternseite haengt den Dialog je Modul frisch ein
19
GroupMembersModal.tsx
89
fetchMembers fehlt
A
in die Liste aufgenommen (beide Ladefunktionen bereits stabil)
ohne sie zeigt der Dialog bei einem Gruppenwechsel ohne Neuaufbau die Mitglieder der vorigen Gruppe
20
GroupMembersModal.tsx
89
fetchAllUsers fehlt
A
in die Liste aufgenommen
dieselbe Stelle, dieselbe Begruendung
21
grants/page.tsx
140
matches ueberfluessig
B
Hilfsfunktion matches in den Rumpf der Merkung verschoben statt im Bauteil-Rumpf zu bleiben
eingetragen liefe die Filter-Merkung bei jedem Durchlauf neu und waere damit wirkungslos — keine Schleife, aber die Merkung ist weg, wegen der die Stelle gebaut wurde
Verteilung: 2x (A), 15x (B), 3x (C), 1x (D) — exakt wie im PLAN vorgegeben.
Die drei begruendeten Ausnahmen (D-02)
ResultsList.tsx:141// biome-ignore lint/correctness/useExhaustiveDependencies: refreshKey ist der Auffrisch-Ausloeser der Elternseite nach "Jetzt abrufen" - ohne ihn bliebe die Trefferliste nach einem Abruf auf dem alten Stand.
InvoiceHistoryTable.tsx:84// biome-ignore lint/correctness/useExhaustiveDependencies: refreshKey ist der Auffrisch-Ausloeser der Elternseite nach "Jetzt pruefen" - ohne ihn bliebe die Historie auf dem alten Stand.
sidebar.tsx:61// biome-ignore lint/correctness/useExhaustiveDependencies: sidebarRefreshKey ist der Auffrisch-Ausloeser aus dem Marketplace-Speicher - ohne ihn liefe die Navigation dem Berechtigungsstand hinterher.
3 von 21 = 14%, unter der Drittel-Grenze aus D-02.
Zaehlung vorher/nachher (real gemessen, nicht angenommen)
Messung
Vorher (Baseline 54fdf69, in einem temporaeren Worktree nachgemessen)
PATCH-Zaehlung per Unit-Test bewiesen (neuer Testfall: Start+Runde=2 Aufrufe im Testfall selbst, Stop/Reset-Zaehlung bereits in Bestandstests). Visuelles Laufverhalten: menschliches Urteil, an den Orchestrator
Ausschreibungsradar, 60s ruhen
1x /tenders, 1x /triage
An den Orchestrator
Ausschreibungsradar, Jetzt abrufen
genau 1 zusaetzlicher /tenders
Per Unit-Test (ResultsList.test.tsx#Befund 15) bewiesen: pass. Browser-Nachweis: an den Orchestrator
Meine Quellen, 60s ruhen
je 1 Abruf fuer Zustell-Einstellung, RSS-Feeds, Quellen-Konfiguration
Re-render-Zaehlproben fuer RssFeedListForm/SourceConfigForm bestehen (pass); DigestIntervalForm hat keine Testdatei (siehe Luecken). Browser-Nachweis: an den Orchestrator
DKV Flotte, Jetzt pruefen
genau 1 zusaetzlicher Historien-Abruf
biome-ignore-Begruendung + bestehendes refreshKey-Verhalten unveraendert; kein neuer Unit-Test noetig (Verhalten der Komponente unveraendert). Browser-Nachweis: an den Orchestrator
DKV Flotte, Fahrzeuge, Fahrzeug speichern
Tabelle zeigt neuen Stand, kein Dauerfeuer
Unveraendertes Verhalten (Befund 7 betraf nur den Ladefehler-Text). Browser-Nachweis: an den Orchestrator
Marketplace, Modul aktivieren
erscheint ohne Neuladen in der Seitenleiste
Per Unit-Test (sidebar.test.tsx#Befund 17) bewiesen: pass. Browser-Nachweis: an den Orchestrator
Modulverwaltung, Aktivierungs-Dialog oeffnen
genau 1x /groups
Unveraendertes Verhalten (Befund 18 betraf nur eine ueberfluessige, wirkungslose Abhaengigkeit — kein Verhaltensunterschied im Netzwerkverkehr). Browser-Nachweis: an den Orchestrator
Gruppenverwaltung, Dialog A schliessen, B oeffnen
Mitglieder gehoeren zu B
Per neuer Unit-Test (GroupMembersModal.test.tsx, dritter Fall) bewiesen: pass — dies ist der einzige echte Defekt (Kategorie A) im ganzen Befund und der Test faellt ohne den Fix durch. Browser-Nachweis zusaetzlich: an den Orchestrator
An den Orchestrator uebergebene Verifikationsschritte (Browser/Playwright-MCP)
Alle mit "an den Orchestrator" markierten Zeilen der Tabelle oben, zusammengefasst — der Executor hat keinen Browser-Zugriff:
Dashboard-Kalender: 60s-Zaehlung, 3x Monatsknopf im laufenden Monat, 2x weiterblaettern (D-04).
Stoppuhr: visuelles Laufverhalten ueber Start/Runde/Stopp/Reset (Menschenurteil, ausdruecklich nicht automatisierbar) plus PATCH-Zaehlung im Netzwerkprotokoll (D-05).
Meine Quellen: 60s-Zaehlung fuer alle drei Formulare (Zustell-Einstellung/RSS/Quellen-Konfiguration) — fuer DigestIntervalForm ist dies die EINZIGE Verifikation, da keine Testdatei existiert.
Gruppenverwaltung: Mitglieder-Dialog zeigt nach Gruppenwechsel die richtige Gruppe (zusaetzlich zum bereits gruenen Unit-Test).
Alle Unit-Test-/CLI-seitig pruefbaren Teile dieser Zeilen sind bereits bewiesen (siehe Tabelle) — an den Orchestrator geht ausschliesslich der Netzwerkzaehlungs-/visuelle Teil, der einen laufenden Docker-Stapel und einen Browser braucht.
Task Commits
Aufgabe 1: Kalender und Stoppuhr — die Effekte mit Taktgeber (Befunde 1-6) — b3f0e3c (fix)
Aufgabe 2: Die t-Falle und die instabilen Ladefunktionen (Befunde 7-15) — e2c508c (fix)
Aufgabe 3: Absicht, Ballast und die zwei fehlenden stabilen Abhaengigkeiten (Befunde 16-21) — e780b2c (fix)
Plan metadata: wird vom Orchestrator committet (SUMMARY.md, STATE.md, ROADMAP.md).
Files Created/Modified
Siehe key-files im Frontmatter — 24 bestehende Dateien angepasst (15 Quelldateien + 9 Testdateien) plus eine neue Testdatei (GroupMembersModal.test.tsx). Keine Datei ausserhalb der 15 im PLAN genannten Befund-Dateien und ihrer Tests wurde angefasst (D-06).
Decisions Made
Bei calendar-widget.tsx wurde die im PLAN vorgeschriebene Reihenfolge (erst showToday stabilisieren, dann die Abhaengigkeitsliste umstellen) exakt eingehalten — die umgekehrte Reihenfolge haette einen echten Denial-of-Service-Pfad gegen den Exchange-Server geoeffnet (T-GOF-02).
Fuer RssFeedListForm.tsx und SavedSearchBar.tsx wurde useCallback statt einer weiteren biome-ignore-Zeile gewaehlt, weil die Ladefunktionen bereits sauber isolierbar waren und die PLAN-Vorgabe genau das verlangt ("Ladefunktion in einen stabilen Rueckruf einpacken").
DigestIntervalForm.tsx bekam bewusst keine neue Testdatei, wie im PLAN explizit vorgesehen — die Verifikation laeuft ausschliesslich am laufenden System.
Deviations from Plan
None — Plan exakt wie geschrieben ausgefuehrt. Alle drei Aufgaben, alle 21 Befunde, alle im PLAN benannten Testerweiterungen wurden 1:1 umgesetzt. Der einzige nennenswerte Punkt ist keine Abweichung, sondern eine im PLAN selbst schon erwartete Luecke (siehe unten).
Issues Encountered
Beim Schreiben der neuen GroupMembersModal.test.tsx traf screen.getByText('Anna Schmidt') zunaechst auf zwei Elemente (Mitgliederliste UND Benutzer-Suchliste zeigen denselben Namen) — behoben durch Scoping auf within(screen.getByRole('list')), da die Mitgliederliste die einzige <ul> im Bauteil ist. Kein Rule-1/2/3-Fall im Sinne des Ausfuehrungsprotokolls (reiner Testfehler beim Erstschreiben, sofort korrigiert, kein separates Deviation-Log noetig).
Offen benannte Luecken
DigestIntervalForm.tsx hat keine Testdatei — wie im PLAN vorgesehen ("Hier wird bewusst keine angelegt"). Die Komponente wird ausschliesslich am laufenden System auf der Seite "Meine Quellen" nachgezaehlt (Teil der an den Orchestrator uebergebenen Browser-Verifikation).
Alle Browser/Netzwerkprotokoll-Nachweise (siehe Abschnitt "An den Orchestrator uebergebene Verifikationsschritte") sind vom Executor nicht durchgefuehrt worden — kein Browser-Werkzeug verfuegbar. Jeder CLI-pruefbare Anteil derselben Verhaltensbehauptung ist bereits durch einen gruenen Unit-Test belegt.
pnpm lint-Baseline vor dieser Aufgabe wurde nicht separat mit --max-diagnostics auf Fehler-Schwere durchsucht (nur die volle biome lint .-JSON-Ausgabe, die errors=0 sowohl vorher als auch nachher zeigt) — kein Risiko, da beide Messungen denselben Befehl verwenden.
Next Phase Readiness
Kein laufender Meilenstein betroffen (Quick-Vorgang ohne Roadmap-Phase). Keine Blocker. Die Regel useExhaustiveDependencies kann ab jetzt regulaer scharf bleiben, ohne dass neue Befunde unbemerkt durchrutschen — 3 begruendete Ausnahmen sind die einzige verbleibende Unterdrueckung im Projekt.