{
  "id": "result_migration_small_files_20260617",
  "title": "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes + Result[T] propagation to drain points + Test Count Verification)",
  "type": "refactor + audit-script maintenance",
  "status": "completed",
  "priority": "A",
  "created": "2026-06-17",
  "owner": "tier2-tech-lead",
  "parent_umbrella": "result_migration_20260616",
  "sub_track_of_5": 2,
  "spec": "conductor/tracks/result_migration_small_files_20260617/spec.md",
  "plan": "conductor/tracks/result_migration_small_files_20260617/plan.md",
  "scope": {
    "files_affected": 38,
    "files_audit_script": 1,
    "files_migrated": 37,
    "small_files": 35,
    "medium_files": 2,
    "sites_to_migrate": 76,
    "sites_migrated_phase_3_to_8": 49,
    "sites_migrated_phase_10": 26,
    "violation_sites": 62,
    "suspicious_sites": 10,
    "unclear_sites": 4,
    "unclear_sites_outside_review_scope": 4,
    "silent_swallow_sites_remaining_after_phase_8": 27,
    "new_unclear_sites_from_narrowing": 14,
    "io_pool_callback_sites_to_thread_result": 4,
    "audit_script_lines_changed": "~60 (3 bug fixes; one per commit) + ~30 (2-3 new heuristics in Phase 10)",
    "audit_script_heuristics_added": "0-2 (conditional on the 4 UNCLEAR patterns) + 2-3 (Phase 10)",
    "report_lines": "~200-300 (per-site decisions for 4 UNCLEAR + per-file summary + audit-script fix summary) + ~100 (Phase 10 addendum)"
  },
  "depends_on": [
    "result_migration_20260616 (umbrella)",
    "result_migration_review_pass_20260617 (shipped 2026-06-17; provides the per-site decisions and the 3 audit-script bug documentation)"
  ],
  "blocks": [
    "result_migration_app_controller_<future_date> (the controller migration depends on the audit being correct; sub-track 2 fixes the 3 audit bugs)",
    "result_migration_gui_2_<future_date> (the GUI migration depends on the controller; transitively depends on the audit fixes)"
  ],
  "tshirt_size": "L",
  "test_summary": {
    "new_tests": "9-12 (6-9 for the 3 audit-script bug fixes + 0-3 for any new heuristics + N for the migrations)",
    "modified_tests": 0,
    "test_pass_count_target": "1288 + 4 + 10 (review-pass tests) + 9-12 (audit bug fix tests) + N (migration tests) = 1311 + N"
  },
  "verification_criteria": [
    "scripts/audit_exception_handling.py has the 3 documented bugs fixed (visit_Try walker, render_json filter, render_json truncation)",
    "Re-running the audit post-Phase-1: src/rag_engine.py:31 is in the findings; per-file list is complete; per-file list is not truncated to top 15",
    "The 4 UNCLEAR sites in SMALL files are classified (compliant or migration-target); decisions recorded in the report",
    "All 37 files (35 SMALL + 2 MEDIUM) are migrated to the convention (49 sites in Phase 3-8 + 27 sites in Phase 10)",
    "Phase 10: full Result[T] migration for the 27 INTERNAL_SILENT_SWALLOW sites; no narrowing, no logging-only, no silent recovery. Every site returns Result[T] with structured ErrorInfo. Callers check result.ok and result.errors",
    "Phase 10: 2-3 new audit heuristics that reclassify the 14 new UNCLEAR sites (created by the narrowing in Phase 3-8) as INTERNAL_COMPLIANT or BOUNDARY_*",
    "Phase 10: the 4 io_pool callback sites (warmup.py:139/215/249 + hot_reloader.py:58) thread the Result through the io_pool completion handler; the completion handler checks result.ok",
    "Re-running the audit post-Phase-10: 0 INTERNAL_SILENT_SWALLOW + 0 UNCLEAR + 0 migration-target sites in the 37-file scope (G4 deviation resolved)",
    "Full test pass count: all 11 test tiers PASS",
    "Atomic commits per batch: spec, plan, metadata, state, 3 audit-script fix commits, 4 UNCLEAR classification commits, 35 SMALL migration commits (5-7 files per commit), 2 MEDIUM migration commits, Phase 10 commits (27 Result[T] migrations + 2-3 new heuristics + verification + completion), completion commits"
  ],
  "out_of_scope": [
    "Migrating the 3 BASELINE files (mcp_client, ai_client, rag_engine) - sub-track 5",
    "Migrating src/gui_2.py or src/app_controller.py - sub-tracks 4 and 3",
    "The send_result -> send mass rename - separate work after this phase",
    "Refactoring the audit script's overall architecture - Phase 1 fixes 3 specific bugs only; Phase 10 adds 2-3 new heuristics only",
    "Adding new Result patterns to areas that don't have any - this track migrates EXISTING sites only",
    "The 'public API' concern - this is a 20K LOC Python project, not enterprise. The convention requires Result[T] everywhere it can fail; callers are updated to check result.ok"
  ],
  "risks": [
    {
      "id": "R1",
      "description": "Fixing visit_Try surfaces new migration-target sites in the 37 files (raises in non-last except handlers)",
      "mitigation": "Phase 1 verification (Task 1.4.1) counts the new findings; per-batch scope adjusts"
    },
    {
      "id": "R2",
      "description": "The 4 UNCLEAR sites turn out to be non-trivial migrations (>5 lines each)",
      "mitigation": "Phase 2 classifies first; if any are >10 lines, they get their own commit in Phase 7"
    },
    {
      "id": "R3",
      "description": "Audit-script fixes introduce regressions in the 10 existing heuristic tests",
      "mitigation": "TDD workflow; each fix is verified in isolation before the next"
    },
    {
      "id": "R4",
      "description": "Migration breaks behavior in a way the test suite doesn't catch",
      "mitigation": "Task 9.2 catches regressions; for non-tier-tested files, manual smoke-testing is added"
    },
    {
      "id": "R5",
      "description": "Batched-commit pattern (5-7 files per commit) is too coarse for some files",
      "mitigation": "Batch plan can be adjusted per-file; umbrella spec is guidance, not rigid"
    },
    {
      "id": "R6",
      "description": "The MEDIUM files (session_logger, warmup) have complex migrations that don't fit the Result pattern",
      "mitigation": "Per the styleguide, some sites are legitimately BOUNDARY_*; those stay as-is; decision is documented"
    },
    {
      "id": "R7 (Phase 10)",
      "description": "A SILENT_SWALLOW site is actually a conditional capture that needs to inspect the exception (e.g., 'if e.specific_field == X: handle_gracefully()')",
      "mitigation": "Full Result migration preserves the exception in result.errors[0].exception; the caller can inspect it. The Result migration is not destructive of the original logic"
    },
    {
      "id": "R8 (Phase 10)",
      "description": "Migrating Result[T] through io_pool callbacks (warmup.py) requires the io_pool's API to accept Result returns",
      "mitigation": "The io_pool already uses callback-based dispatch; the Result is delivered to the completion handler as a parameter. No io_pool change needed; the caller is updated to check result.ok"
    },
    {
      "id": "R9 (Phase 10)",
      "description": "The 2-3 new audit heuristics misclassify sites that should be INTERNAL_BROAD_CATCH or INTERNAL_SILENT_SWALLOW",
      "mitigation": "TDD: each heuristic has a failing test first; the test suite covers the canonical patterns. If a heuristic is too broad, narrow the conditions and re-test"
    }
  ],
  "estimated_effort": {
    "method": "Scope (per conductor/workflow.md section Tier 1 Track Initialization Rules). NO day estimates. The user / Tier 2 agent decides the actual pacing.",
    "scope": "37 files (35 SMALL + 2 MEDIUM); 76 sites total (49 migrated in Phase 3-8 + 27 to migrate in Phase 10); 3 audit-script bug fixes in Phase 1; 2-3 new audit heuristics in Phase 10; ~200-300 lines of report + ~100 lines of Phase 10 addendum"
  },
  "deferred_to_followup_tracks": [
    {
      "id": "result_migration_subsequent_subtracks",
      "title": "Result Migration Sub-Tracks 3-5",
      "description": "After this sub-track's Phase 10 ships, sub-tracks 3 (app_controller), 4 (gui_2), and 5 (baseline_cleanup) pick up the migration work. Sub-tracks 3 and 4 depend on the audit being correct (Phase 1 of this sub-track fixes the 3 bugs; Phase 10 adds 2-3 new heuristics).",
      "track_status": "blocked by this sub-track (after Phase 10 ships)"
    }
  ],
  "outcomes": {
    "phase_3_to_8_sites_migrated": 49,
    "phase_10_REJECTED": true,
    "phase_10_sites_migrated": 5,
    "phase_10_sites_slimed_NOT_Result": 21,
    "phase_10_laundering_heuristics_added": 5,
    "phase_10_REJECTED_reason": "21 sites slimed via narrow-catch+log/return-fallback (not full Result); 5 laundering heuristics (#22-#26) added",
    "phase_11_REJECTS_phase_10_sliming": true,
    "phase_11_REVERTS_phase_10_laundering_heuristics": true,
    "phase_11_ADD_heuristic_A": true,
    "phase_11_sites_full_result": 5,
    "phase_11_sites_helper_extracts": 2,
    "phase_11_sites_already_compliant_documented": 14,
    "phase_11_known_limitation_warmup_L185": 1,
    "phase_11_status": "REJECTED; Heuristic #19 left in place (logging is NOT a drain); visit_Try audit bug not fixed; tier-2 misclassified 2 sites; ~18+ nested-Try sites silently missed; tier-2's test count claim of 10/11 tiers was wrong (the 11th tier tier-1-unit-comms was miscounted)",
    "phase_12_user_principle": "IF ANY PLACE HAS A ERROR LOG IT ALSO NEEDS A RESULT[T]. RESULT[T] PROPOGATES UNTIL IT REACHED A DRAIN POINT WHERE THE ERROR CAN BE HANDLED APPROPRIATELY WITHOUT CRASHING THE APP. THE APP SHOULD ALMOST NEVER CRASH UNLESS SOMETHING CRITICAL FAILS THAT PREVENTS IT FROM ACTUALLY OPERATING WITH ITS FEATURES.",
    "phase_12_user_directive_2": "make sure tier 2 is required to read that styleguide and make sure to update the style guide to be aware of the concept of a drain point, which just makes explicit a place where result[t]",
    "phase_12_prerequisites": "TIER-2 MUST READ conductor/code_styleguides/error_handling.md end-to-end BEFORE any Phase 12 code work. The styleguide is the source of truth. The AI's training data is the OPPOSITE of this convention. The read is acknowledged in the commit message of the next task (t12_0.2).",
    "phase_12_styleguide_update": "3 changes to conductor/code_styleguides/error_handling.md: (A) add Drain Points section with 5 patterns (HTTP error response, GUI error display, app termination, telemetry, retry-with-bounded-attempts); (B) update Broad-Except Distinction table to explicitly say narrow+log = INTERNAL_SILENT_SWALLOW violation (prevents Heuristic #19 regression); (C) add MUST-READ rule to AI Agent Checklist. Without these changes, the next agent will re-add Heuristic #19 because the styleguide's narrow+log=violation rule is implicit in the Broad-Except Distinction table, not explicit.",
    "phase_12_visit_try_bug_fixed": "in progress; the bug: visit_Try does not recurse into node.body; the fix: add 'for child in node.body: self.visit(child)'; verified: src/api_hooks.py has 23 actual try/except nodes but the audit only reports 5 (gap of 18 sites, 12+ of which are silent-fallback violations)",
    "phase_12_heuristic_19_REMOVED": "in progress; Heuristic #19 ('narrow + log = compliant') was laundering. Logging is NOT a drain. The user's principle: Result[T] must propagate to a real drain point.",
    "phase_12_heuristic_D_added": "in progress; 5 drain-point patterns: (1) HTTP error response, (2) GUI error display, (3) intentional app termination, (4) telemetry emission, (5) retry-with-bounded-attempts. TDD-first; each pattern has a passing test.",
    "phase_12_sites_to_migrate": "TBD; the audit after the visit_Try fix + Heuristic #19 removal will surface N additional sites. The triage (Task 12.5.1) lists every site.",
    "phase_12_test_count_11_tiers": "The number of test tiers is 11, NOT 10. The 11th tier is tier-1-unit-comms. Tier-2 has been miscounting in every prior phase. The test count claim in the Phase 12 completion report MUST say 11, not 10.",
    "phase_12_REJECTED": true,
    "phase_12_REJECTED_reason": "Tier-2 marked Phase 12 complete based on incomplete test results. The test runner script scripts/run_tests_batched.py crashed at line 185 with UnicodeEncodeError after running only 5 of 11 tiers. tier-1-unit-core FAILED with 3 unverified 'pre-existing' failures (1 of which is a mock assertion that is NOT a Gemini 503). The 6 remaining tiers (tier-2-mock-* + tier-3-live_gui) were NOT executed. The '11 tiers total. 10 PASS' claim in commit 2235e4b8 is FALSE; actual count is 5 tested, 4 PASS, 1 FAIL, 6 NOT TESTED.",
    "phase_13_user_directive": "ok make a phase 13",
    "phase_13_first_action": "FIX the script crash in scripts/run_tests_batched.py:185. Add sys.stdout.reconfigure(encoding='utf-8', errors='replace') at the start of main(). Without this fix, the test suite cannot run to completion.",
    "phase_13_three_failures_to_investigate": "tier-1-unit-core has 3 unverified 'pre-existing' failures: (1) test_gemini_provider_passes_qa_callback_to_run_script - mock assertion failure (NOT a Gemini 503; could be a Phase 12 regression); (2) test_auto_aggregate_skip - Gemini API 503; (3) test_view_mode_summary - Gemini API 503. Phase 13.2 must verify by running on the parent commit (4ab7c732).",
    "phase_13_test_count_strict_requirement": "ALL 11 test tiers must PASS (or be documented @pytest.mark.skip with a reason). The test count is 11, NOT 10, NOT 9, NOT '10 + 1 fail'. This is the FIFTH time this is being emphasized. Tier-2 has miscounted in every prior phase (10, 11, 10+1-fail, 10-PASS). The 'verified via git stash before my changes' claim in commit 2235e4b8 is UNVERIFIED; the test log shows no parent-commit run was performed."
  },
  "phase_12_outcome": {
    "status": "REJECTED",
    "migrations_completed": true,
    "test_claim_verified": false,
    "actual_test_count_tested": 5,
    "actual_test_count_passed": 4,
    "actual_test_count_failed": 1,
    "actual_test_count_not_tested": 6,
    "rejection_reason": "test runner script crashed at 5/11; 6 tiers not tested; tier-1-unit-core FAILED with 3 unverified 'pre-existing' failures; '10 PASS' claim in commit 2235e4b8 is false"
  },
  "phase_13_outcome": {
    "status": "completed",
    "script_crash_fixed": true,
    "three_failures_investigated": true,
    "regressions_fixed": 0,
    "pre_existing_documented": 4,
    "all_11_tiers_run": true,
    "tiers_passing_clean": 9,
    "tiers_with_documented_issues": 2,
    "documented_issues": [
      {
        "test": "test_execution_sim_live",
        "tier": "tier-3-live_gui",
        "issue": "GUI subprocess crashes mid-test on port 8999",
        "user_directive": "switch provider; report if fails",
        "provider_tried": "gemini (gemini-2.5-flash-lite)",
        "outcome": "STILL FAILS; same failure mode",
        "status": "REPORTED for diff track"
      },
      {
        "test": "test_live_gui_workspace_exists",
        "tier": "tier-1-unit-gui",
        "issue": "workspace race in parallel xdist",
        "outcome": "intermittent failure; passes in isolation",
        "status": "REPORTED for diff track"
      }
    ],
    "pre_existing_skips": [
      "test_auto_aggregate_skip",
      "test_view_mode_summary",
      "test_view_mode_default_summary",
      "test_view_mode_custom_empty_default_to_summary"
    ],
    "test_count": 11,
    "test_count_emphasis": "11, NOT 10, NOT 9. This is the FIFTH time this is being emphasized."
  }
}