Zuletzt aktualisiert:

Statistik-Reife & Heute-Beat-Vertrag (SILV-241, live)

StratoClaude → MacClaude, 13.06.2026 (SILV-241, Sub von SILV-110 Statistik-Raum, R2, high). Aus dem Statistik-Streitgespräch (app/ios-native/reimplementierung/ statistik-redesign/synthese.md §3/§5, Dennis-gelockt). Empirie aus den DB-Counts: Geld 33 Monate reich, kcal wochenjung → die Helligkeit der Aussagen folgt der Datenreife. Alles additiv, Anti-Drift (Server erzeugt Bedeutung/Satz/tone, Client zeigt nur). Code: app/backend/main.py; Contract-Tests app/tests/contract/test_native_preis.py.

Gelockte Wertungsregeln (gelten überall in der Statistik)

Reife-Schwellen (eine Stelle: STATS_MATURITY)

Achse reif ab Datenbasis
spending (Geld) ≥ 3 abgeschlossene Monate mit Bons familienweit (receipts ohne user_id)
kcal ≥ 14 geloggte Tage dieses Nutzers diary pro user
activity ≥ 2 Wochen mit Aktivität dieses Nutzers activities pro user
top_food ≥ 3 geloggte Tage & Top ≥ 2× diary pro user/Woche

1. GET /api/stats/today-beat?user=<id>{axis, text, tone}

EIN server-formulierter Wochen-Rückblick-Satz für den Heute-Beat. Der Server wählt die reifste Achse — Geld führt (33 Monate); kcal/Aktivität nur, wenn für diesen Nutzer reif. Alle unreif → axis="onboarding" (ehrlicher Vorfreude-Satz).

{ "axis": "spending", "tone": "good",
  "text": "Diese Woche 62 € unter dem Schnitt (59 € statt Ø 121 €)." }

2. GET /api/stats/headline{value, sentence, tone}

Der „Raum-Held": die EINE überraschende Geld-Langzeit-Erkenntnis (Regel B). Aktuell: der teuerste abgeschlossene Monat als Anker (laufender Monat zählt nicht).

{ "value": "859 €", "tone": "neutral",
  "sentence": "November 2023 war euer teuerster Monat – 859 €." }

value = prägnante Zahl, sentence = fertiger Satz. tone neutral (Wow-Fakt, keine Scham). Bei zu wenig Historie: value=null + ehrlicher Platzhalter-Satz.

3. GET /api/stats/overviewmonths additiv

Je Monatseintrag zusätzlich:

{ "month": "2026-06", "total": 172.65, "bons": 3,
  "is_current": true, "delta_to_avg": null }

4. GET /api/stats/kcal/{uid} — neue Form {count, days[]}

{ "count": 9,
  "days": [ { "date": "2026-06-13", "kcal": 2668, "over_budget": true }, … ] }

Bewusst zurückgestellt