From 1fa2b1925717117abffbbaeeee1c91128f4371cf Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 20 Jun 2026 14:13:09 -0400 Subject: [PATCH] conductor(plan): mark Phase 11 complete (ai_client SS 11->0; CRITICAL anti-sliming) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 11: ai_client silent-swallow cleanup (11 sites migrated). Helpers added to src/ai_client.py: - _try_warm_sdk_result(name) -> Result[Any] (sites 1+2) - _set_tool_preset_result(preset_name) -> Result[None] (site 5) - _set_bias_profile_result(profile_name) -> Result[None] (site 6) - _extract_gemini_thoughts_result(resp) -> Result[str] (site 7) - _list_minimax_models_result(api_key) -> Result[list[str]] (site 8) - _count_gemini_tokens_for_stats_result(md_content) -> Result[int] (sites 9+10) Helpers reused from earlier phases: - _delete_gemini_cache_result from Phase 10 (sites 3+4) - _set_tool_preset_result from site 5 (site 11) Per-site decision (TIER1_REVIEW Phase 11 anti-sliming protocol): - Sites with 'except: pass': MIGRATE to Result (no sentinel-None) - Sites with 'except (NarrowType): sys.stderr.write': MIGRATE to Result - _try_warm_sdk_result: Result variant (NOT sentinel-None which the audit flagged as UNCLEAR; Result pattern matches Heuristic A) Dilemma resolved: initial sentinel approach (_try_warm_sdk -> Any | None) flagged as UNCLEAR (Heuristic B requires class method + self.attr assign). Per Phase 9 redo precedent: migrate to Result instead of adding heuristic. Audit state (after Phase 11): mcp_client: 0 migration-target (Phase 3-8 complete) ai_client: 18 -> 7 migration-target BC: 0 (Phase 10 done) SS: 11 -> 0 ✓ RETHROW: 6 (Phase 12) UNCLEAR: 0 COMPLIANT: 27 -> 33 (+6 from helpers) rag_engine: 9 migration-target (Phase 13) Tests: 97 pass (was 79 in Phase 10; +18 Phase 11 site/invariant tests). --- .../state.toml | 27 ++++--- tests/tier2/phase11_invariant_test.py | 80 +++++++++++++++++++ 2 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 tests/tier2/phase11_invariant_test.py diff --git a/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml b/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml index 52bcf388..856e8d19 100644 --- a/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml +++ b/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml @@ -29,7 +29,7 @@ phase_7 = { status = "completed", checkpointsha = "44607f79", name = "mcp_client phase_8 = { status = "completed", checkpointsha = "dec1780", name = "mcp_client silent-swallow + UNCLEAR (5 + 1 = 6 sites; CRITICAL anti-sliming)" } phase_9 = { status = "completed", checkpointsha = "84b7a693", name = "ai_client Batch A (broad-catch; <=8 sites)" } phase_10 = { status = "completed", checkpointsha = "40a60e63", name = "ai_client Batch B (broad-catch; 9 sites migrated via 7 helpers; BC 9->0)" } -phase_11 = { status = "pending", checkpointsha = "", name = "ai_client silent-swallow (9 sites; CRITICAL anti-sliming)" } +phase_11 = { status = "completed", checkpointsha = "26ebbf78", name = "ai_client silent-swallow (11 sites; CRITICAL anti-sliming; SS 11->0, UNCLEAR 0->0)" } phase_12 = { status = "pending", checkpointsha = "", name = "ai_client rethrow classification (7 sites; Pattern 1/2/3 or migrate)" } phase_13 = { status = "pending", checkpointsha = "", name = "rag_engine migration (1 SS + 5 BC + 3 RETHROW = 9 sites)" } phase_14 = { status = "pending", checkpointsha = "", name = "Audit gate + end-of-track report (5 tasks; --include-baseline --strict exits 0; 11/11 tiers PASS; campaign 100% complete)" } @@ -143,17 +143,18 @@ t10_8 = { status = "completed", commit_sha = "40a60e63", description = "Migrate t10_9 = { status = "in_progress", commit_sha = "", description = "Add Phase 10 invariant test; Phase 10 checkpoint" } # Phase 11: ai_client silent-swallow (9 sites; CRITICAL anti-sliming) -t11_0 = { status = "pending", commit_sha = "", description = "Phase 11 styleguide re-read + ack commit (CRITICAL anti-sliming)" } -t11_1 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 1" } -t11_2 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 2" } -t11_3 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 3" } -t11_4 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 4" } -t11_5 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 5" } -t11_6 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 6" } -t11_7 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 7" } -t11_8 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 8" } -t11_9 = { status = "pending", commit_sha = "", description = "Migrate silent-swallow site 9" } -t11_10 = { status = "pending", commit_sha = "", description = "Add Phase 11 invariant test; Phase 11 checkpoint" } +t11_0 = { status = "completed", commit_sha = "8237833", description = "Phase 11 styleguide re-read + ack commit (CRITICAL anti-sliming)" } +t11_1 = { status = "completed", commit_sha = "26ebbf78", description = "Migrate sites 1+2 (_classify_*_error; try_warm_sdk_result helper)" } +t11_2 = { status = "completed", commit_sha = "26ebbf78", description = "Migrate site 2 (combined with site 1)" } +t11_3 = { status = "completed", commit_sha = "fb7014cd", description = "Migrate sites 3+4 (cleanup + reset_session; reuse _delete_gemini_cache_result from Phase 10)" } +t11_4 = { status = "completed", commit_sha = "fb7014cd", description = "Migrate site 4 (combined with site 3)" } +t11_5 = { status = "completed", commit_sha = "343b855a", description = "Migrate site 5 (set_tool_preset)" } +t11_6 = { status = "completed", commit_sha = "343b855a", description = "Migrate site 6 (set_bias_profile; combined with site 5)" } +t11_7 = { status = "completed", commit_sha = "89000dec", description = "Migrate site 7 (_extract_gemini_thoughts)" } +t11_8 = { status = "completed", commit_sha = "89000dec", description = "Migrate site 8 (_list_minimax_models; combined with site 7)" } +t11_9 = { status = "completed", commit_sha = "80eebfb8", description = "Migrate sites 9+10 (get_token_stats count_tokens for gemini+gemini_cli)" } +t11_10 = { status = "completed", commit_sha = "48cca536", description = "Migrate site 11 (top-level SLOP_TOOL_PRESET env var; reuse _set_tool_preset_result)" } +t11_11 = { status = "in_progress", commit_sha = "", description = "Add Phase 11 invariant test; Phase 11 checkpoint" } # Phase 12: ai_client rethrow classification (7 sites) t12_0 = { status = "pending", commit_sha = "", description = "Phase 12 styleguide re-read (Re-Raise Patterns lines 625-690) + ack commit" } @@ -198,7 +199,7 @@ phase_7_complete = true phase_8_complete = true phase_9_complete = true phase_10_complete = true -phase_11_complete = false +phase_11_complete = true phase_12_complete = false phase_13_complete = false phase_14_complete = false diff --git a/tests/tier2/phase11_invariant_test.py b/tests/tier2/phase11_invariant_test.py new file mode 100644 index 00000000..fb19ed8f --- /dev/null +++ b/tests/tier2/phase11_invariant_test.py @@ -0,0 +1,80 @@ +"""Phase 11 invariant tests (GREEN). + +11 SS sites migrated via 8 helpers + 1 reused helper: +- _try_warm_sdk_result (sites 1+2; both classify functions) +- _delete_gemini_cache_result (reused from Phase 10 for sites 3+4) +- _set_tool_preset_result (site 5) +- _set_bias_profile_result (site 6; also used by site 11) +- _extract_gemini_thoughts_result (site 7) +- _list_minimax_models_result (site 8) +- _count_gemini_tokens_for_stats_result (sites 9+10) +- _set_tool_preset_result (site 11; reused from site 5) +""" +import sys +sys.path.insert(0, ".") + + +def test_phase11_ai_client_ss_count_zero(): + """After Phase 11: ai_client SS count is 0 (was 11).""" + import json + import subprocess + r = subprocess.run( + ["uv", "run", "python", "scripts/audit_exception_handling.py", + "--include-baseline", "--json"], + capture_output=True, text=True + ) + data = json.loads(r.stdout) + files = {f["filename"]: f for f in data["files"]} + ai = files["src\\ai_client.py"] + ss = sum(1 for x in ai["findings"] if x["category"] == "INTERNAL_SILENT_SWALLOW") + assert ss == 0, f"expected ai_client SS=0 after Phase 11, got {ss}" + + +def test_phase11_ai_client_unclear_count_zero(): + """After Phase 11: ai_client UNCLEAR count is 0.""" + import json + import subprocess + r = subprocess.run( + ["uv", "run", "python", "scripts/audit_exception_handling.py", + "--include-baseline", "--json"], + capture_output=True, text=True + ) + data = json.loads(r.stdout) + files = {f["filename"]: f for f in data["files"]} + ai = files["src\\ai_client.py"] + unclear = sum(1 for x in ai["findings"] if x["category"] == "UNCLEAR") + assert unclear == 0, f"expected ai_client UNCLEAR=0 after Phase 11, got {unclear}" + + +def test_phase11_all_helpers_exist(): + """All 7 new _result helpers must exist on ai_client.""" + import src.ai_client + expected = [ + "_try_warm_sdk_result", + "_set_tool_preset_result", + "_set_bias_profile_result", + "_extract_gemini_thoughts_result", + "_list_minimax_models_result", + "_count_gemini_tokens_for_stats_result", + ] + for name in expected: + assert hasattr(src.ai_client, name), f"{name} helper missing" + + +def test_phase11_legacy_functions_preserved(): + """All legacy functions must still be callable.""" + import src.ai_client + legacy = [ + "_classify_anthropic_error", + "_classify_gemini_error", + "cleanup", + "reset_session", + "set_tool_preset", + "set_bias_profile", + "_extract_gemini_thoughts", + "_list_minimax_models", + "get_token_stats", + ] + for name in legacy: + assert hasattr(src.ai_client, name), f"{name} legacy function missing" + assert callable(getattr(src.ai_client, name)), f"{name} not callable" \ No newline at end of file