import asyncio import unittest from unittest.mock import MagicMock, AsyncMock from orchestrator import BuddyOrchestrator from config import CONFIDENCE_THRESHOLD_HIGH, CONFIDENCE_THRESHOLD_MEDIUM class TestAdaptiveFailureMode(unittest.IsolatedAsyncioTestCase): def setUp(self): self.orchestrator = BuddyOrchestrator() # Mock strategy manager self.orchestrator.strategy_manager = MagicMock() self.orchestrator.strategy_manager.solve_with_strategy = AsyncMock() # Mock internal methods to isolate orchestration logic self.orchestrator._classify_question = AsyncMock(return_value={"complexity": "COMPLEX", "num_parts": 1}) self.orchestrator._extract_key_data = AsyncMock(return_value={}) self.orchestrator.smart_solve = AsyncMock(return_value={"sections": []}) async def test_high_confidence_flow(self): print(f"\n🟢 Testing High Confidence (> {CONFIDENCE_THRESHOLD_HIGH}):") self.orchestrator._last_ocr_confidence = CONFIDENCE_THRESHOLD_HIGH + 0.05 await self.orchestrator.solve_problem("x + 1 = 2 and we need to solve it step by step for the student", "י'", "TestStudent") # Verify smart_solve was called with ambiguity_warning=False args, kwargs = self.orchestrator.smart_solve.call_args self.assertFalse(kwargs['ambiguity_warning']) print(f" āœ… High Confidence {self.orchestrator._last_ocr_confidence} - Passed (No warning)") async def test_medium_confidence_soft_recovery(self): print(f"\n🟔 Testing Medium Confidence ({CONFIDENCE_THRESHOLD_MEDIUM} - {CONFIDENCE_THRESHOLD_HIGH}):") # Ensure we are in the medium range self.orchestrator._last_ocr_confidence = (CONFIDENCE_THRESHOLD_HIGH + CONFIDENCE_THRESHOLD_MEDIUM) / 2 # Force escalation to smart_solve by mocking quick_solve failure self.orchestrator._quick_solve = AsyncMock(return_value=None) await self.orchestrator.solve_problem("x + 1 = 2 and we need to solve it step by step for the student", "י'", "TestStudent") # Verify smart_solve was called with ambiguity_warning=True args, kwargs = self.orchestrator.smart_solve.call_args self.assertTrue(kwargs['ambiguity_warning']) print(f" āœ… Medium Confidence {self.orchestrator._last_ocr_confidence} - Passed (Soft Recovery triggered)") async def test_low_confidence_hard_stop(self): # We need to make sure we are BELOW CONFIDENCE_THRESHOLD_MEDIUM # In DEV it is 0.01, so let's use 0.005 low_val = min(0.005, CONFIDENCE_THRESHOLD_MEDIUM - 0.001) print(f"\nšŸ”“ Testing Low Confidence (< {CONFIDENCE_THRESHOLD_MEDIUM}):") self.orchestrator._last_ocr_confidence = low_val result = await self.orchestrator.solve_problem("x + 1 = 2 and we need to solve it step by step for the student", "י'", "TestStudent") # V7.3: Check logic_error and error_type instead of 'status' self.assertTrue(result.get("logic_error")) self.assertEqual(result.get("error_type"), "RECAPTURE_REQUIRED") self.orchestrator.smart_solve.assert_not_called() print(f" āœ… Low Confidence {self.orchestrator._last_ocr_confidence} - Passed (Hard Stop triggered)") if __name__ == "__main__": unittest.main()