mitai-jinkendo/.claude/docs/functional/PHASE_0B_IMPROVEMENTS.md

1791 lines
65 KiB
Markdown
Raw Normal View History

# Phase 0b Placeholder Improvements & Missing Values
> **Status:** 🔴 Draft - User Input in Progress
> **Datum:** 29.03.2026
> **Zweck:** Sammlung fehlender Platzhalter und Verbesserungspotenziale nach Phase 0b
---
## Executive Summary: Zwei Kritische Gaps (29.03.2026)
### 🚨 Gap #1: Quality Label wird nicht berücksichtigt
**Activity Platzhalter berücksichtigen `quality_label` nicht!**
- ❌ **Alle** activity-bezogenen Platzhalter nutzen ALLE Trainings (inkl. poor/excluded)
- ⚠️ **Betroffene Platzhalter:** `{{activity_summary}}`, `{{activity_detail}}`, `{{trainingstyp_verteilung}}`, `{{training_minutes_week}}`, `{{training_frequency_7d}}`, `{{ability_balance_*}}`, etc.
- ✅ **Einzige Ausnahme:** `{{quality_sessions_pct}}` (zählt nur excellent/good)
- 🔧 **Infrastruktur vorhanden:** `quality_filter.py` existiert bereits, wird aber NICHT genutzt
**Auswirkung:** Standard-Auswertungen in KI-Prompts zählen schlechte/ausgeschlossene Trainings mit → **verfälschte Analysen**!
**Empfohlene Lösung:**
1. Quality-Filter in `data_layer/activity_metrics.py` einbauen (6-8h)
2. Neue Platzhalter für Evaluation-Breakdown (3h)
3. Quality-Weighted Metrics (2h)
**Teilsumme:** 11-13h
---
### 🚨 Gap #2: Keine Trainingstyp-spezifischen Platzhalter
**KI kann nicht nach Trainings-Kategorien differenzieren!**
- ❌ **Keine Kategorie-spezifischen Platzhalter** (Kraft, Cardio, Kampfsport getrennt)
- ❌ **Keine Subcategory-Differenzierung** (Hypertrophie vs. Maximalkraft vs. Kraftausdauer)
- ❌ **Keine Ruhepausen-Analyse** nach Trainingstyp (48h zwischen Kraft-Einheiten?)
- ❌ **Keine Muskelerhalt-Logik** (mind. 2x/Woche Kraft?)
- ❌ **Keine Balance-Analysen** (Cardio:Kraft Ratio, fehlende Kategorien)
- ✅ **Was existiert:** `{{trainingstyp_verteilung}}` (nur Top 3 Kategorien), `{{ability_balance_*}}`
**Auswirkung:** KI kann NICHT coachen zu:
- "Zu wenig Krafttraining für Muskelerhalt" (kein `{{strength_frequency}}`)
- "48h Pause zwischen Kraft-Einheiten" (kein `{{days_since_last_strength}}`)
- "Zu cardio-lastig, mehr Kraft empfohlen" (kein `{{cardio_to_strength_ratio}}`)
- "Kein Mobility-Training in 30 Tagen" (kein `{{missing_categories}}`)
**Empfohlene Lösung:**
1. Kategorie-spezifische Count/Minutes Platzhalter (4-5h)
2. Ruhepausen-Analyse nach Kategorie (3h)
3. Balance-Scores & Ratios (2-3h)
4. Subcategory-Analysen (2h)
**Teilsumme:** 11-13h
---
**GESAMT:** 22-26h Implementierung für beide Gaps
---
## 0. Governance-Anforderungen & Fit/Gap-Analyse (User Requirements)
> **Quelle:** `placeholder_requirements_for_development.md` (29.03.2026)
> **Zweck:** Professionelle Placeholder-Governance für Prompt-Bibliothek V1
### Governance-Prinzipien (verbindlich):
1. **Platzhalter = API-Verträge** - keine Ad-hoc-Erfindungen in Prompts
2. **Keine stillschweigenden Änderungen** - Semantik, Zeitfenster, Einheit stabil
3. **Fehlende Werte explizit** - `null` oder strukturierter Status, nicht "nicht verfügbar"
4. **Atomare Platzhalter bevorzugt** - einzelne Felder statt Freitext-Blobs
5. **Zeitbezug immer eindeutig** - `*_7d`, `*_28d`, `*_90d` im Namen
6. **JSON vor Freitext** - strukturierte Objekte für komplexe Daten
7. **Verfügbarkeit trennen** - `*_available` Flags für kritische Felder
8. **Zwei-Stufen-Architektur** - Komplexe Interpretationen via KI statt hardcodiert ⭐ NEU
### Placeholder-Typen (Architektur):
#### Typ 1: Atomic Placeholders
- **Direkt aus Daten** (keine Interpretation)
- Beispiel: `{{weight_aktuell}}`, `{{training_frequency_7d}}`
- Implementierung: Python-Funktion → direkter Wert
#### Typ 2: Raw Data Placeholders
- **Strukturierte JSONs für KI-Input** (keine Interpretation)
- Beispiel: `{{goal_priority_raw_data}}`, `{{constraints_raw_data}}`
- Implementierung: Python aggregiert Rohdaten → JSON
- Verwendung: Input für Basis-Prompts
#### Typ 3: Interpreted Placeholders
- **Von KI generiert** (via Basis-Prompt)
- Beispiel: `{{goal_weighted_priority}}`, `{{main_constraint}}`
- Implementierung: Basis-Prompt interpretiert Raw Data → strukturierter Output
- Verwendung: In übergeordneten Prompts
### Priorisierte Anforderungen (Sprint 1-3):
**Sprint 1 (Must-Have für V1):** 10 Items (P1-P10 + strukturelle)
**Sprint 2 (Diagnose-Ebene):** 7 Items (P21-P27)
**Sprint 3 (Verfeinerung):** 6 Items (niedrigere Priorität)
---
## 0.1 Fit/Gap-Analyse: P1-P27 vs. Aktuelle Datenstruktur
### ✅ Vollständig möglich (mit aktueller Struktur):
#### P1. `goal_summary_json` ✅
- **Datenquelle:** `goals` table (Migration 022)
- **Struktur vorhanden:** id, name, goal_type, status, start_value, target_value, current_value, progress_percentage, target_date, is_primary, focus_contributions
- **Implementierung:** Neue data_layer Funktion `get_goal_summary_data()` → JSON formatieren
- **Aufwand:** 2h (Funktion + Platzhalter)
#### P2. `focus_area_summary_json` ✅
- **Datenquelle:** `focus_area_definitions` + `user_focus_area_weights` + `goal_focus_contributions`
- **Struktur vorhanden:** name, category, user_weight, goal_count, progress per focus area
- **Implementierung:** Neue data_layer Funktion `get_focus_area_summary_data()`
- **Aufwand:** 2h
#### P3-P4. `*_score_available` Flags ✅
- **Datenquelle:** Berechnete Scores
- **Implementierung:** Prüfen ob Score berechnet werden konnte (nicht None)
- **Aufwand:** 1h (alle Score-Platzhalter erweitern)
#### P5. `domain_availability_json` ✅
- **Datenquelle:** Alle Domain-Tabellen (weight_log, nutrition_log, activity_log, sleep_log, etc.)
- **Berechnung:**
```python
{
"body": {"available": true, "confidence": "high", "last_entry": "2026-03-29", "days_coverage_28d": 25},
"nutrition": {"available": true, "confidence": "medium", "last_entry": "2026-03-28", "days_coverage_28d": 18},
"activity": {"available": true, "confidence": "high", "last_entry": "2026-03-29", "days_coverage_28d": 12},
"sleep": {"available": true, "confidence": "low", "last_entry": "2026-03-15", "days_coverage_28d": 8},
"vitals": {"available": true, "confidence": "medium", "last_entry": "2026-03-27", "days_coverage_28d": 15},
"goals": {"available": true, "confidence": "high", "active_goals": 3},
"focus_areas": {"available": true, "confidence": "high", "weighted_areas": 5}
}
```
- **Implementierung:** Neue Funktion `calculate_domain_availability()`
- **Aufwand:** 3-4h (alle Domains prüfen)
#### P8-P11. Body Change Availability Flags ✅
- **Datenquelle:** `weight_log`, `caliper_log`, `circumference_log`
- **Implementierung:** Prüfen ob genug Datenpunkte für Trend (mind. 2 Messungen, 28d Zeitfenster)
- **Aufwand:** 1h
#### P12. `body_change_summary_json` ✅
- **Datenquelle:** Phase 0c data_layer/body_metrics.py Funktionen
- **Struktur:**
```python
{
"weight_trend_28d": {"delta_kg": -2.5, "slope": -0.089, "confidence": "high"},
"fm_change_28d": {"delta_kg": -3.1, "available": true, "confidence": "medium"},
"lbm_change_28d": {"delta_kg": 0.6, "available": true, "confidence": "medium"},
"waist_delta_28d": {"delta_cm": -2.5, "available": true},
"hip_delta_28d": {"delta_cm": -1.2, "available": true},
"waist_hip_ratio": 0.85,
"recomposition_quadrant": "fat_loss_muscle_gain"
}
```
- **Implementierung:** Aggregation bestehender Funktionen
- **Aufwand:** 2h
#### P13. `activity_structure_json` ✅
- **Datenquelle:** Phase 0c data_layer/activity_metrics.py Funktionen
- **Struktur:**
```python
{
"volume_weekly_min": 180,
"frequency_7d": 4,
"type_distribution": {"cardio": 45, "strength": 35, "mobility": 10, "recovery": 10},
"quality_sessions_pct": 75,
"proxy_load_7d": 450,
"monotony_score": 1.2,
"strain_score": 540,
"rest_day_compliance_pct": 85,
"patterns": ["cardio-heavy", "good-recovery-compliance"]
}
```
- **Implementierung:** Aggregation bestehender Funktionen
- **Aufwand:** 2h
#### P16. `sleep_summary_json` ✅
- **Datenquelle:** `sleep_log` (Migration 009), Phase 0c recovery_metrics.py
- **Struktur vorhanden:** duration, segments (deep, rem, light, awake)
- **Implementierung:** Neue Funktion `get_sleep_summary_data()`
- **Aufwand:** 2h
#### P17. `recovery_summary_json` ✅
- **Datenquelle:** `vitals_baseline` (RHR, HRV), `sleep_log`, `rest_days`, `activity_log` (load)
- **Struktur:**
```python
{
"recovery_score": 75,
"main_drivers": ["good_sleep", "hrv_above_baseline"],
"rhr_status": "normal",
"hrv_status": "above_baseline",
"hrv_vs_baseline_pct": 5.2,
"rhr_vs_baseline_pct": -3.1,
"recent_load_interaction": "balanced",
"confidence": "high"
}
```
- **Implementierung:** Aggregation bestehender recovery_metrics Funktionen
- **Aufwand:** 3h
#### P18. `vitals_summary_json` ✅
- **Datenquelle:** `vitals_baseline` (Migration 015)
- **Struktur vorhanden:** resting_hr, hrv, vo2_max, spo2, respiratory_rate
- **Implementierung:** Neue Funktion `get_vitals_summary_data()`
- **Aufwand:** 1-2h
#### P19-P20. HRV/RHR Availability Flags ✅
- **Datenquelle:** `vitals_baseline`
- **Implementierung:** Prüfen ob Baseline berechnet werden kann (mind. 7 Messungen)
- **Aufwand:** 30min
#### P21. `correlation_summary_json` ✅
- **Datenquelle:** Phase 0c correlations.py Funktionen
- **Struktur:**
```python
{
"energy_weight_lag": {"best_lag_days": 7, "correlation": 0.68, "confidence": "high"},
"protein_lbm": {"correlation": 0.52, "confidence": "medium"},
"load_hrv_lag": {"best_lag_days": 3, "correlation": -0.45, "confidence": "medium"},
"load_rhr_lag": {"best_lag_days": 2, "correlation": 0.38, "confidence": "low"},
"sleep_recovery": {"correlation": 0.61, "confidence": "high"}
}
```
- **Implementierung:** Aggregation bestehender Korrelationsfunktionen
- **Aufwand:** 2h
#### P22-P24. Plateau & Drivers ✅
- **Datenquelle:** Phase 0c correlations.py (`detect_plateau_periods()`, `identify_top_drivers()`)
- **Struktur:**
```python
{
"plateau_status": "likely", # likely / possible / not_detected / insufficient_data
"plateau_detected_at": "2026-03-15",
"plateau_duration_days": 14,
"top_drivers_positive": [
{"driver": "protein_adequacy", "impact_score": 0.72},
{"driver": "sleep_quality", "impact_score": 0.65}
],
"top_drivers_negative": [
{"driver": "training_monotony", "impact_score": -0.58},
{"driver": "insufficient_strength_volume", "impact_score": -0.42}
],
"confidence": "medium"
}
```
- **Implementierung:** Wrapper um bestehende Funktionen + Klassifikation
- **Aufwand:** 2-3h
#### P25-P27. Underfueling Risk ✅
- **Datenquelle:** `nutrition_log` (kcal), `activity_log` (kcal_active), `weight_log` (trend)
- **Berechnung:**
```python
# Energy Availability = (intake - training_expenditure) / lean_body_mass
# RED-S Risk: EA < 30 kcal/kg LBM/day
{
"underfueling_risk_flag": true,
"underfueling_risk_reason": "ea_below_threshold",
"energy_availability_summary": {
"intake_avg_7d": 1800,
"training_expenditure_avg_7d": 600,
"net_availability": 1200,
"ea_per_kg_lbm": 25.5, # kcal/kg/day
"deficit_magnitude": "moderate",
"load_context": "high",
"recovery_context": "impaired",
"warning_level": "high",
"confidence": "medium"
}
}
```
- **Implementierung:** Neue Funktion `calculate_energy_availability()`
- **Aufwand:** 3-4h (RED-S Logik komplex)
---
### ⚠️ Teilweise möglich (braucht Erweiterung):
#### P7. `critical_missing_fields_json` ⚠️
- **Problem:** Braucht Meta-Tracking welche Felder wann erfasst wurden
- **Was fehlt:** Keine Tabelle die "expected fields" vs. "captured fields" trackt
- **Lösung:** Heuristik basierend auf entry counts pro Domain
- **Beispiel:**
```python
{
"critical_missing": [
{"field": "body_fat_measurements", "last_entry": "2026-02-15", "days_ago": 42, "impact": "high"},
{"field": "hrv_measurements", "last_entry": null, "days_ago": null, "impact": "medium"},
{"field": "sleep_tracking", "coverage_28d": 8, "expected": 28, "impact": "medium"}
],
"recommendation_priority": ["body_fat_measurements", "hrv_measurements", "sleep_tracking"]
}
```
- **Aufwand:** 3h (Heuristik-Logik)
#### P14. `training_quality_score` ⚠️
- **Was existiert:** `quality_label` per Activity, `quality_sessions_pct` Platzhalter
- **Was fehlt:** Aggregierter Quality-Score über alle Sessions (gewichtet)
- **Berechnung:**
```python
# Weighted average: excellent=100, good=80, acceptable=60, poor=30, excluded=0
quality_score = sum(quality_weight × duration) / total_duration
```
- **Aufwand:** 1h
#### P15. `load_balance_class` ⚠️
- **Was existiert:** `proxy_internal_load_7d` Platzhalter
- **Was fehlt:** Klassifikation in low/moderate/high/strained
- **Berechnung:**
```python
if load < 300: "low"
elif load < 600: "moderate"
elif load < 900: "high"
else: "strained"
```
- **Aufwand:** 30min
---
### ✅ Möglich mit Zwei-Stufen-Architektur (Data + KI Interpretation):
#### P31. `goal_weighted_priority` ✅ (2-Stufen)
- **Was existiert:** Goals + Focus Areas + Priorisierungssystem
- **Architektur:**
- **Stufe 1 (Data Layer):** `get_goal_priority_raw_data()` → strukturiertes JSON
```python
{
"goals": [
{
"id": 1,
"name": "Gewichtsverlust 85kg",
"progress_pct": 42,
"behind_schedule_days": 5,
"focus_contributions": [
{"focus_area": "Körpergewicht", "weight": 40}
],
"total_focus_weight": 75
}
],
"focus_area_weights": {"Körper": 75, "Aktivität": 20},
"context": {...}
}
```
- **Stufe 2 (KI-Prompt):** Basis-Prompt "Goal Priority Interpreter" interpretiert Rohdaten
- Input: `{{goal_priority_raw_data}}`
- Output: `{{goal_weighted_priority}}` (strukturiertes JSON mit Prioritäten + Rationale)
- **Aufwand:** 3h (2h Data Layer + 1h Basis-Prompt)
#### P32. `main_constraint` ✅ (2-Stufen)
- **Was existiert:** Activity patterns, frequency, gaps
- **Architektur:**
- **Stufe 1:** `get_constraints_raw_data()` → JSON
```python
{
"time_budget": {
"avg_sessions_per_week": 3.2,
"longest_gap_days": 4,
"typical_session_duration_min": 45
},
"activity_patterns": {
"weekday_sessions": 2.5,
"weekend_sessions": 0.7
},
"missing_categories": ["mobility", "recovery"],
"data_gaps": {...}
}
```
- **Stufe 2:** Basis-Prompt "Constraint Identifier"
- Input: `{{constraints_raw_data}}`
- Output: `{{main_constraint}}` (Haupteinschränkung + Typ)
- **Aufwand:** 2-3h (2h Data Layer + 1h Basis-Prompt)
#### P33. `main_strength` ✅ (2-Stufen)
- **Was existiert:** Tracking compliance, consistency scores, quality metrics
- **Architektur:**
- **Stufe 1:** `get_strengths_raw_data()` → JSON
```python
{
"tracking_compliance": {
"weight_entries_28d": 28,
"nutrition_entries_28d": 26,
"activity_entries_28d": 12
},
"consistency_scores": {
"macro_consistency": 85,
"training_frequency_stability": 92
},
"quality_metrics": {
"quality_sessions_pct": 78,
"sleep_regularity": 0.85
},
"standout_values": [
{"metric": "protein_adequacy", "value": 95, "percentile": "top_10"}
]
}
```
- **Stufe 2:** Basis-Prompt "Strength Identifier"
- Input: `{{strengths_raw_data}}`
- Output: `{{main_strength}}` (Hauptstärke + Begründung)
- **Aufwand:** 2-3h (2h Data Layer + 1h Basis-Prompt)
#### P34. `next_best_actions` ⚠️ (2-Stufen, teilweise)
- **Was existiert:** Gaps, low scores, fehlende Kategorien
- **Architektur:**
- **Stufe 1:** `get_improvement_opportunities_raw_data()` → JSON
```python
{
"gaps": [
{"domain": "activity", "gap": "no_strength_training_7d", "severity": "high"},
{"domain": "nutrition", "gap": "protein_below_target", "severity": "medium"}
],
"low_scores": [
{"metric": "mobility_sessions_28d", "value": 0, "target": 4}
],
"quick_wins": [
{"opportunity": "add_1_strength_session", "effort": "low", "expected_impact": "medium"}
],
"high_impact": [
{"opportunity": "increase_protein_20g", "effort": "medium", "expected_impact": "high"}
]
}
```
- **Stufe 2:** Basis-Prompt "Action Recommender"
- Input: `{{improvement_opportunities_raw_data}}`
- Output: `{{next_best_actions}}` (Top 3 Actions mit Begründung)
- **Problem:** Braucht domänenspezifisches Wissen (z.B. welche Proteinmenge sinnvoll)
- **Aufwand:** 3-5h (3h Data Layer + 2h Basis-Prompt mit Domänen-Wissen)
---
### ❌ Nicht möglich / Redundant:
#### P6. `domain_confidence_json` ❌ REDUNDANT
- **Problem:** Überschneidung mit P5 `domain_availability_json`
- **Lösung:** In P5 integrieren (bereits confidence per domain)
- **Aufwand:** 0h
#### P30. `blood_pressure_summary_json` ⚠️ OPTIONAL (Sprint 3)
- **Was existiert:** `blood_pressure_log` table (Migration 015)
- **Was fehlt:** Aggregationsfunktion für BP summary
- **Berechnung:**
```python
{
"mean_systolic_28d": 125,
"mean_diastolic_28d": 82,
"category": "elevated", # WHO/ISH classification
"contexts": {"nüchtern": 15, "nach_essen": 8, "nach_training": 5},
"trend_28d": "stable",
"irregularity_count": 2,
"afib_detected": false,
"confidence": "high"
}
```
- **Aufwand:** 2h (neue data_layer Funktion)
- **Empfehlung:** Sprint 3 (niedrigere Priorität als P31-P34)
---
### 📊 Zusammenfassung Fit/Gap (aktualisiert):
| Kategorie | Anzahl | Aufwand | Details |
|-----------|--------|---------|---------|
| ✅ Vollständig möglich (direkt) | 20 Items | 35-40h | P1-P5, P8-P13, P16-P27 |
| ✅ Möglich (2-Stufen-Architektur) | 4 Items | 10-14h | P31-P34 (Data Layer + KI) |
| ⚠️ Teilweise möglich | 3 Items | 4-5h | P7, P14, P15 |
| ❌ Redundant / Optional | 2 Items | 2h | P6 (redundant), P30 (optional) |
| **TOTAL MÖGLICH** | **27 Items** | **49-59h** | **Alle User Requirements umsetzbar!** |
**Architektur-Verbesserung durch 2-Stufen-Ansatz:**
- ✅ **P31-P34 von "nicht möglich" → "möglich"** durch intelligente Architektur
- ✅ **Gleicher Aufwand** wie ursprünglich geschätzt (10-14h)
- ✅ **Bessere Qualität:** Flexibler, wartbarer, erweiterbarer
- ✅ **Nutzt bestehendes System:** Unified Prompt System + Basis-Prompts
---
## 0.2 Governance-Implementierung
### Konkrete Maßnahmen für Governance-Regeln:
#### G1-G2: API-Stabilität & Keine Semantikänderungen
**Maßnahme:** Placeholder Versioning System einführen
```python
PLACEHOLDER_MAP_V1 = {
'{{weight_aktuell}}': {
'resolver': get_latest_weight,
'version': '1.0.0',
'semantic': 'latest weight entry, no averaging',
'unit': 'kg',
'timeframe': 'latest',
'fallback': 'nicht verfügbar'
},
# ...
}
```
**Aufwand:** 3h (Metadata-System + alle Platzhalter dokumentieren)
#### G3: Fehlende Werte explizit
**Maßnahme 1:** Alle "nicht verfügbar" Strings durch `null` ersetzen
**Maßnahme 2:** Neue Platzhalter mit `*_available` Flags
```python
'{{goal_progress_score}}': 75,
'{{goal_progress_score_available}}': true,
'{{goal_progress_score_reason}}': null # or "insufficient_goals"
```
**Aufwand:** 2h (alle betroffenen Platzhalter umstellen)
#### G4: JSON vor Freitext
**Maßnahme:** Alle Summary-Felder erhalten strukturierte JSON-Pendants
- `{{activity_summary}}` bleibt → + `{{activity_structure_json}}`
- `{{caliper_summary}}` bleibt → + `{{body_change_summary_json}}`
**Aufwand:** Bereits in P1-P27 enthalten
#### G5: Zeitfenster im Namen
**Maßnahme:** Alle zeitabhängigen Platzhalter prüfen und ggf. umbenennen
```python
# ❌ Unklar:
'{{weight_trend}}' # 7d? 28d? 90d?
# ✅ Klar:
'{{weight_trend_28d}}'
'{{weight_slope_28d}}'
```
**Aufwand:** 2h (Audit + Renaming + Migration)
#### G6: Verfügbarkeit trennen
**Maßnahme:** Systematisch alle kritischen Platzhalter mit Flags ergänzen
- Body: `{{fm_28d_change_available}}`, `{{lbm_28d_change_available}}`, etc.
- Vitals: `{{hrv_vs_baseline_available}}`, `{{rhr_vs_baseline_available}}`
- Goals: `{{goal_progress_score_available}}`
**Aufwand:** Bereits in P3-P4, P8-P11, P19-P20 enthalten
#### G7: Keine Ad-hoc-Platzhalter
**Maßnahme:** Placeholder Approval Process einführen
1. Neuer Platzhalter → Request in PHASE_0B_IMPROVEMENTS.md
2. Bewertung gegen Governance-Regeln
3. Implementierung nur nach Approval
4. Dokumentation in placeholder_catalog aktualisieren
**Aufwand:** 1h (Process-Dokumentation)
#### G8: Zwei-Stufen-Architektur für komplexe Interpretationen ⭐ NEU
**Maßnahme:** Komplexe Logik NICHT hardcoded, sondern via KI-Interpretation
**Wann Zwei-Stufen-Ansatz nutzen:**
- Interpretation braucht Kontext-Verständnis
- Logik ist nicht eindeutig regelbasiert
- Flexibilität wichtiger als Performance
- Domänen-Wissen erforderlich
**Implementierungs-Pattern:**
1. **Data Layer:** `get_<topic>_raw_data()` → strukturiertes JSON (Typ 2 Placeholder)
2. **Basis-Prompt:** Interpretiert Rohdaten → strukturierter Output (Typ 3 Placeholder)
3. **Verwendung:** Übergeordnete Prompts nutzen Typ 3 Placeholder
**Beispiel:**
```python
# Data Layer (Python)
def get_goal_priority_raw_data(profile_id):
return {
"goals": [...],
"focus_weights": {...},
"context": {...}
}
# Platzhalter Typ 2 (Raw Data)
'{{goal_priority_raw_data}}': lambda pid: json.dumps(get_goal_priority_raw_data(pid))
# Basis-Prompt (KI)
Name: "Goal Priority Interpreter"
Input: {{goal_priority_raw_data}}
Output: JSON mit priority_ranking
# Platzhalter Typ 3 (Interpreted)
'{{goal_weighted_priority}}': <von KI generiert via Basis-Prompt>
```
**Aufwand:** 0h (bereits in P31-P34 enthalten)
**Vorteile:**
- ✅ Flexibler: Prompt-Änderung ohne Code-Deploy
- ✅ Wartbarer: Klare Trennung Data vs. Interpretation
- ✅ Erweiterbarer: Gleiche Rohdaten für mehrere Prompts nutzbar
- ✅ Testbarer: Rohdaten-Struktur separat testbar
---
## 0.3 Sprint-Planung (User Requirements integriert)
### Sprint 1: Must-Have für V1 (20 Items, 35-40h)
**Governance & Infrastructure (8h):**
1. Placeholder Versioning System (3h)
2. "nicht verfügbar" → null Migration (2h)
3. Zeitfenster-Audit & Renaming (2h)
4. Approval Process Dokumentation (1h)
**Strukturierte JSONs (15-18h):**
- P1: goal_summary_json (2h)
- P2: focus_area_summary_json (2h)
- P5: domain_availability_json (3-4h)
- P12: body_change_summary_json (2h)
- P13: activity_structure_json (2h)
- P16: sleep_summary_json (2h)
- P17: recovery_summary_json (3h)
- P18: vitals_summary_json (1-2h)
**Availability Flags (3h):**
- P3-P4: Score availability flags (1h)
- P8-P11: Body change availability (1h)
- P19-P20: HRV/RHR availability (30min)
- P7: critical_missing_fields_json (3h) - teilweise
**Diagnose & Correlation (5-6h):**
- P21: correlation_summary_json (2h)
- P22-P24: plateau_status + drivers (2-3h)
- P14: training_quality_score (1h) - teilweise
- P15: load_balance_class (30min) - teilweise
**Energy Availability (3-4h):**
- P25-P27: underfueling risk + energy_availability_summary (3-4h)
**Sprint 1 Gesamt:** 34-41h
---
### Sprint 2: Quality Label + Training Categories (16-19h + 10-13h = 26-32h)
**Quality Label Gap (bereits definiert in Sektion 7):**
- Quality-Filter in activity_metrics.py (6-8h)
- Evaluation-Breakdown (1h)
- Placeholder-Updates (2h)
- Dedizierte Quality-Platzhalter (2h)
- Poor Sessions Warning (1h)
**Training Categories Gap (bereits definiert in Sektion 7):**
- Category-Specific Metrics (2h)
- Kategorie-spezifische Platzhalter (3h)
- Days Since Last Training (2h)
- Training Balance Calculator (2-3h)
- Weitere Kategorie-Platzhalter (2h)
- Subcategory Distribution (3h)
**Sprint 2 Gesamt:** 26-32h
---
### Sprint 3: Zwei-Stufen-Platzhalter + Optional (10-16h)
**P31-P34: Zwei-Stufen-Architektur (10-14h):**
- P31: goal_weighted_priority (3h) - Data Layer + Basis-Prompt
- P32: main_constraint (2-3h) - Data Layer + Basis-Prompt
- P33: main_strength (2-3h) - Data Layer + Basis-Prompt
- P34: next_best_actions (3-5h) - Data Layer + Basis-Prompt (komplex)
**Optional (falls gewünscht, 2h):**
- P30: blood_pressure_summary_json (2h)
**Sprint 3 Gesamt:** 12-16h
**Besonderheit Sprint 3:**
- Nutzt Unified Prompt System für KI-Interpretation
- Basis-Prompts sind wiederverwendbar
- Flexibler als hardcodierte Logik
- Kann iterativ verfeinert werden (Prompt-Änderung ohne Code-Deploy)
---
### Gesamtaufwand (alle 3 Sprints):
| Sprint | Inhalt | Aufwand |
|--------|--------|---------|
| Sprint 1 | User Requirements P1-P27 + Governance | 34-41h |
| Sprint 2 | Quality Label + Training Categories | 26-32h |
| Sprint 3 | Blood Pressure + Goal-Weighted (optional) | 12-16h |
| **TOTAL** | **Alle Requirements + Beide Gaps** | **72-89h** |
---
## 1. Fehlende Platzhalter
### Kategorie: Körper (Body Metrics)
#### `{{placeholder_name}}`
- **Zweck:** Wofür wird der Wert benötigt?
- **Datenquelle:** Tabelle/Funktion (z.B. `weight_log`, `body_metrics.py`)
- **Berechnung:** Wie soll er ermittelt werden?
- **Format:** Beispiel-Output (z.B. "4.5 kg", "85%", "nicht verfügbar")
- **Use Case:** In welchem Prompt wird das benötigt?
---
### Kategorie: Ernährung (Nutrition)
#### `{{placeholder_name}}`
- **Zweck:**
- **Datenquelle:**
- **Berechnung:**
- **Format:**
- **Use Case:**
---
### Kategorie: Training / Aktivität
#### `{{activity_summary_acceptable_plus}}`
- **Zweck:** Aktivitäts-Zusammenfassung nur mit mindestens "acceptable" Qualität
- **Datenquelle:** `activity_log` WHERE quality_label IN ('excellent', 'good', 'acceptable')
- **Berechnung:** Wie aktuelles `{{activity_summary}}`, aber mit quality_filter
- **Format:** "8 Einheiten in 14 Tagen (Ø 45 min/Einheit, 2400 kcal gesamt)"
- **Use Case:** Standard-Auswertungen, die nur valide Trainings berücksichtigen
#### `{{activity_summary_excellent}}`
- **Zweck:** Aktivitäts-Zusammenfassung nur mit "excellent" Qualität
- **Datenquelle:** `activity_log` WHERE quality_label = 'excellent'
- **Berechnung:** Wie aktuelles `{{activity_summary}}`, aber nur excellent
- **Format:** "3 Einheiten in 14 Tagen (Ø 60 min/Einheit, 1200 kcal gesamt)"
- **Use Case:** Analyse von Top-Trainings, Benchmark für Qualität
#### `{{poor_sessions_count}}`
- **Zweck:** Anzahl schlechter/ausgeschlossener Trainings
- **Datenquelle:** `activity_log` WHERE quality_label IN ('poor', 'excluded')
- **Berechnung:** COUNT(*) der poor/excluded sessions (7d oder 28d)
- **Format:** "2 Sessions" oder "keine schlechten Sessions"
- **Use Case:** Warnung bei zu vielen schlechten Trainings
#### `{{evaluation_breakdown}}`
- **Zweck:** Verteilung der Trainings nach Evaluation-Stufen
- **Datenquelle:** `activity_log` GROUP BY quality_label
- **Berechnung:** COUNT(*) pro quality_label mit Prozentangaben
- **Format:** "Excellent: 3 (25%), Good: 5 (42%), Acceptable: 3 (25%), Poor: 1 (8%)"
- **Use Case:** Qualitäts-Übersicht in Coaching-Prompts
#### `{{training_minutes_quality}}`
- **Zweck:** Trainingsminuten nur mit acceptable+ Qualität
- **Datenquelle:** `activity_log` WHERE quality_label IN ('excellent', 'good', 'acceptable')
- **Berechnung:** SUM(duration_min) mit quality_filter (7d)
- **Format:** "180 Minuten" (nur valide Trainings)
- **Use Case:** WHO-Empfehlung Vergleich (150-300 min/Woche)
---
### Kategorie: Training / Aktivität - Trainingstyp-spezifisch ⚠️ NEU
#### `{{strength_training_count_7d}}`
- **Zweck:** Anzahl Krafttrainings in letzten 7 Tagen
- **Datenquelle:** `activity_log` WHERE training_category = 'strength'
- **Berechnung:** COUNT(*) mit quality='quality' filter (7d)
- **Format:** "3 Einheiten" oder "keine Krafttrainings"
- **Use Case:** Muskelerhalt-Check (mind. 2x/Woche empfohlen)
#### `{{strength_training_minutes_7d}}`
- **Zweck:** Trainingsminuten Kraft in letzten 7 Tagen
- **Datenquelle:** `activity_log` WHERE training_category = 'strength'
- **Berechnung:** SUM(duration_min) mit quality='quality' filter (7d)
- **Format:** "135 Minuten" oder "0 Minuten Krafttraining"
- **Use Case:** Volumen-Check für Muskelerhalt
#### `{{cardio_training_count_7d}}`
- **Zweck:** Anzahl Cardio-Trainings in letzten 7 Tagen
- **Datenquelle:** `activity_log` WHERE training_category = 'cardio'
- **Berechnung:** COUNT(*) mit quality='quality' filter (7d)
- **Format:** "4 Einheiten"
- **Use Case:** WHO-Empfehlung (3-5x/Woche Cardio)
#### `{{cardio_training_minutes_7d}}`
- **Zweck:** Trainingsminuten Cardio in letzten 7 Tagen
- **Datenquelle:** `activity_log` WHERE training_category = 'cardio'
- **Berechnung:** SUM(duration_min) mit quality='quality' filter (7d)
- **Format:** "180 Minuten"
- **Use Case:** WHO-Empfehlung (150-300 min/Woche)
#### `{{martial_arts_frequency_28d}}`
- **Zweck:** Kampfsport-Frequenz (Sessions/Woche durchschnittlich über 28d)
- **Datenquelle:** `activity_log` WHERE training_category = 'martial_arts'
- **Berechnung:** COUNT(*) / 4 Wochen
- **Format:** "2.5 Einheiten/Woche" oder "kein Kampfsport in 28 Tagen"
- **Use Case:** Kampfsport-spezifisches Coaching
#### `{{recovery_sessions_count_28d}}`
- **Zweck:** Anzahl aktiver Erholungseinheiten
- **Datenquelle:** `activity_log` WHERE training_category = 'recovery'
- **Berechnung:** COUNT(*) (28d)
- **Format:** "3 Erholungseinheiten"
- **Use Case:** Regenerations-Balance prüfen
#### `{{mobility_sessions_count_28d}}`
- **Zweck:** Anzahl Mobility/Dehnung Sessions
- **Datenquelle:** `activity_log` WHERE training_category = 'mobility'
- **Berechnung:** COUNT(*) (28d)
- **Format:** "2 Mobility-Einheiten" oder "keine Mobility-Trainings"
- **Use Case:** Mobility-Warnung bei 0 Sessions
#### `{{days_since_last_strength}}`
- **Zweck:** Tage seit letzter Krafteinheit
- **Datenquelle:** `activity_log` WHERE training_category = 'strength'
- **Berechnung:** CURRENT_DATE - MAX(date)
- **Format:** "2 Tage" oder ">7 Tage (kritisch!)"
- **Use Case:** Ruhepausen-Check / Muskelerhalt-Warnung
#### `{{days_since_last_cardio}}`
- **Zweck:** Tage seit letzter Cardio-Einheit
- **Datenquelle:** `activity_log` WHERE training_category = 'cardio'
- **Berechnung:** CURRENT_DATE - MAX(date)
- **Format:** "1 Tag" oder ">5 Tage"
- **Use Case:** Ausdauer-Kontinuität prüfen
#### `{{days_since_last_martial_arts}}`
- **Zweck:** Tage seit letzter Kampfsport-Einheit
- **Datenquelle:** `activity_log` WHERE training_category = 'martial_arts'
- **Berechnung:** CURRENT_DATE - MAX(date)
- **Format:** "3 Tage" oder ">14 Tage"
- **Use Case:** Technik-Kontinuität prüfen
#### `{{cardio_to_strength_ratio}}`
- **Zweck:** Verhältnis Cardio zu Kraft (Minuten-basiert, 28d)
- **Datenquelle:** `activity_log` WHERE training_category IN ('cardio', 'strength')
- **Berechnung:** cardio_minutes / strength_minutes
- **Format:** "3:1 (cardio-lastig)" oder "1:2 (kraft-lastig)" oder "balanced"
- **Use Case:** Balance-Coaching
#### `{{training_balance_score}}`
- **Zweck:** Balance-Score 0-100 basierend auf Kategorie-Verteilung
- **Datenquelle:** `activity_log` (alle Kategorien)
- **Berechnung:** Score = 100 - std_dev(category_percentages) × 2
- **Format:** "75" (Zahl 0-100)
- **Use Case:** Gesamtbalance bewerten
#### `{{missing_training_categories}}`
- **Zweck:** Liste fehlender Trainings-Kategorien (28d)
- **Datenquelle:** `activity_log` (alle Kategorien)
- **Berechnung:** Vergleich [cardio, strength, mobility, recovery] mit tatsächlichen
- **Format:** "Fehlt: Mobility, Recovery" oder "Alle Kategorien abgedeckt"
- **Use Case:** Lücken-Identifikation
#### `{{strength_frequency_adequate}}`
- **Zweck:** Ja/Nein Check für Muskelerhalt (mind. 2x/Woche Kraft)
- **Datenquelle:** `activity_log` WHERE training_category = 'strength'
- **Berechnung:** COUNT(*) >= 2 in 7d?
- **Format:** "Ja" oder "Nein (nur 1x Kraft/Woche - Risiko Muskelabbau)"
- **Use Case:** Direkter Muskelerhalt-Check
#### `{{muscle_preservation_risk}}`
- **Zweck:** Warnung bei zu wenig Krafttraining
- **Datenquelle:** `activity_log` WHERE training_category = 'strength'
- **Berechnung:** IF strength_count_7d < 2 THEN "Risiko: nur Xx Kraft"
- **Format:** "Kein Risiko" oder "Risiko: nur 1x Kraft in 7d"
- **Use Case:** Explizite Warnung für KI-Prompt
#### `{{strength_type_distribution}}`
- **Zweck:** Verteilung innerhalb Krafttraining (Subcategories)
- **Datenquelle:** `activity_log` JOIN `training_types` WHERE category = 'strength'
- **Berechnung:** COUNT(*) per subcategory (hypertrophy, maxstrength, endurance)
- **Format:** "Hypertrophie: 60%, Maximalkraft: 30%, Kraftausdauer: 10%"
- **Use Case:** Periodisierungs-Analyse
#### `{{hypertrophy_vs_maxstrength_ratio}}`
- **Zweck:** Verhältnis Hypertrophie zu Maximalkraft
- **Datenquelle:** `activity_log` WHERE subcategory IN ('hypertrophy', 'maxstrength')
- **Berechnung:** hypertrophy_count / maxstrength_count (28d)
- **Format:** "3:1" oder "nur Hypertrophie" oder "nur Maximalkraft"
- **Use Case:** Kraft-Periodisierungs-Check
#### `{{technique_vs_sparring_balance}}`
- **Zweck:** Technik vs. Kampf im Kampfsport (Subcategories)
- **Datenquelle:** `activity_log` WHERE subcategory IN ('technique', 'sparring')
- **Berechnung:** Verhältnis technique / sparring (28d)
- **Format:** "2:1 (technik-lastig)" oder "balanced"
- **Use Case:** Kampfsport-spezifisches Coaching
---
### Kategorie: Erholung / Vitalwerte
#### `{{placeholder_name}}`
- **Zweck:**
- **Datenquelle:**
- **Berechnung:**
- **Format:**
- **Use Case:**
---
### Kategorie: Ziele (Goals)
#### `{{placeholder_name}}`
- **Zweck:**
- **Datenquelle:**
- **Berechnung:**
- **Format:**
- **Use Case:**
---
### Kategorie: Korrelationen
#### `{{placeholder_name}}`
- **Zweck:**
- **Datenquelle:**
- **Berechnung:**
- **Format:**
- **Use Case:**
---
## 2. Verbesserungspotenziale bei existierenden Platzhaltern
### `{{activity_summary}}` ⚠️ KRITISCH
- **Aktuelles Verhalten:** Zeigt ALLE Aktivitäten ohne Rücksicht auf quality_label
- **Problem:** Schlechte/ausgeschlossene Trainings werden mitgezählt → verfälscht Auswertungen
- **Vorschlag:**
- **Option A:** Default auf quality='acceptable_plus' ändern (Breaking Change)
- **Option B:** Neuen Parameter `quality_level` hinzufügen, default='all' (Non-Breaking)
- **Option C:** Neuer Platzhalter `{{activity_summary_quality}}`, alter bleibt (Redundanz)
- **Breaking Change:** Ja (Option A), Nein (Option B+C)
- **Use Case:** ALLE Standard-Coaching-Prompts sollten nur valide Trainings nutzen
### `{{activity_detail}}` ⚠️ KRITISCH
- **Aktuelles Verhalten:** Listet ALLE Aktivitäten ohne quality_label Berücksichtigung
- **Problem:** Schlechte Trainings erscheinen in Detail-Liste ohne Kennzeichnung
- **Vorschlag:**
- Entweder quality_filter hinzufügen (nur acceptable+)
- Oder quality_label als Badge in Output aufnehmen: "30.03. Laufen (60 min) [excellent]"
- **Breaking Change:** Teilweise (Format-Änderung)
- **Use Case:** Detail-Analyse sollte Qualität pro Training zeigen
### `{{trainingstyp_verteilung}}` ⚠️
- **Aktuelles Verhalten:** Zeigt Verteilung ALLER Trainingstypen
- **Problem:** Schlechte Sessions werden in Kategorie-Statistik mitgezählt
- **Vorschlag:** quality_filter auf acceptable+ anwenden
- **Breaking Change:** Ja (Zahlen ändern sich)
- **Use Case:** Verteilung sollte nur valide Trainings zeigen
### `{{training_minutes_week}}` ⚠️
- **Aktuelles Verhalten:** Summiert ALLE Trainingsminuten
- **Problem:** Schlechte Trainings werden voll gezählt
- **Vorschlag:**
- Nur acceptable+ Trainings zählen
- Oder: quality_weighted sum (excellent=1.0, good=0.95, acceptable=0.85, poor=0.5)
- **Breaking Change:** Ja
- **Use Case:** WHO-Empfehlung sollte nur valide Minuten berücksichtigen
### `{{training_frequency_7d}}` ⚠️
- **Aktuelles Verhalten:** Zählt ALLE Sessions
- **Problem:** Poor/excluded sessions werden mitgezählt
- **Vorschlag:** Nur acceptable+ Sessions zählen
- **Breaking Change:** Ja
- **Use Case:** Frequenz-Statistik sollte nur valide Trainings zählen
### `{{ability_balance_*}}` ⚠️
- **Aktuelles Verhalten:** Berechnet Balance aus ALLEN Activities
- **Problem:** Schlechte Trainings beeinflussen Ability-Balance
- **Vorschlag:** Nur acceptable+ Activities für Berechnung nutzen
- **Breaking Change:** Ja (Balance-Scores ändern sich)
- **Use Case:** Balance-Berechnung sollte nur valide Trainings nutzen
### `{{proxy_internal_load_7d}}` ℹ️ TEILWEISE KORREKT
- **Aktuelles Verhalten:** Nutzt quality_label als Gewichtungsfaktor (excellent=1.15, poor=0.75)
- **Problem:** Lädt ALLE Activities, gewichtet sie dann runter - aber poor sollte gar nicht gezählt werden
- **Vorschlag:** Filter auf acceptable+ PLUS quality-Gewichtung
- **Breaking Change:** Teilweise
- **Use Case:** Load-Monitoring sollte nur valide Trainings berücksichtigen
---
## 3. Neue Berechnungslogik / Funktionen
### Feature: Quality-Aware Activity Metrics
- **Beschreibung:** Alle activity_metrics Funktionen erhalten quality_level Parameter
- **Input:**
- `profile_id: str`
- `days: int`
- `quality_level: str = 'quality'` (new parameter)
- **Output:** Wie bisher, aber gefiltert nach quality_level
- **Algorithmus:**
```python
from quality_filter import get_quality_filter_sql
def get_activity_summary_data(profile_id, days=14, quality_level='quality'):
profile = get_profile_data(profile_id)
profile['quality_filter_level'] = quality_level
quality_sql = get_quality_filter_sql(profile) # Returns "AND quality_label IN (...)"
query = f"""
SELECT COUNT(*) as count, ...
FROM activity_log
WHERE profile_id=%s AND date >= %s
{quality_sql}
"""
```
- **Modul:** `backend/data_layer/activity_metrics.py` (alle Funktionen)
- **Dependencies:**
- `quality_filter.py` (bereits vorhanden)
- `get_profile_data()` für quality_filter_level
### Feature: Evaluation Breakdown Calculator
- **Beschreibung:** Berechnet Verteilung nach quality_label für Zeitraum
- **Input:** `profile_id: str`, `days: int = 28`
- **Output:**
```python
{
"excellent": {"count": 3, "percentage": 25, "minutes": 180},
"good": {"count": 5, "percentage": 42, "minutes": 225},
"acceptable": {"count": 3, "percentage": 25, "minutes": 90},
"poor": {"count": 1, "percentage": 8, "minutes": 30},
"excluded": {"count": 0, "percentage": 0, "minutes": 0},
"total": 12,
"confidence": "high"
}
```
- **Algorithmus:**
```sql
SELECT quality_label,
COUNT(*) as count,
SUM(duration_min) as minutes
FROM activity_log
WHERE profile_id = %s
AND date >= CURRENT_DATE - INTERVAL '%s days'
GROUP BY quality_label
```
- **Modul:** `backend/data_layer/activity_metrics.py` (neue Funktion)
- **Dependencies:** Keine
### Feature: Category-Specific Activity Metrics
- **Beschreibung:** Count/Minutes pro Trainings-Kategorie
- **Input:** `profile_id: str`, `category: str`, `days: int = 7`, `quality_level: str = 'quality'`
- **Output:**
```python
{
"category": "strength",
"count": 3,
"total_minutes": 135,
"avg_minutes_per_session": 45,
"sessions_per_week": 3.0,
"percentage_of_total": 35.0, # 35% aller Trainings
"confidence": "high",
"days_analyzed": 7
}
```
- **Algorithmus:**
```python
def get_category_activity_data(profile_id, category, days=7, quality_level='quality'):
profile = get_profile_data(profile_id)
profile['quality_filter_level'] = quality_level
quality_sql = get_quality_filter_sql(profile)
query = f"""
SELECT COUNT(*) as count,
SUM(duration_min) as total_minutes
FROM activity_log
WHERE profile_id = %s
AND training_category = %s
AND date >= CURRENT_DATE - INTERVAL '%s days'
{quality_sql}
"""
# Calculate derived metrics...
```
- **Modul:** `backend/data_layer/activity_metrics.py` (neue Funktion)
- **Dependencies:** quality_filter.py
### Feature: Days Since Last Training (per Category)
- **Beschreibung:** Tage seit letzter Einheit einer bestimmten Kategorie
- **Input:** `profile_id: str`, `category: str`, `quality_level: str = 'quality'`
- **Output:**
```python
{
"category": "strength",
"days_since_last": 2,
"last_date": "2026-03-27",
"status": "ok", # ok / warning / critical
"recommendation": "Nächste Einheit in 1-2 Tagen empfohlen",
"confidence": "high"
}
```
- **Algorithmus:**
```sql
SELECT MAX(date) as last_date
FROM activity_log
WHERE profile_id = %s
AND training_category = %s
AND quality_label IN ('excellent', 'good', 'acceptable')
```
```python
days_since = (datetime.now().date() - last_date).days
# Status logic (category-specific thresholds)
if category == 'strength':
status = 'critical' if days_since > 7 else 'warning' if days_since > 3 else 'ok'
elif category == 'cardio':
status = 'critical' if days_since > 5 else 'warning' if days_since > 2 else 'ok'
# etc.
```
- **Modul:** `backend/data_layer/activity_metrics.py` (neue Funktion)
- **Dependencies:** quality_filter.py
### Feature: Training Category Balance Calculator
- **Beschreibung:** Berechnet Balance-Score basierend auf Verteilung
- **Input:** `profile_id: str`, `days: int = 28`
- **Output:**
```python
{
"balance_score": 75, # 0-100
"cardio_pct": 45,
"strength_pct": 35,
"mobility_pct": 10,
"recovery_pct": 5,
"martial_arts_pct": 5,
"missing_categories": ["hiit"],
"recommendation": "Gut balanciert, aber kein HIIT in 28 Tagen",
"cardio_to_strength_ratio": "1.3:1",
"status": "balanced" # balanced / cardio_heavy / strength_heavy
}
```
- **Algorithmus:**
```python
# Get category distribution
categories = {'cardio': 0, 'strength': 0, 'mobility': 0, 'recovery': 0, ...}
for category, minutes in distribution.items():
categories[category] = (minutes / total_minutes) * 100
# Balance score = 100 - (std_dev × 2)
balance_score = 100 - (statistics.stdev(categories.values()) * 2)
# Ratio calculations
cardio_to_strength = categories['cardio'] / categories['strength']
# Missing categories (expected but 0)
expected = ['cardio', 'strength', 'mobility']
missing = [c for c in expected if categories[c] == 0]
```
- **Modul:** `backend/data_layer/activity_metrics.py` (neue Funktion)
- **Dependencies:** statistics
### Feature: Subcategory Distribution (within Category)
- **Beschreibung:** Verteilung nach Subcategories innerhalb einer Kategorie
- **Input:** `profile_id: str`, `category: str = 'strength'`, `days: int = 28`
- **Output:**
```python
{
"category": "strength",
"distribution": [
{"subcategory": "hypertrophy", "count": 6, "percentage": 60},
{"subcategory": "maxstrength", "count": 3, "percentage": 30},
{"subcategory": "endurance", "count": 1, "percentage": 10}
],
"total_sessions": 10,
"ratio_hypertrophy_to_max": "2:1",
"recommendation": "Gut verteilt, Periodisierung erkennbar",
"confidence": "high"
}
```
- **Algorithmus:**
```sql
SELECT tt.subcategory,
COUNT(*) as count
FROM activity_log a
JOIN training_types tt ON a.training_type_id = tt.id
WHERE a.profile_id = %s
AND a.training_category = %s
AND a.date >= CURRENT_DATE - INTERVAL '%s days'
AND a.quality_label IN ('excellent', 'good', 'acceptable')
GROUP BY tt.subcategory
ORDER BY count DESC
```
- **Modul:** `backend/data_layer/activity_metrics.py` (neue Funktion)
- **Dependencies:** training_types table, quality_filter.py
---
### Feature: Zwei-Stufen-Architektur für Interpretations-Platzhalter ⭐ NEU
#### Architektur-Überblick:
```
Data Layer (Python) → Raw Data Placeholder (JSON) → Basis-Prompt (KI) → Interpreted Placeholder
```
#### Beispiel: Goal-Weighted Priority
**Stufe 1: Data Layer**
```python
# backend/data_layer/scores.py (neu)
def get_goal_priority_raw_data(profile_id: str) -> Dict:
"""
Aggregiert Rohdaten für Goal-Priorisierung.
KEINE Interpretation, nur strukturierte Daten!
"""
with get_db() as conn:
cur = get_cursor(conn)
# 1. Aktive Ziele mit Focus Contributions
cur.execute("""
SELECT g.id, g.name, g.goal_type, g.progress_percentage,
g.target_date, g.start_date, g.is_primary,
COALESCE(
json_agg(
json_build_object(
'focus_area', fad.name_de,
'category', fad.category,
'contribution_weight', gfc.contribution_weight
)
) FILTER (WHERE fad.id IS NOT NULL),
'[]'::json
) as focus_contributions
FROM goals g
LEFT JOIN goal_focus_contributions gfc ON g.id = gfc.goal_id
LEFT JOIN focus_area_definitions fad ON gfc.focus_area_id = fad.id
WHERE g.profile_id = %s AND g.status = 'active'
GROUP BY g.id
""", (profile_id,))
goals = [dict(row) for row in cur.fetchall()]
# 2. Focus Area Weights
from data_layer.scores import get_user_focus_weights
focus_weights = get_user_focus_weights(profile_id)
# 3. Calculate derived metrics
for goal in goals:
# Total focus weight (Summe aller Contributions)
goal['total_focus_weight'] = sum(
fc['contribution_weight'] for fc in goal['focus_contributions']
)
# Behind schedule calculation
if goal['target_date']:
from datetime import datetime
today = datetime.now().date()
target = goal['target_date']
start = goal['start_date']
total_days = (target - start).days
elapsed_days = (today - start).days
expected_progress = (elapsed_days / total_days) * 100
actual_progress = goal['progress_percentage']
goal['behind_schedule_days'] = int(
((expected_progress - actual_progress) / 100) * total_days
)
else:
goal['behind_schedule_days'] = None
# 4. Context
context = {
"behind_schedule_count": sum(
1 for g in goals if g.get('behind_schedule_days', 0) > 0
),
"on_track_count": sum(
1 for g in goals if g.get('behind_schedule_days', 0) <= 0
),
"primary_goal": next(
(g['name'] for g in goals if g['is_primary']),
None
)
}
return {
"goals": goals,
"focus_area_weights": focus_weights,
"context": context
}
```
**Stufe 2: Platzhalter-Registration (Raw Data)**
```python
# backend/placeholder_resolver.py
PLACEHOLDER_MAP = {
# ... existing placeholders ...
# Raw Data Placeholders (Typ 2)
'{{goal_priority_raw_data}}': lambda pid: json.dumps(
get_goal_priority_raw_data(pid),
indent=2
),
}
```
**Stufe 3: Basis-Prompt (KI Interpretation)**
```yaml
# Admin → KI-Prompts → Neuer Basis-Prompt
Name: Goal Priority Interpreter
Type: base
Output Format: json
Output Schema:
{
"priority_ranking": [
{
"goal_name": "string",
"priority_score": "number (0-100)",
"rationale": "string",
"conflicts": ["string"]
}
],
"recommended_focus": "string",
"goal_conflicts": [
{
"goal_a": "string",
"goal_b": "string",
"conflict_type": "string",
"severity": "string"
}
]
}
Template:
---
Analysiere die folgenden Ziel-Rohdaten und erstelle eine priorisierte Liste.
# Rohdaten
{{goal_priority_raw_data}}
# Aufgabe
1. Sortiere Ziele nach kombinierter Priorität:
- Focus-Weight (höheres Gewicht = höhere Priorität)
- Behind-Schedule Status (hinter Plan = höhere Priorität)
- Primary-Flag (Primary-Goal = Boost)
2. Für jedes Ziel:
- Berechne Priority-Score (0-100)
- Begründe die Priorisierung
- Identifiziere Konflikte mit anderen Zielen
3. Identifiziere Goal-Konflikte:
- Muskelaufbau vs. Kaloriendefizit (konfliktär)
- Gewichtsverlust + Kraftaufbau (möglich mit Rekomposition)
- etc.
4. Empfehle Fokus-Reihenfolge für nächste 4 Wochen
# Output
Gib das Ergebnis als JSON zurück (siehe Schema oben).
---
```
**Stufe 4: Interpreted Placeholder (von KI generiert)**
```python
# Wird automatisch durch Unified Prompt System erzeugt
# Wenn Basis-Prompt "Goal Priority Interpreter" ausgeführt wird:
'{{goal_weighted_priority}}' = <KI-generiertes JSON>
# Beispiel-Output:
{
"priority_ranking": [
{
"goal_name": "Gewichtsverlust 85kg",
"priority_score": 92,
"rationale": "Höchstes Focus-Weight (75) + 5 Tage hinter Plan + Primary Goal",
"conflicts": ["Kraftaufbau (moderate Konflikt bei zu großem Defizit)"]
},
{
"goal_name": "Kraftaufbau",
"priority_score": 58,
"rationale": "Moderates Focus-Weight (20) + On Track + Secondary Goal",
"conflicts": ["Gewichtsverlust (erfordert moderates Defizit)"]
}
],
"recommended_focus": "Primär Gewichtsverlust mit moderatem Defizit, dabei Krafttraining 2-3x/Woche für Muskelerhalt",
"goal_conflicts": [
{
"goal_a": "Gewichtsverlust",
"goal_b": "Kraftaufbau",
"conflict_type": "energy_availability",
"severity": "moderate"
}
]
}
```
**Stufe 5: Verwendung in übergeordneten Prompts**
```yaml
# Pipeline-Prompt: "Weekly Coaching Report"
Template:
---
# Ziel-Priorisierung
{{goal_weighted_priority}}
# Basierend auf deinen Prioritäten...
[restlicher Prompt nutzt die Priorisierung]
---
```
#### Vorteile dieser Architektur:
1. **Flexibilität:** Prompt-Änderung ohne Code-Deploy
2. **Wartbarkeit:** Klare Trennung Data vs. Interpretation
3. **Erweiterbarkeit:** Gleiche Rohdaten für mehrere Prompts nutzbar
4. **Testbarkeit:** Rohdaten-Struktur separat testbar
5. **Transparenz:** Rohdaten sichtbar (Debug-Modus)
6. **Iterierbarkeit:** KI-Interpretation kann verfeinert werden
#### Implementierungs-Aufwand:
- **Data Layer Funktion:** 2h (get_goal_priority_raw_data)
- **Placeholder Registration:** 10min (einfacher Lambda)
- **Basis-Prompt:** 1h (Prompt-Engineering + Testing)
- **TOTAL:** 3h
#### Anwendbar für:
- P31: goal_weighted_priority ✅
- P32: main_constraint ✅
- P33: main_strength ✅
- P34: next_best_actions ⚠️ (braucht mehr Domänen-Wissen)
---
## 4. Datenqualität & Edge Cases
### Problem: Activities ohne quality_label (NULL values)
- **Beschreibung:** Alte Activities oder Imports haben kein quality_label → NULL
- **Betroffene Platzhalter:** ALLE activity-bezogenen Platzhalter
- **Vorschlag:** Wie sollte damit umgegangen werden?
- [x] NULL behandeln als "uncategorized" (separate Kategorie)
- [x] Bei quality_filter: NULL = excluded (nicht mitzählen)
- [ ] Batch-Evaluation für alte Activities nachholen
- [ ] Warnung in confidence_score wenn >20% NULL
### Problem: Quality-Filter zu strikt für manche Platzhalter
- **Beschreibung:** Bei "excellent" only → zu wenig Daten für Statistik
- **Betroffene Platzhalter:** `{{activity_summary_excellent}}`, etc.
- **Vorschlag:** Wie sollte damit umgegangen werden?
- [x] Confidence-Score anpassen (insufficient wenn <3 activities)
- [x] Fallback-Message: "Nur 2 excellent Sessions in 14 Tagen (zu wenig für Statistik)"
- [ ] Zeitraum automatisch erweitern (14d → 28d → 90d)
### Problem: quality_label vs. user quality_filter_level
- **Beschreibung:** Es gibt zwei Quality-Konzepte, die verwechselt werden können:
- `quality_label` (DB-Spalte): Evaluation-Ergebnis pro Activity (excellent, good, acceptable, poor, excluded)
- `quality_filter_level` (Profile-Einstellung): User-Präferenz für globalen Filter (all, quality, very_good, excellent)
- **Betroffene Platzhalter:** Alle activity-bezogenen Platzhalter
- **Vorschlag:**
- [x] Platzhalter verwenden IMMER default='quality' (acceptable+) → konsistent für KI-Analysen
- [x] User quality_filter_level nur für manuelle UI-Filter (Charts, Activity Page)
- [x] Keine Vermischung: Platzhalter = fix 'quality', UI = user preference
- [ ] Dokumentation: Klarstellung der beiden Konzepte
---
## 5. Placeholder-Kategorisierung & Organisation
### Vorschlag für neue Kategorien:
- [ ] Kategorie-Name: ___
- Platzhalter: `{{...}}`, `{{...}}`
- Begründung: ___
### Umstrukturierung existierender Kategorien:
- [ ] Von Kategorie X nach Y verschieben: `{{placeholder}}`
- Begründung: ___
---
## 6. Dokumentation & Metadaten
### Fehlende Beschreibungen:
- `{{placeholder}}` - Beschreibung fehlt oder ist unklar
### Fehlende Beispiele:
- `{{placeholder}}` - Beispiel-Output fehlt
---
## 7. Prioritäten & Abhängigkeiten
### Must-Have (kritisch für Prompt-Qualität):
#### Gap #1: Quality Label
1. **Quality-Filter in data_layer/activity_metrics.py** - ALLE Funktionen betroffen
- Breaking Change, aber notwendig für korrekte Auswertungen
- Dauer: 4-6h (9 Funktionen + Tests)
- Blockiert: Alle neuen Platzhalter
2. **Neue Platzhalter für Evaluation-Breakdown**
- `{{evaluation_breakdown}}` - Übersicht über Qualitätsverteilung
- Dauer: 1h (Funktion + Platzhalter)
3. **Placeholder-Updates in placeholder_resolver.py**
- Alle activity-Platzhalter auf quality='quality' umstellen
- Dauer: 2h (Updates + Testen)
**Teilsumme Gap #1:** 7-9h
#### Gap #2: Training Categories
4. **Category-Specific Activity Metrics (data_layer)**
- `get_category_activity_data(category)` - Count/Minutes pro Kategorie
- Dauer: 2h (1 Funktion, alle Kategorien abdecken)
5. **Kategorie-spezifische Platzhalter (Top Priority)**
- `{{strength_training_count_7d}}`, `{{strength_training_minutes_7d}}`
- `{{cardio_training_count_7d}}`, `{{cardio_training_minutes_7d}}`
- `{{strength_frequency_adequate}}`, `{{muscle_preservation_risk}}`
- Dauer: 3h (6-8 Platzhalter, kritisch für Muskelerhalt-Coaching)
6. **Days Since Last Training (per Category)**
- `get_days_since_last_training(category)` - Funktion
- `{{days_since_last_strength}}`, `{{days_since_last_cardio}}`, etc.
- Dauer: 2h (Funktion + 3-4 Platzhalter)
7. **Training Balance Calculator**
- `get_training_balance_data()` - Balance-Score + Ratios
- `{{cardio_to_strength_ratio}}`, `{{training_balance_score}}`, `{{missing_training_categories}}`
- Dauer: 2-3h (Funktion + 3 Platzhalter)
**Teilsumme Gap #2:** 9-10h
**TOTAL Must-Have:** 16-19h
### Should-Have (sinnvolle Ergänzungen):
#### Gap #1: Quality Label
1. **Dedizierte Quality-Platzhalter**
- `{{activity_summary_acceptable_plus}}`, `{{activity_summary_excellent}}`
- Dauer: 2h (4-5 neue Platzhalter)
2. **Poor Sessions Warning Platzhalter**
- `{{poor_sessions_count}}`, `{{poor_sessions_warning}}`
- Dauer: 1h
#### Gap #2: Training Categories
3. **Weitere Kategorie-Platzhalter**
- `{{martial_arts_frequency_28d}}`, `{{recovery_sessions_count_28d}}`, `{{mobility_sessions_count_28d}}`
- Dauer: 2h (3-4 Platzhalter)
4. **Subcategory Distribution**
- `get_subcategory_distribution(category)` - Funktion
- `{{strength_type_distribution}}`, `{{hypertrophy_vs_maxstrength_ratio}}`, `{{technique_vs_sparring_balance}}`
- Dauer: 3h (Funktion + 3 Platzhalter)
5. **NULL-Handling für alte Activities**
- Batch-Evaluation Script für Activities ohne quality_label
- Dauer: 2h
**Teilsumme Should-Have:** 10h
### Nice-to-Have (optional):
1. **Quality-Weighted Metrics**
- `{{training_minutes_quality_weighted}}` - gewichtet nach Qualität
- Dauer: 1h
2. **Auto-Timeframe-Expansion**
- Bei insufficient data: automatisch von 14d → 28d → 90d erweitern
- Dauer: 3h (Logik + alle Funktionen anpassen)
3. **Advanced Subcategory Analysen**
- Periodisierungs-Erkennung (Maximalkraft-Phase → Hypertrophie-Phase?)
- Dauer: 2-3h
**Teilsumme Nice-to-Have:** 6-7h
### Geschätzte Gesamt-Dauer (Original):
- **Must-Have (Gap #1 + #2):** 16-19h (beide Gaps kritisch!)
- **Should-Have:** 10h
- **Nice-to-Have:** 6-7h
- **TOTAL (ohne User Requirements):** 32-36h
### Gesamt-Dauer (mit User Requirements P1-P27):
- **Sprint 1 (User Req + Governance):** 34-41h
- **Sprint 2 (Gap #1 + #2):** 26-32h
- **Sprint 3 (Optional):** 12-16h
- **TOTAL (inkl. User Requirements):** 72-89h
**Empfehlung:** Sprint 1 + Sprint 2 parallel bearbeiten wo möglich (viele unabhängige Tasks)
### Abhängigkeiten:
1. Quality-Filter in activity_metrics.py (MUSS zuerst)
2. Dann: Neue Platzhalter können parallel implementiert werden
3. Dann: Tests für alle Änderungen
4. Letzter Schritt: Bestehende Prompts auf neue Platzhalter umstellen
---
## Notizen
### Technische Details: quality_label System
**Verfügbare Quality Labels (activity_log.quality_label):**
- `'excellent'` - ⭐ Exzellentes Training (z.B. HR in Zone, Dauer optimal, RPE passend)
- `'very_good'` - ✓✓ Sehr gutes Training
- `'good'` - ✓ Gutes Training
- `'acceptable'` - ✓ Akzeptables Training (Mindestschwelle)
- `'poor'` - ⚠ Schlechtes Training (zu kurz, HR zu niedrig, etc.)
- `'excluded'` - ❌ Auszuschließen (fehlerhafte Messung, Dummy-Eintrag)
- `NULL` - Nicht evaluiert (alte Einträge, Imports ohne Evaluation)
**Quality Filter Levels (für User-Präferenz, nicht Platzhalter!):**
- `'all'` - Alle Activities (kein Filter)
- `'quality'` - Hochwertig (acceptable+) ← **DEFAULT für Platzhalter**
- `'very_good'` - Sehr gut+ (excellent, good)
- `'excellent'` - Nur exzellent
**Bestehende Infrastruktur (quality_filter.py):**
```python
get_quality_filter_sql(profile, table_alias='')
# Returns: "AND quality_label IN ('excellent', 'good', 'acceptable')"
get_quality_filter_tuple(profile)
# Returns: ('excellent', 'good', 'acceptable')
filter_activities_by_quality(activities, profile)
# Post-query filtering
```
**Migration Path:**
1. Alle data_layer Funktionen erweitern um `quality_level='quality'` Parameter
2. Alle Platzhalter updaten: `lambda pid: get_activity_summary_data(pid, quality_level='quality')`
3. Neue Platzhalter für andere Levels: `{{activity_summary_excellent}}`
4. Tests schreiben für alle Kombinationen
5. Bestehende Prompts prüfen und ggf. anpassen
### Verfügbare Trainings-Kategorien & Subcategories:
**7 Hauptkategorien (training_category):**
1. **cardio** → Ausdauer
- Subcategories: running, cycling, swimming, rowing, other
2. **strength** → Kraft
- Subcategories: hypertrophy, maxstrength, endurance, functional
3. **hiit** → Schnellkraft
- Subcategories: hiit, explosive, circuit
4. **martial_arts** → Kampfsport
- Subcategories: technique, sparring, strength
5. **mobility** → Beweglichkeit
- Subcategories: static, dynamic, yoga, fascia
6. **recovery** → Erholung (aktiv)
- Subcategories: walk, swim_light, regeneration
7. **other** → Sonstiges
**Abilities-Mapping (JSONB in training_types.abilities):**
- strength, endurance, mental, coordination, mobility
**Bestehende Platzhalter (nutzen bereits Categories):**
- `{{trainingstyp_verteilung}}` - Top 3 Kategorien mit %
- `{{ability_balance_strength}}` - Ability-Score 0-100 (nutzt abilities JSONB)
- `{{ability_balance_endurance}}` - Ability-Score 0-100
**Migration Path Training Categories:**
1. Neue data_layer Funktionen: get_category_activity_data(), get_days_since_last_training(), etc.
2. Platzhalter für JEDE Kategorie (mindestens count + minutes für strength/cardio)
3. Balance-Funktionen (Ratios, fehlende Kategorien)
4. Subcategory-Analysen (innerhalb strength, martial_arts)
5. Tests für alle Kombinationen
6. Bestehende Prompts erweitern mit neuen Platzhaltern
---
### Offene Fragen:
#### Gap #1: Quality Label
1. **Breaking Change akzeptabel?** Zahlen ändern sich bei allen activity-Platzhaltern
2. **NULL-Handling:** Als 'excluded' behandeln oder separate Kategorie?
3. **Batch-Evaluation:** Alte Activities nachträglich evaluieren? (Performance-Impact?)
4. **Confidence-Anpassung:** Thresholds senken wenn quality_filter aktiv? (weniger Daten)
#### Gap #2: Training Categories
5. **Ruhepausen-Thresholds:** Welche Schwellenwerte pro Kategorie?
- Kraft: >3d warning, >7d critical?
- Cardio: >2d warning, >5d critical?
- Kampfsport: >7d warning, >14d critical?
6. **Balance-Definition:** Was ist "gut balanciert"?
- Cardio:Kraft 2:1 bis 1:1 ok?
- Mobility mindestens 5% aller Trainings?
7. **Subcategory-Priorität:** Welche Subcategories zuerst?
- Kraft (hypertrophy/maxstrength/endurance) → Top Priority
- Kampfsport (technique/sparring) → Nice-to-Have?
8. **Missing Categories Logic:** Welche Kategorien sind "Pflicht"?
- Core: cardio, strength, mobility
- Optional: recovery, hiit, martial_arts?
### User Requirements Summary (P1-P27):
**Sprint 1 - Must-Have (10 Core Items):**
1. goal_summary_json → vollständige Zielübersicht
2. focus_area_summary_json → strukturierte Focus Areas
3. domain_availability_json → Verfügbarkeit pro Domäne
4. body_change_summary_json → Körperentwicklung strukturiert
5. activity_structure_json → Training strukturiert
6. sleep_summary_json → Schlaf strukturiert
7. recovery_summary_json → Erholung strukturiert
8. vitals_summary_json → Vitalwerte strukturiert
9. correlation_summary_json → Korrelationen strukturiert
10. plateau_status + top_drivers → Diagnose strukturiert
**Sprint 1 - Governance (4 Items):**
- Placeholder Versioning System
- "nicht verfügbar" → null Migration
- Zeitfenster-Audit & Renaming
- Availability Flags (systematic)
**Sprint 2 - Energy & Risk:**
- underfueling_risk_flag + energy_availability_summary
- training_quality_score (aggregiert)
- load_balance_class (klassifiziert)
**Sprint 3 - Zwei-Stufen-Architektur (P31-P34):**
- goal_weighted_priority (✅ möglich via 2-Stufen)
- main_constraint (✅ möglich via 2-Stufen)
- main_strength (✅ möglich via 2-Stufen)
- next_best_actions (⚠️ teilweise, braucht Domänen-Wissen)
**Sprint 3 - Optional:**
- blood_pressure_summary_json (niedrigere Priorität)
### User Input benötigt:
#### Gap #1: Quality Label
- [ ] Strategie-Entscheidung: Breaking Change (Option A) vs. Non-Breaking (Option B)?
- [ ] NULL-Handling: excluded oder uncategorized?
- [ ] Batch-Evaluation: Ja/Nein?
#### Gap #2: Training Categories
- [ ] Ruhepausen-Thresholds definieren (pro Kategorie)
- [ ] Balance-Kriterien festlegen (Ratios, Mindest-%)
- [ ] Subcategory-Priorität: Kraft zuerst, dann Kampfsport? Oder parallel?
- [ ] Muskelerhalt-Schwelle: 2x/Woche Kraft ok? Oder 3x?
#### User Requirements (P1-P27):
- [ ] Sprint-Priorisierung: Sprint 1 + Sprint 2 parallel? Oder sequentiell?
- [ ] Sprint 3: Zwei-Stufen-Platzhalter (P31-P34) gewünscht? Oder später?
- [ ] Governance: Placeholder Versioning System sofort einführen oder später?
- [ ] Breaking Changes: "nicht verfügbar" → null jetzt oder schrittweise?
- [ ] JSON-Struktur-Review: Beispiel-Strukturen (siehe P1-P27) absegnen?
#### Zwei-Stufen-Architektur (⭐ NEU):
- [ ] **Architektur-Approval:** Zwei-Stufen-Ansatz (Data + KI) für P31-P34 ok?
- [ ] **Basis-Prompts:** Wer erstellt/reviewed die Basis-Prompts? (User oder Claude?)
- [ ] **Prompt-Governance:** Wie werden Basis-Prompts versioniert/getestet?
- [ ] **Raw Data Sichtbarkeit:** Sollen Raw Data Placeholders auch in UI-Export sichtbar sein?
- [ ] **Iterative Verfeinerung:** Basis-Prompts initial "good enough" oder erst perfekt dann deployen?
---
## 📊 Finale Zusammenfassung: Impact der Fit/Gap-Analyse
### Vor der Analyse (Original):
- **Gap #1 (Quality Label):** 11-13h
- **Gap #2 (Training Categories):** 11-13h
- **TOTAL:** 22-26h
- **User Requirements:** Nicht bewertet
- **P31-P34:** Als "nicht möglich" eingestuft
### Nach der Analyse (aktualisiert):
- **Sprint 1 (User Req + Governance):** 34-41h
- **Sprint 2 (Gap #1 + #2):** 26-32h
- **Sprint 3 (Zwei-Stufen-Architektur):** 12-16h
- **TOTAL:** 72-89h
- **Alle 27 User Requirements:** ✅ Umsetzbar!
- **P31-P34:** ✅ Möglich via Zwei-Stufen-Architektur
### Wichtigste Erkenntnisse:
#### ✅ Architektur-Durchbruch:
**Zwei-Stufen-Architektur** löst das Problem komplexer Interpretations-Platzhalter:
- Data Layer stellt strukturierte Rohdaten bereit
- KI interpretiert via Basis-Prompts
- Flexibler, wartbarer, erweiterbarer als hardcodierte Logik
#### ✅ Vollständige Umsetzbarkeit:
**Alle 27 User Requirements (P1-P34) sind umsetzbar:**
- 20 Items direkt möglich (mit aktueller Datenstruktur)
- 4 Items möglich via Zwei-Stufen-Architektur
- 3 Items teilweise möglich (einfache Erweiterungen)
- Nur P6 redundant, P30 optional
#### ✅ Governance-Framework:
**8 verbindliche Governance-Regeln** für stabile Placeholder-API:
- Platzhalter = API-Verträge
- Keine stillschweigenden Änderungen
- JSON vor Freitext
- Zwei-Stufen-Architektur für Interpretationen
#### ✅ Klare Sprint-Struktur:
**3 Sprints mit klaren Zielen:**
- Sprint 1: Foundation (User Req + Governance)
- Sprint 2: Quality + Categories (kritische Gaps)
- Sprint 3: Interpretations-Platzhalter (Zwei-Stufen)
### Empfohlenes Vorgehen:
1. **User-Entscheidungen einholen** (siehe "User Input benötigt")
2. **Sprint 1 starten** (strukturierte JSONs + Governance)
3. **Sprint 2 parallel** (Quality + Categories, unabhängig von Sprint 1)
4. **Sprint 3 nach Approval** (Zwei-Stufen-Architektur)
### Geschätzter Gesamtaufwand:
- **Minimum:** 72h (optimistisch, parallele Arbeit)
- **Realistisch:** 89h (inkl. Testing, Iterationen, Reviews)
- **Mit Buffer:** 100-110h (Puffer für Unvorhergesehenes)
### ROI / Nutzen:
- ✅ **Stabile Placeholder-API** für professionelle Prompt-Bibliothek
- ✅ **Alle 27 User Requirements** erfüllt
- ✅ **Zukunftssichere Architektur** (Zwei-Stufen erweiterbar)
- ✅ **Quality + Categories Gaps** geschlossen (kritisch für KI-Coaching)
- ✅ **Governance-Framework** verhindert technische Schulden
---
**Status:** 🔴 Draft - Bereit für User Review & Entscheidungen
**Nächster Schritt:** User Input einholen → Umsetzungskonzept erstellen → Sprint 1 starten