# Phase 10 Target Sites — Per-Site Enumeration

## Audit Source
`uv run python scripts/audit_exception_handling.py --json > audit_pre_phase10.json`
Generated after Phase 9 (current state). The 37-file scope (35 SMALL + 2 MEDIUM) is filtered.

## Site Counts

| Category | Count | Notes |
|---|---|---|
| `INTERNAL_SILENT_SWALLOW` | 26 | Narrow-catch + `pass` patterns. These need full `Result[T]` migration. (Spec estimated 27; off by 1 due to the `load_track_state` defensive fix already done in Phase 9.) |
| `UNCLEAR` | 18 | Includes 4 sites that were classified in Phase 2 (outline_tool.py:49, summarize.py:36, conductor_tech_lead.py:120, openai_compatible.py:87 — the original 4 UNCLEARs). The other 14 emerged from the Phase 3-8 narrowing strategy. |

## SILENT_SWALLOW Sites (26 total) — Phase 10.2 migration targets

| File | Line | Kind | Function context | Strategy |
|---|---|---|---|---|
| `src/aggregate.py` | 105 | EXCEPT | `stats` outer try | Full Result[T] migration |
| `src/api_hooks.py` | 914 | EXCEPT | websocket connection cleanup | Full Result[T] migration |
| `src/context_presets.py` | 16 | EXCEPT | `load_all_context_presets` | Full Result[T] migration |
| `src/external_editor.py` | 82 | EXCEPT | `_find_vscode_in_registry` subprocess.run | Full Result[T] migration |
| `src/file_cache.py` | 98 | EXCEPT | `_get_mtime` cache fallback | Full Result[T] migration |
| `src/log_registry.py` | 249 | EXCEPT | `_log_summary` stderr.write | Full Result[T] migration |
| `src/models.py` | 508 | EXCEPT | `from_dict` datetime.fromisoformat | Full Result[T] migration |
| `src/multi_agent_conductor.py` | 317 | EXCEPT | persona load fallback | Full Result[T] migration |
| `src/orchestrator_pm.py` | 37 | EXCEPT | track metadata.json read | Full Result[T] migration |
| `src/orchestrator_pm.py` | 49 | EXCEPT | track spec.md read | Full Result[T] migration |
| `src/outline_tool.py` | 90 | EXCEPT | ast.unparse ImGui context | Full Result[T] migration |
| `src/outline_tool.py` | 109 | EXCEPT | outer except in walk | Full Result[T] migration |
| `src/project_manager.py` | 366 | EXCEPT | `get_all_tracks` state.from_dict | Full Result[T] migration |
| `src/project_manager.py` | 378 | EXCEPT | `get_all_tracks` metadata.json read | Full Result[T] migration |
| `src/project_manager.py` | 393 | EXCEPT | `get_all_tracks` plan.md read | Full Result[T] migration |
| `src/session_logger.py` | 147 | EXCEPT | log_api_hook write | Full Result[T] migration |
| `src/session_logger.py` | 160 | EXCEPT | log_comms json.dump | Full Result[T] migration |
| `src/session_logger.py` | 201 | EXCEPT | log_tool_call write | Full Result[T] migration |
| `src/session_logger.py` | 245 | EXCEPT | log_cli_call write | Full Result[T] migration |
| `src/startup_profiler.py` | 40 | EXCEPT | `_end_phase` stderr.write | Full Result[T] migration |
| `src/theme_2.py` | 282 | EXCEPT | markdown_helper import + clear_cache | Full Result[T] migration |
| `src/warmup.py` | 139 | EXCEPT | `on_complete` callback fire | Full Result[T] migration (io_pool callback) |
| `src/warmup.py` | 215 | EXCEPT | `_record_success` callback fire | Full Result[T] migration (io_pool callback) |
| `src/warmup.py` | 249 | EXCEPT | `_record_failure` callback fire | Full Result[T] migration (io_pool callback) |
| `src/warmup.py` | 276 | EXCEPT | `_log_canary` stderr.write | Full Result[T] migration |
| `src/warmup.py` | 300 | EXCEPT | `_log_summary` stderr.write | Full Result[T] migration |

## UNCLEAR Sites (18 total) — Phase 10.3 heuristic targets

### Original 4 (Phase 2 already classified)
- `src/outline_tool.py:49` (Phase 2 decision: Migration-target)
- `src/summarize.py:36` (Phase 2 decision: Migration-target)
- `src/conductor_tech_lead.py:120` (Phase 2 decision: Compliant)
- `src/openai_compatible.py:87` (Phase 2 decision: Compliant)

### New 14 (emerged from Phase 3-8 narrowing)
- `src/aggregate.py:50` (EXCEPT — PureWindowsPath drive check)
- `src/aggregate.py:274` (EXCEPT — file read with traceback)
- `src/aggregate.py:446` (EXCEPT — AST skeleton fallback)
- `src/commands.py:116` (EXCEPT — generate_md)
- `src/commands.py:147` (EXCEPT — save_all)
- `src/diff_viewer.py:167` (EXCEPT — apply_patch)
- `src/file_cache.py:84` (EXCEPT — path mtime stat)
- `src/markdown_helper.py:200` (EXCEPT — render_table fallback)
- `src/models.py:1081` (EXCEPT — MCP config load)
- `src/multi_agent_conductor.py:517` (EXCEPT — file view injection)
- `src/project_manager.py:98` (EXCEPT — git rev-parse)
- `src/session_logger.py:188` (EXCEPT — log_tool_call script file write)
- `src/shell_runner.py:99` (EXCEPT — subprocess cleanup on error)
- `src/summarize.py:187` (EXCEPT — summarise_file fallback)

## io_pool Callback Sites (4 sites in Phase 10.2)

The warmup and hot_reloader paths use callback-based dispatch through `io_pool`. When a callback now returns `Result[T]`, the completion handler must check `result.ok` and thread the Result through:

- `src/warmup.py:139` — `on_complete` callback fire (in WarmupManager.on_complete())
- `src/warmup.py:215` — `_record_success` callback fire (in WarmupManager._record_success())
- `src/warmup.py:249` — `_record_failure` callback fire (in WarmupManager._record_failure())
- `src/hot_reloader.py:58` — `reload()` (in HotReloader.reload())

The current pattern: callback returns None (silent swallow). After migration:
- Callback signature: `def callback(result: Result[Snapshot]) -> None`
- The wrapper `try: callback(...) except SomeError as e: ...` becomes the wrapper
- The completion handler iterates over callbacks and threads the Result

## Summary

| Metric | Pre-Phase-10 |
|---|---|
| Files needing migration | 16 |
| Sites to migrate to Result[T] | 26 |
| New audit heuristics needed | 2-3 |
| Audit reclassification target | 14 new UNCLEAR → INTERNAL_COMPLIANT or BOUNDARY_* |
| io_pool callback sites to thread Result | 4 |
| Estimated per-file sites | 1-3 sites per file |

The 4 original UNCLEAR sites (outline_tool.py:49, summarize.py:36, conductor_tech_lead.py:120, openai_compatible.py:87) were classified in Phase 2; conductor_tech_lead.py:120 and openai_compatible.py:87 stay as-is (Compliant), and outline_tool.py:49 + summarize.py:36 are migration-targets and will be covered by Phase 10.2's outline_tool.py and summarize.py migrations.
