"""Phase 10 sites 7+8+9: run_tier4_* Result helpers. Site 7 (run_tier4_analysis): returns str with '[QA ANALYSIS FAILED]' on error. Site 8 (run_tier4_patch_callback): returns Optional[str] with None on error. Site 9 (run_tier4_patch_generation): returns str with '[PATCH GENERATION FAILED]' on error. All 3 follow the same pattern: try: ...AI call... except Exception as e: return "[XXX FAILED] {e}" (or None) Migrate via Result[str] / Result[Optional[str]] helpers. """ import sys sys.path.insert(0, ".") def test_phase10_sites789_run_tier4_analysis_result_exists(): import src.ai_client assert hasattr(src.ai_client, "_run_tier4_analysis_result"), \ "_run_tier4_analysis_result helper missing" def test_phase10_sites789_run_tier4_patch_callback_result_exists(): import src.ai_client assert hasattr(src.ai_client, "_run_tier4_patch_callback_result"), \ "_run_tier4_patch_callback_result helper missing" def test_phase10_sites789_run_tier4_patch_generation_result_exists(): import src.ai_client assert hasattr(src.ai_client, "_run_tier4_patch_generation_result"), \ "_run_tier4_patch_generation_result helper missing" def test_phase10_sites789_all_helpers_return_result(): import src.ai_client import inspect for name in ("_run_tier4_analysis_result", "_run_tier4_patch_callback_result", "_run_tier4_patch_generation_result"): fn = getattr(src.ai_client, name) sig = inspect.signature(fn) assert "Result" in str(sig.return_annotation), \ f"{name} return must be Result, got {sig.return_annotation}" def test_phase10_sites789_legacy_unchanged(): """Legacy functions preserved EXCEPT those OBLITERATED by code_path_audit_phase_2 cleanup. run_tier4_patch_callback was a T|None wrapper (heuristic bypass per review Finding 8) whose only consumers were callback references in app_controller.py and multi_agent_conductor.py. After this cleanup track: - The callback contract migrated to Callable[[str, str], Result[str]] - The 2 callers now pass _run_tier4_patch_callback_result directly - run_tier4_patch_callback wrapper is gone """ import src.ai_client legacy = ["run_tier4_analysis", "run_tier4_patch_generation"] obliterated = ["run_tier4_patch_callback"] for name in legacy: assert hasattr(src.ai_client, name), f"{name} missing" assert callable(getattr(src.ai_client, name)), f"{name} not callable" for name in obliterated: assert not hasattr(src.ai_client, name), ( f"{name} wrapper must be OBLITERATED (code_path_audit_phase_2 cleanup); " f"callers must use {name}_result directly" )