"""Closed vocabularies shared by EasyCom event pre-label and review tools.""" from __future__ import annotations EXCLUDE_REASONS = { "OUT_OF_SCOPE_NORMAL_COMPLETION", "OUT_OF_SCOPE_WITHIN_TURN_CONTINUATION", "OUT_OF_SCOPE_POST_COMPLETION_ACTIVITY", "OUT_OF_SCOPE_NON_EVENT", "INSUFFICIENT_EVIDENCE", "DATA_ANNOTATION_ERROR", "DATA_RECORDING_BOUNDARY", "DATA_MISSING_CONTEXT", "DATA_NON_SPEECH_ARTIFACT", "DATA_TIMESTAMP_CORRUPTION", } # Accepted only when loading or editing old review records. New DeepSeek and UI # outputs use the prefixed taxonomy above so scope and data-quality counts are # never silently combined. LEGACY_EXCLUDE_REASONS = { "ANNOTATION_ERROR", "RECORDING_BOUNDARY", "MISSING_CONTEXT", "NON_SPEECH_ARTIFACT", "TIMESTAMP_CORRUPTION", "UNRESOLVABLE", } def exclude_reason_group(reason: str | None) -> str | None: """Map a leaf reason to a stable aggregation group.""" if reason is None: return None if reason.startswith("OUT_OF_SCOPE_"): return "OUT_OF_SCOPE" if reason == "INSUFFICIENT_EVIDENCE": return "INSUFFICIENT_EVIDENCE" if reason.startswith("DATA_"): return "DATA_QUALITY" if reason in LEGACY_EXCLUDE_REASONS: return "LEGACY_UNSPECIFIED" return "UNKNOWN"