- Adjusted the total number of placeholders from 116 to 114 across various documentation and code files to reflect the current state of the system. - Enhanced TDEE calculation logic in `nutrition_metrics.py` to prioritize Mifflin–St Jeor BMR with PAL when demographic data is available, with a fallback to a weight-based estimate. - Updated placeholder registrations to ensure consistency with the new metadata structure and improved data handling. - Revised documentation to clarify the authoritative source of placeholder metadata and the implications of the changes on existing functionalities. These updates improve the accuracy and consistency of the placeholder system and enhance the nutritional assessment capabilities within the application.
499 lines
13 KiB
Markdown
499 lines
13 KiB
Markdown
# Placeholder Registry Framework - Verbindliche Dokumentation
|
|
|
|
**Status:** VERBINDLICH (ab 2026-04-02)
|
|
**Version:** 1.0
|
|
**Geltungsbereich:** Alle Placeholder/Metrics im System
|
|
|
|
---
|
|
|
|
## 1. Zweck
|
|
|
|
Das **Placeholder Registry Framework** ist die zentrale, verbindliche Metadaten-Verwaltung für alle Placeholder und Metrics im System.
|
|
|
|
**Kernprinzip:** Single Source of Truth
|
|
|
|
**Ziele:**
|
|
1. Einheitliche Metadaten-Struktur für alle Placeholder
|
|
2. Vermeidung von Duplikation und Inkonsistenzen
|
|
3. Zentrale Verwaltung für alle Konsumenten
|
|
4. Evidence-basierte Transparenz
|
|
5. Erweiterbarkeit und Wartbarkeit
|
|
|
|
---
|
|
|
|
## 2. Verbindlichkeit
|
|
|
|
### 2.1 Pflicht zur Nutzung
|
|
|
|
**ALLE neuen Placeholder/Metrics MÜSSEN über das Registry Framework registriert werden.**
|
|
|
|
Keine Ausnahmen ohne explizite technische Begründung und Freigabe.
|
|
|
|
### 2.2 Betroffene Systeme
|
|
|
|
Folgende Systeme MÜSSEN die Registry als Single Source of Truth nutzen:
|
|
|
|
1. **Backend Prompt-Injektion** (Layer 2a)
|
|
- Placeholder-Resolver
|
|
- Prompt-Template-Engine
|
|
|
|
2. **GUI Auswahllisten**
|
|
- Placeholder-Picker
|
|
- Kategorie-Filter
|
|
- Metadata-Anzeige
|
|
|
|
3. **Extended Export**
|
|
- `/api/prompts/placeholders/export-values-extended`
|
|
- Catalog-Generierung
|
|
- ZIP-Export
|
|
|
|
4. **Validierung** (zukünftig)
|
|
- Metadata-Completeness-Checks
|
|
- Evidence-Quality-Assurance
|
|
- Compliance-Reports
|
|
|
|
5. **Diagramm-Zuordnung** (zukünftig)
|
|
- Chart-Metadata-Mapping
|
|
- Layer-2b-Integration
|
|
|
|
### 2.3 Verbotene Praktiken
|
|
|
|
**VERBOTEN:**
|
|
- Hardcoded Metadaten außerhalb der Registry
|
|
- Duplizierte Metadaten-Definitionen
|
|
- Placeholder ohne Registry-Registrierung
|
|
- Direkte Manipulation von Metadaten im Export-Code
|
|
- Inkonsistente Metadaten zwischen Systemen
|
|
|
|
---
|
|
|
|
## 3. Framework-Architektur
|
|
|
|
### 3.1 Kernkomponenten
|
|
|
|
**Modul:** `backend/placeholder_registry.py`
|
|
|
|
**Klassen:**
|
|
- `PlaceholderMetadata` - Metadata-Dataclass (22 Pflichtfelder)
|
|
- `MissingValuePolicy` - Strukturierte Missing-Value-Behandlung
|
|
- `PlaceholderRegistry` - Zentrale Registry (Singleton)
|
|
- `EvidenceType` - Enum für Evidenz-Tagging
|
|
- `OutputType` - Enum für Output-Typen
|
|
- `PlaceholderType` - Enum für Placeholder-Typen
|
|
|
|
**Singleton-Instanz:**
|
|
```python
|
|
from placeholder_registry import get_registry
|
|
|
|
registry = get_registry()
|
|
```
|
|
|
|
### 3.2 Registrierungs-Package
|
|
|
|
**Package:** `backend/placeholder_registrations/`
|
|
|
|
**Struktur:** Vollständige Cluster-Module (u. a. Ernährung, Körper, Aktivität, Schlaf,
|
|
Vitalwerte, Profil/Zeitraum, Phase-0b-Ziele, Korrelationen); siehe `__init__.py` für die
|
|
Import-Liste. **Anzahl:** 114 Platzhalter, identisch zu `PLACEHOLDER_MAP` in
|
|
`placeholder_resolver.py`.
|
|
|
|
**Auto-Registration:**
|
|
- Import des Package triggert automatische Registrierung aller Placeholder
|
|
- Keine manuelle Registrierung erforderlich
|
|
|
|
### 3.3 Export-Integration
|
|
|
|
**Modul:** `backend/placeholder_registry_export.py`
|
|
|
|
**Funktionen:**
|
|
- `get_registry_metadata_for_export()` - Metadata aus Registry
|
|
- `merge_registry_with_legacy_export()` - Backward-Compatibility
|
|
- `get_enhanced_export_with_registry()` - Vollständiger Export
|
|
|
|
**Endpoint-Integration:**
|
|
```python
|
|
# backend/routers/prompts.py
|
|
import placeholder_registrations # Auto-registers
|
|
from placeholder_registry_export import get_registry_metadata_for_export
|
|
|
|
registry_data = get_registry_metadata_for_export(profile_id)
|
|
export_data['registry_metadata'] = registry_data
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Metadata-Schema
|
|
|
|
### 4.1 Pflichtfelder (22 Felder)
|
|
|
|
**Core Identification (3):**
|
|
- `key` - Placeholder-Schlüssel (z.B. "kcal_avg")
|
|
- `category` - Kategorie (z.B. "Ernährung")
|
|
- `description` - Kurzbeschreibung
|
|
|
|
**Technical (6):**
|
|
- `resolver_module` - Modul-Pfad des Resolvers
|
|
- `resolver_function` - Funktionsname des Resolvers
|
|
- `data_layer_module` - Data Layer Modul (optional)
|
|
- `data_layer_function` - Data Layer Funktion (optional)
|
|
- `source_tables` - Liste der Quelltabellen
|
|
- `_resolver_func` - Runtime-Resolver (nicht exportiert)
|
|
|
|
**Semantic (8):**
|
|
- `semantic_contract` - Semantische Definition
|
|
- `business_meaning` - Fachliche Bedeutung
|
|
- `unit` - Einheit (z.B. "kcal/day")
|
|
- `time_window` - Zeitfenster (z.B. "30d")
|
|
- `output_type` - Output-Typ (Enum)
|
|
- `placeholder_type` - Placeholder-Typ (Enum)
|
|
- `format_hint` - Format-Information
|
|
- `example_output` - Beispiel-Ausgabe
|
|
|
|
**Quality (5):**
|
|
- `minimum_data_requirements` - Mindestanforderungen (optional)
|
|
- `quality_filter_policy` - Qualitätsfilter (optional)
|
|
- `confidence_logic` - Confidence-Berechnung (optional)
|
|
- `missing_value_policy` - Missing-Value-Handling
|
|
- `known_limitations` - Bekannte Einschränkungen (optional)
|
|
|
|
**Architecture (5):**
|
|
- `layer_1_decision` - Layer-1-Zuordnung (optional)
|
|
- `layer_2a_decision` - Layer-2a-Zuordnung (optional)
|
|
- `layer_2b_reuse_possible` - Chart-Reuse möglich (optional)
|
|
- `architecture_alignment` - Architektur-Konformität (optional)
|
|
- `issue_53_alignment` - Issue #53 Konformität (optional)
|
|
|
|
**Evidence Tracking (1):**
|
|
- `evidence` - Dict mapping Feldname → EvidenceType
|
|
|
|
### 4.2 Evidence-Typen
|
|
|
|
**Enum:** `EvidenceType`
|
|
|
|
**Werte:**
|
|
- `CODE_DERIVED` - Aus Code belegt (z.B. aus Import-Statement, SQL-Query)
|
|
- `DRAFT_DERIVED` - Aus Canonical Requirements Draft übernommen
|
|
- `MIXED` - Teilweise Code, teilweise Draft/abgeleitet
|
|
- `UNRESOLVED` - Nicht explizit dokumentiert, offen
|
|
- `TO_VERIFY` - Behauptung, muss noch verifiziert werden
|
|
|
|
**Verwendung:**
|
|
```python
|
|
metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
metadata.set_evidence("layer_2b_reuse_possible", EvidenceType.TO_VERIFY)
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Registrierungs-Workflow
|
|
|
|
### 5.1 Neuen Placeholder registrieren
|
|
|
|
**Schritt 1: Metadata-Objekt erstellen**
|
|
|
|
```python
|
|
# backend/placeholder_registrations/my_cluster.py
|
|
|
|
from placeholder_registry import (
|
|
PlaceholderMetadata,
|
|
MissingValuePolicy,
|
|
EvidenceType,
|
|
OutputType,
|
|
PlaceholderType,
|
|
register_placeholder
|
|
)
|
|
|
|
metadata = PlaceholderMetadata(
|
|
key="my_placeholder",
|
|
category="Meine Kategorie",
|
|
description="Kurzbeschreibung",
|
|
|
|
# Technical (CODE_DERIVED)
|
|
resolver_module="backend/placeholder_resolver.py",
|
|
resolver_function="get_my_placeholder",
|
|
data_layer_module="backend/data_layer/my_metrics.py",
|
|
data_layer_function="get_my_data",
|
|
source_tables=["my_table"],
|
|
|
|
# Semantic
|
|
semantic_contract="Was liefert dieser Placeholder?",
|
|
business_meaning="Fachliche Bedeutung",
|
|
unit="einheit",
|
|
time_window="30d",
|
|
output_type=OutputType.NUMERIC,
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|
format_hint="Ganzzahl",
|
|
example_output="42",
|
|
|
|
# Quality
|
|
confidence_logic="Wie wird Verlässlichkeit berechnet?",
|
|
missing_value_policy=MissingValuePolicy(
|
|
available=False,
|
|
value_raw=None,
|
|
missing_reason="insufficient_data",
|
|
legacy_display="nicht genug Daten"
|
|
),
|
|
known_limitations="Einschränkungen dokumentieren",
|
|
|
|
# Architecture
|
|
layer_1_decision="Data Layer (my_metrics.get_my_data)",
|
|
layer_2a_decision="Placeholder Resolver (formatting only)",
|
|
architecture_alignment="Phase 0c conform"
|
|
)
|
|
```
|
|
|
|
**Schritt 2: Evidence setzen**
|
|
|
|
```python
|
|
# Code-derived Felder
|
|
metadata.set_evidence("resolver_module", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("resolver_function", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("data_layer_module", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("source_tables", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
|
metadata.set_evidence("time_window", EvidenceType.CODE_DERIVED)
|
|
|
|
# Draft-derived Felder
|
|
metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
metadata.set_evidence("known_limitations", EvidenceType.DRAFT_DERIVED)
|
|
|
|
# Unresolved Felder
|
|
metadata.set_evidence("minimum_data_requirements", EvidenceType.UNRESOLVED)
|
|
```
|
|
|
|
**Schritt 3: Registrieren**
|
|
|
|
```python
|
|
register_placeholder(metadata)
|
|
```
|
|
|
|
**Schritt 4: Auto-Import sicherstellen**
|
|
|
|
```python
|
|
# backend/placeholder_registrations/__init__.py
|
|
from . import my_cluster
|
|
|
|
__all__ = ['nutrition_part_a', 'my_cluster']
|
|
```
|
|
|
|
### 5.2 Resolver-Funktion bereitstellen (optional)
|
|
|
|
Wenn der Placeholder runtime-resolved werden soll:
|
|
|
|
```python
|
|
from placeholder_resolver import get_my_placeholder
|
|
|
|
register_placeholder(
|
|
metadata,
|
|
resolver_func=lambda pid: get_my_placeholder(pid)
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 6. API-Nutzung
|
|
|
|
### 6.1 Metadata abrufen
|
|
|
|
```python
|
|
from placeholder_registry import get_registry
|
|
|
|
registry = get_registry()
|
|
|
|
# Einzelner Placeholder
|
|
meta = registry.get("kcal_avg")
|
|
print(meta.unit) # "kcal/day"
|
|
print(meta.time_window) # "30d"
|
|
|
|
# Alle Placeholder
|
|
all_metadata = registry.get_all() # Dict[str, PlaceholderMetadata]
|
|
|
|
# Nach Kategorie
|
|
ernaehrung = registry.get_by_category("Ernährung") # List[PlaceholderMetadata]
|
|
```
|
|
|
|
### 6.2 Export
|
|
|
|
```python
|
|
# Für Extended Export
|
|
export_data = registry.get_all_for_export() # List[Dict]
|
|
|
|
# Mit Runtime-Werten
|
|
from placeholder_registry_export import get_registry_metadata_for_export
|
|
|
|
registry_data = get_registry_metadata_for_export(profile_id)
|
|
# Returns: {flat, by_category, evidence_report, validation_report}
|
|
```
|
|
|
|
### 6.3 Validierung
|
|
|
|
```python
|
|
# Alle Placeholder validieren
|
|
issues = registry.validate_all() # Dict[str, List[str]]
|
|
|
|
if issues:
|
|
for key, problems in issues.items():
|
|
print(f"{key}: {problems}")
|
|
```
|
|
|
|
### 6.4 QA / Evidence-Tracking
|
|
|
|
```python
|
|
# Placeholder mit unresolved Fields finden
|
|
unresolved = registry.get_by_evidence_type(EvidenceType.UNRESOLVED)
|
|
# Returns: Dict[placeholder_key, List[field_names]]
|
|
|
|
# Placeholder die verifiziert werden müssen
|
|
to_verify = registry.get_by_evidence_type(EvidenceType.TO_VERIFY)
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Best Practices
|
|
|
|
### 7.1 Evidence-Tagging
|
|
|
|
**DO:**
|
|
- Jedes Feld mit Evidence-Tag versehen
|
|
- `CODE_DERIVED` nur wenn direkt aus Code ableitbar
|
|
- `TO_VERIFY` für Behauptungen, die noch geprüft werden müssen
|
|
- `UNRESOLVED` für fehlende/unklare Informationen
|
|
|
|
**DON'T:**
|
|
- Felder ohne Evidence lassen
|
|
- Evidence halluzinieren (wenn nicht belegt, `UNRESOLVED` nutzen)
|
|
- `CODE_DERIVED` für Draft-Informationen nutzen
|
|
|
|
### 7.2 Metadata-Vollständigkeit
|
|
|
|
**Minimum Required:**
|
|
- `key`, `category`, `description`
|
|
- `resolver_module`, `resolver_function`
|
|
- `semantic_contract`
|
|
- `unit`, `time_window`
|
|
- `output_type`, `placeholder_type`
|
|
|
|
**Optional but Recommended:**
|
|
- `data_layer_module`, `data_layer_function`
|
|
- `source_tables`
|
|
- `confidence_logic`, `missing_value_policy`
|
|
- `layer_1_decision`, `layer_2a_decision`
|
|
|
|
### 7.3 Modularisierung
|
|
|
|
**Registrations nach Cluster gruppieren:**
|
|
- `nutrition_part_a.py` - Nutrition Basis (4 Placeholder)
|
|
- `nutrition_part_b.py` - Nutrition Protein (5 Placeholder)
|
|
- `body_metrics.py` - Körper-Metriken (N Placeholder)
|
|
|
|
**Nicht:**
|
|
- Alle Placeholder in eine riesige Datei
|
|
- Placeholder ohne thematische Gruppierung
|
|
|
|
### 7.4 Backward-Compatibility
|
|
|
|
**Export-Endpoint MUSS:**
|
|
- Legacy-Export beibehalten (`export_data['legacy']`)
|
|
- Graceful degradation bei Registry-Fehler
|
|
- Registry-Metadata als separate Sektion (`export_data['registry_metadata']`)
|
|
|
|
---
|
|
|
|
## 8. Migration bestehender Placeholder
|
|
|
|
### 8.1 Priorität
|
|
|
|
**Part A (erledigt):** Nutrition Basis (kcal_avg, protein_avg, carb_avg, fat_avg)
|
|
|
|
**Nächste Priorität:**
|
|
1. Part B - Nutrition Protein (5 Placeholder)
|
|
2. Part C - Nutrition Balance (4 Placeholder)
|
|
3. Part D - Nutrition Meta (1 Placeholder)
|
|
4. Body Metrics (ca. 15 Placeholder)
|
|
5. Activity Metrics (ca. 20 Placeholder)
|
|
|
|
### 8.2 Migration-Workflow
|
|
|
|
**Für jeden Placeholder:**
|
|
1. Code inspizieren (Resolver, Data Layer, SQL)
|
|
2. Evidence ableiten (was ist code-derived, was draft-derived?)
|
|
3. Metadata-Objekt erstellen
|
|
4. Registrieren
|
|
5. Export testen
|
|
6. Werte-Identität bestätigen
|
|
|
|
**Keine Logikänderung während Migration!**
|
|
|
|
---
|
|
|
|
## 9. Compliance & Enforcement
|
|
|
|
### 9.1 Code-Review-Checkliste
|
|
|
|
**Für neue Placeholder:**
|
|
- [ ] Registry-Registrierung vorhanden?
|
|
- [ ] Evidence-Tags gesetzt?
|
|
- [ ] Metadata-Vollständigkeit (minimum required)?
|
|
- [ ] Auto-Import in `__init__.py`?
|
|
- [ ] Export getestet?
|
|
|
|
### 9.2 CI/CD-Integration (zukünftig)
|
|
|
|
**Geplante Checks:**
|
|
- Alle Placeholder in PLACEHOLDER_MAP sind in Registry registriert
|
|
- Keine Placeholder ohne Evidence-Tags
|
|
- Keine doppelten Registrierungen
|
|
- Metadata-Vollständigkeit für production-ready Placeholder
|
|
|
|
---
|
|
|
|
## 10. Support & Weiterentwicklung
|
|
|
|
### 10.1 Fragen & Issues
|
|
|
|
**Bei Unklarheiten:**
|
|
1. Diese Dokumentation prüfen
|
|
2. Bestehende Registrations als Vorlage nutzen (`nutrition_part_a.py`)
|
|
3. Code-Review anfragen
|
|
|
|
### 10.2 Framework-Erweiterungen
|
|
|
|
**Geplante Features:**
|
|
- GUI-Integration (Placeholder-Picker mit Registry-Metadata)
|
|
- Validation-Dashboard (QA-Monitoring)
|
|
- Evidence-Report-Endpoint (Metadata-Qualität)
|
|
- Resolver-Test-Framework (Automatisierte Werteänderungs-Detektion)
|
|
- Chart-Metadata-Mapping (Layer-2b-Integration)
|
|
|
|
### 10.3 Versions-History
|
|
|
|
**v1.0 (2026-04-02):**
|
|
- Initial Release
|
|
- Part A Implementation (4 Nutrition Placeholders)
|
|
- Core Framework + Export-Integration
|
|
|
|
---
|
|
|
|
## 11. Referenzen
|
|
|
|
**Code:**
|
|
- `backend/placeholder_registry.py` - Core Framework
|
|
- `backend/placeholder_registrations/nutrition_part_a.py` - Part A Implementation
|
|
- `backend/placeholder_registry_export.py` - Export-Integration
|
|
- `backend/routers/prompts.py` - Export-Endpoint
|
|
|
|
**Dokumentation:**
|
|
- `.claude/task/rework_0b_placeholder/NUTRITION_PART_A_CHANGE_PLAN.md`
|
|
- `.claude/task/rework_0b_placeholder/NUTRITION_PART_A_IMPLEMENTATION_REPORT.md`
|
|
|
|
**Beispiel-Export:**
|
|
```bash
|
|
curl "https://dev.mitai.jinkendo.de/api/prompts/placeholders/export-values-extended?token=XXX"
|
|
```
|
|
|
|
---
|
|
|
|
**Ende Verbindliche Dokumentation**
|