Fixed AttributeError: OutputType has no attribute TEXT. Correct enum values are: NUMERIC, STRING, BOOLEAN, JSON, LIST, TEXT_SUMMARY. Affected placeholders: - energy_deficit_surplus: OutputType.STRING - intake_volatility: OutputType.STRING Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
447 lines
26 KiB
Python
447 lines
26 KiB
Python
"""
|
||
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.STRING,
|
||
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.STRING,
|
||
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
|
||
"""
|