""" Declarative schemas for template-based training evaluation (Layer 1 scaffold). Templates select built-in algorithms by id and pass parameters; they do not embed executable logic. See resolver and algorithm registry. """ from __future__ import annotations from dataclasses import dataclass, field from typing import Any, Dict, List, Mapping, Optional @dataclass(frozen=True) class FocusAreaMapping: """Maps a share of one dimension's score to a Focus Area (by stable key).""" focus_area_key: str weight: float @dataclass(frozen=True) class DimensionSpec: """ One evaluation dimension: algorithm + inputs + params + FA mapping. inputs: names of keys expected in the flat activity_inputs dict passed to the resolver. """ key: str algorithm_id: str inputs: tuple[str, ...] params: Mapping[str, Any] maps_to: tuple[FocusAreaMapping, ...] @dataclass(frozen=True) class CalculationTemplate: """Declarative multi-dimensional calculation template (in-code registry).""" id: str version: str label: str dimensions: tuple[DimensionSpec, ...] @dataclass(frozen=True) class TrainingBaseProfile: """ Conceptual base profile: links a training context to a default template. allowed_dimension_keys: if set, dimensions not listed are skipped at resolve time. """ key: str label: str default_template_id: str allowed_dimension_keys: Optional[frozenset[str]] = None @dataclass class AlgorithmRunResult: """Output of a single built-in algorithm execution.""" raw_score: float normalized_score: float missing_inputs: List[str] detail: Dict[str, Any] = field(default_factory=dict) @dataclass class DimensionResult: """Per-dimension result after resolution.""" dimension_key: str algorithm_id: str raw_score: float normalized_score: float missing_inputs: List[str] evidence: Dict[str, Any] = field(default_factory=dict) @dataclass class TrainingEvaluationResult: """ Stable structured result for Layer 2 (KI, charts, APIs, future persistence). focus_area_contributions: aggregated contribution per focus_area key (additive). """ template_id: str template_version: str base_profile_key: Optional[str] dimension_results: List[DimensionResult] focus_area_contributions: Dict[str, float] confidence: str evidence: Dict[str, Any] trace: Optional[Dict[str, Any]] = None def to_serializable(self) -> Dict[str, Any]: """JSON-compatible dict (for APIs / storage).""" return { "template_id": self.template_id, "template_version": self.template_version, "base_profile_key": self.base_profile_key, "dimension_results": [ { "dimension_key": d.dimension_key, "algorithm_id": d.algorithm_id, "raw_score": d.raw_score, "normalized_score": d.normalized_score, "missing_inputs": d.missing_inputs, "evidence": d.evidence, } for d in self.dimension_results ], "focus_area_contributions": dict(self.focus_area_contributions), "confidence": self.confidence, "evidence": self.evidence, "trace": self.trace, }