diff --git a/tests/tui_gateway/test_seeded_branch_title_routing.py b/tests/tui_gateway/test_seeded_branch_title_routing.py new file mode 100644 index 0000000000..5c05fa5488 --- /dev/null +++ b/tests/tui_gateway/test_seeded_branch_title_routing.py @@ -0,0 +1,59 @@ +"""Seeded Desktop branches keep generated titles out of memory identity.""" + +import subprocess + +import pytest + +from hermes_state import SessionDB +from plugins.memory.honcho.client import HonchoClientConfig + + +@pytest.mark.parametrize("strategy", ["per-repo", "per-directory", "global"]) +def test_seeded_desktop_branch_title_preserves_memory_strategy(monkeypatch, tmp_path, strategy): + monkeypatch.setattr("hermes_cli.banner.prefetch_update_check", lambda: None) + from tui_gateway import server + + project = tmp_path / "example-project" + project.mkdir() + subprocess.run(["git", "init", "-q", str(project)], check=True) + db = SessionDB(tmp_path / "state.db") + monkeypatch.setattr(server, "_get_db", lambda: db) + monkeypatch.setattr(server, "_sessions", {}) + monkeypatch.setattr(server, "_load_cfg", lambda: {}) + monkeypatch.setattr(server, "_profile_home", lambda *a: None) + monkeypatch.setattr(server, "_resolve_model", lambda: "test-model") + monkeypatch.setattr(server, "_enable_gateway_prompts", lambda: None) + monkeypatch.setattr(server, "_schedule_agent_build", lambda *a: None) + monkeypatch.setattr(server, "_schedule_session_cap_enforcement", lambda: None) + monkeypatch.setattr(server, "_register_session_cwd", lambda *a: None) + monkeypatch.setattr(server, "_project_info_for_cwd", lambda *a: None) + history = [{"role": "user", "content": "Synthetic parent input"}, + {"role": "assistant", "content": "Synthetic parent response"}] + try: + db.create_session("parent", source="desktop", cwd=str(project)) + db.set_auto_title("parent", "Generated parent title", source="llm") + response = server._methods["session.create"]("create", { + "source": "desktop", "cwd": str(project), + "parent_session_id": "parent", "messages": history, + }) + assert "error" not in response, response + child = response["result"]["stored_session_id"] + cfg = HonchoClientConfig(session_strategy=strategy, workspace_id="shared-memory") + expected = cfg.resolve_session_name(cwd=str(project), session_id=child) + assert cfg.resolve_session_name( + cwd=str(project), session_id=child, + session_title=db.get_session_title(child), + session_title_source=db.get_session_title_source(child), + ) == expected + assert db.get_session_title_source(child) == SessionDB.TITLE_SOURCE_DERIVED + assert db.message_count(child) == len(history) + # A subsequent explicit rename must retain user authority. + db.set_session_title(child, "User chosen title") + assert db.get_session_title_source(child) == SessionDB.TITLE_SOURCE_USER + assert cfg.resolve_session_name( + cwd=str(project), session_id=child, + session_title=db.get_session_title(child), + session_title_source=db.get_session_title_source(child), + ) == cfg.resolve_session_name(cwd=str(project), session_title="User chosen title") + finally: + db.close() diff --git a/tests/tui_gateway/test_tui_gateway_server.py b/tests/tui_gateway/test_tui_gateway_server.py index 2a808838ec..e2c3c607ad 100644 --- a/tests/tui_gateway/test_tui_gateway_server.py +++ b/tests/tui_gateway/test_tui_gateway_server.py @@ -15973,8 +15973,9 @@ def test_session_create_persists_seeded_branch_child(monkeypatch): def append_messages_batch(self, session_id, messages, **kwargs): seen["messages"] = list(messages) - def set_session_title(self, key, title): + def set_auto_title(self, key, title, *, source): seen["title"] = title + seen["title_source"] = source return True monkeypatch.setattr(server, "_get_db", lambda: _FakeDB()) @@ -16017,6 +16018,7 @@ def test_session_create_persists_seeded_branch_child(monkeypatch): assert seen.get("parent") == "20260823_084113_6de211" assert seen.get("branched_from") == "20260823_084113_6de211" assert seen.get("title") == "My Parent Session #2" + assert seen.get("title_source") == "derived" # Seeded transcript copied into the durable row so REST prefetch and # defer_history hydration both find it immediately. diff --git a/website/docs/user-guide/features/honcho.md b/website/docs/user-guide/features/honcho.md index f302e694f9..3052368c81 100644 --- a/website/docs/user-guide/features/honcho.md +++ b/website/docs/user-guide/features/honcho.md @@ -144,7 +144,7 @@ Directory-based strategies and manual `sessions` mappings use the logical sessio Messaging gateways keep their stable per-chat session key regardless of strategy or title. For other sessions, `per-session` identity takes priority, followed by a manual directory mapping, an explicit title, and the configured strategy. -Automatically generated Hermes titles (`derived` or `llm`) are display metadata and do not override `sessionStrategy`. An explicit user title remains an intentional session-name override for non-gateway, non-`per-session` sessions without a manual mapping. +Automatically generated Hermes titles (`derived` or `llm`), including lineage titles for Desktop branches, are display metadata and do not override `sessionStrategy`. An explicit user title remains an intentional session-name override for non-gateway, non-`per-session` sessions without a manual mapping. Sessions created before title provenance was recorded retain legacy behavior: because an old automatic title cannot be distinguished from an old user title, a title with no source is treated as an explicit override.