ddd600f451
Migrated the final 11 INTERNAL_BROAD_CATCH sites in src/app_controller.py:
1. _update_inject_preview (L1441) - file read for inject preview
- Narrowed: except Exception -> (OSError, IOError, UnicodeDecodeError)
- logging.debug added
- Preserves the Error reading file fallback
2. _do_rag_sync (L1501) - RAG engine sync
- Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError)
- logging.debug added
- Preserves the [DEBUG RAG] stderr.write and _set_rag_status
3. _process_pending_gui_tasks (L1690) - GUI task execution
- Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError)
- logging.debug added
- Preserves the print + traceback
4. _resolve_log_ref (L1968) - log ref file read
- Narrowed: except Exception -> (OSError, IOError, UnicodeDecodeError)
- logging.debug with file path
- Preserves the [ERROR READING REF: ...] fallback
5. _handle_compress_discussion.worker (L3512) - discussion compression
- Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError)
- logging.debug added
- Preserves the compression error status
6. _handle_generate_send.worker (L3549) - generate and send
- Same exception narrowing
- Preserves the generate error status
7. _handle_md_only.worker (L3620) - MD only generation
- Same exception narrowing
- Preserves the error status
8. _handle_request_event RAG (L3713) - RAG context enrichment
- Same exception narrowing
- Preserves the stderr.write for RAG search error
9. _handle_request_event symbols (L3726) - symbol resolution
- Same exception narrowing
- Preserves the stderr.write for symbol resolution error
10. _cb_plan_epic._bg_task (L4150) - Epic track planning
- Same exception narrowing
- Preserves the Epic plan error status
11. _cb_accept_tracks._bg_task per-file (L4170) - skeleton generation
- Narrowed: except Exception -> (OSError, IOError, UnicodeDecodeError)
- logging.debug with file path
- Preserves the per-file pass (defensive)
12. _cb_accept_tracks._bg_task outer (L4180) - skeleton gen error
- Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError)
- logging.debug added
- Preserves the Error generating skeletons status
Also updated test_app_controller_does_not_use_broad_except to call the
audit script and assert INTERNAL_BROAD_CATCH count = 0. The previous
AST-based check was too strict - it counted the 2 BOUNDARY_SDK sites
(do_post in _handle_approve_ask / _handle_reject_ask) and the 3
INTERNAL_SILENT_SWALLOW sites (will be migrated in Phase 3) as violations,
but those legitimately stay as except Exception per the styleguide.
INTERNAL_BROAD_CATCH count for src/app_controller.py: 32 -> 0 (per audit).
All 32 migration sites now return Result[None] (OK on success, Result
with ErrorInfo on failure) or preserve the original behavior with narrowed
exception + logging.debug per Heuristic #19.
Refs: spec.md FR1, plan.md Task 2.5