import '../models/habit.dart'; /// Output of LLM frame suggestion. Always L2/L3 — L0/L1 candidates are /// discarded by [parseFrameCandidates] + `validateFrameLevel`. class FrameCandidate { final FrameLevel level; final String framedText; final double confidence; final String? sourcePatternId; const FrameCandidate({ required this.level, required this.framedText, this.confidence = 0.5, this.sourcePatternId, }); @override bool operator ==(Object other) => other is FrameCandidate && other.level == level && other.framedText == framedText && other.confidence == confidence && other.sourcePatternId == sourcePatternId; @override int get hashCode => Object.hash(level, framedText, confidence, sourcePatternId); } /// Input bundle for [suggestFrame]. class SuggestFrameInput { final String rawText; final HabitType habitType; final String? anchorHint; const SuggestFrameInput({ required this.rawText, required this.habitType, this.anchorHint, }); }