# Track Specification: Result Migration — Sub-Track 1 (Review Pass)

**Track ID:** `result_migration_review_pass_20260617`
**Parent umbrella:** [`result_migration_20260616`](../../result_migration_20260616/spec.md) (sub-track 1 of 5)
**Type:** audit + documentation (informational; no production code change)
**Priority:** A (foundational; feeds all later sub-tracks)
**T-shirt size:** S
**Status:** ready to start (blocked-by cleared; unblocked)

---

## 0. Overview

This is sub-track 1 of the 5-sub-track `result_migration_20260616` campaign that eliminates the 268 "bad" exception-handling sites across 42 files (per the `exception_handling_audit_20260616` audit). Sub-track 1 is the **review pass**: it does not migrate any production code. It makes 43 ambiguous audit classifications into 43 definite decisions (compliant or migration-target), updates the audit script's heuristics for the patterns the human review found to be common, and produces the per-site decision table that sub-tracks 2-4 will use as their starting scope.

## 1. Current State Audit (as of 2026-06-17, base commit `b6caca40`)

### 1.1 The 348-Site Baseline (per `scripts/audit_exception_handling.py --json`)

The audit script classifies every `try/except/finally/raise` site into 10 categories. As of 2026-06-17:

| Category | Count | Status |
|---|---|---|
| Compliant | varies | ok |
| Violations | 211 | migration target |
| Suspicious | 25 | reviewable |
| UNCLEAR | 32 | needs human review |

**Note:** the audit script's heuristics were updated since the original report (`docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md`); the current re-run shows **24 UNCLEAR + 19 INTERNAL_RETHROW = 43 sites** across 11 files (down from the report's 32 + 25 = 57 across 15). Some sites have been reclassified as compliant by the new heuristics; the per-site inventory below is the live state.

### 1.2 The 24 UNCLEAR Sites (per-file inventory)

| File | Sites | Lines | In baseline? |
|---|---|---|---|
| `src/gui_2.py` | 13 | 65, 69, 684, 806, 1349, 2401, 2411, 2533, 2561, 2759, 4106, 4159, 6830 | no (migration target) |
| `src/mcp_client.py` | 4 | 126, 152, 177, 987 | **yes** (refactored 2026-06-12) |
| `src/ai_client.py` | 2 | 828, 2813 | **yes** (refactored 2026-06-12) |
| `src/app_controller.py` | 2 | 1842, 3740 | no |
| `src/models.py` | 2 | 452, 457 | no |
| `src/multi_agent_conductor.py` | 1 | 236 | no |

**Total: 24 sites across 6 files.**

### 1.3 The 19 INTERNAL_RETHROW Sites (per-file inventory)

| File | Sites | Lines | In baseline? |
|---|---|---|---|
| `src/ai_client.py` | 6 | 277, 801, 802, 1234, 1529, 2520 | **yes** (all `RAISE` kind) |
| `src/rag_engine.py` | 4 | 29, 36, 57, 75 | **yes** |
| `src/app_controller.py` | 3 | 1224, 1250, 2982 | no (all `RAISE`) |
| `src/gui_2.py` | 2 | 757, 760 | no (both `RAISE` in `__getattr__`) |
| `src/api_hooks.py` | 2 | 938, 941 | no (1 EXCEPT + 1 RAISE in `main`) |
| `src/models.py` | 1 | 268 | no (`RAISE` in `__getattr__`) |
| `src/warmup.py` | 1 | 85 | no (`RAISE` in `submit`) |

**Total: 19 sites across 7 files.**

### 1.4 The 3 Legitimate Re-Raise Patterns (per `conductor/code_styleguides/error_handling.md` §"Re-Raise Patterns", added 2026-06-16)

The styleguide defines 3 patterns where `try/except + raise` is legitimate (not a violation):

1. **PATTERN 1: catch + convert + raise as different type** (e.g., `except IOError as e: raise ProviderError(str(e))` — converts an SDK-boundary exception into a domain exception)
2. **PATTERN 2: catch + log + re-raise** (e.g., `except Exception as e: logger.exception("..."); raise` — preserves the original traceback for debugging)
3. **PATTERN 3: catch + cleanup + re-raise** (e.g., `except Exception: lock.release(); raise` — runs cleanup logic and re-raises the original)

Sites that don't match any of the 3 patterns are migration-target (remove the try/except or convert to Result-based).

### 1.5 The Audit Script's Classification Logic (reference)

The script (`scripts/audit_exception_handling.py`) uses Python's `ast` module to classify each site. The `UNCLEAR` category fires when the script cannot determine the classification from the AST alone (the body of the `except` is too complex, or the surrounding context is ambiguous). The `INTERNAL_RETHROW` category fires on `try/except + raise` patterns without context about WHY the re-raise happens.

## 2. Goals

The track has 3 goals, all bounded by scope (not time):

