feat: Placeholder Registry Part C - Nutrition Consistency & Balance
Registers 5 nutrition-related placeholders with complete metadata: - macro_consistency_score: CV-based Makro-Konsistenz Score (0-100) - energy_balance_7d: Energiebilanz (kcal/day avg, intake - TDEE) - energy_deficit_surplus: Status (deficit/maintenance/surplus) - intake_volatility: Klassifikation (stable/moderate/high) - nutrition_days: Anzahl valider Ernährungstage (30d) All placeholders with evidence-based tagging: - 22 metadata fields per placeholder - CODE_DERIVED: Technical fields, formulas from code inspection - DRAFT_DERIVED: Semantic fields from canonical requirements - MIXED: Calculation logic (TDEE model, thresholds, formulas) - TO_VERIFY: Architecture layer decisions Critical details documented: - macro_consistency_score: CV formula + thresholds explicitly documented - energy_balance_7d: TDEE model (weight_kg × 32.5), unit clarified (kcal/day avg) - energy_deficit_surplus: Status thresholds (<-200, -200 to +200, >+200) - intake_volatility: Category mapping from macro_consistency_score - nutrition_days: Validation criteria (any entry = valid day) Known limitations captured: - TDEE model is simplified (no activity/age/gender adjustment) - Thresholds are somewhat arbitrary (e.g., 200 kcal for deficit/surplus) - High volatility not necessarily bad (context-dependent) Registry now contains 14 placeholders total: - Part A: 4 (kcal_avg, protein_avg, carb_avg, fat_avg) - Part B: 5 (protein targets + adequacy) - Part C: 5 (consistency + balance + meta) Framework: PLACEHOLDER_REGISTRY_FRAMEWORK.md (verbindlich ab 2026-04-02) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0c19e0c0ed
commit
ffb30eaff5
|
|
@ -7,5 +7,6 @@ Auto-imports all placeholder registrations to populate the global registry.
|
||||||
# Import all registration modules to trigger auto-registration
|
# Import all registration modules to trigger auto-registration
|
||||||
from . import nutrition_part_a
|
from . import nutrition_part_a
|
||||||
from . import nutrition_part_b
|
from . import nutrition_part_b
|
||||||
|
from . import nutrition_part_c
|
||||||
|
|
||||||
__all__ = ['nutrition_part_a', 'nutrition_part_b']
|
__all__ = ['nutrition_part_a', 'nutrition_part_b', 'nutrition_part_c']
|
||||||
|
|
|
||||||
446
backend/placeholder_registrations/nutrition_part_c.py
Normal file
446
backend/placeholder_registrations/nutrition_part_c.py
Normal file
|
|
@ -0,0 +1,446 @@
|
||||||
|
"""
|
||||||
|
Placeholder Registrations - Nutrition Part C
|
||||||
|
|
||||||
|
Registers 5 nutrition-related placeholders with complete metadata:
|
||||||
|
- macro_consistency_score
|
||||||
|
- energy_balance_7d
|
||||||
|
- energy_deficit_surplus
|
||||||
|
- intake_volatility
|
||||||
|
- nutrition_days
|
||||||
|
|
||||||
|
All placeholders follow Phase 0c Multi-Layer Architecture.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from placeholder_registry import (
|
||||||
|
PlaceholderMetadata,
|
||||||
|
MissingValuePolicy,
|
||||||
|
EvidenceType,
|
||||||
|
OutputType,
|
||||||
|
PlaceholderType,
|
||||||
|
register_placeholder
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 1. macro_consistency_score
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
macro_consistency_metadata = PlaceholderMetadata(
|
||||||
|
key="macro_consistency_score",
|
||||||
|
category="Ernährung",
|
||||||
|
description="Makro-Konsistenz Score (0-100)",
|
||||||
|
|
||||||
|
# Technical
|
||||||
|
resolver_module="backend/placeholder_resolver.py",
|
||||||
|
resolver_function="_safe_int('macro_consistency_score', pid)",
|
||||||
|
data_layer_module="backend/data_layer/nutrition_metrics.py",
|
||||||
|
data_layer_function="calculate_macro_consistency_score",
|
||||||
|
source_tables=["nutrition_log"],
|
||||||
|
|
||||||
|
# Semantic
|
||||||
|
semantic_contract="Liefert einen standardisierten Score (0-100), der die Stabilität bzw. Varianz der Makronährstoffzufuhr über 28 Tage bewertet. Niedriger CV (Coefficient of Variation) = höherer Score.",
|
||||||
|
business_meaning="Verdichteter Konsistenzindikator für Ernährungsumsetzung. Score basiert auf durchschnittlicher Variabilität der Makros (kcal, protein, fat, carbs).",
|
||||||
|
unit="score (0-100)",
|
||||||
|
time_window="28d",
|
||||||
|
output_type=OutputType.NUMERIC,
|
||||||
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||||||
|
format_hint="Ganzzahl 0-100",
|
||||||
|
example_output="74",
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
minimum_data_requirements="Mindestens 18 Einträge in 28 Tagen (60% coverage) für verlässliche Varianzberechnung.",
|
||||||
|
quality_filter_policy="Unvollständige oder stark lückenhafte Tage schwächen Aussagekraft. NULL-Werte bei einzelnen Makros werden für CV-Berechnung übersprungen.",
|
||||||
|
confidence_logic="Aus Datenabdeckung ableiten: 18+ Einträge = ausreichend für CV-Berechnung. Score selbst ist bereits ein Konsistenzmaß.",
|
||||||
|
missing_value_policy=MissingValuePolicy(
|
||||||
|
available=False,
|
||||||
|
value_raw=None,
|
||||||
|
missing_reason="insufficient_data",
|
||||||
|
legacy_display="nicht verfügbar"
|
||||||
|
),
|
||||||
|
known_limitations=(
|
||||||
|
"Score-Formel: CV (Coefficient of Variation) = std_dev / mean für jeden Makro. "
|
||||||
|
"Durchschnittlicher CV über alle 4 Makros. "
|
||||||
|
"Thresholds: CV<0.2=100, CV<0.3=85, CV<0.4=70, CV<0.5=55, CV>=0.5=max(30,100-CV*100). "
|
||||||
|
"WICHTIG: Niedrige Konsistenz ist nicht automatisch schlecht (bewusste Zyklen, Refeed-Tage). "
|
||||||
|
"Interpretation hängt vom Zielkontext ab."
|
||||||
|
),
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
layer_1_decision="Data Layer (nutrition_metrics.calculate_macro_consistency_score)",
|
||||||
|
layer_2a_decision="Placeholder Resolver (_safe_int, keine zusätzliche Logik)",
|
||||||
|
layer_2b_reuse_possible="Ja - Chart für Konsistenz-Verlauf oder Score-Trend möglich",
|
||||||
|
architecture_alignment="Phase 0c conform - Data Layer liefert Score, Resolver formatiert nur",
|
||||||
|
issue_53_alignment="Konform - Data Layer berechnet, Resolver wraps",
|
||||||
|
|
||||||
|
# Evidence (not exported, internal tracking)
|
||||||
|
evidence={}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Evidence tagging
|
||||||
|
macro_consistency_metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("data_layer_function", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("source_tables", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("output_type", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("minimum_data_requirements", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("quality_filter_policy", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("confidence_logic", EvidenceType.CODE_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||||||
|
macro_consistency_metadata.set_evidence("known_limitations", EvidenceType.MIXED) # Formula from code, interpretation from draft
|
||||||
|
macro_consistency_metadata.set_evidence("layer_1_decision", EvidenceType.TO_VERIFY)
|
||||||
|
macro_consistency_metadata.set_evidence("layer_2a_decision", EvidenceType.TO_VERIFY)
|
||||||
|
macro_consistency_metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
||||||
|
|
||||||
|
register_placeholder(macro_consistency_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 2. energy_balance_7d
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
energy_balance_metadata = PlaceholderMetadata(
|
||||||
|
key="energy_balance_7d",
|
||||||
|
category="Ernährung",
|
||||||
|
description="Energiebilanz 7-Tage (kcal/Tag Durchschnitt)",
|
||||||
|
|
||||||
|
# Technical
|
||||||
|
resolver_module="backend/placeholder_resolver.py",
|
||||||
|
resolver_function="_safe_float('energy_balance_7d', pid, decimals=0)",
|
||||||
|
data_layer_module="backend/data_layer/nutrition_metrics.py",
|
||||||
|
data_layer_function="calculate_energy_balance_7d",
|
||||||
|
source_tables=["nutrition_log", "weight_log"],
|
||||||
|
|
||||||
|
# Semantic
|
||||||
|
semantic_contract="Liefert die geschätzte Energiebilanz über 7 Tage als Differenz zwischen durchschnittlicher Energieaufnahme und geschätztem TDEE (Total Daily Energy Expenditure). Positiver Wert = Überschuss, Negativer Wert = Defizit.",
|
||||||
|
business_meaning="Kernindikator für Defizit-/Überschussrichtung im Kurzfristfenster. Zeigt, ob aktuelle Ernährung auf Gewichtsverlust, Erhaltung oder Aufbau ausgerichtet ist.",
|
||||||
|
unit="kcal/day (Durchschnitt)",
|
||||||
|
time_window="7d",
|
||||||
|
output_type=OutputType.NUMERIC,
|
||||||
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||||||
|
format_hint="Ganzzahl, gerundet auf 0 Dezimalstellen",
|
||||||
|
example_output="-380",
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
minimum_data_requirements="Mindestens 4 Tage mit Kalorienerfassung in 7-Tage-Fenster. Aktuelles Gewicht aus weight_log erforderlich.",
|
||||||
|
quality_filter_policy="Unvollständige Intake-Daten und fehlende Gewichtsmessung reduzieren Verlässlichkeit. TDEE-Schätzung ist vereinfacht (weight_kg × 32.5).",
|
||||||
|
confidence_logic=(
|
||||||
|
"Kombiniert Intake-Abdeckung und Robustheit des Verbrauchsmodells. "
|
||||||
|
"Niedrigere Confidence bei <7 Tagen Daten oder fehlendem Gewicht. "
|
||||||
|
"TDEE-Modell ist vereinfacht → inherent uncertainty."
|
||||||
|
),
|
||||||
|
missing_value_policy=MissingValuePolicy(
|
||||||
|
available=False,
|
||||||
|
value_raw=None,
|
||||||
|
missing_reason="insufficient_data",
|
||||||
|
legacy_display="nicht verfügbar"
|
||||||
|
),
|
||||||
|
known_limitations=(
|
||||||
|
"TDEE-MODELL: Vereinfacht als bodyweight_kg × 32.5 (mittlerer Multiplikator). "
|
||||||
|
"NICHT berücksichtigt: Aktivitätslevel, Alter, Geschlecht, Stoffwechselanpassungen. "
|
||||||
|
"TODO in Code: Harris-Benedict oder Mifflin-St Jeor für präzisere TDEE-Schätzung. "
|
||||||
|
"ACHTUNG: Energiebilanz ist modellbasiert, nicht direkt gemessen. "
|
||||||
|
"Einheit ist kcal/Tag (daily average), NICHT 7d-Total."
|
||||||
|
),
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
layer_1_decision="Data Layer (nutrition_metrics.calculate_energy_balance_7d) - berechnet Balance aus Intake und TDEE",
|
||||||
|
layer_2a_decision="Placeholder Resolver (_safe_float, rundet auf 0 Dezimalstellen)",
|
||||||
|
layer_2b_reuse_possible="Ja - Chart für Energiebilanz-Verlauf oder Defizit-Trend",
|
||||||
|
architecture_alignment="Phase 0c conform - Data Layer berechnet Balance, Resolver formatiert",
|
||||||
|
issue_53_alignment="Konform - Berechnung in Data Layer",
|
||||||
|
|
||||||
|
# Evidence
|
||||||
|
evidence={}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Evidence tagging
|
||||||
|
energy_balance_metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("data_layer_function", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("source_tables", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("unit", EvidenceType.MIXED) # Code says kcal/day, canonical was ambiguous
|
||||||
|
energy_balance_metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("output_type", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("minimum_data_requirements", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("quality_filter_policy", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("confidence_logic", EvidenceType.MIXED)
|
||||||
|
energy_balance_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||||||
|
energy_balance_metadata.set_evidence("known_limitations", EvidenceType.MIXED) # TDEE formula from code, limitations from both
|
||||||
|
energy_balance_metadata.set_evidence("layer_1_decision", EvidenceType.TO_VERIFY)
|
||||||
|
energy_balance_metadata.set_evidence("layer_2a_decision", EvidenceType.TO_VERIFY)
|
||||||
|
energy_balance_metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
||||||
|
|
||||||
|
register_placeholder(energy_balance_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 3. energy_deficit_surplus
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
energy_deficit_surplus_metadata = PlaceholderMetadata(
|
||||||
|
key="energy_deficit_surplus",
|
||||||
|
category="Ernährung",
|
||||||
|
description="Energie Defizit/Überschuss Status",
|
||||||
|
|
||||||
|
# Technical
|
||||||
|
resolver_module="backend/placeholder_resolver.py",
|
||||||
|
resolver_function="_safe_str('energy_deficit_surplus', pid)",
|
||||||
|
data_layer_module="backend/data_layer/nutrition_metrics.py",
|
||||||
|
data_layer_function="calculate_energy_deficit_surplus",
|
||||||
|
source_tables=["nutrition_log", "weight_log"], # Indirect via energy_balance_7d
|
||||||
|
|
||||||
|
# Semantic
|
||||||
|
semantic_contract="Liefert qualitative Einordnung, ob aktuelle Energiezufuhr relativ zum geschätzten Bedarf in einem Defizit ('deficit'), auf Erhaltung ('maintenance') oder im Überschuss ('surplus') liegt.",
|
||||||
|
business_meaning="Leicht interpretierbarer Energie-Statusindikator. Vereinfacht Energiebilanz zu verständlichen Kategorien.",
|
||||||
|
unit="state (string)",
|
||||||
|
time_window="7d",
|
||||||
|
output_type=OutputType.TEXT,
|
||||||
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||||||
|
format_hint="Einer von drei Statuswerten: 'deficit', 'maintenance', 'surplus'",
|
||||||
|
example_output="deficit",
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
minimum_data_requirements="Wie energy_balance_7d: mindestens 4 Tage mit Kalorienerfassung + aktuelles Gewicht.",
|
||||||
|
quality_filter_policy="Wie energy_balance_7d: unvollständige Intake-Daten und vereinfachte TDEE-Schätzung reduzieren Verlässlichkeit.",
|
||||||
|
confidence_logic="Abgeleitet von energy_balance_7d. Confidence der Balance überträgt sich auf Status.",
|
||||||
|
missing_value_policy=MissingValuePolicy(
|
||||||
|
available=False,
|
||||||
|
value_raw=None,
|
||||||
|
missing_reason="insufficient_data",
|
||||||
|
legacy_display="nicht verfügbar"
|
||||||
|
),
|
||||||
|
known_limitations=(
|
||||||
|
"Status-Schwellen: balance < -200 kcal/day = 'deficit', "
|
||||||
|
"balance > +200 kcal/day = 'surplus', "
|
||||||
|
"-200 bis +200 = 'maintenance'. "
|
||||||
|
"WICHTIG: Nur so gut wie zugrunde liegende TDEE-Schätzung (siehe energy_balance_7d). "
|
||||||
|
"Minimale Abweichungen nahe Maintenance-Schwelle können zu Statuswechsel führen. "
|
||||||
|
"200 kcal Schwelle ist willkürlich gewählt - physiologisch könnten auch 100-300 kcal sinnvoll sein."
|
||||||
|
),
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
layer_1_decision="Data Layer (nutrition_metrics.calculate_energy_deficit_surplus) - mapped Balance zu Status",
|
||||||
|
layer_2a_decision="Placeholder Resolver (_safe_str, keine zusätzliche Logik)",
|
||||||
|
layer_2b_reuse_possible="Ja - Status-Anzeige oder Kategorien-Chart",
|
||||||
|
architecture_alignment="Phase 0c conform - Status-Mapping in Data Layer",
|
||||||
|
issue_53_alignment="Konform - Kategorisierung in Data Layer",
|
||||||
|
|
||||||
|
# Evidence
|
||||||
|
evidence={}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Evidence tagging
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("data_layer_function", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("source_tables", EvidenceType.MIXED) # Indirect via energy_balance_7d
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("output_type", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("minimum_data_requirements", EvidenceType.MIXED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("quality_filter_policy", EvidenceType.MIXED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("confidence_logic", EvidenceType.MIXED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("known_limitations", EvidenceType.MIXED) # Thresholds from code, interpretation mixed
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("layer_1_decision", EvidenceType.TO_VERIFY)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("layer_2a_decision", EvidenceType.TO_VERIFY)
|
||||||
|
energy_deficit_surplus_metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
||||||
|
|
||||||
|
register_placeholder(energy_deficit_surplus_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 4. intake_volatility
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
intake_volatility_metadata = PlaceholderMetadata(
|
||||||
|
key="intake_volatility",
|
||||||
|
category="Ernährung",
|
||||||
|
description="Intake-Volatilität (Klassifikation)",
|
||||||
|
|
||||||
|
# Technical
|
||||||
|
resolver_module="backend/placeholder_resolver.py",
|
||||||
|
resolver_function="_safe_str('intake_volatility', pid)",
|
||||||
|
data_layer_module="backend/data_layer/nutrition_metrics.py",
|
||||||
|
data_layer_function="calculate_intake_volatility",
|
||||||
|
source_tables=["nutrition_log"],
|
||||||
|
|
||||||
|
# Semantic
|
||||||
|
semantic_contract="Liefert qualitative Klassifikation der Variabilität der täglichen Kalorienaufnahme über 28 Tage. 'stable' = hohe Konstanz, 'moderate' = mittlere Schwankung, 'high' = starke Variabilität.",
|
||||||
|
business_meaning="Konsistenz- und Adhärenzindikator für Ernährungsumsetzung. Zeigt, wie gleichmäßig die Kalorienaufnahme über die Zeit ist.",
|
||||||
|
unit="category (string)",
|
||||||
|
time_window="28d",
|
||||||
|
output_type=OutputType.TEXT,
|
||||||
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||||||
|
format_hint="Einer von drei Werten: 'stable', 'moderate', 'high'",
|
||||||
|
example_output="moderate",
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
minimum_data_requirements="Wie macro_consistency_score: mindestens 18 Einträge in 28 Tagen (60% coverage).",
|
||||||
|
quality_filter_policy="Ausreißer, lückenhafte Tage und unvollständige Logs reduzieren Verlässlichkeit. Abgeleitet von macro_consistency_score.",
|
||||||
|
confidence_logic="Aus Datenabdeckung und Vollständigkeit ableiten. Abhängig von macro_consistency_score Confidence.",
|
||||||
|
missing_value_policy=MissingValuePolicy(
|
||||||
|
available=False,
|
||||||
|
value_raw=None,
|
||||||
|
missing_reason="insufficient_data",
|
||||||
|
legacy_display="nicht verfügbar"
|
||||||
|
),
|
||||||
|
known_limitations=(
|
||||||
|
"Klassifikation basiert auf macro_consistency_score: "
|
||||||
|
"score >= 80: 'stable', score >= 60: 'moderate', score < 60: 'high'. "
|
||||||
|
"WICHTIG: Hohe Volatilität ist nicht automatisch schlecht (bewusste Refeed-/Diet-Break-Tage, unregelmäßige Wochenenden). "
|
||||||
|
"Interpretation hängt von Zielkontext und Trainingslogik ab. "
|
||||||
|
"Vereinfacht komplexes Konsistenzmuster zu drei Kategorien."
|
||||||
|
),
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
layer_1_decision="Data Layer (nutrition_metrics.calculate_intake_volatility) - mapped macro_consistency_score zu Kategorie",
|
||||||
|
layer_2a_decision="Placeholder Resolver (_safe_str, keine zusätzliche Logik)",
|
||||||
|
layer_2b_reuse_possible="Ja - Kategorie-Anzeige oder Trend-Chart",
|
||||||
|
architecture_alignment="Phase 0c conform - Kategorisierung in Data Layer",
|
||||||
|
issue_53_alignment="Konform - Mapping in Data Layer",
|
||||||
|
|
||||||
|
# Evidence
|
||||||
|
evidence={}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Evidence tagging
|
||||||
|
intake_volatility_metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("data_layer_function", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("source_tables", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("output_type", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("minimum_data_requirements", EvidenceType.MIXED)
|
||||||
|
intake_volatility_metadata.set_evidence("quality_filter_policy", EvidenceType.MIXED)
|
||||||
|
intake_volatility_metadata.set_evidence("confidence_logic", EvidenceType.MIXED)
|
||||||
|
intake_volatility_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||||||
|
intake_volatility_metadata.set_evidence("known_limitations", EvidenceType.MIXED) # Thresholds from code, interpretation mixed
|
||||||
|
intake_volatility_metadata.set_evidence("layer_1_decision", EvidenceType.TO_VERIFY)
|
||||||
|
intake_volatility_metadata.set_evidence("layer_2a_decision", EvidenceType.TO_VERIFY)
|
||||||
|
intake_volatility_metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
||||||
|
|
||||||
|
register_placeholder(intake_volatility_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 5. nutrition_days
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
nutrition_days_metadata = PlaceholderMetadata(
|
||||||
|
key="nutrition_days",
|
||||||
|
category="Ernährung",
|
||||||
|
description="Anzahl valider Ernährungstage (30d)",
|
||||||
|
|
||||||
|
# Technical
|
||||||
|
resolver_module="backend/placeholder_resolver.py",
|
||||||
|
resolver_function="get_nutrition_days(pid, 30)",
|
||||||
|
data_layer_module="backend/data_layer/nutrition_metrics.py",
|
||||||
|
data_layer_function="get_nutrition_days_data",
|
||||||
|
source_tables=["nutrition_log"],
|
||||||
|
|
||||||
|
# Semantic
|
||||||
|
semantic_contract="Liefert die Anzahl der Tage mit valider Ernährungserfassung im 30-Tage-Fenster. Zählt alle unique Datums-Einträge in nutrition_log.",
|
||||||
|
business_meaning="Direktes Maß für Datenabdeckung und Aussagekraft der Ernährungsplaceholder. Zeigt, an wie vielen Tagen im Zeitfenster Ernährungsdaten erfasst wurden.",
|
||||||
|
unit="days",
|
||||||
|
time_window="30d",
|
||||||
|
output_type=OutputType.NUMERIC,
|
||||||
|
placeholder_type=PlaceholderType.META,
|
||||||
|
format_hint="Ganzzahl 0-30",
|
||||||
|
example_output="22",
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
minimum_data_requirements="Keine Mindestmenge für Existenz des Placeholders selbst. Wert kann 0 sein.",
|
||||||
|
quality_filter_policy=(
|
||||||
|
"Definition 'valider Tag': Jeder Tag mit mindestens einem Eintrag in nutrition_log gilt als valide. "
|
||||||
|
"WICHTIG: Sagt NICHTS über Qualität oder Vollständigkeit des einzelnen Tages. "
|
||||||
|
"Auch Teil-Tage (z.B. nur Frühstück erfasst) zählen als valider Tag. "
|
||||||
|
"Keine Prüfung auf Mindest-Kalorienanzahl oder vollständige Makros."
|
||||||
|
),
|
||||||
|
confidence_logic="Nicht klassisch nötig - der Wert selbst dient als Verlässlichkeitsindikator für andere Ernährungsplaceholder.",
|
||||||
|
missing_value_policy=MissingValuePolicy(
|
||||||
|
available=True, # Always available, even if 0 days
|
||||||
|
value_raw=0,
|
||||||
|
missing_reason=None,
|
||||||
|
legacy_display="0"
|
||||||
|
),
|
||||||
|
known_limitations=(
|
||||||
|
"Zählt nur UNIQUE dates mit Einträgen, nicht die Anzahl der Einträge. "
|
||||||
|
"Sagt nichts über Qualität der einzelnen Tage (z.B. Vollständigkeit, Plausibilität). "
|
||||||
|
"Nur Abdeckungsmaß, kein Qualitätsmaß. "
|
||||||
|
"Bei mehreren Einträgen pro Tag wird Tag nur einmal gezählt."
|
||||||
|
),
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
layer_1_decision="Data Layer (nutrition_metrics.get_nutrition_days_data) - zählt unique dates",
|
||||||
|
layer_2a_decision="Placeholder Resolver (get_nutrition_days, formatiert zu String)",
|
||||||
|
layer_2b_reuse_possible="Ja - Coverage-Chart oder Datenqualitäts-Dashboard",
|
||||||
|
architecture_alignment="Phase 0c conform - Count in Data Layer, Formatting in Resolver",
|
||||||
|
issue_53_alignment="Konform - Zählung in Data Layer",
|
||||||
|
|
||||||
|
# Evidence
|
||||||
|
evidence={}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Evidence tagging
|
||||||
|
nutrition_days_metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("data_layer_function", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("source_tables", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("output_type", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("minimum_data_requirements", EvidenceType.CODE_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("quality_filter_policy", EvidenceType.MIXED) # Logic from code, definition from inspection
|
||||||
|
nutrition_days_metadata.set_evidence("confidence_logic", EvidenceType.DRAFT_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("semantic_contract", EvidenceType.MIXED) # Count logic from code, interpretation from draft
|
||||||
|
nutrition_days_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||||||
|
nutrition_days_metadata.set_evidence("known_limitations", EvidenceType.MIXED)
|
||||||
|
nutrition_days_metadata.set_evidence("layer_1_decision", EvidenceType.TO_VERIFY)
|
||||||
|
nutrition_days_metadata.set_evidence("layer_2a_decision", EvidenceType.TO_VERIFY)
|
||||||
|
nutrition_days_metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
||||||
|
|
||||||
|
register_placeholder(nutrition_days_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# Registration Summary
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
"""
|
||||||
|
Part C Registration Complete:
|
||||||
|
- macro_consistency_score: Score-based consistency indicator (CV-based)
|
||||||
|
- energy_balance_7d: kcal/day average balance (intake - estimated TDEE)
|
||||||
|
- energy_deficit_surplus: Status classification (deficit/maintenance/surplus)
|
||||||
|
- intake_volatility: Category classification (stable/moderate/high)
|
||||||
|
- nutrition_days: Count of valid nutrition days (meta indicator)
|
||||||
|
|
||||||
|
Total Nutrition Cluster:
|
||||||
|
- Part A: 4 placeholders (kcal_avg, protein_avg, carb_avg, fat_avg)
|
||||||
|
- Part B: 5 placeholders (protein targets + adequacy)
|
||||||
|
- Part C: 5 placeholders (consistency + balance + meta)
|
||||||
|
→ 14 nutrition placeholders total
|
||||||
|
|
||||||
|
All registrations follow Phase 0c Multi-Layer Architecture:
|
||||||
|
- Layer 1 (Data Layer): Calculations
|
||||||
|
- Layer 2a (Placeholder Resolver): Formatting only
|
||||||
|
- No logic changes from existing implementations
|
||||||
|
- Evidence-based metadata tagging
|
||||||
|
"""
|
||||||
Loading…
Reference in New Issue
Block a user