"""Non-fatal consistency checks for Phase 7 analysis records.""" from __future__ import annotations from .models import LogConsistencyIssue, PersonAnalysisRecord class LogConsistencyChecker: """Report suspicious analysis combinations without stopping a run.""" def check(self, records: list[PersonAnalysisRecord]) -> list[LogConsistencyIssue]: issues: list[LogConsistencyIssue] = [] seen: set[int] = set() for item in records: if item.track_id in seen: self._add(issues, "duplicate_summary", item, "Duplicate track summary") seen.add(item.track_id) if item.response_detected and not (item.prompt_played or item.pseudo_prompt): self._add(issues, "missing_prompt_for_response", item, "Response has no prompt or pseudo prompt") if item.reaction_time_sec is not None and item.reaction_time_sec < 0: self._add(issues, "invalid_reaction_time", item, "Reaction time is negative") if item.response_detected and not item.turn_confirmed: self._add(issues, "response_without_turn", item, "Response has no confirmed turn") if item.prompt_played and not item.response_window_started: self._add(issues, "prompt_without_response_window", item, "Prompt has no response window") if item.pseudo_prompt and item.voice_mode != "control": self._add(issues, "inconsistent_voice_mode", item, "Pseudo prompt is not control mode") if item.valid_for_voice_analysis and item.prompt_condition == "unknown": self._add(issues, "inconsistent_voice_mode", item, "Valid record has unknown condition") if item.excluded and item.exclusion_reason == "none": self._add(issues, "unknown", item, "Excluded record has no reason") return issues @staticmethod def _add(items: list[LogConsistencyIssue], kind: str, record: PersonAnalysisRecord, message: str) -> None: items.append(LogConsistencyIssue(kind, "warning", record.track_id, None, message, {}))