# Track Specification: Result Migration (Phase 2 — eliminate all bad exception handling) **Track ID:** `result_migration_20260616` (umbrella for the 5 sub-tracks below) **Status:** Active (spec approved 2026-06-16) **Priority:** A (foundational; the 3 refactored baseline files + 5 migration sub-tracks complete the data-oriented error handling convention) **Owner:** Tier 2 Tech Lead **Type:** refactor (5 sub-tracks, each a separate TDD execution) **Scope:** 268 sites across 42 files (per the `exception_handling_audit_20260616` audit) **Parent tracks:** `data_oriented_error_handling_20260606` (shipped 2026-06-12), `exception_handling_audit_20260616` (shipped 2026-06-16) **Sibling tracks:** `data_structure_strengthening_20260606` (planned, parallel; uses the cleaner Result API from this phase) > **Note on effort estimates:** per the Tier 1 rules (see `conductor/workflow.md` > §"Tier 1 Track Initialization Rules"), this spec does NOT include day > estimates. Effort is measured by scope (N files, M sites) and T-shirt > size (S/M/L/XL) per sub-track. The user / Tier 2 agent decides the > actual pacing. --- ## 0. TL;DR This is the **migration phase** that completes the data-oriented error handling convention. The 2026-06-12 parent track established the convention; this umbrella track plans 5 sub-tracks that eliminate the remaining 211 violations + 25 suspicious + 32 unclear = **268 "bad" sites** across the codebase. **Per-file baseline (per `exception_handling_audit_20260616`):** | Bucket | Files | V+S sites | What | |---|---|---|---| | **LARGE** | 2 (gui_2, app_controller) | 77 | Dedicated track per file (T-shirt: XL) | | **MEDIUM** | 2 (session_logger, warmup) | 15 | Folds into the small-files track | | **SMALL** | 35 | 57 | Batched in one track (T-shirt: L) | | **BASELINE** | 3 (mcp_client, ai_client, rag_engine) | 87 | Closes the gaps in the convention reference (T-shirt: L) | **5 sub-tracks with consistent `result_migration_*` prefix:** 1. `result_migration_review_pass` (T-shirt: S) — 57 sites (32 UNCLEAR + 25 INTERNAL_RETHROW); updates the audit's heuristics 2. `result_migration_small_files` (T-shirt: L) — 37 files (35 SMALL + 2 MEDIUM; 72 V+S sites) 3. `result_migration_app_controller` (T-shirt: XL) — 56 sites (35 V + 3 S + 2 ? + 16 C; 13 FastAPI boundary stay as-is) 4. `result_migration_gui_2` (T-shirt: XL) — 54 sites (37 V + 2 S + 13 ? + 2 C) 5. `result_migration_baseline_cleanup` (T-shirt: L) — 112 sites (77 V + 10 S + 6 ? + 19 C in the 3 refactored files) **Total: 5 sub-tracks, 268 sites migrated, ~2100 lines changed across ~42 files.** --- ## 1. Overview ### 1.1 The State Before This Phase (as of 2026-06-16) Per `exception_handling_audit_20260616`: - **Convention is applied to 3 of 65 `src/` files** (mcp_client.py, ai_client.py, rag_engine.py — the "baseline"). - **62 `src/` files are in the migration-target state** — they still use idiomatic Python (`try/except`, `Optional[T]`, broad `except Exception`). - **211 violations + 25 suspicious + 32 unclear = 268 "bad" sites** across 42 files. - **Test pass count: 1288 + 4 + 0** (the codebase works correctly; the audit identifies refactor opportunities, not bugs). ### 1.2 The Goal Migrate **all 268 "bad" sites** in the 42 affected files to the data-oriented error handling convention. After this phase, the codebase will have: - Zero `INTERNAL_SILENT_SWALLOW` (except ...: pass / log-only). - Zero `INTERNAL_BROAD_CATCH` (except Exception without ErrorInfo conversion, in non-`*_result` code). - Zero `INTERNAL_OPTIONAL_RETURN` (try/except + return None/Optional[T]). - Zero `INTERNAL_RETHROW` (try/except + raise without ErrorInfo conversion) — except where the new "Re-Raise Patterns" section allows. - Zero `UNCLEAR` (manual review confirms each is compliant or gets migrated). The 5 sub-tracks collectively achieve this. The convention's "delete to turn off" audit script (`scripts/audit_exception_handling.py`) becomes useful as a **CI gate** in `--strict` mode after this phase: any new violation introduced by future code will fail CI. ### 1.3 The 5 Sub-Tracks (consistent `result_migration_*` prefix) All 5 sub-tracks follow the naming pattern `result_migration__`. The umbrella spec uses placeholders; each sub-track gets its own date when it starts. The umbrella commit names (this spec) use `20260616`. #### Sub-track 1: `result_migration_review_pass_` **Scope:** 32 UNCLEAR + 25 INTERNAL_RETHROW = 57 sites across 15 files. **T-shirt size:** S (smallest sub-track; mostly research + audit-script edits). **Why first:** the UNCLEAR sites are ambiguous; a human review pass turns them into definite decisions (compliant or migration-target). The INTERNAL_RETHROW sites need the 3 legitimate re-raise patterns from `conductor/code_styleguides/error_handling.md` (added 2026-06-16) to be applied. Both feed into all later sub-tracks. **What it does:** - For each of the 32 UNCLEAR sites, a human looks at the site and decides compliant-or-migration. Updates the audit's heuristics for sites that turn out to be a common pattern. - For each of the 25 INTERNAL_RETHROW sites, classify as one of the 3 legitimate re-raise patterns (convert, log+raise, cleanup+raise) or mark for migration. - Output: a doc with the per-site decision (added as an appendix to this umbrella spec when the sub-track ships). **Dependency:** none (it's the first sub-track). #### Sub-track 2: `result_migration_small_files_` **Scope:** 37 files (the 35 SMALL + 2 MEDIUM from the `--by-size` bucket); 72 V+S sites. **T-shirt size:** L (batched; ~700 lines changed across 37 files; mechanical). **Why second:** the small files are quick wins; they don't depend on the orchestrator (app_controller) or the GUI. Some of them DO depend on sub-track 1's review pass (so the UNCLEAR sites are classified first). **What it does:** - Migrates each of the 37 files to the convention. - Each file's migration is a small `Result[T]` introduction + an `except as e: return Result(data=NIL_T, errors=[ErrorInfo(...)])` replacement. - The 2 MEDIUM files (session_logger, warmup) get dedicated commits; the 35 SMALL files get batched commits (5-7 files per commit). **Dependency:** sub-track 1 (for the UNCLEAR classification). #### Sub-track 3: `result_migration_app_controller_` **Scope:** `src/app_controller.py` (166KB); 56 sites (35 V + 3 S + 2 ? + 16 C). **T-shirt size:** XL (the orchestrator; high coordination with Hook API + MMA + RAG; ~700 lines changed in 1 file). **Why dedicated:** the controller is the orchestrator; it touches every subsystem. Changes here require careful coordination with the `_predefined_callbacks` and `_gettable_fields` Hook API registries, the MMA conductor, and the RAG engine. **What it does:** - Migrates the 22 migration-target sites (35 V - 13 FastAPI boundary = 22). - The 13 FastAPI boundary sites (per the new "Boundary Types" section in `conductor/code_styleguides/error_handling.md`) stay as-is. - The 16 compliant sites stay as-is. - Uses the 5-file-commit pattern from the parent track's `doeh_test_thinking_cleanup_20260615` (not 11 separate test mocks). - Adds tests for the new Result-based API (similar to `test_ai_client_result.py`). **Dependency:** sub-track 1 (for the 2 UNCLEAR sites at lines 1842 and 1668). #### Sub-track 4: `result_migration_gui_2_` **Scope:** `src/gui_2.py` (260KB); 54 sites (37 V + 2 S + 13 ? + 2 C). **T-shirt size:** XL (the largest file; immediate-mode UI; ~700 lines changed in 1 file). **Why dedicated:** the largest file in the codebase. The immediate-mode UI means changes here affect every render frame. The migration should be done incrementally with the hot-reload mechanism (`Ctrl+Alt+R`) so the user can verify each change visually. **What it does:** - Migrates the 37 V + 2 S + 13 ? = 52 migration-target sites. - The 2 compliant sites stay as-is. - The 13 UNCLEAR sites are the trickiest (per sub-track 1's review pass). - Uses the hot-reload mechanism for visual verification. **Dependency:** sub-track 1 (for the 13 UNCLEAR sites); sub-track 3 (strong coordination, since app_controller calls gui_2 methods; the controller should be migrated first to give the GUI a clean API). #### Sub-track 5: `result_migration_baseline_cleanup_` **Scope:** the 3 refactored files (mcp_client.py, ai_client.py, rag_engine.py); 112 sites (77 V + 10 S + 6 ? + 19 C). **T-shirt size:** L (parent's Path C deferred work; ~600 lines changed across 3 files). **Why last:** the baseline files ARE the convention reference. The remaining 77 violations are gaps in the reference (mostly the parent's "deferred" work — the 30+ tool functions in mcp_client.py, the SDK-exception-classification helpers in ai_client.py, the non-`*_result` methods in rag_engine.py). Closing these makes the convention reference **pure** — no migration-target sites in the baseline. **What it does:** - Migrates the 30+ tool functions in mcp_client.py (the parent's Path C deferred work). - Migrates the broad-catches in the SDK-exception-classification helpers in ai_client.py (catch `anthropic.APIError` + convert to ErrorInfo). - Migrates the non-`*_result` methods in rag_engine.py. - Result: the 3 refactored files become 100% convention-compliant. **Dependency:** none (independent of the other 4 sub-tracks; can run in parallel with sub-tracks 2-4 if the Tier 2 agents coordinate). ### 1.4 Out of Scope (Explicit) - **`send_result` → `send` mass rename** (user's stated manual refactor; separate work after this phase ships). - **`data_structure_strengthening_20260606`** (parallel track; uses the cleaner Result API from this phase). - **`live_gui_mock_injection_20260615`** (separate infrastructure track). - **Removing the `send()` deprecation** (followup; once the rename ships). - **Migrating `tests/` files** (the `public_api_migration_20260606` track already migrated 22 test files to `send_result()`; the remaining tests are out of scope for this phase). - **Adding new `Result` patterns to areas that don't have any** (this phase migrates EXISTING `try/except` sites, not adds new ones). --- ## 2. Recommended Sequence ``` [Track 1: review pass] (S; informational; can run in parallel with 2-5) ↓ [Track 2: small files] (L; 37 files) ↓ [Track 3: app_controller] (XL; high coordination) ↓ [Track 4: gui_2] (XL; depends on 3 for clean API) ↓ [Track 5: baseline cleanup] (L; can run in parallel with 3-4) ``` **Parallelization options:** - Tracks 2 + 5 can run in parallel (different files). - Tracks 3 + 5 can run in parallel (different files; both touch app_controller's interface but Track 5 only touches the convention reference files). - Track 4 depends on Track 3 (the GUI calls controller methods). - Track 1 is independent (informational; can run any time). --- ## 3. Architecture Reference ### 3.1 The Convention - `conductor/code_styleguides/error_handling.md` — the canonical styleguide (5 patterns + 5 doc-clarification sections added 2026-06-16) - `docs/AGENTS.md` §"The 4 memory dimensions" — the cross-cutting lens - `docs/guide_ai_client.md` "Data-Oriented Error Handling (Fleury Pattern)" — the in-context guide for the provider layer - `docs/guide_mcp_client.md` "Data-Oriented Error Handling (Fleury Pattern)" — the in-context guide for the MCP tool layer - `docs/guide_rag.md` "Data-Oriented Error Handling (Fleury Pattern)" — the in-context guide for the RAG engine - `conductor/code_styleguides/data_oriented_design.md` — the canonical DOD reference ### 3.2 The Audit Script - `scripts/audit_exception_handling.py` — the static analyzer (10-category classification; `--json`, `--top`, `--verbose`, `--strict`, `--summary`, `--by-size` modes) - `docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md` — the audit report (the 268-site inventory; the per-file + per-category breakdown) - `docs/guide_app_controller.md` "Exception Handling" — the app_controller-specific guide (the 13 FastAPI boundary sites; the 22 migration-target sites) ### 3.3 The 4 Enforcement Audit Scripts (CI gates) This phase's goal is to make `--strict` mode of `scripts/audit_exception_handling.py` a viable CI gate. The other 3 enforcement scripts are: - `scripts/audit_weak_types.py` — the `dict[str, Any]` / `list[dict[...]]` type-strengthening audit - `scripts/audit_optional_in_3_files.py` — the `Optional[T]` return type ban in the 3 refactored files (referenced by `error_handling.md` but not yet committed; should be created in `data_structure_strengthening_20260606` per its spec §12.2) - `scripts/audit_main_thread_imports.py` — the main-thread import graph purity invariant After this phase ships, all 4 scripts should be wired into CI as `--strict` mode gates. --- ## 4. Per-Sub-Track Plan (just sub-track 1; the rest are detailed when each sub-track starts) Sub-track 1 (`result_migration_review_pass`) is the only one with a detailed plan; the other 4 are detailed when each starts. The reason: the audit's UNCLEAR + INTERNAL_RETHROW classification may change the migration scope of the later sub-tracks (some UNCLEAR sites may turn out to be compliant, reducing the migration work). ### Phase 1: Setup (Sub-track 1) - [x] **Task 1.1: Initialize the sub-track folder** - WHERE: `conductor/tracks/result_migration_review_pass_/` - WHAT: spec.md, plan.md, metadata.json - HOW: Copy this umbrella spec as the starting point; customize for the review pass - [x] **Task 1.2: Update `conductor/tracks.md`** - WHERE: `conductor/tracks.md` (new row for the sub-track) - WHAT: Add the sub-track under the umbrella row - HOW: Same pattern as the previous tracks ### Phase 2: Review (Sub-track 1) - [x] **Task 2.1: Review the 32 UNCLEAR sites** - WHERE: All `src/` files - WHAT: For each site, decide compliant-or-migration; record the decision in a doc - HOW: Use the audit's JSON output; for each site, read the snippet + context + 2-3 lines around it; classify - [x] **Task 2.2: Classify the 25 INTERNAL_RETHROW sites** - WHERE: All `src/` files - WHAT: For each site, apply the 3 legitimate re-raise patterns from the new styleguide section; record the decision - HOW: Same as 2.1; the decisions feed into the migration scope of sub-tracks 2-4 - [x] **Task 2.3: Update the audit script's heuristics** - WHERE: `scripts/audit_exception_handling.py` - WHAT: For sites that turned out to be compliant (a common pattern the script doesn't recognize), add a heuristic to the classification logic - HOW: Add to the `_classify_except` / `_classify_raise` functions ### Phase 3: Report (Sub-track 1) - [x] **Task 3.1: Write the review pass report** - WHERE: `docs/reports/RESULT_MIGRATION_REVIEW_PASS_.md` - WHAT: Per-site decision table; updated migration scope for the later sub-tracks; updated audit script heuristics - HOW: Use the format of the `EXCEPTION_HANDLING_AUDIT_20260616.md` report ### Phase 4: Verification (Sub-track 1) - [x] **Task 4.1: Verify the updated audit script** - WHERE: `scripts/audit_exception_handling.py` - WHAT: Re-run the audit; the UNCLEAR count should drop to 0; the INTERNAL_RETHROW count should drop to whatever the 3 legitimate patterns don't cover - HOW: `uv run python scripts/audit_exception_handling.py --by-size` - [x] **Task 4.2: Document the updated migration scope** - WHERE: This umbrella spec (the per-sub-track plan section) - WHAT: The sub-track 2-4 scope may change after the review pass; document the changes --- ## 5. Verification Criteria (per sub-track) Each sub-track has its own verification criteria. The umbrella's criteria are that **all 5 sub-tracks pass their criteria**; the umbrella is "complete" when: - 268 sites migrated (or marked as legitimate via the review pass). - `--strict` mode of the audit script returns 0 (no violations). - Full test suite: 1288 + 4 + 0 (unchanged; the migration is behavior-preserving). - The convention is now fully applied to all 65 `src/` files. - The 4 enforcement audit scripts can be wired into CI as `--strict` gates. --- ## 6. Risks & Mitigations | ID | Risk | Likelihood | Impact | Mitigation | |---|---|---|---|---| | R1 | The 5 sub-tracks are larger than expected (the parent's Path C deferred work is bigger than estimated) | Medium | High | Track 5 (baseline cleanup) is the biggest risk — the 30+ tool functions in mcp_client.py may be bigger than expected. The plan acknowledges scope can grow; the user decides whether to split sub-tracks further. | | R2 | The migration breaks the Hot Reload mechanism (changes to gui_2.py don't hot-reload correctly) | Medium | High | Sub-track 4 uses the hot-reload mechanism for visual verification. The migration should be done incrementally; the user can verify each change visually. | | R3 | The migration breaks the Hook API (changes to app_controller.py break the `_predefined_callbacks` / `_gettable_fields` registries) | Low | High | Sub-track 3 includes a "before/after" verification of the Hook API (via `live_gui` tests). The convention's `Result` type is structurally compatible with the existing str/None return types if needed. | | R4 | The review pass (sub-track 1) reveals that more sites are violations than the audit's heuristics suggest | Medium | Medium | The review pass updates the audit's heuristics; the migration scope for sub-tracks 2-4 may grow. The plan documents the scope changes in Phase 4. | | R5 | The user wants a different sub-track ordering (e.g., the orchestrator first) | Low | Low | The plan recommends a sequence but the user can reorder. The sub-tracks are independent enough to swap. | --- ## 7. Commits (the umbrella + 5 sub-tracks, in order) The umbrella is 1 commit. Each sub-track is 5+ commits (spec, plan, metadata, code, docs). Total: 1 + 5*5 = 26 commits across the 5 sub-tracks. --- ## 8. See Also - `conductor/code_styleguides/error_handling.md` — the canonical convention (5 patterns + 5 doc-clarification sections) - `conductor/code_styleguides/data_oriented_design.md` — the canonical DOD reference - `docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md` — the audit report (the 268-site inventory) - `scripts/audit_exception_handling.py` — the static analyzer (with `--summary` and `--by-size` modes) - `conductor/tracks/exception_handling_audit_20260616/spec.md` — the audit track's spec - `conductor/tracks/data_oriented_error_handling_20260606/spec.md` §12.2 — the parent's prioritized list of future migration tracks (this umbrella replaces that list) - `conductor/tracks/data_structure_strengthening_20260606/spec.md` — the parallel track (uses the cleaner Result API from this phase)