from __future__ import annotations import unittest from pathlib import Path from uuid import uuid4 from .services.deliberate_practice import ( assess_practice_episode, load_practice_benchmark, prescribe_from_coaching_cards, ) from .services.practice_runtime_observer import ( EvaluatedTurnPair, RuntimePracticeObservationError, derive_runtime_episode, ) BENCHMARK_PATH = ( Path(__file__).resolve().parent / "data" / "deliberate_practice_benchmark_g4.v1.json" ) class PracticeRuntimeObserverTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.pack = load_practice_benchmark(BENCHMARK_PATH) def test_durable_turn_pairs_produce_independent_before_after_episode(self) -> None: case = self.pack.cases[0] prescription = prescribe_from_coaching_cards(case.coaching_cards)[0] session_id = uuid4() same_case = uuid4() persona = uuid4() episode = derive_runtime_episode( prescription=prescription, practice_session_id=session_id, source_case_id=same_case, source_persona_id=persona, practice_case_id=same_case, practice_persona_id=persona, turn_pairs=( EvaluatedTurnPair( counselor_turn_id=uuid4(), counselor_turn_seq=1, client_turn_id=uuid4(), client_turn_seq=2, technique_codes=("facilitative_question",), client_state_codes=("defensive",), appropriateness="warn", utterance_fingerprint="sha256:first", ), EvaluatedTurnPair( counselor_turn_id=uuid4(), counselor_turn_seq=3, client_turn_id=uuid4(), client_turn_seq=4, technique_codes=("reflection",), client_state_codes=("affect_contact",), appropriateness="pos", utterance_fingerprint="sha256:second", ), ), ) assessment = assess_practice_episode(prescription, episode) self.assertEqual(assessment.comparison.change, "improved") self.assertEqual(assessment.progress, "transfer_pending") self.assertEqual(episode.attempts[-1].criterion.source_kind, "model_inferred") self.assertEqual( episode.attempts[-1].criterion.perspective, "independent_observer", ) def test_server_identity_marks_cross_case_as_unseen_transfer(self) -> None: case = self.pack.cases[0] prescription = prescribe_from_coaching_cards(case.coaching_cards)[0] episode = derive_runtime_episode( prescription=prescription, practice_session_id=uuid4(), source_case_id=uuid4(), source_persona_id=uuid4(), practice_case_id=uuid4(), practice_persona_id=uuid4(), turn_pairs=( EvaluatedTurnPair( counselor_turn_id=uuid4(), counselor_turn_seq=1, client_turn_id=uuid4(), client_turn_seq=2, technique_codes=("reflection",), client_state_codes=("thought_organizing",), appropriateness="pos", utterance_fingerprint="sha256:novel", ), ), ) prior_state = case.graph.states[0].model_copy( update={ "band": "consistent_local", "attempt_count": 1, "familiar_demonstrations": 1, "highest_familiar_difficulty": 1, "evidence_refs": tuple( case.episodes[0].attempts[0].criterion.evidence_refs ), } ) assessment = assess_practice_episode( prescription, episode, prior_state=prior_state, ) self.assertEqual(episode.attempts[0].scenario_novelty, "unseen_transfer") self.assertEqual(assessment.progress, "mastered") def test_unknown_competency_mapping_fails_closed(self) -> None: case = self.pack.cases[0] prescription = prescribe_from_coaching_cards(case.coaching_cards)[0].model_copy( update={"competency_id": "competency.unknown-skill"} ) with self.assertRaisesRegex(RuntimePracticeObservationError, "unsupported"): derive_runtime_episode( prescription=prescription, practice_session_id=uuid4(), source_case_id=uuid4(), source_persona_id=uuid4(), practice_case_id=uuid4(), practice_persona_id=uuid4(), turn_pairs=(), ) def test_durable_audio_metadata_can_satisfy_voice_retry_without_capture(self) -> None: case = self.pack.cases[3] prescription = prescribe_from_coaching_cards(case.coaching_cards)[0] episode = derive_runtime_episode( prescription=prescription, practice_session_id=uuid4(), source_case_id=uuid4(), source_persona_id=uuid4(), practice_case_id=None, practice_persona_id=None, turn_pairs=( EvaluatedTurnPair( counselor_turn_id=uuid4(), counselor_turn_seq=1, client_turn_id=uuid4(), client_turn_seq=2, technique_codes=("holding",), client_state_codes=("thought_organizing",), appropriateness="pos", utterance_fingerprint="sha256:voice", has_voice_feature=True, ), ), ) assessment = assess_practice_episode(prescription, episode) self.assertEqual(assessment.attempts[0].outcome, "passed") self.assertIn( "voice_feature", {item.kind for item in assessment.attempts[0].evidence_refs}, ) if __name__ == "__main__": unittest.main()