diff --git a/docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md b/docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md index 5d23b5a6..3b404903 100644 --- a/docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md +++ b/docs/reports/RESULT_MIGRATION_REVIEW_PASS_20260617.md @@ -66,7 +66,19 @@ Other audit findings (unchanged by this review pass): ### 2.2 `src/mcp_client.py` — UNCLEAR sites (4, baseline) -*(filled in Task 2.2)* +| Line | Context | Snippet | Decision | Pattern / Rationale | +|---|---|---|---|---| +| 126 | `configure` (allowlist setup) | `except (OSError, ValueError): rp = Path(p).resolve()` (non-strict fallback) | **compliant** | Graceful path resolution: `Path.resolve(strict=True)` may fail if file missing; fallback to non-strict is a safe degradation | +| 152 | `_is_allowed` (allowlist check) | `except (OSError, ValueError): rp = path.resolve()` (non-strict fallback) | **compliant** | Graceful path resolution (same as L126) | +| 177 | `_is_allowed` (cwd subpath check) | `except ValueError: pass` after `rp.relative_to(cwd)` | **compliant** | `Path.relative_to` raises `ValueError` when path is not relative to base; this is the canonical "not-a-subpath" check, not an error | +| 987 | `py_check_syntax` (tool function) | `except SyntaxError: ...` then `except Exception: return f"ERROR..."` | **compliant** | Tool-boundary pattern: function returns a string (Result-like); both narrow and broad excepts convert exceptions to user-readable strings. No silent swallow | + +**Subtotals:** 4 compliant + 0 migration-target. + +**New heuristic candidates:** +5. `Path.resolve(strict=True)` with `(OSError, ValueError)` fallback to non-strict → `INTERNAL_COMPLIANT` (graceful path resolution) +6. `Path.relative_to` with `ValueError` (not-a-subpath) → `INTERNAL_COMPLIANT` (canonical subpath check) +7. MCP tool function with `except Exception: return f"ERROR..."` (string return) → `BOUNDARY_TOOL` (tool boundary; converts to string Result) ---