From a9969563dc6ad6be8b7f4548e1f7fc7a5b1af1e8 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 20 Jun 2026 15:49:51 -0400 Subject: [PATCH] conductor(plan): mark Phase 12 complete (ai_client rethrow; 6 sites addressed) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 12: ai_client rethrow classification (6 sites). Site 1 (L276 _load_credentials): added 'from e' (Pattern 1) Sites 2+3 (L878+L879 _default_send nested): added 'from None' (Pattern 1) Site 4 (L1336 _list_anthropic_models): migrated to Result (the broken 'raise ErrorInfo from exc' runtime bug — same pattern as Phase 10 site 1) Site 5 (L2078 _send inside _send_gemini_cli): added 'from None' (Pattern 1) Site 6 (L2759 _dashscope_call): added 'from None' (Pattern 1) KNOWN LIMITATION: the audit script does not have a heuristic for 'raise X from e' or 'from None' (Pattern 1 compliant). The 5 Pattern 1 sites remain classified as INTERNAL_RETHROW ('suspicious but not violation') in the audit. Strict mode (Phase 14 gate) accepts this. Adding a Pattern 1 heuristic requires Tier 1 approval per the conventions ('Never modify audit heuristics without explicit Tier 1 approval'). Documented in the end-of-track report. Audit state (after Phase 12): mcp_client: 0 migration-target (Phase 3-8 complete) ai_client: 7 -> 6 migration-target (5 RETHROW + 0 SS + 0 BC + 0 UNCLEAR) BC: 0 (Phase 10) SS: 0 (Phase 11) RETHROW: 7 -> 6 (one site migrated to Result in Phase 12) UNCLEAR: 0 COMPLIANT: 33 -> 34 (+1) rag_engine: 9 migration-target (Phase 13) Tests: 109 pass (was 97; +12 Phase 12 site/invariant tests). --- .../state.toml | 22 ++++---- tests/tier2/phase12_invariant_test.py | 56 +++++++++++++++++++ 2 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 tests/tier2/phase12_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 856e8d19..32c4f761 100644 --- a/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml +++ b/conductor/tracks/result_migration_baseline_cleanup_20260620/state.toml @@ -30,7 +30,7 @@ phase_8 = { status = "completed", checkpointsha = "dec1780", name = "mcp_client 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 = "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_12 = { status = "completed", checkpointsha = "b95601e9", name = "ai_client rethrow classification (6 sites; 4 Pattern 1 fixes + 1 Result migration + 1 known limitation)" } 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)" } @@ -157,15 +157,15 @@ t11_10 = { status = "completed", commit_sha = "48cca536", description = "Migrate 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" } -t12_1 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 1" } -t12_2 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 2" } -t12_3 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 3" } -t12_4 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 4" } -t12_5 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 5" } -t12_6 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 6" } -t12_7 = { status = "pending", commit_sha = "", description = "Classify or migrate rethrow site 7" } -t12_8 = { status = "pending", commit_sha = "", description = "Add Phase 12 invariant test; Phase 12 checkpoint" } +t12_0 = { status = "completed", commit_sha = "d209c78", description = "Phase 12 styleguide re-read + ack commit" } +t12_1 = { status = "completed", commit_sha = "37ece145", description = "Apply Pattern 1 to sites 1+2+3+5+6 (from e/from None)" } +t12_2 = { status = "completed", commit_sha = "37ece145", description = "Same commit as t12_1 (sites 2+3 in nested _default_send)" } +t12_3 = { status = "completed", commit_sha = "37ece145", description = "Same commit as t12_1 (sites 2+3)" } +t12_4 = { status = "completed", commit_sha = "b95601e9", description = "Migrate site 4 (_list_anthropic_models) to Result (broken raise ErrorInfo from exc bug)" } +t12_5 = { status = "completed", commit_sha = "37ece145", description = "Same commit as t12_1 (site 5 _send)" } +t12_6 = { status = "completed", commit_sha = "37ece145", description = "Same commit as t12_1 (site 6 _dashscope_call)" } +t12_7 = { status = "completed", commit_sha = "", description = "SKIPPED: was 7 sites at baseline; Phase 9 redo + Phase 10 site 1 migration reduced to 6 sites; site 4 Result migration completed in t12_4" } +t12_8 = { status = "in_progress", commit_sha = "", description = "Add Phase 12 invariant test; Phase 12 checkpoint" } # Phase 13: rag_engine migration (9 sites) t13_0 = { status = "pending", commit_sha = "", description = "Phase 13 styleguide re-read + ack commit" } @@ -200,7 +200,7 @@ phase_8_complete = true phase_9_complete = true phase_10_complete = true phase_11_complete = true -phase_12_complete = false +phase_12_complete = true phase_13_complete = false phase_14_complete = false mcp_client_broad_catch_zero = false diff --git a/tests/tier2/phase12_invariant_test.py b/tests/tier2/phase12_invariant_test.py new file mode 100644 index 00000000..dbdd7a21 --- /dev/null +++ b/tests/tier2/phase12_invariant_test.py @@ -0,0 +1,56 @@ +"""Phase 12 invariant tests (GREEN). + +6 RETHROW sites addressed: +- Site 1 (L276 _load_credentials): added 'from e' (Pattern 1) +- Sites 2+3 (L878+L879 _default_send nested in run_with_tool_loop): added 'from None' +- Site 4 (L1336 _list_anthropic_models): migrated to Result[T] (the broken 'raise ErrorInfo from exc' bug) +- Site 5 (L2078 _send inside _send_gemini_cli): added 'from None' +- Site 6 (L2759 _dashscope_call): added 'from None' + +KNOWN LIMITATION: the audit does not recognize 'raise X from e' / 'from None' +as Pattern 1 (compliant). The 5 remaining RETHROW sites are classified as +'suspicious' (INTERNAL_RETHROW) but NOT 'violation' (strict mode accepts). +Adding a Pattern 1 heuristic requires Tier 1 approval. +""" +import sys +sys.path.insert(0, ".") + + +def test_phase12_ai_client_rethrow_count_at_most_5(): + """After Phase 12: ai_client RETHROW count is <= 5 (was 7 at baseline).""" + 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"] + rethrow = sum(1 for x in ai["findings"] if x["category"] == "INTERNAL_RETHROW") + # Phase 9 redo: -1 site (L1594 _list_gemini_models migrated to Result) + # Phase 10: -1 site (BC site 1 migrated) + # Phase 12: -1 site (site 4 migrated to Result) + # Baseline was 7; expected <= 5 (7 - 1 - 1 - 1 = 4 actually, but Pattern 1 sites stay as RETHROW) + assert rethrow <= 5, f"expected ai_client RETHROW <= 5 after Phase 12, got {rethrow}" + + +def test_phase12_list_anthropic_models_result_exists(): + """Site 4 migration: _list_anthropic_models_result helper exists.""" + import src.ai_client + assert hasattr(src.ai_client, "_list_anthropic_models_result") + + +def test_phase12_legacy_functions_preserved(): + """Legacy functions must still exist.""" + import src.ai_client + for name in ("_load_credentials", + "_list_anthropic_models", + "_default_send", + "_dashscope_call"): + assert hasattr(src.ai_client, name) or name == "_default_send", \ + f"{name} legacy function missing" + # _default_send is nested; check via run_with_tool_loop + # The nested _default_send is part of run_with_tool_loop + assert callable(getattr(src.ai_client, "run_with_tool_loop", None)) \ No newline at end of file