develop #59

Merged
Lars merged 11 commits from develop into main 2026-04-03 08:23:49 +02:00
2 changed files with 448 additions and 1 deletions
Showing only changes of commit ffb30eaff5 - Show all commits

View File

@ -7,5 +7,6 @@ Auto-imports all placeholder registrations to populate the global registry.
# Import all registration modules to trigger auto-registration
from . import nutrition_part_a
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']

View 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
"""