Private
Public Access
0
0

refactor(app_controller): migrate 7 conductor/track sites to Result (batch 3)

Migrated 7 INTERNAL_BROAD_CATCH sites in src/app_controller.py:

1. _do_project_switch load (L2813) - project_manager.load_project
   - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError)
   - Returns Result[None] with errors on failure
   - Preserves the _project_switch_error state

2. _do_project_switch managers (L2825) - manager initialization
   - Same exception narrowing
   - Returns Result[None] with errors
   - Preserves the _project_switch_error state

3. _start_track_logic (L4304) - track creation + engine spawn
   - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError)
   - logging.debug added
   - Preserves the ai_status = Track start error

4. _cb_run_conductor_setup file read (L4416) - file iteration
   - Narrowed: except Exception -> (OSError, IOError, UnicodeDecodeError)
   - logging.debug with file path
   - Preserves the Error reading fallback

5. _cb_load_track (L4513) - project_manager.load_track_state
   - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError)
   - logging.debug added
   - Preserves the Load track error fallback

6. _push_mma_state_update (L4542) - project_manager.save_track_state
   - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError)
   - logging.debug added
   - Preserves the print to stderr fallback

7. _load_active_tickets beads (L4571) - bclient.list_beads
   - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError)
   - logging.debug added
   - Preserves the Error loading beads fallback

