mitai-jinkendo/.claude/rules/LESSONS_LEARNED.md

201 lines
6.7 KiB
Markdown
Raw Permalink Normal View History

# Lessons Learned
Fehler die gemacht wurden – damit sie nicht wiederholt werden.
## 1. Feature-Enforcement Rollback (20.03.2026)
**Was:** Membership-System Feature-Enforcement implementiert
**Problem:** Brach Analyse-Verlauf, Export-Sichtbarkeit und Zähler
**Rollback:** Commit 4fcde4a
**Lösung:** Einfaches ai_enabled + ai_limit_day System aktiv
**Regel:** Feature-Enforcement nie ohne vollständige Test-Suite aktivieren.
Zuerst Shadow-Mode (loggen aber nicht blockieren), dann schrittweise aktivieren.
## 2. session=Depends(require_auth) innerhalb Header()
**Was:** Automatisches Einfügen von Auth in bestehende Endpoints
**Problem:** `session` wurde innerhalb `Header(default=None, session=...)` eingebettet
**Folge:** FastAPI ignorierte Auth stillschweigend – Endpoint ungeschützt
**Lösung:** session immer als separater Parameter
```python
# ❌ Was passiert ist:
def endpoint(x: str = Header(default=None, session=Depends(require_auth))):
# ✅ Korrekt:
def endpoint(x: str = Header(default=None), session: dict = Depends(require_auth)):
```
## 3. PostgreSQL Migration – apt-get Probleme
**Was:** Docker Build mit apt-get postgresql-client
**Problem:** Build hing 30+ Minuten
**Lösung:** Reine Python-Lösung mit psycopg2-binary, kein apt-get
## 4. SQLite → PostgreSQL Datenmigration
**Probleme:**
- Leere date-Strings (`''`) → PostgreSQL wirft Fehler → zu NULL konvertieren
- Boolean: SQLite `0/1` → PostgreSQL `true/false`
- `?` Platzhalter → `%s`
## 5. dayjs.week() Plugin fehlt
**Was:** dayjs().week() ohne isoWeek-Plugin aufgerufen
**Problem:** Weißer Screen auf Verlauf/Ernährung
**Lösung:** Native ISO-Wochenberechnung (siehe FRONTEND.md)
## 6. Bun Crash bei langen Claude Code Sessions
**Was:** Claude Code CLI lief >30 Minuten
**Problem:** Bun (JS Runtime) crashed mit "Illegal instruction"
**Lösung:** Bei komplexen Tasks früher committen und neue Session starten
## 7. Docker Cache nach Dateiänderung
**Was:** main.py auf Pi kopiert, Container neu gestartet
**Problem:** Docker nutzte gecachten Layer – alte Datei im Container
**Lösung:** Immer `--no-cache` bei Änderungen am Code:
```bash
docker compose build --no-cache backend
```
## 8. Placeholder Registry Framework – Kritische Learnings (02.04.2026)
**Was:** Implementation von 14 Nutrition Placeholders mit neuem Registry Framework
### 8.1 OutputType.TEXT existiert nicht
**Problem:** `OutputType.TEXT` verursachte AttributeError
**Richtig:** `OutputType.STRING` für Text-Outputs
**Verfügbar:** NUMERIC, STRING, BOOLEAN, JSON, LIST, TEXT_SUMMARY
```python
# ❌ Falsch:
output_type=OutputType.TEXT
# ✅ Richtig:
output_type=OutputType.STRING
```
### 8.2 Time Window "mixed" ist problematisch
**Problem:** `time_window="mixed"` unklar für Export und Consumers
**Lösung:** Dominante Zeitkomponente wählen, Rest als Kommentar
```python
# ❌ Unklar:
time_window="mixed"
# ✅ Klar:
time_window="7d" # protein 7d avg; weight ist snapshot (secondary)
```
### 8.3 Units müssen präzise sein
**Problem:** Unpräzise Units führen zu Interpretationsproblemen
```python
# ❌ Unpräzise:
unit="score"
unit="kcal"
# ✅ Präzise:
unit="score (0-100)"
unit="kcal/day"
```
### 8.4 Date Aggregation bei CSV-Imports
**Problem:** Mehrere Einträge pro Tag → falsche "Tage"-Zählung
**Lösung:** Immer `GROUP BY date, SUM()` für Tages-Aggregation
```python
# ❌ Falsch (zählt Einträge):
SELECT protein_g FROM nutrition_log WHERE date >= ...
# ✅ Richtig (zählt Tage):
SELECT date, SUM(protein_g) as daily_protein
FROM nutrition_log
WHERE date >= ...
GROUP BY date
```
**Betroffen:** Alle Funktionen die "Tage" zählen oder daily averages berechnen
### 8.5 Evidence-Based = Nie Raten
**Problem:** CODE_DERIVED falsch gesetzt ohne Code-Inspektion
**Lösung:** Bei Unsicherheit UNRESOLVED oder TO_VERIFY nutzen
```python
# Wenn unklar:
metadata.set_evidence("field", EvidenceType.UNRESOLVED) # ehrlich
# Nicht:
metadata.set_evidence("field", EvidenceType.CODE_DERIVED) # halluziniert
```
### 8.6 Known Limitations = Dokumentations-Gold
**Problem:** Inkonsistenzen/Bugs verschwiegen
**Erfolg:** Transparent dokumentiert in `known_limitations`
**Beispiel:**
```python
known_limitations=(
"KRITISCHE INKONSISTENZ: Protein ist geglättet (7d average), "
"Gewicht ist single-point (latest). Anfällig für Gewichts-Outlier."
)
```
**Regel:** Probleme dokumentieren statt verstecken. User entscheidet über Fixes.
### 8.7 Formeln explizit dokumentieren
**Problem:** "Berechnet Score" zu vage, nicht reproduzierbar
**Erfolg:** Alle Formeln, Thresholds, TDEE-Modelle explizit dokumentiert
**Beispiel:**
```python
known_limitations=(
"TDEE-MODELL: weight_kg × 32.5 (vereinfacht). "
"NICHT berücksichtigt: Aktivitätslevel, Alter, Geschlecht."
)
```
### 8.8 No-Change Requirement ist absolut
**Problem:** Versuchung, offensichtliche Bugs zu fixen
**Regel:** NUR dokumentieren, User entscheidet
**Beispiel:** `protein_g_per_kg` hat Zeitfenster-Inkonsistenz (7d protein / latest weight)
→ Dokumentiert in known_limitations, NICHT gefixed
### 8.9 Testing nach jedem Deploy
**Problem:** Fehler erst nach komplettem Cluster entdeckt
**Erfolg:** Testing nach jedem Part (A, B, C) → frühe Fehlerkennung
**Workflow:**
1. Deploy Part A
2. Test Export
3. Werte verifizieren
4. Erst dann Part B
### 8.10 .claude in .gitignore
**Problem:** Versuch, `.claude/task/` Files zu committen
**Lösung:** Nur `backend/` Code committen, `.claude/` ist local docs
## 9. Unmapped-Query: Kreuzjoin Liste × Tagebuch (12.09.2026)
**Was:** Offene Lebensmittel über `food_recipes` mit `nutrition_items` per `recipe_id OR name_normalized` verbinden, um Zutaten ein Datum zu geben.
**Problem:** Nach FDDB-Listenimport Minuten bis Timeout; Zutaten ohne `last_date` fielen im 28-Tage-Filter weg — leere Offene-Liste.
**Lösung:** Nur Items mit `recipe_id` gruppieren; Fallback `recipe.updated_at`. Listen-GET `brief=true`. Rebuild nach Import im Hintergrund.
**Regel:** Kein Join „Name der Liste gegen alle Tagebuchzeilen“. Datum aus der bereits gesetzten FK oder aus dem Eltern-Datensatz.
## 10. `from __future__ import annotations` + FastAPI-Limiter (13.09.2026)
**Was:** `tandoor.py` mit future-annotations und `body: TandoorProbeIn | None` unter `@limiter.limit`.
**Problem:** Pydantic löst den Typ nicht auf → Import-Crash → Backend startet nicht → Login bekommt HTML (`Unexpected token '<'`).
**Lösung:** Kein future-annotations in Routern; `Optional[TandoorProbeIn]`. Import-Test für den Router.
---
**Zusammenfassung Nutrition Cluster:**
- 14 Placeholders erfolgreich implementiert
- 2 Bugs gefunden und behoben (OutputType, Date Aggregation)
- 2 Metadaten-Inkonsistenzen korrigiert (time_window, unit)
- Alle kritischen Formeln dokumentiert
- Framework bewährt und skalierbar