From 841b768cd7a73fe7aff5f72291d83470271361c2 Mon Sep 17 00:00:00 2001 From: Erosika Date: Tue, 8 Sep 2026 16:10:59 -0400 Subject: [PATCH] fix(honcho): keep an empty host alias map when the last alias is cleared Clearing the last alias in peers map popped userPeerAliases from the host block, and the host then inherited the root aliases again. The host block now keeps an empty map, which both config readers treat as an explicit override. The summary says when that empty map hides root aliases. --- plugins/memory/honcho/cli.py | 10 +++++----- tests/honcho_plugin/test_peers_map.py | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/plugins/memory/honcho/cli.py b/plugins/memory/honcho/cli.py index e9fdb9d931..62995b0b18 100644 --- a/plugins/memory/honcho/cli.py +++ b/plugins/memory/honcho/cli.py @@ -1356,10 +1356,8 @@ def _save_alias_map(cfg: dict, host: str, working: dict, aliases_from_root: bool print(" edits no longer reach this profile.") target = cfg if write_root else cfg.setdefault("hosts", {}).setdefault(host, {}) - if working: - target["userPeerAliases"] = working - else: - target.pop("userPeerAliases", None) + # An empty host map is an explicit override; popping the key would re-inherit the root aliases. + target["userPeerAliases"] = working target_desc = f"host block [{host}]" if write_root: target_desc = "root config (shared by all profiles)" @@ -1374,7 +1372,9 @@ def _save_alias_map(cfg: dict, host: str, working: dict, aliases_from_root: bool print(f" {', '.join(names)}) — picked peers may not exist there.") _write_config(cfg) - print(f"\n userPeerAliases = {working if working else '{}'}") + print(f"\n userPeerAliases = {working}") + if not working and not write_root and cfg.get("userPeerAliases"): + print(f" (empty host map: root aliases no longer apply to [{host}])") print(f" written to {target_desc} in {_local_config_path()}\n") diff --git a/tests/honcho_plugin/test_peers_map.py b/tests/honcho_plugin/test_peers_map.py index 45aeca1703..57c9f253ff 100644 --- a/tests/honcho_plugin/test_peers_map.py +++ b/tests/honcho_plugin/test_peers_map.py @@ -114,12 +114,26 @@ class TestCmdPeersMap: @pytest.mark.parametrize("aliases, expected_host", [ ({"111": "eri", "222": "tek"}, {"userPeerAliases": {"222": "tek"}}), - ({"111": "eri"}, {}), - ], ids=["one-of-two", "last-alias-drops-key"]) + ({"111": "eri"}, {"userPeerAliases": {}}), + ], ids=["one-of-two", "last-alias-keeps-empty-map"]) def test_dash_clears_alias(self, monkeypatch, tmp_path, aliases, expected_host): written = _run_map(monkeypatch, tmp_path, answers=["111", "-", ""], cfg=_cfg(userPeerAliases=aliases)) assert written["cfg"]["hosts"]["hermes"] == expected_host + def test_cleared_host_map_does_not_resurrect_root_aliases(self, monkeypatch, tmp_path, capsys): + """A host block without the key inherits root, so clearing must leave an empty map behind.""" + from plugins.memory.honcho.client import HonchoClientConfig + + monkeypatch.setenv("HERMES_HOME", str(tmp_path)) + cfg = _cfg(root={"userPeerAliases": {"111": "root-person"}}, userPeerAliases={"111": "host-person"}) + written = _run_map(monkeypatch, tmp_path, answers=["111", "-", ""], cfg=cfg) + assert written["cfg"]["hosts"]["hermes"]["userPeerAliases"] == {} + assert "root aliases no longer apply to [hermes]" in capsys.readouterr().out + + path = tmp_path / "honcho.json" + path.write_text(json.dumps(written["cfg"])) + assert HonchoClientConfig.from_global_config(host="hermes", config_path=path).user_peer_aliases == {} + @pytest.mark.parametrize("cfg, answers, kwargs", [ (_cfg(), [""], {}), (_cfg(userPeerAliases={"111": "eri"}), ["111", "eri", ""], {}),