mitai-jinkendo/.claude/docs/working/PHASE_0C_TASKS.md
Lars 7940dc7560 docs: Struktur .claude/docs versionieren, working/, Gitea-Index, Regeln
- .gitignore: .claude/docs, rules, commands tracken; settings.local weiter ignorieren
- DOCUMENTATION.md: verbindliche Ablage functional/technical/working/issues
- .claude/README.md: Agent-Einstieg; GITEA_ISSUES_INDEX aus MCP (Stand 2026-04-08)
- Arbeitspapiere von docs/ nach .claude/docs/working/ verschoben
- docs/MEMBERSHIP_SYSTEM.md als Stub; kanonisch technical/MEMBERSHIP_SYSTEM.md
- CLAUDE.md Pflichtlektüre und Links angepasst; docs/README.md vereinfacht

Made-with: Cursor
2026-04-08 13:01:49 +02:00

7.6 KiB
Raw Permalink Blame History

Phase 0c Architecture Cleanup & Refactoring

Datum: 2026-03-28 Voraussetzung: Phase 0b abgeschlossen Geschätzter Aufwand: 12-16 Stunden


Ziele

Phase 0c fokussiert auf Architektur-Verbesserungen und Structured Data, ohne neue Features hinzuzufügen.

Kernprinzip: Von Formatted Strings zu Structured Data → Basis für Phase 0c Refactoring (Charts/Diagramme).


Task 1: Dynamic Aggregation Methods (3-4h)

Problem: Aggregationsmethoden sind im Frontend hardcoded.

Lösung:

Backend

# backend/routers/goal_types.py
@router.get("/aggregation-methods")
def get_aggregation_methods():
    """Return all available aggregation methods with metadata"""
    return [
        {
            "value": "latest",
            "label_de": "Letzter Wert",
            "label_en": "Latest",
            "description": "Aktuellster Wert aus Tabelle",
            "compatible_types": ["DECIMAL", "INTEGER", "FLOAT"],
            "requires_numeric": False
        },
        {
            "value": "avg_7d",
            "label_de": "Durchschnitt 7 Tage",
            "label_en": "7-day average",
            "description": "Mittelwert über 7 Tage",
            "compatible_types": ["DECIMAL", "INTEGER", "FLOAT"],
            "requires_numeric": True
        },
        # ... alle Methoden aus goal_utils.py
    ]

Implementierung:

  1. Endpoint erstellen (goal_types.py)
  2. Auto-Discovery aus goal_utils.py Docstrings oder Introspection
  3. Frontend anpassen (AdminGoalTypesPage.jsx)
  4. Migration für Backfill (falls nötig)

Dokumentation: .claude/docs/technical/AGGREGATION_METHODS.md (exists)


Task 2: Dynamic Placeholder Catalog (4-5h)

Problem: Platzhalter sind im Frontend nicht sichtbar/suchbar.

Lösung:

Backend

# backend/routers/prompts.py
@router.get("/placeholders/catalog")
def get_placeholder_catalog(session: dict = Depends(require_auth)):
    """
    Return all registered placeholders with metadata.
    Enables auto-complete and placeholder selector in frontend.
    """
    return {
        "categories": [
            {
                "name": "Profil",
                "placeholders": [
                    {
                        "key": "name",
                        "placeholder": "{{name}}",
                        "description": "Name des Nutzers",
                        "example": "Lars",
                        "data_type": "string"
                    },
                    # ...
                ]
            },
            # ... weitere Kategorien
        ],
        "total_count": 111
    }

Frontend

// PlaceholderSelector Component
<PlaceholderSelector
  onSelect={(placeholder) => insertAtCursor(placeholder)}
  categories={fetchedCatalog.categories}
  searchable={true}
  showExamples={true}
/>

Implementierung:

  1. Endpoint erstellen (nutzt PLACEHOLDER_CATALOG aus placeholder_resolver.py)
  2. React Component: PlaceholderSelector
  3. Integration in UnifiedPromptModal (Prompt-Editor)
  4. Keyboard-Shortcuts (Strg+Space für Auto-Complete)

Dokumentation: .claude/docs/technical/PLACEHOLDER_SYSTEM.md (neu erstellen)


Task 3: Calculation Functions → Structured Return (5-7h)

Problem: Calculation Functions returnen formatted strings statt strukturierte Daten.

Lösung: Refactoring aller Calculation Functions zu structured return.

Beispiel-Refactoring

Vorher (Phase 0b):

def calculate_weight_trend(profile_id: str) -> str:
    # ... calculation ...
    return f"sinkend (-0.9 kg in 28 Tagen)"

