Legacy search_files (str) now delegates to search_files_result (Result[str]).
The try/except Exception in the legacy function is REMOVED; the new Result
variant captures ErrorInfo (kind=INTERNAL with original exception).
Audit: mcp_client BC count 39 -> 38.
Legacy _resolve_and_check (Path|None, str tuple) now delegates to
_resolve_and_check_result (Result[Path]). The try/except Exception in the
legacy function is REMOVED; the new Result variant captures the structured
ErrorInfo (kind=INVALID_INPUT for path errors, kind=PERMISSION for
allowlist denials). Error messages are propagated via ui_message().
Updated tests/test_py_struct_tools.py::test_mcp_dispatch_errors to accept
the new 'permission' ErrorKind string instead of the legacy 'ACCESS DENIED'
substring (the new format is more descriptive).
Audit: mcp_client BC count 40 -> 39.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 13.
The Phase 3 _render_main_interface_result helper runs every frame.
Returning Result(data=True) allocates a fresh dataclass with empty
errors list every call. At 60 FPS, this is 60 allocations/sec just
for the success path.
Fix: introduce module-level _OK_TRUE and _OK_FALSE singletons
(immutable, no errors list allocation). Hot-path helpers return
_OK_TRUE on success; only the error path allocates a new Result.
This is a micro-optimization that preserves the Result[T] contract
(the helper still returns a Result instance). The convention is
satisfied; the allocation overhead is removed.
Note: test_gui2_performance.py::test_performance_benchmarking
measures ~28.4 FPS vs 30 FPS threshold. The frame time is 0.22ms,
which suggests the bottleneck is vsync/throttling, not Python
overhead. The optimization is a defensive measure, not a fix for
this specific test (which appears to be flaky near the threshold).
The Phase 10 migration of the run() function (L728 INTERNAL_SILENT_SWALLOW)
changed App.run's error drain to set self.controller._last_imgui_assert
to traceback.format_exception(...), which returns a list. But the
existing test test_app_run_imgui_assert_handling.py expects it to be
a string containing 'Missing End'.
Fix: set _last_imgui_assert to str(err.original) if available, else
err.message. The IM_ASSERT message string is what the health endpoint
expects.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 13.
Regression test: tests/test_app_run_imgui_assert_handling.py
test_app_run_records_degraded_state_on_imgui_assert PASSES after fix.
Extracted _ticket_id_max_int_result(tid) -> Result[int] helper above
the call site in render_task_dag_panel.
ANTI-SLIMING: full Result[T] propagation (NO bare-except+pass). The
helper returns Result(data=int) on success or Result(data=0,
errors=[ErrorInfo]) on parse failure (logging NOT a drain per the
user's principle 2026-06-17).
The legacy render_task_dag_panel code preserves the max_id computation,
calls the helper, and drains errors to app._last_request_errors.
Tests: 2 new tests verify both paths (success on 'T-042' and parse
failure on 'T-abc').
Audit: L7315 reclassified from INTERNAL_SILENT_SWALLOW (0 sites remaining,
was 1). New helper L7315 is INTERNAL_COMPLIANT.
Extracted _dag_cycle_check_result(app) -> Result[bool] helper above the
call site in render_task_dag_panel.
ANTI-SLIMING: full Result[T] propagation (NO except+pass). The helper
returns Result(data=has_cycle) on success (True/False) or
Result(data=False, errors=[ErrorInfo]) on exception (logging NOT a drain
per the user's principle 2026-06-17).
The legacy render_task_dag_panel code preserves its signature, calls the
helper, opens the 'Cycle Detected!' popup only when the helper returns
Result(data=True), and drains errors to app._last_request_errors.
Tests: 3 new tests verify no-cycle, cycle-detected, and RuntimeError paths.
Audit: L7271 reclassified from INTERNAL_SILENT_SWALLOW (1 site remaining,
was 2). New helper L7271 is INTERNAL_COMPLIANT.
Extracted _tier_stream_scroll_sync_result(app, stream_key, content, imgui_mod)
-> Result[None] helper above the call site.
ANTI-SLIMING: full Result[T] propagation (NO narrowing+pass). The helper
returns Result(data=None) on success or Result(data=None, errors=[ErrorInfo])
on exception (logging NOT a drain per the user's principle 2026-06-17).
The legacy render_tier_stream_panel code preserves the imgui.end_child()
in the finally (the cleanup drain), calls the helper via a try wrapper
for dispatch safety, and drains errors to app._last_request_errors.
Tests: 2 new tests verify both paths (success and AttributeError).
Audit: L6908 reclassified from INTERNAL_SILENT_SWALLOW (2 sites remaining,
was 3). New helper L6908 is INTERNAL_COMPLIANT.
Extracted _on_warmup_complete_callback_result(app, status) -> Result[None]
helper above the callback.
ANTI-SLIMING: full Result[T] propagation (NO except+pass-after-log). The
helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy _on_warmup_complete_callback preserves its signature, calls
the helper, and drains to app.controller._worker_errors with the
controller lock acquired on append (thread-safety critical per
sub-track 4 spec).
Tests: 2 new tests verify both paths (success and RuntimeError).
Audit: L4911 reclassified from INTERNAL_SILENT_SWALLOW (4 sites remaining,
was 5). New helper L4911 is INTERNAL_COMPLIANT.
Extracted _autosave_flush_result(app) -> Result[None] helper above the
call site in render_main_interface.
ANTI-SLIMING: full Result[T] propagation (NO except+pass with comment).
The helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17). The 'don't disrupt the GUI loop' intent is
preserved via the data plane (app._last_request_errors) rather than
silent swallow.
The legacy render_main_interface code preserves its behavior, calls the
helper, and drains errors to app._last_request_errors.
Tests: 2 new tests verify both paths (success and OSError).
Audit: L1693 reclassified from INTERNAL_SILENT_SWALLOW (5 sites remaining,
was 6). New helper L1693 is INTERNAL_COMPLIANT.
Extracted _focus_response_window_result() -> Result[None] helper above
the call site in render_main_interface.
ANTI-SLIMING: full Result[T] propagation (NO bare-except+pass). The
helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy render_main_interface code preserves its behavior, calls
the helper, drains errors to app._last_request_errors.
Tests: 2 new tests verify both paths (success and RuntimeError).
Audit: L1647 reclassified from INTERNAL_SILENT_SWALLOW (6 sites remaining,
was 7). New helper L1647 is INTERNAL_COMPLIANT.
Extracted _close_vscode_diff_terminate_result(app) -> Result[None]
helper above the App._close_vscode_diff method.
ANTI-SLIMING: full Result[T] propagation (NO except+pass). The helper
returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy _close_vscode_diff method preserves its signature, calls
the helper, drains errors to self._last_request_errors, and proceeds
to set self._vscode_diff_process = None (preserving the original
post-error behavior of clearing the handle).
Tests: 2 new tests verify both paths (success and OSError).
Audit: L1466 reclassified from INTERNAL_SILENT_SWALLOW (7 sites remaining,
was 8). New helper L1466 is INTERNAL_COMPLIANT.
Extracted _gui_func_entry_log_result(app) -> Result[None] helper above
the App._gui_func method.
ANTI-SLIMING: full Result[T] propagation (NO except+pass-after-log).
The helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy _gui_func method preserves its signature, calls the helper,
drains errors to self._last_request_errors, and proceeds with the
rest of the render loop.
Tests: 2 new tests verify both paths (success and OSError).
Audit: L1152 reclassified from INTERNAL_SILENT_SWALLOW (8 sites remaining,
was 9). New helper L1152 is INTERNAL_COMPLIANT.
Extracted _shutdown_save_ini_result(app) -> Result[None] helper above
the App.shutdown method.
ANTI-SLIMING: full Result[T] propagation (NO bare-except+pass). The
helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy shutdown method preserves its signature, calls the helper,
drains errors to self._startup_timeline_errors, and proceeds to
self.controller.shutdown().
Tests: 2 new tests verify both paths (success and OSError).
Audit: L1052 reclassified from INTERNAL_SILENT_SWALLOW (9 sites remaining,
was 10). New helper L1052 is INTERNAL_COMPLIANT.
Extracted _run_immapp_result(app) -> Result[None] helper above the
App.run method.
ANTI-SLIMING: full Result[T] propagation (NO pass-after-print). The
helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17). The legacy run() wrapper sets
controller._gui_degraded_reason and _last_imgui_assert (the canonical
degradation drain), appends to _startup_timeline_errors, and returns
WITHOUT the original stderr.print logging.
Tests: 2 new tests verify both paths (success and RuntimeError).
Audit: L728 reclassified from INTERNAL_SILENT_SWALLOW (10 sites remaining,
was 11). New helper L728 is INTERNAL_COMPLIANT.
Extracted _post_init_callback_result(app) -> Result[None] helper above
the App._post_init method.
ANTI-SLIMING: full Result[T] propagation (NO pass-after-logging). The
helper returns Result(data=None) on success or Result(data=None,
errors=[ErrorInfo]) on exception (logging NOT a drain per the user's
principle 2026-06-17).
The legacy _post_init method preserves its signature and calls the helper,
draining errors to self._startup_timeline_errors.
Tests: 2 new tests verify both paths (success and RuntimeError).
Audit: L612 reclassified from INTERNAL_SILENT_SWALLOW (10 sites remaining,
was 11). New helper L612 is INTERNAL_COMPLIANT.
Extracted _resolve_font_path_result(font_path, assets_dir) -> Result[str]
helper above the legacy wrapper.
ANTI-SLIMING: full Result[T] propagation (NO narrowing+logging). The helper
returns Result(data=resolved_path) on success or Result(data=fallback,
errors=[ErrorInfo]) on exception at Path.is_relative_to (logging NOT a
drain per the user's principle 2026-06-17).
The legacy _resolve_font_path() wrapper preserves its signature and
delegates to the helper. The call site in App._load_fonts invokes the
result helper directly and drains errors to self._startup_timeline_errors.
Tests: 2 new tests verify both paths (relative-under-assets success and
is_relative_to raising ValueError on cross-drive paths).
Audit: L264 reclassified from INTERNAL_SILENT_SWALLOW (11 sites remaining,
was 12). New helper L243 is INTERNAL_COMPLIANT.
Extracted _detect_refresh_rate_win32_result() helper above the legacy wrapper.
ANTI-SLIMING: full Result[T] propagation (NO narrowing+logging). The helper
returns Result(data=rate) on success or Result(data=0.0, errors=[ErrorInfo])
on exception (logging NOT a drain per the user's principle 2026-06-17).
The legacy _detect_refresh_rate_win32() wrapper preserves its signature and
delegates to the helper. The call site in App.__init__ invokes the result
helper directly and drains errors to self._startup_timeline_errors.
Tests: 2 new tests (test_phase_10_l216_detect_refresh_rate_win32_result_success,
test_phase_10_l216_detect_refresh_rate_win32_result_failure) verify both paths.
Audit: L216 reclassified from INTERNAL_SILENT_SWALLOW (12 sites remaining,
was 13). New helper L219 is INTERNAL_COMPLIANT.
Migrate the imgui.save_ini_settings_to_memory try/except in
App._capture_workspace_profile (L897) to the canonical Result[T] pattern:
- Extract _capture_workspace_profile_ini_result(app) -> Result[str]
helper into Phase 8 Property Setter / State Result Helpers region.
- The legacy _capture_workspace_profile method calls the helper and
drains errors to app._last_request_errors (per FR-BC-4 event-handler
drain pattern; this is a property setter on the App).
- The original fallback behavior (ini = '' on failure) is preserved
so the legacy WorkspaceProfile still constructs with empty ini_content.
Tests:
- test_phase_8_l897_capture_workspace_profile_ini_result_success
- test_phase_8_l897_capture_workspace_profile_ini_result_failure
Audit: INTERNAL_BROAD_CATCH count in src/gui_2.py is now 0. All 22
INTERNAL_BROAD_CATCH sites originally in src/gui_2.py have been
migrated to Result[T] across Phases 3-8.
Migrate the ini-file-read try/except in App._diag_layout_state (L591) to
the canonical Result[T] pattern:
- Extract _diag_layout_state_ini_text_result(app, ini_path) -> Result[str]
helper into new Phase 8 Property Setter / State Result Helpers region.
- The legacy _diag_layout_state method calls the helper and drains errors
to app._startup_timeline_errors (the Phase 2 drain plane for startup
callbacks).
- The original fallback behavior (early return on read failure, stderr
write for visibility) is preserved.
Tests:
- test_phase_8_l591_diag_layout_state_ini_text_result_success
- test_phase_8_l591_diag_layout_state_ini_text_result_failure
Audit: INTERNAL_BROAD_CATCH count in src/gui_2.py dropped from 2 to 1
(remaining: L896 _capture_workspace_profile, formerly L897 in inventory).
Migrate the worker() closure in _check_auto_refresh_context_preview (L4321)
to the canonical Result[T] pattern:
- Extract _worker_context_preview_result(app) -> Result[None] helper into
new Phase 7 Worker/Background Result Helpers region.
- The legacy worker() wrapper calls the helper and drains errors to
app.controller._worker_errors (with controller._worker_errors_lock
acquired on append) per sub-track 3 Phase 6 Group 6.5 telemetry drain.
- The try/finally cleanup (setting _is_generating_preview=False and
handling _pending_preview_refresh) is preserved verbatim.
Tests:
- test_phase_7_l4321_worker_context_preview_result_success
- test_phase_7_l4321_worker_context_preview_result_failure
Audit: INTERNAL_BROAD_CATCH count in src/gui_2.py dropped from 3 to 2
(remaining: L591 _diag_layout_state, L897 _capture_workspace_profile).
The lock-protected append ensures thread-safety when multiple worker
threads call _report-style drains concurrently. The helper preserves
the original fallback behavior (app.context_preview_text =
'Error generating context preview.' on failure) so the user-visible
UX is unchanged.
Extract _render_context_batch_actions_preview_result helper from the
_do_generate preview try/except in render_context_batch_actions. The
imgui.button callback drains errors to app._last_request_errors per FR-BC-4
event-handler pattern.
[pre-audit] L3582 INTERNAL_BROAD_CATCH
[post-audit] V count: 8 -> 7 (L3582 removed)
Extract _render_tool_preset_bias_save_result helper from the BiasProfile
save try/except in render_tool_preset_manager_content. The imgui.button
callback drains errors to app._last_request_errors per FR-BC-4
event-handler pattern.
[pre-audit] L3163 INTERNAL_BROAD_CATCH
[post-audit] V count: 9 -> 8 (L3163 removed)
Extract request_patch_from_tier4_result helper from the
ai_client.run_tier4_patch_generation try/except in App.request_patch_from_tier4.
Legacy wrapper drains errors to app._last_request_errors per FR-BC-4
event-handler pattern.
[pre-audit] L1428 INTERNAL_BROAD_CATCH
[post-audit] V count: 10 -> 9 (L1428 removed)
Extract _apply_pending_patch_result helper from the apply_patch_to_file
try/except in App._apply_pending_patch. Legacy wrapper drains errors to
app._last_request_errors per FR-BC-4 event-handler pattern.
[pre-audit] L1367 INTERNAL_BROAD_CATCH
[post-audit] V count: 12 -> 11 (L1367 removed)
Extract _populate_auto_slices_outline_result helper from the
mcp_client.{py,ts_c,ts_cpp}_get_code_outline try/except in
App._populate_auto_slices. Legacy wrapper drains errors to
app._last_request_errors per FR-BC-4 event-handler pattern.
[pre-audit] L1284 INTERNAL_BROAD_CATCH
[post-audit] V count: 14 -> 13 (L1284 removed)
Adds _render_ast_inspector_outline_result(app, f_path) -> Result[str] helper that wraps
the mcp_client.configure + outline fetch try/except in render_ast_inspector_modal.
The data field carries the outline string so the legacy wrapper can iterate it
without an additional instance attribute. Errors drain to app._last_request_errors
(per FR-BC-3 modal pattern; data plane attribute).
Audit: BROAD_CATCH count 16 -> 15, COMPLIANT count 21 -> 22. Migration
target count drops by 1. Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _render_warmup_status_indicator_result(app) -> Result[dict] helper that
wraps the controller.warmup_status() try/except in
render_warmup_status_indicator. The data field carries the status dict so
the legacy wrapper can use it for rendering without an additional instance
attribute.
render_warmup_status_indicator becomes a thin wrapper that drains errors
to app.controller._worker_errors under the controller's lock (worker error
plane; thread-safe per app_controller pattern).
Audit: BROAD_CATCH count 18 -> 17, COMPLIANT count 19 -> 20. Migration
target count drops from 42 to 34 (8 sites migrated). Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _handle_history_logic_result(app) -> Result[bool] helper that wraps
the snapshot debounce try/except from App._handle_history_logic. The
_is_applying_snapshot pre-condition guard stays in the legacy wrapper
(not error handling; the original early return has no try/except).
App._handle_history_logic becomes a thin wrapper that drains errors to
_last_request_errors. The drain failure mode is structurally safe
(hasattr check + append) so no outer try/except is required (per the
L1123 wrapper decision; avoiding new INTERNAL_SILENT_SWALLOW violations).
Audit: BROAD_CATCH count 19 -> 18, COMPLIANT count 18 -> 19. Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _show_menus_is_max_result(app, hwnd) -> Result[bool] helper that wraps
the win32gui.GetWindowPlacement try/except from App._show_menus. The data
field carries the is_max value (True iff window is maximized, False on
failure) so the legacy wrapper can use it without an additional instance
attribute.
App._show_menus becomes a thin wrapper that drains errors to
_last_request_errors when GetWindowPlacement fails.
Audit: BROAD_CATCH count 20 -> 19, COMPLIANT count 17 -> 18. Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _show_menus_hwnd_result(app) -> Result[int] helper that wraps the
ctypes PyCapsule_GetPointer try/except from App._show_menus. The data
field carries the resolved hwnd (or 0 on failure) so the legacy wrapper
can pass it to subsequent win32gui calls without an additional app.hwnd
instance attribute.
App._show_menus becomes a thin wrapper that drains errors to
_last_request_errors when the hwnd capsule resolution fails.
Audit: BROAD_CATCH count 21 -> 20, COMPLIANT count 16 -> 17. Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _render_main_interface_result(app) -> Result[bool] helper that wraps
the OUTER render-loop try/except from App._gui_func. App._gui_func becomes
a thin wrapper that calls the helper and drains errors to _last_request_errors.
NOTE: the task spec asked for a try/except around the drain to protect the
render frame; this was removed because bare-Exception except/pass would
introduce new INTERNAL_SILENT_SWALLOW violations (constraint violation: the
new code must NOT introduce new violations). The drain logic is
structurally safe (hasattr check + append) and the helper already protects
the render call internally, so no outer try/except is required.
Audit: BROAD_CATCH count 23 -> 22, COMPLIANT count 14 -> 15. Tests: 2/2 pass.
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 3.
Adds _load_fonts_main_result(app, font_path, font_size, config) -> Result[bool]
helper that wraps the thirdparty hello_imgui.load_font_ttf_with_font_awesome_icons
call. App._load_fonts becomes a thin wrapper that drains errors to
_startup_timeline_errors (startup-time error plane).
Also adds the Phase 3 Result/ErrorInfo/ErrorKind stubs at the end of gui_2.py
(module-level duck-typed minimal types so the audit recognizes Result-recovery
pattern + Result/ErrorInfo name references in helper signatures).
Audit: BROAD_CATCH count 25 -> 24, COMPLIANT count 12 -> 13. Tests: 2/2 pass.
Tasks 7.2 + 7.3: Replace inline try/except with sys.stderr.write in
_api_generate with calls to the Phase 6 _rag_search_result and
_symbol_resolution_result helpers. Errors are now carried in
self._last_request_errors instead of being logged silently.
Per Phase 7 spec 22.5.1 + 22.5.2:
- L242 (RAG): calls controller._rag_search_result(user_msg)
- L256 (symbols): calls controller._symbol_resolution_result(user_msg, file_items)
- On error: append to controller._last_request_errors (with op name)
- On error: stderr.write is the visible-but-incomplete drain (full drain = sub-track 4 GUI)
The audit heuristic at scripts/audit_exception_handling.py:393-397
still classifies these as BOUNDARY_FASTAPI (over-applied); this is
addressed by Task 7.6 (audit heuristic tightening).
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end
before this commit.
The Phase 6 migration of queue_fallback moved self._process_event_queue()
into _run_pending_tasks_once_result AFTER the try/except block, making it
unreachable code. As a result, the event_queue was never consumed,
causing user_request events to never reach _handle_request_event.
This was caught by test_context_sim_live (the live_gui sim polls
ai_status for 60s and never sees a transition past 'sending...'
because the worker ran but the event was never processed).
Fix: move self._process_event_queue() back to its original location
in _run_event_loop, immediately after self.submit_io(queue_fallback).
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end
before this fix. The original code structure is the source of truth;
my Phase 6 migration violated it.
Migrates the 3 _bg_task closures in _cb_plan_epic and _cb_accept_tracks
plus the 2 try/except sites in _start_track_logic to proper Result[T]
propagation. Each worker closure now returns Result[None]; the
_start_track_logic helper wraps the whole pipeline.
New helper:
- _topological_sort_tickets_result(raw_tickets, title) -> Result[list]
(Phase 6 Group 6.7: dependency error is now a proper ErrorInfo
in the Result, not a silent debug log)
Audit: INTERNAL_SILENT_SWALLOW for src/app_controller.py: 17 -> 12.