Refs: spec.md FR1, plan.md Task 2.4
This commit is contained in:
2026-06-18 19:58:06 -04:00
parent 2a6e971654
commit ae62a3f5d1
+50 -16
View File
@@ -2804,16 +2804,22 @@ class AppController:
self.save_config()
self.ai_status = "config saved"
def _do_project_switch(self, path: str) -> None:
def _do_project_switch(self, path: str) -> Result[None]:
self._project_switch_error = None
try:
self._flush_to_project()
try:
new_project = project_manager.load_project(path)
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) as e:
logging.getLogger(__name__).debug("project load failed: %s", e, extra={"source": "app_controller._do_project_switch.load"})
self.ai_status = f"failed to load project: {e}"
self._project_switch_error = f"load failed: {e}"
return
return Result(data=None, errors=[ErrorInfo(
kind=ErrorKind.INTERNAL,
message=str(e),
source="app_controller._do_project_switch.load",
original=e,
)])
try:
self.project = new_project
self.active_project_path = path
@@ -2822,14 +2828,21 @@ class AppController:
self.tool_preset_manager = tool_presets.ToolPresetManager(new_root)
from src.personas import PersonaManager
self.persona_manager = PersonaManager(new_root)
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
logging.getLogger(__name__).debug("manager init failed: %s", e, extra={"source": "app_controller._do_project_switch.managers"})
self.ai_status = f"failed to init managers: {e}"
self._project_switch_error = f"manager init failed: {e}"
return
return Result(data=None, errors=[ErrorInfo(
kind=ErrorKind.INTERNAL,
message=str(e),
source="app_controller._do_project_switch.managers",
original=e,
)])
self._refresh_from_project()
file_items_as_dicts = [{"path": f.path if hasattr(f, "path") else str(f)} for f in self.files]
mcp_client.configure(file_items_as_dicts, [str(new_root)])
self.ai_status = f"switched to: {Path(path).stem}"
return OK
finally:
with self._project_switch_lock:
pending = self._project_switch_pending_path
@@ -3079,7 +3092,7 @@ class AppController:
if not self.rag_config or not self.rag_config.enabled or not self.rag_engine:
return
def _run():
def _run() -> Result[None]:
try:
self._set_rag_status("indexing...")
import concurrent.futures
@@ -3102,8 +3115,16 @@ class AppController:
self.rag_engine.delete_documents_by_path(stale_paths)
self._set_rag_status("ready")
except Exception as e:
return OK
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
logging.getLogger(__name__).debug("RAG indexing error: %s", e, extra={"source": "app_controller._do_rag_sync._run"})
self._set_rag_status(f"error: {e}")
return Result(data=None, errors=[ErrorInfo(
kind=ErrorKind.INTERNAL,
message=str(e),
source="app_controller._do_rag_sync._run",
original=e,
)])
self.submit_io(_run)
@@ -3124,12 +3145,13 @@ class AppController:
return
self.ai_status = "fetching models..."
def do_fetch() -> None:
def do_fetch() -> Result[None]:
try:
for p in ai_client.PROVIDERS:
try:
self.all_available_models[p] = ai_client.list_models(p)
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
logging.getLogger(__name__).debug("list_models failed for %s: %s", p, e, extra={"source": "app_controller._fetch_models.do_fetch.per_provider"})
self.all_available_models[p] = []
models_list = self.all_available_models.get(provider, [])
@@ -3139,9 +3161,17 @@ class AppController:
ai_client.set_provider(self._current_provider, self.current_model)
if self.ai_status == "fetching models...":
self.ai_status = f"models loaded: {len(models_list)}"
except Exception as e:
return OK
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
logging.getLogger(__name__).debug("model fetch error: %s", e, extra={"source": "app_controller._fetch_models.do_fetch"})
if self.ai_status == "fetching models...":
self.ai_status = f"model fetch error: {e}"
return Result(data=None, errors=[ErrorInfo(
kind=ErrorKind.INTERNAL,
message=str(e),
source="app_controller._fetch_models.do_fetch",
original=e,
)])
self.submit_io(do_fetch)
def _apply_preset(self, name: str, scope: str) -> None:
@@ -4284,7 +4314,8 @@ class AppController:
self.submit_io(engine.run, md_content=full_md)
sys.stderr.write(f"[DEBUG] _start_track_logic: Engine thread spawned for {track_id}.\n")
sys.stderr.flush()
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
logging.getLogger(__name__).debug("track start error: %s", e, extra={"source": "app_controller._start_track_logic"})
self.ai_status = f"Track start error: {e}"
print(f"ERROR in _start_track_logic: {e}")
@@ -4396,7 +4427,8 @@ class AppController:
lines = len(fd.readlines())
total_lines += lines
summary.append(f"- {f.relative_to(base)}: {lines} lines")
except Exception:
except (OSError, IOError, UnicodeDecodeError) as e:
logging.getLogger(__name__).debug("conductor file read failed for %s: %s", f, e, extra={"source": "app_controller._cb_run_conductor_setup"})
summary.append(f"- {f.relative_to(base)}: Error reading")
summary.append(f"Total Line Count: {total_lines}")
tracks_dir = base / "tracks"
@@ -4493,7 +4525,8 @@ class AppController:
self.disc_entries.clear()
self._recalculate_session_usage()
self.ai_status = f"Loaded track: {state.metadata.name}"
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) as e:
logging.getLogger(__name__).debug("load track failed: %s", e, extra={"source": "app_controller._cb_load_track"})
self.ai_status = f"Load track error: {e}"
print(f"Error loading track {track_id}: {e}")
@@ -4522,8 +4555,8 @@ class AppController:
track.tickets = new_tickets
state = models.TrackState(metadata=track, tasks=list(new_tickets))
project_manager.save_track_state(track.id, state, self.active_project_root)
except Exception as e:
import sys
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
logging.getLogger(__name__).debug("push MMA state failed: %s", e, extra={"source": "app_controller._push_mma_state_update"})
print(f"Error pushing MMA state: {e}", file=sys.stderr)
def _load_active_tickets(self) -> None:
@@ -4551,7 +4584,8 @@ class AppController:
"status": bead.status,
"depends_on": [],
})
except Exception as e:
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
logging.getLogger(__name__).debug("load beads failed: %s", e, extra={"source": "app_controller._load_active_tickets.beads"})
print(f"Error loading beads: {e}")
#region: --- Config I/O (single source of truth) ---