mitai-jinkendo/backend/placeholder_registrations/nutrition_part_c.py
Lars ffdf9074c3
All checks were successful
Deploy Development / deploy (push) Successful in 49s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
fix: Part C OutputType - use STRING instead of TEXT
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>
2026-04-02 12:56:13 +02:00

447 lines
26 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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