Phase 5 (1 of 9 cruft sites obliterated):
OBLITERATED: RAGEngine._chunk_code wrapper. It delegated to _chunk_code_result
and provided a fallback to _chunk_text on AST failure.
Migration: index_file() now calls _chunk_code_result directly with .ok check
+ chunk-size threshold check + fallback to _chunk_text inline. The structured
ErrorInfo is propagated if needed (no caller currently consumes it).
Sub-track 5 tests updated:
- tests/tier2/phase13_invariant_test.py: _chunk_code moved to obliterated list
- tests/tier2/phase13_site2_test.py: _legacy_no_broad_except -> _legacy_obliterated
- tests/test_cruft_removal.py: 2 new tests (wrapper-obliterated invariant +
caller-uses-result invariant)
PITFALL encountered: the edit_file tool removed a leading space on the
next class method's 'def' line, causing an IndentationError. Fixed by
binary-write replacement preserving CRLF + leading-space styleguide convention
(project uses 1-space indentation; class body methods start at column 1).
Test result: 124/124 pass.
Audit gate: src/rag_engine.py --strict exits 0 (no new violations).
Wrapper count: 3 -> 2 (Phase 6 remaining: gui_2 2).
Site 5 (BC at L290): _async_search_mcp (nested in _search_mcp) had:
try:
data = json.loads(res_str)
if isinstance(data, list): return data
elif isinstance(data, dict) and 'results' in data: return data['results']
return []
except:
return []
Body: bare 'except:' + return [] = empty default = SS-style violation.
Migrated to Result[T] via new module-level helper _parse_search_response_result:
- Returns Result(data=parsed_list) on success
- Returns Result(data=None, errors=[ErrorInfo]) on JSON parse failure
- Handles the list/dict/no-results branch logic
The helper is module-level (does not use self) and is placed BEFORE
class RAGEngine to avoid breaking the class definition (a def at column 0
inside a class ends the class prematurely).
Legacy _async_search_mcp delegates to the helper; on Result errors,
returns [] (preserving the original behavior).
Audit: rag_engine BC 1 -> 0; migration-target: 0.
Remaining 4 INTERNAL_RETHROW sites are Pattern 1/3 of the styleguide
(known audit limitation).
index_file had 3 try/except sites with similar patterns:
Site 3 (BC at L247): try: mtime = os.path.getmtime(full_path); except Exception: return
Site 4 (BC at L261): try: with open(full_path, ...) as f: content = f.read(); except Exception: return
Site 6 (SS at L255): try: res = self.collection.get(...); ...; except Exception: pass
Body: broad catch + early return/pass = SS-style violation.
New helpers:
- _get_file_mtime_result(full_path) -> Result[float]
Catches OSError only (specific to file stat failures).
- _check_existing_index_result(file_path, mtime) -> Result[bool]
Catches broad Exception (chromadb collection.get failures vary).
Returns data=True if already indexed (skip), data=False if needs re-indexing.
- _read_file_content_result(full_path) -> Result[str]
Catches (OSError, UnicodeDecodeError) (file I/O + encoding failures).
Legacy index_file calls each helper; on Result errors, returns early
(preserving the original behavior of skipping the file on failure).
Audit: rag_engine BC 3 -> 1 (L341 _async_search_mcp remaining).
SS: 1 -> 0.
Site 2 (BC at L224): _chunk_code had a fallback to text chunking on any
failure:
try:
parser = ASTParser('python')
tree = parser.parse(content)
...
return chunks
except Exception:
return self._chunk_text(content)
Body: broad catch + fallback to a different implementation = empty-default
fallback = SS-style violation.
New helper _chunk_code_result(content, file_path) -> Result[List[str]]:
- Returns Result(data=chunks) on AST parse success
- Returns Result(data=None, errors=[ErrorInfo]) on parse failure
Legacy _chunk_code calls helper; on Result errors, falls back to
_chunk_text (preserving original behavior). The catch logic is in the
legacy, not the helper, so the caller decides the fallback strategy.
Audit: rag_engine BC 4 -> 3.
Site 1 (BC at L33) was:
except Exception as e:
sys.stderr.write(f'FAILED to import sentence_transformers: {e}')
sys.stderr.flush()
raise e
Per TIER1_REVIEW: catch + log + re-raise is Pattern 2 of the styleguide.
The fix is to narrow the except to specific exception types that
sentence_transformers could raise on import (ImportError, AttributeError).
Refactored to:
except (ImportError, AttributeError) as e:
sys.stderr.write(f'FAILED to import sentence_transformers: {e}')
sys.stderr.flush()
raise
The bare 'raise' re-raises the current exception being handled,
preserving the original type and traceback. (Replaces 'raise e' which
raised a specific value but lost the traceback context.)
Audit: rag_engine BC 5 -> 4. RETHROW +1 (the narrowed except is now
classified as Pattern 3 catch+re-raise; strict mode accepts).
Phase 12: ai_client rethrow classification (6 sites).
Site 1 (L276 _load_credentials): added 'from e' (Pattern 1)
Sites 2+3 (L878+L879 _default_send nested): added 'from None' (Pattern 1)
Site 4 (L1336 _list_anthropic_models): migrated to Result (the broken
'raise ErrorInfo from exc' runtime bug — same pattern as Phase 10 site 1)
Site 5 (L2078 _send inside _send_gemini_cli): added 'from None' (Pattern 1)
Site 6 (L2759 _dashscope_call): added 'from None' (Pattern 1)
KNOWN LIMITATION: the audit script does not have a heuristic for
'raise X from e' or 'from None' (Pattern 1 compliant). The 5 Pattern 1
sites remain classified as INTERNAL_RETHROW ('suspicious but not
violation') in the audit. Strict mode (Phase 14 gate) accepts this.
Adding a Pattern 1 heuristic requires Tier 1 approval per the
conventions ('Never modify audit heuristics without explicit Tier 1
approval'). Documented in the end-of-track report.
Audit state (after Phase 12):
mcp_client: 0 migration-target (Phase 3-8 complete)
ai_client: 7 -> 6 migration-target (5 RETHROW + 0 SS + 0 BC + 0 UNCLEAR)
BC: 0 (Phase 10)
SS: 0 (Phase 11)
RETHROW: 7 -> 6 (one site migrated to Result in Phase 12)
UNCLEAR: 0
COMPLIANT: 33 -> 34 (+1)
rag_engine: 9 migration-target (Phase 13)
Tests: 109 pass (was 97; +12 Phase 12 site/invariant tests).
Site 4 (L1337) had:
try: anthropic = _require_warmed('anthropic'); ... client.models.list() ...
except Exception as exc:
raise _classify_anthropic_error(exc) from exc
BUG: _classify_anthropic_error returns ErrorInfo (a dataclass), NOT
an Exception. 'raise ErrorInfo from exc' would fail at runtime.
Migration per Phase 9 redo precedent: convert to Result[T]. This is
the same fix pattern applied to _list_gemini_models in Phase 10.
New helper _list_anthropic_models_result() -> Result[list[str]]:
- Returns Result(data=sorted_models) on success
- Returns Result(data=[], errors=[_classify_anthropic_error(...)])
on SDK/credentials failure
Legacy _list_anthropic_models returns result.data (preserves signature).
Audit: ai_client RETHROW 5 -> 5 (no change; site 4 was previously
counted as INTERNAL_RETHROW, now classified as INTERNAL_COMPLIANT
since the try/except is gone — the helper has the Result-returning
exception body which matches Heuristic A).
Actually let me verify with audit_summary...
Per styleguide §7.6 Pattern 1: 'catch + convert + raise as different type'
requires 'raise X from e' to preserve the original exception in the
traceback.
Sites updated:
Site 1 (L277 _load_credentials):
except FileNotFoundError as e:
raise FileNotFoundError(f'...') from e
Sites 2+3 (L878+L879 _default_send, nested in run_with_tool_loop):
if not res.ok:
raise res.errors[0].original from None
raise RuntimeError(...) from None
The exceptions come from a Result, not a local except; 'from None'
suppresses the implicit context.
Site 5 (L2061 _send inside _send_gemini_cli):
raise cast(Exception, send_result.errors[0].original) from None
Site 6 (L2742 _dashscope_call):
raise classify_dashscope_error(_dashscope_exception_from_response(resp)) from None
KNOWN LIMITATION: the audit script does not have a heuristic for
'raise X from e' / 'from None' (Pattern 1). The sites remain
INTERNAL_RETHROW in the audit. INTERNAL_RETHROW is 'suspicious but
not violation' (strict mode accepts). Adding a heuristic requires
Tier 1 approval per the conventions.
Audit: ai_client RETHROW 6 -> 5 (site 4 migrated separately; these
4 sites stay as INTERNAL_RETHROW by audit classification but follow
Pattern 1 by styleguide).
Both classify functions had:
try:
sdk = _require_warmed('xxx')
if isinstance(exc, sdk.SomeException): return ErrorInfo(...)
...
except (ImportError, AttributeError):
pass
# body-string matching fallback
...
Body: bare 'except: pass' = SS violation (silent recovery).
Migration per TIER1_REVIEW directive (per-site decision):
- Initial attempt: _try_warm_sdk(name) -> Any sentinel (None on failure)
- Audit flagged the sentinel helper as UNCLEAR (Heuristic B requires class
method with self.attr assignment; module-level sentinel doesn't match)
- Per Phase 9 redo precedent: migrate to Result instead of adding heuristic
Final approach: _try_warm_sdk_result(name) -> Result[Any]
Returns Result(data=module) on success,
Result(data=None, errors=[ErrorInfo]) on ImportError/AttributeError.
Classify callers check result.ok and use result.data on success.
Audit: ai_client SS 2 -> 0; UNCLEAR 1 -> 0 (after Result migration).
COMPLIANT 32 -> 33.
Site 11 at module level had:
if os.environ.get('SLOP_TOOL_PRESET'):
try:
set_tool_preset(os.environ['SLOP_TOOL_PRESET'])
except Exception:
pass
Body: bare 'except Exception: pass' = SS violation.
Migration: call the _set_tool_preset_result helper from Phase 11 site 5.
The helper returns Result[None]; on error it captures the structured
ErrorInfo. The top-level loader ignores the Result (env-var preset is
optional, errors are not fatal at module load time).
Audit: ai_client SS 3 -> 2.
Both sites 9 (gemini) and 10 (gemini_cli) in get_token_stats had:
try: _ensure_gemini_client()
if _gemini_client:
resp = _gemini_client.models.count_tokens(model=_model, contents=md_content)
total_tokens = cast(int, resp.total_tokens)
except Exception: pass
Body: pass = SS violation.
New helper _count_gemini_tokens_for_stats_result(md_content) -> Result[int]:
- Returns Result(data=token_count) on success
- Returns Result(data=0, errors=[ErrorInfo]) on SDK failure or warmup failure
- Caller treats 0 as 'token count unavailable' and falls back to
character-based estimation
Legacy get_token_stats now uses:
if p in ('gemini', 'gemini_cli'):
total_tokens = _count_gemini_tokens_for_stats_result(md_content).data
(combined both branches into one since the logic was identical)
Audit: ai_client SS 5 -> 3. COMPLIANT 31 -> 32.
Both functions had:
try: ToolPresetManager().load_all() ...
except (OSError, ValueError, AttributeError) as e:
sys.stderr.write(f'[ERROR] Failed to set {preset_name}: {e}')
sys.stderr.flush()
sys.stderr.write is logging = NOT a drain = SS violation per MUST-NOT-DO #6.
New helpers:
- _set_tool_preset_result(preset_name: Optional[str]) -> Result[None]
Empty/None preset short-circuits to Result(data=None).
On failure: Result(data=None, errors=[ErrorInfo]).
- _set_bias_profile_result(profile_name: Optional[str]) -> Result[None]
Same pattern.
Legacy wrappers set the global state (or skip on empty preset) and
delegate to the _result helper. Cache invalidation runs regardless.
Audit: ai_client SS 9 -> 7. COMPLIANT 27 -> 29.
Sites L432 (cleanup) and L450 (reset_session) had:
try: _gemini_client.caches.delete(name=_gemini_cache.name)
except Exception: pass
This is bare 'except: pass' = INTERNAL_SILENT_SWALLOW violation (logging is NOT
a drain; 'pass' is the worst form of silent recovery).
Migration: use existing _delete_gemini_cache_result() helper (added Phase 10).
The helper returns Result[None]; on SDK error logs a warning to comms.
The caller ignores the Result (cleanup is best-effort).
Audit: ai_client SS 11 -> 9.
All 3 run_tier4_* functions had the same pattern:
try: ... AI call ...
except Exception as e: return '[XXX FAILED] {e}' (or None)
Per TIER1_REVIEW: empty-default return = MIGRATE to Result[T].
New helpers:
- _run_tier4_analysis_result(stderr: str) -> Result[str]
Returns Result(data=analysis) on success, Result(data='', errors=[ErrorInfo])
on SDK failure. Empty stderr short-circuits to Result(data='').
- _run_tier4_patch_callback_result(stderr: str, base_dir: str) -> Result[Optional[str]]
Returns Result(data=patch) on valid diff, Result(data=None) when no
valid diff, Result(data=None, errors=[ErrorInfo]) on SDK failure.
- _run_tier4_patch_generation_result(error: str, file_context: str) -> Result[str]
Returns Result(data=patch) on success, Result(data='', errors=[ErrorInfo])
on SDK failure. Empty error short-circuits to Result(data='').
Legacy wrappers delegate to _result helpers and return result.data,
preserving original signatures (str for sites 7,9; Optional[str] for site 8).
Existing tier4 tests pass (13/13 in test_tier4_patch_generation +
test_tier4_interceptor).
Audit: ai_client BC 3 -> 0. All 9 Phase 10 BC sites migrated.
Site L1990: inner _send(r_idx) in _send_gemini_cli had:
try: resp_data = adapter.send(...)
except Exception as e: events.emit('response_received', {'error': str(e)}); raise
This is Re-Raise Pattern 2 (catch + emit event + raise). Per TIER1_REVIEW,
the migration is to Result[T] because the audit does not yet recognize
events.emit as a structured error carrier.
New helper _send_cli_round_result(r_idx, adapter, payload, ...) -> Result[dict]:
- Emits request_start + [CLI] comms before SDK call
- Returns Result(data=resp_data) on SDK success
- On failure: emits response_received error event + returns Result(errors=[ErrorInfo(original=e)])
Inner _send refactored:
send_result = _send_cli_round_result(r_idx, adapter, payload, ...)
if not send_result.ok:
raise cast(Exception, send_result.errors[0].original)
resp_data = send_result.data
This preserves the original re-raise behavior so the outer
_send_gemini_cli try/except still catches and converts to Result.
Audit: ai_client BC 4 -> 3.
Site L1773: cache.create block in _send_gemini had multiple global side
effects (sets _gemini_cache, _gemini_cache_created_at, _gemini_cached_file_paths,
returns chat_config with cached_content). Except body reset globals on failure.
Per TIER1_REVIEW: logging is NOT a drain. MIGRATE to Result[Any].
New helper _create_gemini_cache_result(sys_instr, tools_decl, file_items) -> Result[Any]:
- Returns Result(data=chat_config) on SDK success (sets globals, logs [CACHE CREATED])
- Returns Result(data=None, errors=[ErrorInfo]) on SDK failure (resets globals,
logs [CACHE FAILED])
- Preserves original semantics: globals set on success, reset on failure
Caller:
cached_config_result = _create_gemini_cache_result(sys_instr, tools_decl, file_items)
if cached_config_result.ok:
chat_config = cached_config_result.data
Audit: ai_client BC 5 -> 4. _send_gemini cache-related BC sites all migrated.
Site L1732: count_tokens block in _send_gemini had:
try: count_resp = _gemini_client.models.count_tokens(...)
... set should_cache based on total_tokens ...
except Exception as e: _append_comms('[COUNT FAILED]')
Per TIER1_REVIEW: logging is NOT a drain. MIGRATE to Result[bool].
New helper _should_cache_gemini_result(sys_instr: str) -> Result[bool]:
- Result(data=True) if token count >= 2048
- Result(data=False) if below threshold + [CACHING SKIPPED] comms note
- Result(data=False, errors=[ErrorInfo]) on SDK failure + [COUNT FAILED] comms
Caller: should_cache = _should_cache_gemini_result(sys_instr).data
Audit: ai_client BC 6 -> 5. Site L1732 (now shifted to L1752) no longer BC.
Sites L1680 (cache.delete on context change) and L1692 (cache.delete on
TTL expiry) had identical patterns:
try: _gemini_client.caches.delete(name=_gemini_cache.name)
except Exception as e: _append_comms('OUT', 'request', {'message': f'[CACHE DELETE WARN] {e}'})
Per TIER1_REVIEW: logging is NOT a drain. MIGRATE to Result[T].
Single helper _delete_gemini_cache_result() -> Result[None]:
- Returns Result(data=None) on success
- Returns Result(data=None, errors=[ErrorInfo]) on SDK failure + logs warning to comms
- Caller (_send_gemini) ignores errors (best-effort cleanup)
Audit: ai_client BC 8 -> 6. Both sites migrated.
The original function had a broken pattern: 'raise _classify_gemini_error(exc)
from exc' which raises an ErrorInfo (not an Exception) — a runtime bug.
Per TIER1_REVIEW 2026-06-20 directive: per-site decision. The body raised a
structured error carrier (ErrorInfo), but the pattern was incorrect (ErrorInfo
is not an Exception). Cleanest fix: full Result[T] migration.
New helper:
- _list_gemini_models_result(api_key: str) -> Result[list[str]]
Returns Result(data=sorted_models) on success, Result(data=[], errors=[ErrorInfo])
on SDK/network failure.
Legacy wrapper:
- _list_gemini_models(api_key: str) -> list[str]
Returns result.data (preserves original signature; callers don't see errors).
Audit: ai_client BC 9 -> 8. Site L1594 (now shifted to L1609 due to helper insertion)
no longer in INTERNAL_BROAD_CATCH.