test(audit): add 3 Heuristic E regression tests (TIER1_REVIEW Phase 9 redo)
3 regression tests for the new Heuristic E (narrow + structured error carrier):
1. test_heuristic_e_narrow_return_errorinfo_is_compliant
- Asserts narrow except + return ErrorInfo(...) is classified as compliant
- Accepts both INTERNAL_COMPLIANT (Heuristic E) and BOUNDARY_CONVERSION
(existing creates_errorinfo check, fires first)
2. test_heuristic_e_narrow_dict_error_true_assign_is_compliant
- Asserts narrow except + dict[error] = True is classified as compliant
- The in-band error flag pattern (per Tier 1 directive)
3. test_heuristic_e_empty_default_args_is_NOT_compliant
- NEGATIVE test: narrow except + args = {} must NOT be classified as compliant
- Guards against future heuristic additions that would laundering the
sliming empty-default pattern (per TIER1_REVIEW)
Total: 16 audit heuristic tests pass (13 existing + 3 new).
This commit is contained in:
@@ -296,3 +296,93 @@ def test_lazy_loading_sentinel_fallback_in_get_is_compliant():
|
||||
f"(direct `self._cached = _BarStub()`) should be INTERNAL_COMPLIANT "
|
||||
f"(canonical graceful-degradation pattern); got {category}. Hint: {hint}"
|
||||
)
|
||||
|
||||
|
||||
# ============ Phase 9 redo: Heuristic E regression tests (TIER1_REVIEW) ============
|
||||
|
||||
def test_heuristic_e_narrow_return_errorinfo_is_compliant():
|
||||
"""Phase 9 redo: narrow except + return ErrorInfo(...) is a true drain.
|
||||
|
||||
Per TIER1_REVIEW_phase9_dilemma_20260620: a narrow except body that
|
||||
returns a structured ErrorInfo carries the original exception and is
|
||||
the function's contract. This is NOT sliming (the error context is
|
||||
preserved in `original=e`).
|
||||
"""
|
||||
src = (
|
||||
"def _classify_anthropic_error(exc, source):\n"
|
||||
" try:\n"
|
||||
" err_data = exc.response.json()\n"
|
||||
" except (ValueError, AttributeError) as e:\n"
|
||||
" return ErrorInfo(kind=ErrorKind.UNKNOWN, message=str(e), source=source, original=e)\n"
|
||||
)
|
||||
visitor = _make_visitor(src, "_classify_anthropic_error")
|
||||
try_node = _find_handler(visitor)
|
||||
handler = try_node.handlers[0]
|
||||
category, hint = visitor._classify_except(handler, try_node)
|
||||
assert category in ("INTERNAL_COMPLIANT", "BOUNDARY_CONVERSION"), (
|
||||
f"Heuristic E regression: narrow except + return ErrorInfo(...) "
|
||||
f"should be a compliant classification (INTERNAL_COMPLIANT via Heuristic E "
|
||||
f"or BOUNDARY_CONVERSION via existing creates_errorinfo check); got {category}. Hint: {hint}"
|
||||
)
|
||||
|
||||
|
||||
def test_heuristic_e_narrow_dict_error_true_assign_is_compliant():
|
||||
"""Phase 9 redo: narrow except + dict[error] = True is a true drain (in-band flag).
|
||||
|
||||
Per TIER1_REVIEW: `except (NarrowType) as e: item["error"] = True`
|
||||
is a structured error carrier. The caller is expected to inspect the
|
||||
`error` flag (per-site decision documented in track notes; the audit
|
||||
does NOT verify caller reads the flag).
|
||||
"""
|
||||
src = (
|
||||
"def _reread_file_items(file_items):\n"
|
||||
" try:\n"
|
||||
" content = p.read_text()\n"
|
||||
" new_item = {**item, 'content': content}\n"
|
||||
" except (OSError, UnicodeDecodeError) as e:\n"
|
||||
" err_item = {**item, 'content': f'ERROR: {e}'}\n"
|
||||
" err_item['error'] = True\n"
|
||||
" refreshed.append(err_item)\n"
|
||||
)
|
||||
visitor = _make_visitor(src, "_reread_file_items")
|
||||
try_node = _find_handler(visitor)
|
||||
handler = try_node.handlers[0]
|
||||
category, hint = visitor._classify_except(handler, try_node)
|
||||
assert category == "INTERNAL_COMPLIANT", (
|
||||
f"Heuristic E regression: narrow except + dict['error'] = True "
|
||||
f"should be INTERNAL_COMPLIANT (in-band error flag carrier); got {category}. Hint: {hint}"
|
||||
)
|
||||
|
||||
|
||||
def test_heuristic_e_empty_default_args_is_NOT_compliant():
|
||||
"""Phase 9 redo: narrow except + args = {} is NOT a drain (sliming).
|
||||
|
||||
Per TIER1_REVIEW: the empty-default pattern loses error context. The
|
||||
caller cannot distinguish success from failure. Heuristic E
|
||||
explicitly does NOT match this pattern (this test is a regression
|
||||
guard against future "helpful" heuristic additions that would
|
||||
laundering this sliming pattern).
|
||||
|
||||
Structure: extract into a helper function so the try is at the top
|
||||
level of the function body (required by _find_handler test helper).
|
||||
"""
|
||||
src = (
|
||||
"def _parse_tool_args(tool_args_str):\n"
|
||||
" try:\n"
|
||||
" args = json.loads(tool_args_str)\n"
|
||||
" except (ValueError, TypeError):\n"
|
||||
" args = {}\n"
|
||||
" return args\n"
|
||||
)
|
||||
visitor = _make_visitor(src, "_parse_tool_args")
|
||||
try_node = _find_handler(visitor)
|
||||
handler = try_node.handlers[0]
|
||||
category, hint = visitor._classify_except(handler, try_node)
|
||||
# The site is narrow + non-broad but the body is empty-default.
|
||||
# Heuristic E should NOT classify as COMPLIANT. May be INTERNAL_BROAD_CATCH
|
||||
# (no drain) or UNCLEAR. NOT INTERNAL_COMPLIANT or BOUNDARY_CONVERSION.
|
||||
assert category not in ("INTERNAL_COMPLIANT", "BOUNDARY_CONVERSION"), (
|
||||
f"Heuristic E regression: narrow except + args = {{}} (empty default) "
|
||||
f"must NOT be classified as compliant (INTERNAL_COMPLIANT or BOUNDARY_CONVERSION "
|
||||
f"would be sliming per TIER1_REVIEW). Got {category} which would laundering the pattern. Hint: {hint}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user