1. **Per-site decision** for all 24 UNCLEAR sites: `compliant` (with a heuristic update) or `migration-target` (queued for sub-tracks 2-4).
2. **Per-site classification** for all 19 INTERNAL_RETHROW sites: `PATTERN_1`, `PATTERN_2`, `PATTERN_3`, or `migration-target`.
3. **Updated audit script heuristics** for the 5-10 most common compliant patterns the review pass discovered.

## 3. Functional Requirements

- **FR1:** A per-site decision table is written to `docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md` covering all 43 sites.
- **FR2:** The audit script's classification logic (`scripts/audit_exception_handling.py`, the `_classify_except` and `_classify_raise` functions) is updated with at least 1 new heuristic for each commonly-compliant pattern.
- **FR3:** Re-running `uv run python scripts/audit_exception_handling.py --json` after the heuristic updates shows the UNCLEAR count is 0 (or close to it; ±2 sites that the user classifies as "ambiguous, leave as UNCLEAR").
- **FR4:** The umbrella spec's per-sub-track plan section (`conductor/tracks/result_migration_20260616/spec.md`) is updated to reflect the post-review migration scope (some UNCLEAR sites may be compliant; sub-tracks 2-4 site counts change).

## 4. Non-Functional Requirements

- **NF1:** No production code change. Only the audit script and documentation are modified.
- **NF2:** Atomic per-task commits. Each review batch is its own commit (e.g., "review `src/gui_2.py` UNCLEAR sites").
- **NF3:** Per-commit git notes summarizing the per-site decisions.
- **NF4:** Test pass count is unchanged: 1288 + 4 + 0 (the review pass is informational).

## 5. Architecture Reference

- `conductor/code_styleguides/error_handling.md` §"Re-Raise Patterns" — the 3 legitimate re-raise patterns to apply to INTERNAL_RETHROW sites
- `docs/AGENTS.md` §"Convention Enforcement" — the 4 enforcement audit scripts (this track updates one of them)
- `docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md` — the parent audit report (the original 268-site inventory)
- `conductor/tracks/result_migration_20260616/spec.md` — the umbrella spec (the parent)
- `conductor/tracks/exception_handling_audit_20260616/spec.md` — the audit track (the grandparent)
- `scripts/audit_exception_handling.py` — the audit script being updated
- `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

## 6. Out of Scope (Explicit)

- **Migrating any production code.** Sub-track 1 is informational; the migration happens in sub-tracks 2-4.
- **Updating the umbrella spec's recommendation sequence** (sub-tracks 2-4 ordering is unchanged).
- **Adding new `Result` patterns to areas that don't have any** (this track classifies EXISTING sites only).
- **Refactoring the audit script's overall architecture** (only the `_classify_except` and `_classify_raise` functions are touched).
- **The 211 violations + remaining 6 INTERNAL_RETHROW-equivalent sites** (those are sub-tracks 2-5's work).

## 7. Verification Criteria

- **G1:** `docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md` exists and contains a per-site decision table for all 43 sites.
- **G2:** `scripts/audit_exception_handling.py` has at least 1 new heuristic for commonly-compliant patterns (count recorded in the report).
- **G3:** Re-running the audit post-heuristics: UNCLEAR count is 0 (±2 acceptable).
- **G4:** `conductor/tracks/result_migration_20260616/spec.md` §1.3 is updated with the post-review site counts.
- **G5:** Full test pass count: 1288 + 4 + 0 (unchanged; informational track).
- **G6:** Atomic commits: spec, plan, metadata + state, per-file review batches, audit script update, umbrella spec update, report, final verification.

## 8. Risks

- **R1:** Review reveals more sites are violations than the audit's heuristics suggest → the migration scope for sub-tracks 2-4 grows; mitigated by the per-site decision table that records every site.
- **R2:** User disagrees with a classification on a disputed case → the plan defers to the user as the final arbiter; no site is left without a decision.
- **R3:** Audit script updates introduce regressions (e.g., a new heuristic misclassifies a known site) → mitigated by running the audit before and after each heuristic change and comparing counts.

## 9. Notes for the Tier 2 Implementer

- This is a **research task, not a refactor**. Read the code, classify the site, write the decision. No production code edits.
- For each site, read the snippet + 2-3 lines of context. The audit's `context` field gives the enclosing function name; `line` gives the exact line.
- For UNCLEAR sites, the question is: "is this a pattern the audit script SHOULD recognize as compliant?" If yes, mark `compliant` and add a heuristic. If no, mark `migration-target`.
- For INTERNAL_RETHROW sites, the question is: "is this one of the 3 legitimate re-raise patterns?" Check the styleguide's Re-Raise Patterns section. If none, mark `migration-target`.
- The user is the final arbiter on disputed cases. If a site's classification is unclear after human review, ask the user.
- The review pass is bounded by site count, not time. 43 sites; ~2-3 hours of focused review.
