393 lines
15 KiB
Python
393 lines
15 KiB
Python
|
|
"""Registry: Ziele, Fokusbereiche, Kategorie-Scores und formatierte Listen (Phase 0b)."""
|
|||
|
|
|
|||
|
|
from placeholder_registry import (
|
|||
|
|
PlaceholderMetadata,
|
|||
|
|
MissingValuePolicy,
|
|||
|
|
OutputType,
|
|||
|
|
PlaceholderType,
|
|||
|
|
register_placeholder,
|
|||
|
|
)
|
|||
|
|
from ._evidence import tag_standard_evidence
|
|||
|
|
|
|||
|
|
CAT = "Ziele & Fokus (Phase 0b)"
|
|||
|
|
MVP = lambda reason, disp: MissingValuePolicy(
|
|||
|
|
available=False, value_raw=None, missing_reason=reason, legacy_display=disp
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def register_phase_0b_ziele_fokus():
|
|||
|
|
# Top-Ziel / Top-Fokusbereich
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key="top_goal_name",
|
|||
|
|
category=CAT,
|
|||
|
|
description="Name/Typ des höchstpriorisierten Ziels",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_str",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="get_top_priority_goal",
|
|||
|
|
source_tables=["goals"],
|
|||
|
|
semantic_contract="Feld name oder goal_type aus get_top_priority_goal",
|
|||
|
|
business_meaning="Priorisierung für KI-Empfehlungen",
|
|||
|
|
unit="text",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.STRING,
|
|||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|||
|
|
format_hint="Kurztext",
|
|||
|
|
example_output="Gewicht 80kg",
|
|||
|
|
minimum_data_requirements="Mindestens ein aktives Ziel",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.get_top_priority_goal",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.get_top_priority_goal",
|
|||
|
|
layer_2a_decision="_safe_str('top_goal_name')",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key="top_goal_progress_pct",
|
|||
|
|
category=CAT,
|
|||
|
|
description="Fortschritt Top-Ziel (%)",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_int",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="get_top_priority_goal",
|
|||
|
|
source_tables=["goals"],
|
|||
|
|
semantic_contract="progress_pct aus get_top_priority_goal",
|
|||
|
|
business_meaning="Priorisierung für KI-Empfehlungen",
|
|||
|
|
unit="%",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.NUMERIC,
|
|||
|
|
placeholder_type=PlaceholderType.SCORE,
|
|||
|
|
format_hint="Ganzzahl",
|
|||
|
|
example_output="65",
|
|||
|
|
minimum_data_requirements="Mindestens ein aktives Ziel",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.get_top_priority_goal",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.get_top_priority_goal",
|
|||
|
|
layer_2a_decision="_safe_int('top_goal_progress_pct')",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key="top_goal_status",
|
|||
|
|
category=CAT,
|
|||
|
|
description="Status-Label Top-Ziel",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_str",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="get_top_priority_goal",
|
|||
|
|
source_tables=["goals"],
|
|||
|
|
semantic_contract="status aus get_top_priority_goal",
|
|||
|
|
business_meaning="Priorisierung für KI-Empfehlungen",
|
|||
|
|
unit="text",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.STRING,
|
|||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|||
|
|
format_hint="Kurztext",
|
|||
|
|
example_output="active",
|
|||
|
|
minimum_data_requirements="Mindestens ein aktives Ziel",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.get_top_priority_goal",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.get_top_priority_goal",
|
|||
|
|
layer_2a_decision="_safe_str('top_goal_status')",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key="top_focus_area_name",
|
|||
|
|
category=CAT,
|
|||
|
|
description="Bezeichnung des gewichtet stärksten Fokusbereichs",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_str",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="get_top_focus_area",
|
|||
|
|
source_tables=["user_focus_area_weights", "focus_area_definitions"],
|
|||
|
|
semantic_contract="label aus get_top_focus_area",
|
|||
|
|
business_meaning="Priorisierung für KI-Empfehlungen",
|
|||
|
|
unit="text",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.STRING,
|
|||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|||
|
|
format_hint="Kurztext",
|
|||
|
|
example_output="Kraft",
|
|||
|
|
minimum_data_requirements="Gewichtete Fokusbereiche",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.get_top_focus_area",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.get_top_focus_area",
|
|||
|
|
layer_2a_decision="_safe_str('top_focus_area_name')",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key="top_focus_area_progress",
|
|||
|
|
category=CAT,
|
|||
|
|
description="Fortschritt Top-Fokusbereich (%)",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_int",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="get_top_focus_area",
|
|||
|
|
source_tables=["user_focus_area_weights", "focus_area_definitions", "goals"],
|
|||
|
|
semantic_contract="progress aus get_top_focus_area",
|
|||
|
|
business_meaning="Priorisierung für KI-Empfehlungen",
|
|||
|
|
unit="%",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.NUMERIC,
|
|||
|
|
placeholder_type=PlaceholderType.SCORE,
|
|||
|
|
format_hint="Ganzzahl",
|
|||
|
|
example_output="58",
|
|||
|
|
minimum_data_requirements="Gewichtete Fokusbereiche",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.get_top_focus_area",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.get_top_focus_area",
|
|||
|
|
layer_2a_decision="_safe_int('top_focus_area_progress')",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
# Kategorie Progress / Weight (7 Kategorien)
|
|||
|
|
for slug in (
|
|||
|
|
"körper",
|
|||
|
|
"ernährung",
|
|||
|
|
"aktivität",
|
|||
|
|
"recovery",
|
|||
|
|
"vitalwerte",
|
|||
|
|
"mental",
|
|||
|
|
"lebensstil",
|
|||
|
|
):
|
|||
|
|
key_p = f"focus_cat_{slug}_progress"
|
|||
|
|
key_w = f"focus_cat_{slug}_weight"
|
|||
|
|
m_p = PlaceholderMetadata(
|
|||
|
|
key=key_p,
|
|||
|
|
category=CAT,
|
|||
|
|
description=f"Aggregierter Fortschritt Kategorie „{slug}“ (%)",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_int",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="calculate_category_progress",
|
|||
|
|
source_tables=["goals", "focus_area_definitions", "user_focus_area_weights"],
|
|||
|
|
semantic_contract=f"scores.calculate_category_progress(pid, '{slug}')",
|
|||
|
|
business_meaning="Focus-Area-Kategorie-Score",
|
|||
|
|
unit="%",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.NUMERIC,
|
|||
|
|
placeholder_type=PlaceholderType.SCORE,
|
|||
|
|
format_hint="Ganzzahl",
|
|||
|
|
example_output="55",
|
|||
|
|
minimum_data_requirements="Gewichtete Bereiche in Kategorie",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.calculate_category_progress",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.calculate_category_progress",
|
|||
|
|
layer_2a_decision="_safe_int",
|
|||
|
|
layer_2b_reuse_possible=True,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m_p)
|
|||
|
|
register_placeholder(m_p)
|
|||
|
|
|
|||
|
|
m_w = PlaceholderMetadata(
|
|||
|
|
key=key_w,
|
|||
|
|
category=CAT,
|
|||
|
|
description=f"Nutzer-Gewichtung Kategorie „{slug}“ (Anteil 0–1)",
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function="_safe_float",
|
|||
|
|
data_layer_module="backend/data_layer/scores.py",
|
|||
|
|
data_layer_function="calculate_category_weight",
|
|||
|
|
source_tables=["user_focus_area_weights", "focus_area_definitions"],
|
|||
|
|
semantic_contract=f"scores.calculate_category_weight(pid, '{slug}')",
|
|||
|
|
business_meaning="Kategorie-Gewichtung im Fokusmodell",
|
|||
|
|
unit="0–1",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.NUMERIC,
|
|||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|||
|
|
format_hint="Dezimal",
|
|||
|
|
example_output="0.25",
|
|||
|
|
minimum_data_requirements="user_focus_area_weights",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="scores.calculate_category_weight",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="scores.calculate_category_weight",
|
|||
|
|
layer_2a_decision="_safe_float",
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m_w)
|
|||
|
|
register_placeholder(m_w)
|
|||
|
|
|
|||
|
|
# Strukturierte Ziele / Fokus
|
|||
|
|
for key, res_fn, dl_mod, dl_fn, desc, out, ptype in [
|
|||
|
|
(
|
|||
|
|
"active_goals_json",
|
|||
|
|
"_safe_json",
|
|||
|
|
"backend/goal_utils.py",
|
|||
|
|
"get_active_goals",
|
|||
|
|
"Aktive Ziele als JSON",
|
|||
|
|
OutputType.JSON,
|
|||
|
|
PlaceholderType.RAW_DATA,
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"active_goals_md",
|
|||
|
|
"_safe_str",
|
|||
|
|
"backend/placeholder_resolver.py",
|
|||
|
|
"_format_goals_as_markdown",
|
|||
|
|
"Aktive Ziele als Markdown-Tabelle",
|
|||
|
|
OutputType.TEXT_SUMMARY,
|
|||
|
|
PlaceholderType.INTERPRETED,
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"focus_areas_weighted_json",
|
|||
|
|
"_safe_json",
|
|||
|
|
"backend/placeholder_resolver.py",
|
|||
|
|
"_get_focus_areas_weighted_json",
|
|||
|
|
"Gewichtete Fokusbereiche mit Namen (JSON)",
|
|||
|
|
OutputType.JSON,
|
|||
|
|
PlaceholderType.RAW_DATA,
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"focus_areas_weighted_md",
|
|||
|
|
"_safe_str",
|
|||
|
|
"backend/placeholder_resolver.py",
|
|||
|
|
"_format_focus_areas_as_markdown",
|
|||
|
|
"Gewichtete Fokusbereiche als Markdown",
|
|||
|
|
OutputType.TEXT_SUMMARY,
|
|||
|
|
PlaceholderType.INTERPRETED,
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"focus_area_weights_json",
|
|||
|
|
"_safe_json",
|
|||
|
|
"backend/data_layer/scores.py",
|
|||
|
|
"get_user_focus_weights",
|
|||
|
|
"Rohe Gewichtungen key→Anteil (JSON)",
|
|||
|
|
OutputType.JSON,
|
|||
|
|
PlaceholderType.RAW_DATA,
|
|||
|
|
),
|
|||
|
|
]:
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key=key,
|
|||
|
|
category=CAT,
|
|||
|
|
description=desc,
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function=res_fn,
|
|||
|
|
data_layer_module=dl_mod,
|
|||
|
|
data_layer_function=dl_fn,
|
|||
|
|
source_tables=["goals", "focus_area_definitions", "user_focus_area_weights"],
|
|||
|
|
semantic_contract=f"{dl_fn} (siehe Modul {dl_mod})",
|
|||
|
|
business_meaning="Strukturierte Übersicht für Prompts",
|
|||
|
|
unit="JSON" if out == OutputType.JSON else "markdown",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=out,
|
|||
|
|
placeholder_type=ptype,
|
|||
|
|
format_hint="String aus Resolver",
|
|||
|
|
example_output="[]" if out == OutputType.JSON else "—",
|
|||
|
|
minimum_data_requirements="Ziele bzw. Fokusgewichte",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic="Resolver + goal_utils / scores",
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "[]" if out == OutputType.JSON else "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision=dl_fn,
|
|||
|
|
layer_2a_decision=res_fn,
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 1",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
for key, res_fn, dl_fn, desc, ex in [
|
|||
|
|
(
|
|||
|
|
"top_3_focus_areas",
|
|||
|
|
"_safe_str",
|
|||
|
|
"_format_top_focus_areas",
|
|||
|
|
"Top-3 Fokusbereiche als formatierter Text",
|
|||
|
|
"1. Kraft …",
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"top_3_goals_behind_schedule",
|
|||
|
|
"_safe_str",
|
|||
|
|
"_format_goals_behind",
|
|||
|
|
"Bis zu drei Ziele hinter Zeitplan",
|
|||
|
|
"—",
|
|||
|
|
),
|
|||
|
|
(
|
|||
|
|
"top_3_goals_on_track",
|
|||
|
|
"_safe_str",
|
|||
|
|
"_format_goals_on_track",
|
|||
|
|
"Bis zu drei Ziele im Plan",
|
|||
|
|
"—",
|
|||
|
|
),
|
|||
|
|
]:
|
|||
|
|
m = PlaceholderMetadata(
|
|||
|
|
key=key,
|
|||
|
|
category=CAT,
|
|||
|
|
description=desc,
|
|||
|
|
resolver_module="backend/placeholder_resolver.py",
|
|||
|
|
resolver_function=res_fn,
|
|||
|
|
data_layer_module="backend/goal_utils.py",
|
|||
|
|
data_layer_function="get_active_goals",
|
|||
|
|
source_tables=["goals", "focus_area_definitions"],
|
|||
|
|
semantic_contract=f"Resolver {dl_fn}",
|
|||
|
|
business_meaning="Kurzlisten für Coaching-Prompts",
|
|||
|
|
unit="text",
|
|||
|
|
time_window="aktuell",
|
|||
|
|
output_type=OutputType.TEXT_SUMMARY,
|
|||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|||
|
|
format_hint="Freitext / Aufzählung",
|
|||
|
|
example_output=ex,
|
|||
|
|
minimum_data_requirements="Ziele / Fokusdaten",
|
|||
|
|
quality_filter_policy=None,
|
|||
|
|
confidence_logic=dl_fn,
|
|||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
|||
|
|
known_limitations=None,
|
|||
|
|
layer_1_decision="goals + focus aggregation",
|
|||
|
|
layer_2a_decision=dl_fn,
|
|||
|
|
layer_2b_reuse_possible=False,
|
|||
|
|
architecture_alignment="Phase 0b",
|
|||
|
|
issue_53_alignment="Layer 2a",
|
|||
|
|
evidence={},
|
|||
|
|
)
|
|||
|
|
tag_standard_evidence(m)
|
|||
|
|
register_placeholder(m)
|
|||
|
|
|
|||
|
|
|
|||
|
|
register_phase_0b_ziele_fokus()
|