"""Phase 11 sites 1+2: _classify_anthropic_error + _classify_gemini_error. Both have: try: sdk = _require_warmed("xxx") if isinstance(exc, sdk.SomeException): return ErrorInfo(...) ... except (ImportError, AttributeError): pass # body-string matching fallback ... Body: pass = SS violation (silent recovery). Migration: extract a _try_warm_sdk sentinel helper. Caller checks for None and proceeds. The sentinel helper itself uses 'try: return ...; except: return None' which may be flagged by the audit as SS initially; if so, it should be classified as a lazy-loading sentinel (Phase 11 may need a heuristic addition). """ import sys sys.path.insert(0, ".") def test_phase11_sites12_try_warm_sdk_result_helper_exists(): import src.ai_client assert hasattr(src.ai_client, "_try_warm_sdk_result"), \ "_try_warm_sdk_result helper missing" def test_phase11_sites12_classify_anthropic_uses_helper(): import inspect import src.ai_client src_text = inspect.getsource(src.ai_client._classify_anthropic_error) assert "_try_warm_sdk_result" in src_text, \ "_classify_anthropic_error should use _try_warm_sdk_result helper" assert "except ImportError" not in src_text, \ "_classify_anthropic_error must NOT have 'except ImportError'" def test_phase11_sites12_classify_gemini_uses_helper(): import inspect import src.ai_client src_text = inspect.getsource(src.ai_client._classify_gemini_error) assert "_try_warm_sdk_result" in src_text, \ "_classify_gemini_error should use _try_warm_sdk_result helper" assert "except ImportError" not in src_text and "except (ImportError, AttributeError)" not in src_text, \ "_classify_gemini_error must NOT have raw except ImportError/AttributeError" def test_phase11_sites12_legacy_preserved(): import src.ai_client assert callable(getattr(src.ai_client, "_classify_anthropic_error", None)) assert callable(getattr(src.ai_client, "_classify_gemini_error", None))