Nachher (Phase 0c):

def calculate_weight_trend(profile_id: str) -> Dict:
    # ... calculation ...
    return {
        "raw_value": -0.9,
        "unit": "kg",
        "period_days": 28,
        "direction": "decreasing",  # "increasing", "stable"
        "confidence": "high",       # "high", "medium", "low"
        "data_points": 15,
        "slope_per_day": -0.032
    }

Formatting Layer

# placeholder_resolver.py
def format_weight_trend(data: Dict) -> str:
    """Format structured weight trend for AI prompts"""
    direction_de = {"decreasing": "sinkend", "increasing": "steigend", "stable": "stabil"}
    return f"{direction_de[data['direction']]} ({data['raw_value']} {data['unit']} in {data['period_days']} Tagen)"

Betroffene Module

  • calculations/body_metrics.py (~15 Funktionen)
  • calculations/nutrition_metrics.py (~12 Funktionen)
  • calculations/activity_metrics.py (~18 Funktionen)
  • calculations/recovery_metrics.py (~10 Funktionen)
  • calculations/scores.py (~8 Funktionen)

Gesamt: ~63 Funktionen zu refactoren

Strategie

  1. Phase 0c/1: Body Metrics (Proof of Concept)
  2. Phase 0c/2: Nutrition + Activity
  3. Phase 0c/3: Recovery + Scores
  4. Phase 0c/4: Placeholder Resolver anpassen (Formatter)

Dokumentation:

  • .claude/docs/technical/CALCULATION_FUNCTIONS.md (neu)
  • .claude/docs/functional/mitai_jinkendo_konzept_diagramme_auswertungen_v2.md (exists, Kontext für Chart-System)

Task 4: Stats/Chart Endpoints (Optional, 3-4h)

Voraussetzung: Task 3 abgeschlossen

Lösung: Separate Endpoints für Chart-Daten (nutzen structured calculation returns)

# backend/routers/stats.py (new)
@router.get("/stats/body/weight-trend")
def get_weight_trend_stats(
    days: int = 30,
    session: dict = Depends(require_auth)
):
    """Return structured weight trend data for charts"""
    trend_data = calculate_weight_trend(session['profile_id'])
    return {
        "trend": trend_data,
        "timeseries": [...],  # Daily data points
        "projections": {...}  # Linear projection
    }

Implementierung:

  1. Neuer Router: stats.py
  2. Endpoints für alle Chart-relevanten Metriken
  3. OpenAPI Schema (für Frontend Type-Generation)

Abhängigkeiten

Task 1 (Aggregation Methods)  ─┐
                               ├─> Unabhängig, parallel möglich
Task 2 (Placeholder Catalog)  ─┘

Task 3 (Structured Returns)   ──> Voraussetzung für Task 4
Task 4 (Stats Endpoints)       ──> Optional, nutzt Task 3 Results

Akzeptanzkriterien Phase 0c

Muss (Must-Have):

  • Aggregation Methods API-gesteuert
  • Placeholder Catalog API verfügbar
  • Mindestens 1 Modul (Body Metrics) zu structured return refactored
  • Dokumentation für alle 3 Tasks

Sollte (Should-Have):

  • Alle Calculation Functions refactored
  • Frontend Placeholder Selector implementiert
  • Stats Endpoints für Body + Nutrition

Kann (Nice-to-Have):

  • Stats Endpoints für alle Module
  • Chart-Preview in Admin-Panel
  • TypeScript Type-Generation aus OpenAPI

Rollback-Plan

Falls Task 3 (Structured Returns) Probleme verursacht:

  1. Calculation Functions returnen beide Formate:
    return {
        "formatted": "sinkend (-0.9 kg)",  # Backward-compat
        "structured": {...}                 # New format
    }
    
  2. Placeholder Resolver nutzt formatted weiterhin
  3. Stats Endpoints nutzen structured
  4. Schrittweise Migration ohne Breaking Changes

Timeline (geschätzt)

Option A (Serial): 12-16 Stunden über 2-3 Tage Option B (Parallel): 8-10 Stunden mit 2 Personen

Empfehlung: Option A, da Tasks eng verzahnt sind.


Nach Phase 0c

Enabler für:

  • Chart/Diagram System (Phase 1)
  • Goal Progress Visualizations
  • Custom Dashboards
  • PDF/Excel Export mit strukturierten Daten
  • API für externe Tools (z.B. Home Assistant)

Nächste Phase (Phase 1):

  • Chart Library Integration (Recharts/Victory)
  • Interactive Dashboards
  • Goal Progress Tracking UI