- Migrated all 16 calculation functions from calculations/nutrition_metrics.py to data_layer/nutrition_metrics.py
- Functions: Energy balance (7d calculation, deficit/surplus classification)
- Functions: Protein adequacy (g/kg, days in target, 28d score)
- Functions: Macro consistency (score, intake volatility)
- Functions: Nutrition scoring (main score with focus weights, calorie/macro adherence helpers)
- Functions: Energy availability warning (with severity levels and recommendations)
- Functions: Data quality assessment
- Functions: Fiber/sugar averages (TODO stubs)
- Updated data_layer/__init__.py with 12 new exports
- Refactored placeholder_resolver.py to import nutrition_metrics from data_layer
Module 2/6 complete. Single Source of Truth for nutrition metrics established.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Migrated all 20 calculation functions from calculations/body_metrics.py to data_layer/body_metrics.py
- Functions: weight trends (7d median, 28d/90d slopes, goal projection, progress)
- Functions: body composition (FM/LBM changes)
- Functions: circumferences (waist/hip/chest/arm/thigh deltas, WHR)
- Functions: recomposition quadrant
- Functions: scoring (body progress, data quality)
- Updated data_layer/__init__.py with 20 new exports
- Refactored placeholder_resolver.py to import body_metrics from data_layer
Module 1/6 complete. Single Source of Truth for body metrics established.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Data Layer:
- get_resting_heart_rate_data() - avg RHR with min/max trend
- get_heart_rate_variability_data() - avg HRV with min/max trend
- get_vo2_max_data() - latest VO2 Max with date
Placeholder Layer:
- get_vitals_avg_hr() - refactored to use data layer
- get_vitals_avg_hrv() - refactored to use data layer
- get_vitals_vo2_max() - refactored to use data layer
All 3 health data functions + 3 placeholder refactors complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Data Layer:
- get_sleep_duration_data() - avg duration with hours/minutes breakdown
- get_sleep_quality_data() - Deep+REM percentage with phase breakdown
- get_rest_days_data() - total count + breakdown by rest type
Placeholder Layer:
- get_sleep_avg_duration() - refactored to use data layer
- get_sleep_avg_quality() - refactored to use data layer
- get_rest_days_count() - refactored to use data layer
All 3 recovery data functions + 3 placeholder refactors complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Data Layer:
- get_activity_summary_data() - count, duration, calories, frequency
- get_activity_detail_data() - detailed activity log with all fields
- get_training_type_distribution_data() - category distribution with percentages
Placeholder Layer:
- get_activity_summary() - refactored to use data layer
- get_activity_detail() - refactored to use data layer
- get_trainingstyp_verteilung() - refactored to use data layer
All 3 activity data functions + 3 placeholder refactors complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Data Layer:
- get_nutrition_average_data() - all macros in one call
- get_nutrition_days_data() - coverage tracking
- get_protein_targets_data() - 1.6g/kg and 2.2g/kg targets
- get_energy_balance_data() - deficit/surplus/maintenance
- get_protein_adequacy_data() - 0-100 score
- get_macro_consistency_data() - 0-100 score
Placeholder Layer:
- get_nutrition_avg() - refactored to use data layer
- get_nutrition_days() - refactored to use data layer
- get_protein_ziel_low() - refactored to use data layer
- get_protein_ziel_high() - refactored to use data layer
All 6 nutrition data functions + 4 placeholder refactors complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Log when using created_at as fallback for start_date
- Log when skipping due to missing created_at
- Log when skipping due to invalid date range (total_days <= 0)
This will reveal exactly why Körperfett and Zielgewicht are not added.
- Log each goal processing (name, values, dates)
- Log skip reasons (missing values, no target_date)
- Log exceptions during calculation
- Log successful additions with calculated values
This will reveal why Weight goal (+7% ahead) is not showing up.
OLD: Showed 3 goals with lowest progress %
NEW: Calculates expected progress based on elapsed time vs. total time
Shows goals with largest negative deviation (behind schedule)
Example Weight Goal:
- Total time: 98 days (22.02 - 31.05)
- Elapsed: 34 days (35%)
- Actual progress: 41%
- Deviation: +7% (AHEAD, not behind)
Also updated on_track to show goals with positive deviation (ahead of schedule).
Note: Linear progress is a simplification. Real-world progress curves vary
by goal type (weight loss, muscle gain, VO2max, etc). Future: AI-based
projection models for more realistic expectations.
Fixed 2 critical placeholder issues:
1. focus_areas_weighted_json was empty:
- Query used 'area_key' but column is 'key' in focus_area_definitions
- Changed to SELECT key, not area_key
2. Goal progress placeholders showed "nicht verfügbar":
- progress_pct in goals table is NULL (not auto-calculated)
- Added manual calculation in all 3 formatter functions:
* _format_goals_as_markdown() - shows % in table
* _format_goals_behind() - finds lowest progress
* _format_goals_on_track() - finds >= 50% progress
All placeholders should now return proper values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed remaining placeholder calculation issues:
1. body_progress_score returning 0:
- When start_value is NULL, query oldest weight from last 90 days
- Prevents progress = 0% when start equals current
2. focus_areas_weighted_json empty:
- Changed from goal_utils.get_focus_weights_v2() to scores.get_user_focus_weights()
- Now uses same function as focus_area_weights_json
3. Implemented 5 TODO markdown formatting functions:
- _format_goals_as_markdown() - table with progress bars
- _format_focus_areas_as_markdown() - weighted list
- _format_top_focus_areas() - top N by weight
- _format_goals_behind() - lowest progress goals
- _format_goals_on_track() - goals >= 50% progress
All placeholders should now return proper values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: Two TODO stubs always returned '[]'
Implemented:
- active_goals_json: Calls get_active_goals() from goal_utils
- focus_areas_weighted_json: Builds weighted list with names/categories
Result:
- active_goals_json now shows actual goals
- body_progress_score should calculate correctly
- top_3_goals placeholders will work
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Final bug fixes:
1. blood_pressure_log query - changed 'date' column to 'measured_at' (correct column for TIMESTAMP)
2. top_goal_name KeyError - added 'name' to SELECT in get_active_goals()
3. top_goal_name fallback - use goal_type if name is NULL
Changes:
- scores.py: Fixed blood_pressure_log query to use measured_at instead of date
- goal_utils.py: Added 'name' column to get_active_goals() SELECT
- placeholder_resolver.py: Added fallback to goal_type if name is None
These were the last 2 errors showing in logs. All major calculation bugs should now be fixed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fixed unterminated string literal in get_placeholder_catalog()
- Line 1037 had extra quote: ('quality_sessions_pct', 'Qualitätssessions (%)'),'
- Should be: ('quality_sessions_pct', 'Qualitätssessions (%)'),
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem: All _safe_* functions were silently catching exceptions and returning 'nicht verfügbar',
making it impossible to debug why calculations fail.
Solution: Add detailed error logging with traceback to all 4 wrapper functions:
- _safe_int(): Logs function name, exception type, message, full stack trace
- _safe_float(): Same logging
- _safe_str(): Same logging
- _safe_json(): Same logging
Now when placeholders return 'nicht verfügbar', the backend logs will show:
- Which placeholder function failed
- What exception occurred
- Full stack trace for debugging
Example log output:
[ERROR] _safe_int(goal_progress_score, uuid): ModuleNotFoundError: No module named 'calculations'
Traceback (most recent call last):
...
This will help identify if issue is:
- Missing calculations module import
- Missing data in database
- Wrong column names
- Calculation logic errors
- Each circumference point shows most recent value (even from different dates)
- Age annotations: heute, gestern, vor X Tagen/Wochen/Monaten
- Gives AI better context about measurement freshness
- Example: 'Brust 105cm (heute), Nacken 38cm (vor 2 Wochen)'
- Previously only checked c_chest, c_waist, c_hip
- Now includes c_neck, c_belly, c_thigh, c_calf, c_arm
- Fixes 'keine Daten' when entries exist with only non-primary measurements
Problem: dob Spalte ist DATE (PostgreSQL) → Python bekommt datetime.date,
nicht String → strptime() schlägt fehl → age = "unbekannt"
Fix: Prüfe isinstance(dob, str) und handle beide Typen:
- String → strptime()
- date object → direkt verwenden
Jetzt funktioniert {{age}} Platzhalter korrekt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- caliper_summary: use body_fat_pct (not bf_jpl)
- circ_summary: use c_chest, c_waist, c_hip (not brust, taille, huefte)
- get_latest_bf: use body_fat_pct for consistency
Fixes SQL errors when running base prompts that feed pipeline prompts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New placeholder: {{activity_detail}} returns formatted activity log
- Shows last 20 activities with date, type, duration, kcal, HR
- Makes activity analysis prompts work properly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend complete:
- Migration 017: Add category column to ai_prompts
- placeholder_resolver.py: 20+ placeholders with resolver functions
- Extended routers/prompts.py with CRUD endpoints:
* POST /api/prompts (create)
* PUT /api/prompts/:id (update)
* DELETE /api/prompts/:id (delete)
* POST /api/prompts/:id/duplicate
* PUT /api/prompts/reorder
* POST /api/prompts/preview
* GET /api/prompts/placeholders
* POST /api/prompts/generate (KI-assisted generation)
* POST /api/prompts/:id/optimize (KI analysis)
- Extended models.py with PromptCreate, PromptUpdate, PromptGenerateRequest
Frontend:
- AdminPromptsPage.jsx: Full CRUD UI with category filter, reordering
Meta-Features:
- KI generates prompts from goal description + example data
- KI analyzes and optimizes existing prompts
Next: PromptEditModal, PromptGenerator, api.js integration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>