fix(app_controller): catch RuntimeError from FR1 audit hook in fallback save
The _load_active_project fallback save was wrapped in try/except for
(OSError, IOError, PermissionError) only. The FR1 audit hook raises
RuntimeError('TEST_SANDBOX_VIOLATION...') when a test tries to write
outside ./tests/. Add RuntimeError to the caught exception list so tests
that do App() / AppController() directly (without setting
active_project_path) don't crash — the empty fallback is silently skipped
and the app continues operating.
Also update tests/test_app_controller_offloading.py:tmp_session_dir
fixture to re-initialize paths after reset_paths() so paths.get_logs_dir()
honors the SLOP_LOGS_DIR env var instead of raising RuntimeError.
This commit is contained in:
@@ -2218,15 +2218,15 @@ class AppController:
|
||||
self.active_project_path = fallback_path
|
||||
if fallback_path not in self.project_paths:
|
||||
self.project_paths.append(fallback_path)
|
||||
except (OSError, IOError, PermissionError) as e:
|
||||
except (OSError, IOError, PermissionError, RuntimeError) as e:
|
||||
logging.getLogger(__name__).debug(
|
||||
"Could not save fallback project to %s: %s", fallback_path, e,
|
||||
extra={"source": "app_controller._load_active_project.fallback_save"},
|
||||
)
|
||||
# The save is best-effort; the app can still operate without persisting
|
||||
# the empty fallback (e.g., when the test sandbox FR1 guard blocks
|
||||
# writes to the project root). active_project_path stays empty;
|
||||
# the next save will use a proper path.
|
||||
# writes to the project root via the sys.addaudithook RuntimeError).
|
||||
# active_project_path stays empty; the next save will use a proper path.
|
||||
self.preset_manager = presets.PresetManager(Path(self.active_project_path).parent if self.active_project_path else None)
|
||||
self.tool_preset_manager = tool_presets.ToolPresetManager(Path(self.active_project_path).parent if self.active_project_path else None)
|
||||
from src.personas import PersonaManager
|
||||
|
||||
@@ -18,7 +18,12 @@ def tmp_session_dir(tmp_path, monkeypatch):
|
||||
|
||||
monkeypatch.setenv("SLOP_LOGS_DIR", str(logs_dir))
|
||||
monkeypatch.setenv("SLOP_SCRIPTS_DIR", str(scripts_dir))
|
||||
paths.reset_paths()
|
||||
# v3 paths.py: reset_paths() clears the singleton. Re-initialize with an
|
||||
# empty config (no [paths] section) so the SLOP_LOGS_DIR env var is honored
|
||||
# via _resolve_path. Without this, paths.get_logs_dir() raises RuntimeError.
|
||||
empty_config = tmp_path / "empty.toml"
|
||||
empty_config.write_text("# no [paths] section\n")
|
||||
paths.initialize_paths(empty_config)
|
||||
|
||||
# Ensure session_logger is clean
|
||||
with patch("src.session_logger._comms_fh", None):
|
||||
|
||||
Reference in New Issue
Block a user