"""Phase 4: lifecycle guard + per-profile observability.""" import pytest class TestServedProfilesStatus: def test_write_and_read_served_profiles(self, tmp_path, monkeypatch): monkeypatch.setenv("HERMES_HOME", str(tmp_path)) import importlib import gateway.status as status importlib.reload(status) try: status.write_runtime_status( gateway_state="running", served_profiles=["default", "coder"] ) rec = status.read_runtime_status() assert rec.get("served_profiles") == ["default", "coder"] finally: importlib.reload(status) class TestNamedProfileMultiplexerGuard: """_guard_named_profile_under_multiplexer is inert unless all conditions hold.""" def test_force_bypasses(self, monkeypatch): from hermes_cli import gateway as gw # Even if it looks like a named profile, force returns immediately. monkeypatch.setattr(gw, "_profile_suffix", lambda: "coder") gw._guard_named_profile_under_multiplexer(force=True) def test_inert_when_no_default_gateway_running(self, monkeypatch, tmp_path): from hermes_cli import gateway as gw monkeypatch.setattr(gw, "_profile_suffix", lambda: "coder") monkeypatch.setattr( "hermes_constants.get_default_hermes_root", lambda: tmp_path ) # No gateway.pid in tmp_path => no running default gateway => no raise. gw._guard_named_profile_under_multiplexer(force=False) def _fake_running_default_gateway(self, monkeypatch, tmp_path): """Make the guard believe a live default gateway exists at tmp_path.""" from hermes_cli import gateway as gw import gateway.status as status monkeypatch.setattr(gw, "_profile_suffix", lambda: "coder") monkeypatch.setattr( "hermes_constants.get_default_hermes_root", lambda: tmp_path ) (tmp_path / "gateway.pid").write_text("12345", encoding="utf-8") monkeypatch.setattr(status, "_read_pid_record", lambda p: {"pid": 12345}) monkeypatch.setattr(status, "_pid_from_record", lambda rec: 12345) monkeypatch.setattr(status, "_pid_exists", lambda pid: True)