# Conflicts: # gateway/config.py # gateway/config_loader.py # gateway/readiness.py # hermes_cli/managed_scope.py # hermes_cli/plugin_python_deps.py # hermes_cli/plugins_cmd.py # hermes_cli/update_cmd_maint.py # plugin-catalog/hindsight.yaml # plugins/plugin_loader.py # providers/__init__.py # scripts/run_tests.sh # tests/gateway/test_control_socket_windows_live.py # tests/gateway/test_gateway_streaming_nested_config.py # tests/hermes_cli/test_doctor.py # tests/hermes_cli/test_plan_reconciliation_windows_live.py # tests/hermes_cli/test_update_apply_shallow_count.py # tests/hermes_cli/test_update_concurrent_quarantine.py # tests/hermes_cli/test_update_shim_self_lock.py # tests/hermes_cli/test_verify_console_scripts.py # tests/tools/test_lazy_deps.py # tests/tui_gateway/test_subprocess_encoding.py # tools/lazy_deps.py
94 lines
4.1 KiB
Python
94 lines
4.1 KiB
Python
"""The holographic fact DB set up with the default path belongs to whichever profile opens it.
|
|
|
|
Setup used to offer, and store, the active profile's concrete path (``~/.hermes/memory_store.db``).
|
|
``profile create --clone`` copies config.yaml verbatim, so the clone opened the source profile's
|
|
facts; ``profile rename`` moves the directory, so the renamed profile opened an empty DB in a
|
|
re-created directory under its old name.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
import hermes_yaml as yaml
|
|
|
|
import hermes_cli.memory_setup as memory_setup
|
|
from hermes_cli.profiles import create_profile, rename_profile
|
|
from plugins.memory.holographic import HolographicMemoryProvider, _load_plugin_config
|
|
|
|
|
|
@pytest.fixture()
|
|
def root(tmp_path, monkeypatch):
|
|
# A ``~/`` path is displayed through Path.home() and expanded through HOME; both name the sandbox.
|
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
monkeypatch.setattr(Path, "home", lambda: tmp_path)
|
|
home = tmp_path / ".hermes"
|
|
home.mkdir()
|
|
monkeypatch.setenv("HERMES_HOME", str(home))
|
|
return home
|
|
|
|
|
|
def _setup_with_defaults(monkeypatch, home: Path) -> dict:
|
|
"""``hermes memory setup`` for holographic with Enter on every field, saved as ``cmd_setup`` does."""
|
|
monkeypatch.setenv("HERMES_HOME", str(home))
|
|
provider = HolographicMemoryProvider(config={"hrr_dim": 64})
|
|
monkeypatch.setattr(memory_setup, "_curses_select", lambda *_a, default=0, **_k: default)
|
|
monkeypatch.setattr(sys, "stdin", io.StringIO("\n" * 10))
|
|
answers: dict = {}
|
|
assert memory_setup._prompt_schema_fields("holographic", provider.get_config_schema(), answers, {})
|
|
provider.save_config(answers, str(home))
|
|
return answers
|
|
|
|
|
|
def _opened_db(monkeypatch, home: Path) -> Path:
|
|
"""The DB a session started with ``hermes -p <profile>`` opens."""
|
|
monkeypatch.setenv("HERMES_HOME", str(home))
|
|
provider = HolographicMemoryProvider(config=_load_plugin_config())
|
|
provider.initialize("s")
|
|
try:
|
|
return provider._store.db_path.resolve()
|
|
finally:
|
|
provider.shutdown()
|
|
|
|
|
|
@pytest.mark.parametrize("lifecycle", ["clone", "rename"])
|
|
def test_default_db_path_follows_the_profile_that_opens_it(root, monkeypatch, lifecycle):
|
|
if lifecycle == "clone":
|
|
answers = _setup_with_defaults(monkeypatch, root)
|
|
monkeypatch.setenv("HERMES_HOME", str(root))
|
|
profile = create_profile("work", clone_config=True, no_alias=True)
|
|
else:
|
|
source = create_profile("alpha", no_alias=True)
|
|
answers = _setup_with_defaults(monkeypatch, source)
|
|
monkeypatch.setenv("HERMES_HOME", str(root))
|
|
with patch("hermes_cli.profiles.check_alias_collision", return_value="skip"):
|
|
profile = rename_profile("alpha", "beta")
|
|
|
|
assert _opened_db(monkeypatch, profile) == (profile / "memory_store.db").resolve()
|
|
if lifecycle == "rename":
|
|
assert not (root / "profiles" / "alpha").exists()
|
|
# The prompt offers the value it stores, so what the user accepted is what config.yaml says.
|
|
assert answers["db_path"] == "$HERMES_HOME/memory_store.db"
|
|
|
|
|
|
@pytest.mark.parametrize("spelling", ["display", "absolute", "elsewhere"])
|
|
def test_save_config_stores_only_this_profiles_default_path_as_the_placeholder(root, monkeypatch, spelling):
|
|
# "display"/"absolute": the concrete value an older setup wrote, and the dashboard form re-submits on
|
|
# its next save. "elsewhere": a deliberately shared store (#4726) is kept as given.
|
|
profile = create_profile("work", no_alias=True)
|
|
monkeypatch.setenv("HERMES_HOME", str(profile))
|
|
given = {
|
|
"display": "~/.hermes/profiles/work/memory_store.db",
|
|
"absolute": str(profile / "memory_store.db"),
|
|
"elsewhere": str(root / "shared" / "facts.db"),
|
|
}[spelling]
|
|
expected = given if spelling == "elsewhere" else "$HERMES_HOME/memory_store.db"
|
|
|
|
HolographicMemoryProvider(config={"hrr_dim": 64}).save_config({"db_path": given, "hrr_dim": "64"}, str(profile))
|
|
|
|
stored = yaml.safe_load((profile / "config.yaml").read_text(encoding="utf-8"))["plugins"]["hermes-memory-store"]
|
|
assert stored == {"db_path": expected, "hrr_dim": "64"}
|