diff --git a/src/app_controller.py b/src/app_controller.py index eccfd157..961f96d0 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -2778,12 +2778,12 @@ class AppController: )]) @property - def _pending_mma_spawn(self) -> Optional[Metadata]: - return self._pending_mma_spawns[0] if self._pending_mma_spawns else None + def _pending_mma_spawn(self) -> Metadata: + return self._pending_mma_spawns[0] if self._pending_mma_spawns else Metadata() @property - def _pending_mma_approval(self) -> Optional[Metadata]: - return self._pending_mma_approvals[0] if self._pending_mma_approvals else None + def _pending_mma_approval(self) -> Metadata: + return self._pending_mma_approvals[0] if self._pending_mma_approvals else Metadata() @property def current_provider(self) -> str: diff --git a/src/models.py b/src/models.py index ad8e403c..1d1e611e 100644 --- a/src/models.py +++ b/src/models.py @@ -474,7 +474,7 @@ class Metadata: @dataclass class TrackState: - metadata: Metadata + metadata: Metadata = field(default_factory=dict) discussion: List[str] = field(default_factory=list) tasks: List[Ticket] = field(default_factory=list) @@ -524,6 +524,10 @@ class TrackState: tasks = [Ticket.from_dict(t) for t in data.get("tasks", [])], ) + +EMPTY_TRACK_STATE: TrackState = TrackState() + + @dataclass class FileItem: path: str diff --git a/src/project_manager.py b/src/project_manager.py index 7c6c43fd..b2b7e70d 100644 --- a/src/project_manager.py +++ b/src/project_manager.py @@ -298,18 +298,19 @@ def save_track_state(track_id: str, state: 'TrackState', base_dir: Union[str, Pa data = clean_nones(state.to_dict()) with open(state_file, "wb") as f: tomli_w.dump(data, f) -def load_track_state(track_id: str, base_dir: Union[str, Path] = ".") -> Optional['TrackState']: +def load_track_state(track_id: str, base_dir: Union[str, Path] = ".") -> "TrackState": """ Loads a TrackState object from conductor/tracks//state.toml. + Returns empty TrackState (zero-init) if not found. [C: tests/test_track_state_persistence.py:test_track_state_persistence] """ - from src.models import TrackState + from src.models import TrackState, EMPTY_TRACK_STATE state_file = paths.get_track_state_dir(track_id, project_path=str(base_dir)) / 'state.toml' - if not state_file.exists(): return None + if not state_file.exists(): return EMPTY_TRACK_STATE try: with open(state_file, "rb") as f: data = tomllib.load(f) except (OSError, tomllib.TOMLDecodeError): - return None + return EMPTY_TRACK_STATE return TrackState.from_dict(data) def load_track_history(track_id: str, base_dir: Union[str, Path] = ".") -> list[str]: diff --git a/src/session_logger.py b/src/session_logger.py index b4c07f1a..a54cc42c 100644 --- a/src/session_logger.py +++ b/src/session_logger.py @@ -163,7 +163,7 @@ def log_comms(entry: dict[str, Any]) -> Result[bool]: except (OSError, TypeError, ValueError) as e: return Result(data=False, errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source="session_logger.log_comms", original=e)]) -def log_tool_call(script: str, result: str, script_path: Optional[str]) -> Optional[str]: +def log_tool_call(script: str, result: str, script_path: Optional[str]) -> str: """ Append a tool-call record to the toolcalls log and write the PS1 script to the session's scripts directory. Returns the path of the written script file.