"""load_profiles_from_dir — and the tally that keeps a partial set from being silent.
A profile whose config.json is unreadable is skipped by design (it must not take
the server down), but the UI then just shows a shorter list. On prod, 2026-10-07
15:20, four of them (modeler_3d, navi_code, secretary, server_admin) were dropped
with `Extra data: line 125 column 1` — a second JSON document appended to the
file — and the only trace was a per-profile error line: nothing said that four
profiles had gone missing.
"""
import json
from structlog.testing import capture_logs
from navi.profiles.base import AgentProfile
from navi.profiles.loader import load_profiles_from_dir, save_profile_to_dir
GOOD_CONFIG = {"id": "good", "name": "Good", "description": "a valid profile"}
def write_profile(base, dirname, config=GOOD_CONFIG, prompt="You are helpful.\n"):
"""Create a profile directory; `config` is written raw as JSON text."""
d = base / dirname
d.mkdir()
(d / "config.json").write_text(
config if isinstance(config, str) else json.dumps(config), encoding="utf-8"
)
(d / "system_prompt.txt").write_text(prompt, encoding="utf-8")
return d
class TestLoading:
def test_valid_profiles_load(self, tmp_path):
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
write_profile(tmp_path, "beta", {**GOOD_CONFIG, "id": "beta"})
profiles = load_profiles_from_dir(tmp_path)
assert [p.id for p in profiles] == ["alpha", "beta"]
def test_a_broken_config_does_not_take_the_others_with_it(self, tmp_path, capfd):
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
write_profile(tmp_path, "corrupt", "{ not json at all")
profiles = load_profiles_from_dir(tmp_path)
assert [p.id for p in profiles] == ["alpha"]
out = capfd.readouterr().out
assert "profile.loader.error" in out
assert "corrupt" in out
def test_a_config_missing_required_keys_is_skipped(self, tmp_path):
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
write_profile(tmp_path, "nameless", {"description": "no id, no name"})
profiles = load_profiles_from_dir(tmp_path)
assert [p.id for p in profiles] == ["alpha"]
def test_subdirectories_without_the_files_are_not_dropped_profiles(self, tmp_path):
"""Stray directories are not corruption — counting them would make the
tally cry wolf on every ordinary tree (e.g. a __pycache__ dir)."""
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
(tmp_path / "__pycache__").mkdir()
(tmp_path / "notes.txt").write_text("not a profile", encoding="utf-8")
profiles = load_profiles_from_dir(tmp_path)
assert [p.id for p in profiles] == ["alpha"]
class TestSummaryLog:
def test_the_tally_names_what_was_skipped(self, tmp_path):
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
write_profile(tmp_path, "corrupt", "{ definitely not json")
with capture_logs() as captured:
load_profiles_from_dir(tmp_path)
errors = [e for e in captured if e["event"] == "profile.loader.error"]
assert [e["profile_dir"] for e in errors] == ["corrupt"]
summary = [e for e in captured if e["event"] == "profile.loader.summary"]
assert len(summary) == 1
assert summary[0]["log_level"] == "warning"
assert summary[0]["loaded"] == 1
assert summary[0]["skipped"] == ["corrupt"]
def test_a_clean_load_warns_about_nothing(self, tmp_path):
write_profile(tmp_path, "alpha", {**GOOD_CONFIG, "id": "alpha"})
with capture_logs() as captured:
load_profiles_from_dir(tmp_path)
assert [e for e in captured if e["log_level"] in ("warning", "error")] == []
class TestAdminOnlyFlag:
"""`is_admin_only` used to live only in the profile_overrides DB table: the
loader never read it and the writer never emitted it, so a config.json that
said `"is_admin_only": true` was silently a no-op."""
def test_read_from_config(self, tmp_path):
write_profile(tmp_path, "root", {**GOOD_CONFIG, "id": "root", "is_admin_only": True})
profiles = load_profiles_from_dir(tmp_path)
assert profiles[0].is_admin_only is True
def test_defaults_to_false(self, tmp_path):
write_profile(tmp_path, "plain", {**GOOD_CONFIG, "id": "plain"})
profiles = load_profiles_from_dir(tmp_path)
assert profiles[0].is_admin_only is False
def test_survives_a_save_and_reload(self, tmp_path):
profile = AgentProfile(**GOOD_CONFIG, system_prompt="You are root.\n", is_admin_only=True)
save_profile_to_dir(profile, tmp_path)
reloaded = load_profiles_from_dir(tmp_path)
assert [p.is_admin_only for p in reloaded] == [True]