from __future__ import annotations import json import tempfile import unittest from pathlib import Path from types import SimpleNamespace from scripts.replay_stream import _controller_config from turn_detection.runtime.controller import ControllerConfig from turn_detection.runtime.predictor import ModelMetadata from turn_detection.runtime.replay import ( PauseCheckpoint, replay_checkpoints, replay_jsonl, summarize_replay, ) class ReplayTest(unittest.TestCase): def test_replay_policy_loads_exported_model_metadata(self) -> None: metadata = ModelMetadata( model_name="preview", architecture="tiny_tcn", threshold=0.74, controller=ControllerConfig( endpoint_threshold=0.74, long_pause_threshold=0.56, min_silence_ms=250, relax_after_ms=900, max_silence_ms=2_000, required_confirmations=2, ), ) with tempfile.TemporaryDirectory() as directory: path = Path(directory) / "model_metadata.json" path.write_text(json.dumps(metadata.to_dict()), encoding="utf-8") args = SimpleNamespace( metadata=str(path), threshold=None, long_pause_threshold=None, min_silence_ms=None, relax_after_ms=None, max_silence_ms=None, confirmations=None, ) loaded = _controller_config(args) self.assertEqual(loaded, metadata.controller) args.threshold = 0.80 overridden = _controller_config(args) self.assertAlmostEqual(overridden.endpoint_threshold, 0.80) self.assertAlmostEqual(overridden.long_pause_threshold, 0.62) def test_product_metrics_count_interruptions_and_delay(self) -> None: checkpoints = [ PauseCheckpoint("a", 300, 300, 0.9, False), PauseCheckpoint("a", 1000, 300, 0.9, True), PauseCheckpoint("b", 200, 200, 0.1, False), PauseCheckpoint("b", 900, 300, 0.9, True), ] records = replay_checkpoints( checkpoints, ControllerConfig(endpoint_threshold=0.6, required_confirmations=1), ) metrics = summarize_replay(records) self.assertEqual(metrics["turns"], 2) self.assertEqual(metrics["turns_with_premature_interruption"], 1) self.assertAlmostEqual(metrics["premature_interruption_probability_per_turn"], 0.5) self.assertEqual(metrics["endpoint_turn_detection_rate"], 0.5) self.assertEqual(metrics["endpoint_delay_p50_ms"], 0.0) self.assertEqual(metrics["response_emissions"], 2) self.assertEqual(metrics["duplicate_response_emissions"], 0) def test_order_is_validated_per_turn(self) -> None: checkpoints = [ PauseCheckpoint("a", 400, 300, 0.5, False), PauseCheckpoint("a", 300, 400, 0.5, True), ] with self.assertRaises(ValueError): replay_checkpoints(checkpoints) def test_jsonl_summary_binds_files_and_labels_synthetic_scope(self) -> None: with tempfile.TemporaryDirectory() as directory: source = Path(directory) / "fixture.jsonl" output = Path(directory) / "decisions.jsonl" source.write_text( json.dumps( { "turn_id": "synthetic-a", "timestamp_ms": 300, "silence_ms": 300, "endpoint_probability": 0.9, "target_endpoint": True, } ) + "\n", encoding="utf-8", ) summary = replay_jsonl( source, output, ControllerConfig(endpoint_threshold=0.6), evidence_scope="synthetic_integration", ) self.assertEqual(summary["evidence_scope"], "synthetic_integration") self.assertIn("not model", summary["evidence_note"]) self.assertEqual(summary["input"]["bytes"], source.stat().st_size) self.assertEqual(summary["decisions"]["bytes"], output.stat().st_size) self.assertEqual(len(summary["input"]["sha256"]), 64) persisted = json.loads(output.with_suffix(".summary.json").read_text()) self.assertEqual(persisted, summary) with self.assertRaisesRegex(ValueError, "unsupported replay evidence scope"): replay_jsonl(source, output, evidence_scope="official_test") if __name__ == "__main__": unittest.main()