diff --git a/src/app_controller.py b/src/app_controller.py index 146650b8..3e7d915e 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -3267,14 +3267,15 @@ class AppController: for d_name in discussions: discussions[d_name]["history"] = [] # Reset project state so stale data from prior live_gui tests does not - # leak into the next session. Mirrors the default-project branch in - # __init__ (see lines 1743-1745). - reset_name = Path(self.active_project_path).stem if self.active_project_path else "unnamed" - self.project = project_manager.default_project(reset_name) - self.active_project_path = "" + # leak into the next session. We do NOT clear self.active_project_path + # because _do_project_switch calls _flush_to_project() which writes to + # self.active_project_path; an empty path would raise OSError and + # create an infinite re-switch loop. (See test_context_sim_live + # regression on 2026-06-08.) + self.project = project_manager.default_project( + Path(self.active_project_path).stem if self.active_project_path else "unnamed" + ) self.project_paths = [] - self.workspace_manager = workspace_manager.WorkspaceManager(project_root=None) - self.workspace_profiles = self.workspace_manager.load_all_profiles() self.ai_status = "session reset" self.ai_response = "" self.ui_ai_input = "" diff --git a/tests/test_handle_reset_session_clears_project.py b/tests/test_handle_reset_session_clears_project.py index 0801e65f..f5606309 100644 --- a/tests/test_handle_reset_session_clears_project.py +++ b/tests/test_handle_reset_session_clears_project.py @@ -1,12 +1,18 @@ """Red-phase test: _handle_reset_session must clear project state. Background: the live_gui session-scoped fixture is shared across all 48 live -tests. Prior tests can leave stale `self.project`, `self.active_project_path`, -and `self.project_paths` on the controller, which leaks into -`test_full_live_workflow` and causes it to fail with "Project not switched". +tests. Prior tests can leave stale `self.project` and `self.project_paths` +on the controller, which leaks into `test_full_live_workflow` and causes +it to fail with "Project not switched". -The fix: `_handle_reset_session` should reset all three fields to a clean -default (matching what `__init__` does for an empty/unset project). +The fix: `_handle_reset_session` should reset `self.project` (to a fresh +default dict) and `self.project_paths` (empty list). + +Note: `self.active_project_path` is INTENTIONALLY NOT cleared, because +`_do_project_switch` calls `_flush_to_project()` which writes to +`self.active_project_path`. An empty path would raise OSError and +create an infinite re-switch loop. (See the regression discovered +in test_context_sim_live on 2026-06-08.) This test uses a real AppController() (per the test_view_presets pattern), pollutes the state, then calls _handle_reset_session and asserts. @@ -34,13 +40,18 @@ def controller(tmp_path): yield ctrl -def test_handle_reset_session_clears_active_project_path(controller): - """Active project path must be cleared or reset to a default.""" +def test_handle_reset_session_keeps_active_project_path(controller): + """Active project path is intentionally NOT cleared. + + `_do_project_switch` writes to it via `_flush_to_project`; clearing it + causes OSError on the next project switch. (Regression: test_context_sim_live + on 2026-06-08.) + """ assert controller.active_project_path.endswith("stale_project.toml") # precondition controller._handle_reset_session() - assert not controller.active_project_path.endswith("stale_project.toml"), ( - f"_handle_reset_session did not clear active_project_path " - f"(still {controller.active_project_path!r})" + assert controller.active_project_path.endswith("stale_project.toml"), ( + f"_handle_reset_session should NOT clear active_project_path " + f"(got {controller.active_project_path!r})" ) @@ -65,3 +76,4 @@ def test_handle_reset_session_resets_project_to_valid_default(controller): # And it must still be a usable project dict assert isinstance(controller.project, dict) assert "project" in controller.project +