from __future__ import annotations from dataclasses import dataclass from typing import List from .schema import SemanticPlan, RiskFlag, ComplexityLevel @dataclass(frozen=True) class PlanValidationResult: ok: bool warnings: List[str] risk_flags: List[RiskFlag] complexity_level: ComplexityLevel def validate_plan(plan: SemanticPlan) -> PlanValidationResult: warnings: List[str] = [] risk_flags: List[RiskFlag] = list(plan.risk_flags) if len(plan.primary_entities) > 5: warnings.append("Too many primary_entities; may reduce coherence.") if RiskFlag.ambiguity not in risk_flags: risk_flags.append(RiskFlag.ambiguity) if len(plan.must_include) > 7: warnings.append("Too many must_include constraints; generation may become brittle.") if plan.complexity_level == ComplexityLevel.low: complexity = ComplexityLevel.medium else: complexity = plan.complexity_level else: complexity = plan.complexity_level lower_moods = {m.lower() for m in plan.mood_emotion} if "calm" in lower_moods and "tense" in lower_moods: warnings.append("Conflicting mood_emotion signals (calm + tense).") if RiskFlag.emotional_conflict not in risk_flags: risk_flags.append(RiskFlag.emotional_conflict) overlap = {x.lower() for x in plan.must_include}.intersection( {y.lower() for y in plan.must_avoid} ) if overlap: warnings.append( "Conflicting constraints: " f"{sorted(overlap)} appear in both must_include and must_avoid." ) if RiskFlag.conflicting_constraints not in risk_flags: risk_flags.append(RiskFlag.conflicting_constraints) return PlanValidationResult( ok=True, warnings=warnings, risk_flags=risk_flags, complexity_level=complexity, )