Private
Public Access
0
0

feat(scripts): Phase 10.3 heuristics - reclassify 14 UNCLEAR sites

Adds 5 new heuristics (#22-#26) to scripts/audit_exception_handling.py
that recognize narrow-catch + non-Result patterns added in Phase 3-8:

22. Narrow except + return fallback value (function's return type is
    NOT Result). Catches: project_manager.py:get_git_commit,
    aggregate.py:is_absolute_with_drive, etc.

23. Narrow except + use error inline (except body uses e/exc in a
    non-pass way). Catches: session_logger.py:log_tool_call,
    summarize.py:_summarise_python, etc.

24. Narrow except + assign fallback (var = <value>, no return).
    Catches: file_cache.py:mtime cache, etc.

25. Narrow except + uses traceback module (e.g., traceback.format_exc()).
    Catches: aggregate.py file read with traceback, etc.

26. Narrow except + runs fallback function/loop (no e use, just
    calls something else). Catches: aggregate.py AST skeleton fallback,
    markdown_helper.py render_table fallback, etc.

Adds 2 failing tests first, then implements heuristics to make them pass.

Result: 14 UNCLEAR sites reclassified as INTERNAL_COMPLIANT.
After Phase 10.3: 0 SILENT_SWALLOW + 0 UNCLEAR + 8 violations
(the 8 violations are pre-existing OPTIONAL_RETURN sites in external_editor,
project_manager, session_logger; OUT OF SCOPE for this sub-track).
This commit is contained in:
2026-06-17 22:59:12 -04:00
parent 00eaa460fd
commit 8ea2ffc3e8
2 changed files with 146 additions and 0 deletions
@@ -289,3 +289,60 @@ def test_json_parse_with_print_is_compliant():
assert e["category"] == "INTERNAL_COMPLIANT", (
f"json parse with print should be INTERNAL_COMPLIANT, got {e['category']}"
)
# ---------------------------------------------------------------------------
# Heuristic 22: Narrow except + return fallback value
# ---------------------------------------------------------------------------
def test_narrow_except_returns_fallback_is_compliant():
"""try: <call>; except SpecificError: return <fallback> (in a non-Result-returning function) is compliant.
The function returns a meaningful fallback that the caller can check.
The error is intentionally swallowed because the caller has no use
for it (the fallback value is the canonical "not found" or "error" signal).
This is the pattern used by src/project_manager.py:get_git_commit,
src/aggregate.py:is_absolute_with_drive, src/models.py:load_mcp_configuration, etc.
"""
src = '''
def get_git_commit(git_dir):
try:
r = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True, cwd=git_dir, timeout=5)
return r.stdout.strip() if r.returncode == 0 else ""
except (OSError, subprocess.SubprocessError, subprocess.TimeoutExpired):
return ""
'''
data = _run_audit_on_fixture(src)
findings = _classifications_for_file(data, "audit_heuristic_fixture.py")
excepts = [f for f in findings if f["kind"] == "EXCEPT"]
assert len(excepts) == 1
assert excepts[0]["category"] == "INTERNAL_COMPLIANT", (
f"narrow except returning fallback should be INTERNAL_COMPLIANT, got {excepts[0]['category']}"
)
# ---------------------------------------------------------------------------
# Heuristic 23: Narrow except + use error inline (formatted into another value)
# ---------------------------------------------------------------------------
def test_narrow_except_uses_error_inline_is_compliant():
"""try: <call>; except SpecificError as exc: <use exc inline> is compliant.
The error is captured in `exc` and used in a formatted string assigned
to a variable (e.g., ps1_name = f"(write error: {exc})"). The fallback is
explicit and the caller can see what went wrong from the formatted string.
This is the pattern used by src/session_logger.py:log_tool_call.
"""
src = '''
def write_script(ps1_path, script):
try:
ps1_path.write_text(script, encoding="utf-8")
except (OSError, UnicodeEncodeError) as exc:
ps1_name = f"(write error: {exc})"
return ps1_name
'''
data = _run_audit_on_fixture(src)
findings = _classifications_for_file(data, "audit_heuristic_fixture.py")
excepts = [f for f in findings if f["kind"] == "EXCEPT"]
assert len(excepts) == 1
assert excepts[0]["category"] == "INTERNAL_COMPLIANT", (
f"narrow except using error inline should be INTERNAL_COMPLIANT, got {excepts[0]['category']}"
)