Files
hermes-agent/tests/pm/test_runtime_context_home.py
ethernet bbec973514 refactor(pm): pm owns the dependency-environment layout and interpreter paths
hermes_cli.runtime_paths (venv generations, selection, activation) moves to
pm.environments, and gains venv_bin_dir / venv_python / project_python. Every
in-tree caller asks pm for an interpreter now; pm no longer reaches back into
hermes_cli for its own environment layout (pm.packages, pm.extras, pm.ensure,
pm.paths imported hermes_cli.runtime_paths). The three open-coded
"Scripts/python.exe or bin/python" ladders in pm collapse onto venv_python.

hermes_constants.venv_python_path / venv_bin_dir and hermes_cli.runtime_paths
stay as frozen-updater-surface shims only (tests/compat/old_updater_surface.json).

To keep the boot path light, pm/__init__ resolves its facade lazily (PEP 562)
and pm.registry loads the built-in package definitions on first read instead of
at import: `import hermes_bootstrap` now loads pm + pm.environments only (25ms,
was 37ms with the eager facade dragging in the downloader). The stripped-payload
fixtures that ship only pre-import files keep working for the same reason.

Also restores two frozen-surface re-exports the F401 sweep dropped
(banner._github_compare_behind, cua_backend.resolve_cua_driver_cmd).
2026-09-18 20:02:36 -04:00

56 lines
2.2 KiB
Python

"""Context-only homes use the same dependency state as their own process."""
from pm import environments as runtime_paths
from pm.publication import PluginSelection
from hermes_cli.runtime_state import recover_publication, runtime_lock
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
from pm import paths, plugins_state
def test_context_home_publication_recovers_from_its_own_process(tmp_path, monkeypatch):
process_home = tmp_path / "process-home"
context_home = tmp_path / "context-home"
context_home.mkdir()
project = tmp_path / "repo"
project.mkdir()
config = context_home / "config.yaml"
original = b"plugins:\n enabled: [old]\n"
config.write_bytes(original)
monkeypatch.setenv("HERMES_HOME", str(process_home))
monkeypatch.setattr(paths, "repo_root", lambda: project)
process_state = runtime_paths.install_state_dir(project)
token = set_hermes_home_override(context_home)
try:
context_state = runtime_paths.install_state_dir(project)
assert context_state != process_state
assert plugins_state.enabled_plugins_ordered() == {
context_home / "plugins": ["old"],
}
with runtime_lock(project):
PluginSelection({"home": str(config.parent), "enabled": ["new"], "disabled": []}).publish(project)
assert config.read_bytes() != original
finally:
reset_hermes_home_override(token)
assert not process_state.exists()
monkeypatch.setenv("HERMES_HOME", str(context_home))
assert runtime_paths.install_state_dir(project) == context_state
with runtime_lock(project):
recover_publication(project)
assert config.read_bytes() == original
assert not (context_state / "publication.json").exists()
def test_named_context_profile_shares_its_install_root(tmp_path, monkeypatch):
home = tmp_path / "home"
profile = home / "profiles" / "worker"
profile.mkdir(parents=True)
monkeypatch.setenv("HERMES_HOME", str(home))
project = tmp_path / "repo"
state = runtime_paths.install_state_dir(project)
token = set_hermes_home_override(profile)
try:
assert runtime_paths.install_state_dir(project) == state
finally:
reset_hermes_home_override(token)