Zusammenfassung der 8 Commits + Beweise (Tests/Check/Build/Smoke), bewusst verschobene Items mit Begruendung pro Item, neu entdeckte und gleich behobene Items, sowie empfohlene Reihenfolge fuer den naechsten Wurf. Adressiert REVIEW-2026-04-18.md, dead-code.md, redundancy.md, structure.md, docs-vs-code.md.
9.0 KiB
Open Issues — Stand nach Review-Fixes
Datum: 2026-04-18 (Nacht-Session)
Branch: review-fixes-2026-04-18
Baseline: REVIEW-2026-04-18.md + 4 Sub-Reports vom Morgen
Tests: 184/184 grün (Baseline waren 158, +26 neue Tests)
svelte-check: 0 Errors, 10 Warnings (alle pre-existing in RecipeEditor.svelte / recipes/[id]/+page.svelte)
Build: npm run build erfolgreich
Smoke-Test: npm run preview + curl auf /api/health, /api/profiles, /api/recipes/abc (400), /api/wishlist mit invalider Body (400 + issues) — alle Endpunkte verhalten sich korrekt
Was wurde gemacht (8 Commits)
| Commit | Inhalt | Verifikation |
|---|---|---|
2289547 |
docs(review): table names, IMAGE_DIR, image endpoints | grep auf alte Namen → 0 |
830c740 |
refactor(constants): SW-Timing-Konstanten, RequestShape/ManifestDiff intern, Image-Endpoint EN | tests + check grün |
739cc2d |
feat(server): api-helpers.ts (parsePositiveIntParam, validateBody, ErrorResponse) | 13 neue Tests |
ff293e9 |
refactor(api): 13 +server.ts handler auf api-helpers (-67 Zeilen netto) | 171/171 |
30a447a |
refactor(client): requireProfile() + asyncFetch wrapper | 5 + 4 Sites umgestellt |
60c8352 |
docs(searxng): Intent-Kommentar fuer Prod-Logs | — |
6d9e79d |
feat(parser): Unicode-Brueche + Mengen-Plausibilitaet | 13 neue Tests |
31c6e5c |
refactor(server): IMAGE_DIR/DATABASE_PATH zentralisieren + Doku-Drift | grep auf alte Pattern → 0 |
Net: 31 Files, +626/-272.
Re-Review per 4 paralleler Explore-Agenten — Beweis
Dead-Code (HIGH-Confidence): Alle vorherigen Findings resolved. RequestShape + ManifestDiff sind nur noch interne Types. yauzl ist explizit als Phase 5b markiert (in session-handoff-2026-04-17.md und ARCHITECTURE.md:33). Kein neuer toter Code durch die Refactors.
Redundancy (HIGH-Confidence): 0 verbleibende function parseId/parsePositiveInt-Definitionen in src/routes/api/. 0 verbleibende safeParse(...) + manueller error(400)-Blöcke. Der gerade behobene IMAGE_DIR-Drift war 6× im Code und 1× in db/index.ts. Verbleibende kleine Pattern siehe unten.
Structure: Constants-Extraktion + API-Error-Shape-Standardisierung erledigt. Ingredient-Parser-Edge-Cases mit 13 Tests abgesichert. Große Pages bleiben groß (siehe „Bewusst verschoben").
Docs-vs-Code: Alle drei Original-Findings behoben. Zwei kleine zusätzliche Mismatches (149→150 Quote-Count, search/-Route gar nicht existent) heute gleich mitgenommen.
⚠ Verbleibende Items — bewusst verschoben mit Begründung
A. Refactor B — Search-State-Store extrahieren (HIGH, halber Tag)
Wo: src/routes/+page.svelte (808 Zeilen, 20+ $state-Vars), src/routes/+layout.svelte (678 Zeilen, dupliziert das Header-Search-Dropdown).
Vorschlag: src/lib/client/search.svelte.ts mit search(), loadMore(), clear() und reaktivem query / hits / loading / error-Zustand.
Warum nicht heute:
- Touch in zwei der drei größten Files der Codebase (808L + 678L)
- Bricht Frontend-Verhalten subtil, wenn Reactive-Glue zwischen Layout-Search und Page-Search nicht 1:1 übernommen wird
- UAT-pflichtig (Live-Suche, Empty-State, Web-Suche-Fallback) — ohne UAT-Slot zu riskant
- Kein automatisches Test-Sicherheitsnetz für die UI-Layer
Empfehlung: Eigene Phase mit /gsd-discuss-phase und Smoke-UAT vor dem Mergen. Anschließend /gsd-execute-phase mit Browser-Check pro Wave.
B. Refactor C — RecipeEditor / RecipeView in Sub-Components zerlegen (MEDIUM, halber Tag)
Wo: src/lib/components/RecipeEditor.svelte (630L), RecipeView.svelte (398L).
Kandidaten: IngredientRow.svelte, StepList.svelte, TimeDisplay.svelte, ImageUploadBox.svelte.
Warum nicht heute:
- REVIEW-2026-04-18.md sagt explizit: "Aber: keine Eile, solange niemand sonst drin arbeitet."
- Solange der Owner allein entwickelt, ist 630L pro Komponente kein Blocker.
- Tests gibt es nur indirekt (über Importer-Tests und Unit-Tests der Parser).
Empfehlung: Spätere Phase, falls eine zweite Person mitarbeitet oder wenn Editor-Bug-Hunting zu schwierig wird. Vorher zumindest die 10 pre-existing svelte-check WARNINGs in RecipeEditor.svelte fixen — die sind schon flackrige Reactive-Patterns ($derived statt $state für abgeleitete Werte).
C. SearXNG Rate-Limit Recovery (MEDIUM, 1-2 h)
Wo: src/lib/server/search/searxng.ts.
Was fehlt: Bei 429/403 wird zwar geloggt, aber kein Backoff oder isStale-Flag. Folgesuchen liefern alten Cache, der User merkt nichts.
Empfehlung: Eigene Phase. Drei mögliche Zutaten: (1) lastFailureAt-Map per Domain, (2) exponentieller Backoff, (3) isStale: boolean im Response, das die UI als „Ergebnisse evtl. veraltet" anzeigt.
D. Service-Worker Zombie-Cleanup unter Last testen (MEDIUM, 2-3 h)
Wo: src/lib/client/pwa.svelte.ts Zombie-Heuristik.
Status: 6 Unit-Tests existieren bereits (tests/unit/pwa-store.test.ts), die beide Pfade abdecken.
Was offen ist: Verhalten unter sehr langsamen Netzen (1500ms-Timeout könnte False-Positive triggern). Sehr edge-case, aber im REVIEW-Original als MEDIUM gelistet.
Empfehlung: Beim nächsten Service-Worker-Touch mit Throttling-DevTools-Profil testen. Kein eigener Sprint nötig.
E. JSON-LD Parser Edge-Cases (MEDIUM, halbe Phase)
Wo: src/lib/server/parsers/json-ld-recipe.ts (402L).
Was abgesichert ist: Ingredient-Parser-Käfer (Unicode-Brüche, Bounds, Komma-Dezimal) sind heute mit 13 neuen Tests dicht.
Was offen ist: JSON-LD selbst hat Edge-Cases — null-Servings, Locale-spezifische Number-Formats, defekte recipeIngredient-Arrays.
Empfehlung: Wenn beim Importieren ein Bug auftaucht, gezielt einen Test schreiben. Kein Vorab-Sprint.
F. Inline UI-Constants (LOW, 30 min)
Wo: ConfirmDialog.svelte, ProfileSwitcher.svelte etc. mit Hardcoded z-index, border-radius: 999px, kleinen Timeouts.
Vorschlag: src/lib/theme.ts mit MODAL_Z_INDEX, POPOVER_Z_INDEX, PILL_RADIUS.
Warum nicht heute: LOW-Severity, kein konkreter Bug damit verbunden, betrifft viele Files punktuell.
G. wishlist/+page.svelte:38 — Profil-Guard mit individueller Message (LOW)
Was: Eine 7. Stelle hat das Profil-Guard-Pattern, aber mit eigenem Text („um mitzuwünschen"). requireProfile() akzeptiert aktuell keine Custom-Message.
Empfehlung: Entweder requireProfile(message?)-Variante einführen oder das Site so lassen — die Custom-Message ist dort wirklich Kontext-Information.
H. RecipeEditor.svelte:54 + :83 — Bild-Upload/Delete mit inline if (!res.ok) (LOW)
Was: Image-Upload und -Delete im Editor nutzen noch das Pattern, das asyncFetch ersetzen sollte. Der Aufwand wäre 5 Minuten, aber RecipeEditor steckt in den 10 svelte-check-WARNINGs (siehe Refactor B-Notiz) — beim nächsten Touch der Datei mitnehmen.
I. Pre-Existing svelte-check Warnings (10 Stück)
Wo: RecipeEditor.svelte (9× Zeilen 28, 97-102, 113, 121) + recipes/[id]/+page.svelte (1× Zeile 43).
Was: Pattern let foo = recipe.bar im Top-Level-Script — Svelte 5 will $derived(recipe.bar). Aktuell snapshot-only.
Risiko: Bei In-Place-Mutation des Rezepts (z. B. nach PATCH) zeigt der Editor ggf. den alten Wert. Tests fangen das nicht.
Empfehlung: Kleine Phase „RecipeEditor auf $derived umstellen" — passt gut zur RecipeEditor-Subkomponentenphase (B oben), oder vorab alleine.
📌 Neu entdeckt in der zweiten Runde — alle behoben
| # | Fund | Severity | Status |
|---|---|---|---|
| 1 | IMAGE_DIR 6× dupliziert + DATABASE_PATH 2× |
HIGH | ✅ src/lib/server/paths.ts |
| 2 | ARCHITECTURE.md:34 — „49 Flachwitze" |
MEDIUM | ✅ → 150 |
| 3 | ARCHITECTURE.md:41 — search/-Route existiert nicht |
LOW | ✅ entfernt |
Empfohlene nächste Schritte
- PR mergen sobald lokal abgenickt — der Branch enthält 8 atomische Commits, jeder einzeln revert-bar.
- Falls UAT erwünscht:
npm run build && npm run preview, dann manuell Profile-Switching, Rezept-Edit, Favoriten-Toggle, Wunschliste, Bild-Upload, Such-Pfade durchklicken. Erwartung: keine Verhaltensänderung gegenübermain. - Phase „RecipeEditor reactive cleanup" für die 10 svelte-check-Warnings (klein) — schließt Item I.
- Phase „Search-State-Store" als nächste größere Phase — schließt Item A und drückt das größte Page-File spürbar runter.
- yauzl/Phase 5b (ZIP-Backup-Restore) bleibt als ungeplant bis explizit gebraucht.
Code-Quality Snapshot
| Metrik | Vorher | Nachher | Δ |
|---|---|---|---|
| Tests gesamt | 158 | 184 | +26 |
| Tests Files | 23 | 24 | +1 (api-helpers) |
| svelte-check Errors | 0 | 0 | — |
| svelte-check Warnings | 10 | 10 | — (alle pre-existing) |
| Build | ✓ | ✓ | — |
| Größte Datei (recipes/[id]/+page.svelte) | 757 | 725 | -32 |
| Größte Datei (+page.svelte) | 808 | 808 | — |
| API +server.ts Boilerplate | ca. 11 Zeilen pro Handler | ca. 4 Zeilen pro Handler | -64% |
| Duplizierte ENV-Defaults | 8 Sites | 1 Site | -7 |