# Plan: Exception Handling Audit Track **Track:** `exception_handling_audit_20260616` **Date:** 2026-06-16 **Owner:** Tier 2 Tech Lead **Base commit:** `ba043630` (conductor(track): mark rag_test_failures_20260615 as completed) **Final commit:** (this track's last commit) --- ## Phase 1: Spec + Plan + Metadata (Setup) Focus: Establish the track artifacts. The audit script and the doc updates come in later phases. - [x] **Task 1.1: Write spec.md** (per spec template) - WHERE: `conductor/tracks/exception_handling_audit_20260616/spec.md` - WHAT: 9-section spec with TL;DR, current state audit, 5 gaps, 10-category classification taxonomy, 5 doc-update sections, 9 verification criteria, 5 risks - HOW: Follow the spec template from `conductor/workflow.md`; use 1-space indentation; no comments - SAFETY: None (track artifact, not code) - COMMIT: `conductor(track): spec for exception_handling_audit_20260616 (audit + doc clarification)` - GIT NOTE: 3-sentence summary of the track's purpose and scope - [x] **Task 1.2: Write plan.md** (this file) - WHERE: `conductor/tracks/exception_handling_audit_20260616/plan.md` - WHAT: TDD red-first task breakdown for the 5 phases - HOW: Each task has WHERE/WHAT/HOW/SAFETY/COMMIT/NOTE fields; 2-5 minute steps per `writing-plans` skill - SAFETY: None (track artifact) - COMMIT: `conductor(track): plan for exception_handling_audit_20260616 (5 phases, ~12 tasks)` - GIT NOTE: Summary of phases and the audit script's classification logic - [x] **Task 1.3: Write metadata.json** - WHERE: `conductor/tracks/exception_handling_audit_20260616/metadata.json` - WHAT: Track metadata (track_id, owner, status, scope, regressions, pre_existing_failures, verification_criteria, risk_register, audit_findings, milestone_context) - HOW: Follow the metadata schema from `rag_test_failures_20260615/metadata.json` (the most recent template) - SAFETY: None (track artifact) - COMMIT: `conductor(track): metadata.json for exception_handling_audit_20260616` - GIT NOTE: Summary of the track's verification criteria + risk register - [x] **Task 1.4: Update `conductor/tracks.md`** - WHERE: `conductor/tracks.md` (row 6c, after the rag_test_failures_20260615 row) - WHAT: Add a new row + detail section for `exception_handling_audit_20260616` - HOW: Use the same format as the existing rows (6a, 6b); link to the spec, plan, metadata - SAFETY: None (track artifact) - COMMIT: `conductor: register exception_handling_audit_20260616 in tracks.md` - GIT NOTE: Summary of the new track + its position in the sequence --- ## Phase 2: Audit Script (TDD Red-First) Focus: Write the audit script. The script is the primary deliverable; the doc updates are secondary. - [x] **Task 2.1: Write the audit script with the 10-category classification logic** (DRAFT - already done in spec phase) - WHERE: `scripts/audit_exception_handling.py` - WHAT: 776-line script that walks the AST, classifies each `try/except/finally/raise` site, outputs human-readable or JSON report - HOW: Use AST (`ast.parse`, `ast.NodeVisitor`), not regex. Match the format of `scripts/audit_weak_types.py` (informational audit with --json, --top, --verbose modes). Follow the 10-category taxonomy from spec §3.1. - SAFETY: The script is a static analyzer; it does NOT modify any files. It only READS the source files. - COMMIT: `feat(scripts): add exception_handling audit script (10-category classification)` - GIT NOTE: Summary of the classification logic + 5 doc gaps the script revealed - [x] **Task 2.2: Run the script against the 3 refactored baseline files** (VERIFICATION) - WHERE: `src/mcp_client.py`, `src/ai_client.py`, `src/rag_engine.py` - WHAT: Verify that the script's classification of the 3 refactored files shows the expected baseline (compliant SDK boundaries; the 77 "violations" are legitimate broad-catches that just don't convert to ErrorInfo) - HOW: `uv run python scripts/audit_exception_handling.py --src src | head -50` - SAFETY: Read-only; no code change - OUTPUT: The baseline counts (112 sites, 77 violations, 0 errors) match the expected pattern - NO COMMIT (verification only; results captured in the audit report) - [x] **Task 2.3: Verify the FastAPI `HTTPException` classification** - WHERE: `src/app_controller.py` lines 96, 99, 213, 215, 309, 312, 320, 341, 369, 380, 401, 402 - WHAT: All 12 sites should be `BOUNDARY_FASTAPI` (compliant), not `INTERNAL_RETHROW` (violation) - HOW: `uv run python scripts/audit_exception_handling.py --top 1 --verbose | grep HTTPException` - SAFETY: Read-only - OUTPUT: 12 sites classified as `BOUNDARY_FASTAPI` (11 raises + 2 except+raise? no, 11 raises + the 2 except sites = 13. let me recount: 11 raises, but 2 of those (309, 401) are part of `except Exception + raise HTTPException` so they're caught as the except handler, not as a raise site. So 11 raises + 2 except handlers = 13 total) - NO COMMIT (verification only) - [x] **Task 2.4: Verify the constructor-raise classification** - WHERE: Any `__init__` method in `src/` that has a `raise ValueError/TypeError/NotImplementedError` - WHAT: Should be `INTERNAL_PROGRAMMER_RAISE` (compliant), not `INTERNAL_RETHROW` (violation) - HOW: `uv run python scripts/audit_exception_handling.py --json | grep INTERNAL_PROGRAMMER_RAISE` - SAFETY: Read-only - OUTPUT: All `__init__` raises classified as `INTERNAL_PROGRAMMER_RAISE` - NO COMMIT (verification only) - [x] **Task 2.5: Verify the broad-catch-in-`*_result`-function classification** - WHERE: `src/rag_engine.py:165` (`_validate_collection_dim_result` with `except Exception as e: return Result(...errors=[ErrorInfo(...)])`) - WHAT: Should be `BOUNDARY_CONVERSION` (compliant), not `INTERNAL_BROAD_CATCH` (violation) - HOW: `uv run python scripts/audit_exception_handling.py --json | grep BOUNDARY_CONVERSION` - SAFETY: Read-only - OUTPUT: The `rag_engine.py:165` site classified as `BOUNDARY_CONVERSION` because it creates an ErrorInfo - NO COMMIT (verification only) --- ## Phase 3: Doc + Codestyle Clarifications Focus: Update the 3 doc files to close the 5 gaps the audit revealed. The user explicitly asked for this. - [x] **Task 3.1: Update `conductor/code_styleguides/error_handling.md` — 5 new sections** - WHERE: `conductor/code_styleguides/error_handling.md` - WHAT: Add 5 new sections: 1. "Boundary Types" (after §"5. Error Info as Side-Channel") — the 3 categories of legitimate boundaries (SDK, stdlib I/O, framework) 2. "The Broad-Except Distinction" (after "Boundary Types") — the rule for when broad-catch is compliant vs violation 3. "Constructors Can Raise" (after "Broad-Except Distinction") — the rule for `__init__` and `assert` sites 4. "Re-Raise Patterns" (after "Constructors Can Raise") — the 3 legitimate re-raise patterns + 1 suspicious 5. "Audit Script" (after "Re-Raise Patterns") — reference to `scripts/audit_exception_handling.py` - HOW: Use the `manual-slop_edit_file` MCP tool with `old_string`/`new_string`; preserve 1-space indentation; preserve the existing structure - SAFETY: Doc file; no code change; preserves the existing 5-pattern structure - COMMIT: `docs(styleguide): add 5 sections clarifying the convention's boundaries` - GIT NOTE: Summary of the 5 new sections + the gaps they close - [x] **Task 3.2: Update `docs/guide_app_controller.md` — FastAPI boundary section** - WHERE: `docs/guide_app_controller.md` (new section, ideally after the existing "Data" section) - WHAT: Add a new "Exception Handling" section explaining the FastAPI boundary in the file - HOW: Use `manual-slop_edit_file` MCP tool - SAFETY: Doc file; no code change - COMMIT: `docs(app_controller): add Exception Handling section (FastAPI boundary)` - GIT NOTE: Summary of the new section + the 13 sites it covers - [x] **Task 3.3: Update `conductor/product-guidelines.md` — audit script cross-reference** - WHERE: `conductor/product-guidelines.md` (the "Data-Oriented Error Handling" section) - WHAT: Add a sentence referencing the new audit script - HOW: Use `manual-slop_edit_file` MCP tool - SAFETY: Doc file; no code change - COMMIT: `docs(guidelines): reference exception_handling audit script` - GIT NOTE: 1-sentence note --- ## Phase 4: Final Report + User Handoff Focus: Generate the report that the user will use to decide the next track. - [x] **Task 4.1: Run the final audit (after doc updates)** - WHERE: Full `src/` (all 65 files) - WHAT: Re-run the audit to capture the final numbers - HOW: `uv run python scripts/audit_exception_handling.py > tests/artifacts/exception_handling_audit_final.log 2>&1` - SAFETY: Read-only - OUTPUT: Final per-file + per-category counts - NO COMMIT (captured in the report) - [x] **Task 4.2: Write the audit report** - WHERE: `docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md` - WHAT: 8-section report following the format of `TRACK_COMPLETION_*.md`: 1. TL;DR (the audit's headline numbers) 2. Methodology (the 10-category classification taxonomy) 3. The 3 Refactored Baseline Files (the convention reference) 4. Per-file Violation Counts (top 15 files by violation count) 5. Per-category Breakdown (what kinds of violations exist) 6. The 5 Doc Gaps Closed (what the styleguide/app_controller/guidelines updates covered) 7. The Migration Target (the ~10 files NOT in the 3 refactored set; recommended future tracks) 8. Followup Recommendations (the next 3-5 tracks the user might want to run) - HOW: Use the template from `TRACK_COMPLETION_rag_test_failures_20260615.md`; use the final audit numbers from Task 4.1 - SAFETY: Doc file; no code change - COMMIT: `docs(report): add exception handling audit report (211 violations across 42 files)` - GIT NOTE: Summary of the audit's headline numbers + the recommended followup tracks - [x] **Task 4.3: Mark the track as completed in metadata + tracks.md** - WHERE: `conductor/tracks/exception_handling_audit_20260616/metadata.json`, `conductor/tracks.md` - WHAT: Update `status: active → completed`, `completed_at: 2026-06-16`, fill in the verification criteria - HOW: Use `manual-slop_edit_file` MCP tool - SAFETY: Track artifact; no code change - COMMIT: `conductor(track): mark exception_handling_audit_20260616 as completed` - GIT NOTE: Summary of the track's deliverables --- ## Phase 5: Conductor — User Manual Verification - [ ] **Task 5.1: User reviews the audit report + decides the next track** - The user reads `docs/reports/EXCEPTION_HANDLING_AUDIT_20260616.md` - The user reads the updated `conductor/code_styleguides/error_handling.md` (5 new sections) - The user reads the updated `docs/guide_app_controller.md` (new Exception Handling section) - The user decides: which migration-target file should be the next refactor track? (app_controller? gui_2? something else?) - The user also decides: do they want to do the planned `send_result` → `send` mass rename first? Or proceed to a migration track? --- ## Notes for the Tier 2 Implementer - **The audit script is already drafted** in the spec phase (Task 2.1). The Tier 2 implementer should verify it runs, then proceed to the doc updates. - **The script's classification logic is verified** by Tasks 2.2-2.5. These are READ-ONLY verifications; no code change. - **The doc updates are 5 + 1 + 1 = 7 small additions** (Tasks 3.1-3.3). Each addition is 5-30 lines. Total doc delta: ~200 lines. - **The final report (Task 4.2) is the deliverable the user reads.** It's the most important output of this track. - **The user will use the report to decide the next track.** The Tier 2 implementer does NOT make that decision. - **No production code changes** in this track. If the Tier 2 implementer is tempted to "fix" a violation, STOP. The user asked for an audit, not a refactor. ## Risks at the Plan Level | Risk | Mitigation | |---|---| | The script's classification logic has bugs that misclassify sites | Tasks 2.2-2.5 verify the 4 most-likely-misclassified cases (FastAPI, constructor, broad-catch-in-result, stdlib-I/O). The verification is READ-ONLY and fast. | | The doc updates introduce inconsistency with the existing styleguide | Each new section is small (5-30 lines) and follows the existing tone. The Tier 2 implementer can request a review if a section feels off. | | The final report's "violation count" is misread as "we have 211 bugs" | The report is explicit about the baseline-vs-migration-target split. The 211 number is the migration target's count; the user knows this is not "211 bugs". |