docs(reports): Phase 12.4+12.5 - re-run audit; triage findings

Phase 12.4: re-run audit_exception_handling.py with Heuristic #19 removed
and Heuristic D added. Total sites: 403.
- INTERNAL_BROAD_CATCH: 134
- INTERNAL_SILENT_SWALLOW: 46 (was logged as INTERNAL_COMPLIANT under #19)
- INTERNAL_RETHROW: 30
- INTERNAL_PROGRAMMER_RAISE: 29
- INTERNAL_COMPLIANT: 93
- UNCLEAR: 20
- BOUNDARY_SDK: 19
- BOUNDARY_FASTAPI: 15
- BOUNDARY_CONVERSION: 12
- INTERNAL_OPTIONAL_RETURN: 5

Phase 12.5: triage per file. Generated docs/reports/PHASE12_TRIAGE_20260617.md.

Top files by violations:
- src/mcp_client.py: 46 (sub-track 3 scope, NOT sub-track 2)
- src/app_controller.py: 45 (sub-track 3 scope)
- src/gui_2.py: 42 (sub-track 4 scope)
- src/ai_client.py: 33 (baseline; not migration target)
- src/api_hooks.py: 16 (sub-track 2; 12.6.1)
- src/rag_engine.py: 9 (baseline; not migration target)
- src/multi_agent_conductor.py: 4 (sub-track 2; 12.6.9)
- src/aggregate.py: 4 (sub-track 2; small file)
- src/shell_runner.py: 3 (sub-track 2; 12.6.11)
- src/warmup.py: 2 (verify Phase 11; 12.6.2)
- src/project_manager.py: 2 (verify Phase 11; 12.6.6)
- src/session_logger.py: 2 (sub-track 2; 12.6.12)
- src/models.py: 2 (sub-track 2; 12.6.8)
- src/orchestrator_pm.py: 1 (verify Phase 11; 12.6.5)

The 16 api_hooks.py sites are HTTP handler sub-functions where the
except body swallows exceptions and returns an empty fallback payload.
The actual HTTP response (self.send_response(200)) happens AFTER the
try/except, not inside the except body. Heuristic D.1 doesn't match
because the send_response is outside the except block.

These sites need full Result[T] migration: controller methods return
Result[dict], except body converts exception to ErrorInfo, HTTP handler
checks result.ok and returns 4xx/5xx on failure. L451/L824/L914 are
different — they call self.send_response(500) INSIDE the except body
(drain point pattern). 13 other sites are silent fallbacks.
This commit is contained in:
ed
2026-06-18 09:41:33 -04:00
parent 45615dadf9
commit 9a9238892d
4 changed files with 3497 additions and 0 deletions
@@ -0,0 +1,94 @@
"""Phase 12.5: Triage the post-fix audit findings.
For each file with violations/UNCLEAR, list the sites with file:line + category + note.
Group by file. Save to docs/reports/PHASE12_TRIAGE_20260617.md.
"""
from __future__ import annotations
import json
from pathlib import Path
from collections import defaultdict
with open(r"docs/reports/PHASE12_AUDIT_POST_FIX_20260617.json") as f:
d = json.load(f)
# Group by file
by_file = defaultdict(list)
for f_info in d["files"]:
fname = f_info["filename"]
for finding in f_info["findings"]:
if finding["category"] in ("INTERNAL_SILENT_SWALLOW", "INTERNAL_BROAD_CATCH",
"INTERNAL_OPTIONAL_RETURN", "UNCLEAR", "INTERNAL_RETHROW"):
by_file[fname].append(finding)
# Phase 12 plan files (priority order)
priority_files = [
"src/api_hooks.py",
"src/warmup.py",
"src/startup_profiler.py",
"src/file_cache.py",
"src/orchestrator_pm.py",
"src/project_manager.py",
"src/log_registry.py",
"src/models.py",
"src/multi_agent_conductor.py",
"src/theme_2.py",
"src/shell_runner.py",
"src/session_logger.py",
]
# Output
out = []
out.append("# Phase 12.5 — Triage of Post-Fix Audit Findings\n")
out.append("**Date:** 2026-06-17 (auto-generated)\n")
out.append("**Source:** `docs/reports/PHASE12_AUDIT_POST_FIX_20260617.json`\n")
out.append("**Total sites:** " + str(d.get("total_sites", "?")) + "\n")
out.append("**Violation sites:** " + str(d.get("violation_sites", "?")) + "\n")
out.append("**UNCLEAR sites:** " + str(d.get("unclear_sites", "?")) + "\n\n")
out.append("This triage enumerates the migration-target sites per file, ")
out.append("in priority order (Phase 12 plan 12.6 sub-batches).\n\n")
for fname in priority_files:
sites = by_file.get(fname, [])
if not sites:
out.append(f"## `{fname}` — NO violations (clean)\n\n")
continue
out.append(f"## `{fname}` — {len(sites)} sites to migrate\n\n")
out.append("| Line | Category | Note |\n")
out.append("|---|---|---|\n")
for s in sorted(sites, key=lambda x: x["line"]):
note = s.get("note", s.get("hint", "")).replace("|", "\\|").replace("\n", " ")[:120]
out.append(f"| {s['line']} | {s['category']} | {note} |\n")
out.append("\n")
# Catch-all: other files with violations
out.append("\n## Other files with violations (not in priority list)\n\n")
for fname in sorted(by_file.keys()):
if fname in priority_files:
continue
sites = by_file[fname]
out.append(f"### `{fname}` — {len(sites)} sites\n\n")
out.append("| Line | Category | Note |\n")
out.append("|---|---|---|\n")
for s in sorted(sites, key=lambda x: x["line"]):
note = s.get("note", s.get("hint", "")).replace("|", "\\|").replace("\n", " ")[:120]
out.append(f"| {s['line']} | {s['category']} | {note} |\n")
out.append("\n")
# Total counts
out.append("\n## Summary by category\n\n")
out.append("| Category | Count |\n|---|---|\n")
from collections import Counter
cats = Counter()
for f_info in d["files"]:
for finding in f_info["findings"]:
cats[finding["category"]] += 1
for c, n in cats.most_common():
out.append(f"| {c} | {n} |\n")
p = Path("docs/reports/PHASE12_TRIAGE_20260617.md")
p.write_text("".join(out), encoding="utf-8", newline="\n")
print(f"wrote {p}: {len(''.join(out))} chars")
print(f"\nPriority file summary:")
for fname in priority_files:
sites = by_file.get(fname, [])
print(f" {fname}: {len(sites)} sites")
@@ -0,0 +1,13 @@
"""Show api_hooks.py violations."""
import json
with open(r"docs/reports/PHASE12_AUDIT_POST_FIX_20260617.json") as f:
d = json.load(f)
for f_info in d["files"]:
if f_info["filename"].endswith("api_hooks.py"):
print(f"## api_hooks.py — {len(f_info['findings'])} findings")
for finding in f_info["findings"]:
if finding["category"] in ("INTERNAL_SILENT_SWALLOW", "INTERNAL_BROAD_CATCH", "INTERNAL_OPTIONAL_RETURN", "UNCLEAR", "INTERNAL_RETHROW"):
note = finding.get("note", finding.get("hint", ""))[:120]
ctx = finding.get("context", "")
print(f" L{finding['line']:4d} [{finding['kind']:7s}] {finding['category']:30s} ctx={ctx:30s} note={note}")
break