Skip to content

fix(honcho): use profile_host_key in peers display (dot vs underscore host-key mismatch) - #64405

Closed
loveruncaged wants to merge 1 commit into
NousResearch:mainfrom
loveruncaged:fix/honcho-peers-hostkey
Closed

fix(honcho): use profile_host_key in peers display (dot vs underscore host-key mismatch)#64405
loveruncaged wants to merge 1 commit into
NousResearch:mainfrom
loveruncaged:fix/honcho-peers-hostkey

Conversation

@loveruncaged

Copy link
Copy Markdown

Bug Report: hermes honcho peers shows wrong host block for non-default profiles

Summary

hermes honcho peers displays (not set) for the user peer and the raw
host key (e.g. hermes.kristi) for the AI peer on any non-default
profile
, even when that profile's honcho.json block is correctly
populated. The runtime uses the correct block — this is a display-only
bug
in the peers command caused by a host-key separator mismatch.

Environment

  • Hermes Agent (gateway + multi-profile setup)
  • Memory provider: self-hosted Honcho
  • Two profiles: default and kristi, each with its own Honcho workspace

Root cause

Two different host-key derivations exist in plugins/memory/honcho/:

  • Runtime resolverclient.py::profile_host_key() sanitizes and joins
    with an underscore:
    return f"{HOST}_{sanitized or 'profile'}"   # -> "hermes_kristi"
  • Display commandcli.py::_all_profile_host_configs() joined with a
    dot:
    h = f"{HOST}.{p.name}"                        # -> "hermes.kristi"

Because the real config block is written under hermes_kristi (underscore)
by the runtime resolver, the display command's hosts.get("hermes.kristi", {})
returns an empty dict and falls back to (not set) / the raw host key.

Reproduction

  1. Create a second profile: hermes profile create kristi --clone
  2. Configure Honcho for it with a distinct workspace/peer:
    kristi memory setup → provider honcho, peer Kristi, workspace kristi
  3. Run kristi honcho peers (or hermes honcho peers)

Expected: kristi Kristi Edna Millay
Actual: kristi (not set) hermes.kristi

Confirm the block is actually correct:

python3 -c "import json; d=json.load(open('~/.hermes/profiles/kristi/honcho.json'.replace('~','/root'))); print(list(d['hosts']))"
# -> ['hermes', 'hermes_kristi']   (underscore, not dot)

Fix

In plugins/memory/honcho/cli.py::_all_profile_host_configs(), use the same
resolver the runtime uses instead of hand-building the key:

     for p in profiles:
         if p.name == "default":
             continue
-        h = f"{HOST}.{p.name}"
+        # Match the runtime resolver (underscore + sanitization), not a dot,
+        # so the display reads the real host block instead of falling back
+        # to "(not set)" / the raw host key.
+        h = profile_host_key(p.name)
         results.append((p.name, h, hosts.get(h, {})))

     return results

profile_host_key is already imported at the top of cli.py, so no new
import is needed. python -m py_compile passes.

Impact

  • Severity: low (cosmetic — no data or runtime behavior affected)
  • Workspace isolation, peer identity, and memory routing all work correctly;
    only the peers summary view is wrong.
  • Confusing for multi-profile users verifying isolation, since the one screen
    meant to confirm per-profile identity is the screen that misreports it.

Suggested test

Add a unit test asserting _all_profile_host_configs() returns the block
keyed by profile_host_key(name) for a profile with a non-trivial name
(e.g. one requiring sanitization), guarding against the dot/underscore drift.

hermes honcho peers showed (not set) for the user peer and the raw host
key (e.g. hermes.kristi) for the AI peer on non-default profiles, because
_all_profile_host_configs() built the host key with a dot separator
(f"{HOST}.{p.name}") while the runtime resolver profile_host_key() uses an
underscore + sanitization (hermes_kristi). The mismatched key missed the
real config block and fell back to defaults.

Use profile_host_key() so the display matches the runtime resolution.
Cosmetic-only: workspace isolation, peer identity, and memory routing were
always correct; only the peers summary view misreported.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for identifying the display/runtime key drift. The canonical-key premise is confirmed on current main: plugins/memory/honcho/cli.py:1010-1011 builds a dot-form key, while plugins/memory/honcho/client.py:36-41 resolves canonical underscore-form keys.

Problems

  • The unchanged direct lookup at plugins/memory/honcho/cli.py:1011 would bypass _host_block(). That helper deliberately retains legacy hermes.<profile> compatibility in plugins/memory/honcho/client.py:44-51, and the runtime behavior is covered by tests/honcho_plugin/test_client.py:530-543. After this change, honcho peers would misreport legacy configurations that runtime resolution still accepts.

Suggested changes

  • Look up the new canonical key with _host_block(cfg, h) rather than hosts.get(h, {}); _host_block is already imported at plugins/memory/honcho/cli.py:14.
  • Add a CLI regression test covering both canonical/sanitized and legacy dot-form profile blocks.

This is an automated hermes-sweeper review.

# with an underscore separator and sanitization (e.g. "hermes_kristi"),
# not a dot ("hermes.kristi"), so a naive f"{HOST}.{p.name}" misses
# the real block and falsely shows "(not set)" / the raw host key.
h = profile_host_key(p.name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please preserve the legacy dot-key fallback when looking up this canonical key: use _host_block(cfg, h) in the append below. Runtime config resolution intentionally supports legacy hermes.<profile> blocks via plugins/memory/honcho/client.py:44-51; direct hosts.get(h, {}) would make peers misreport those still-supported configurations.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers labels Jul 16, 2026
@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users area/memory Memory subsystem: store, providers, sync, background reviews area/profiles Multi-profile isolation, HERMES_HOME scoping labels Jul 16, 2026
@spfcraze

spfcraze commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Heads up: I independently landed the identical fix in #76455 before finding this PR (2.5 weeks senior — deferring to yours).

One thing yours doesn't carry: regression coverage. I've written tests/plugins/memory/test_honcho_cli_peers.py — 4 tests driving the real cmd_peers/_all_profile_host_configs against a temp honcho.json: host keys match the writer form, sanitized profile names (dots/spaces) resolve, peers output shows populated identities with no key leak, and clean fallback for profiles without a block. All green against your exact change.

If you'd like it, the file is at spfcraze:fix/honcho-peers-host-key (commit d9aed4ff9) — cherry-pick just the test file and it's a clean add. Or I can re-propose it as a follow-up PR after yours merges. Either way, nice fix.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Two open PRs address Issue #76414 by replacing the incorrect dot-form profile host key with the canonical key resolver. #64405 makes only that lookup-key change, while #76455 also preserves legacy dot-form configuration compatibility through _host_block() and adds focused regression coverage.

Related pull requests

Duplicates

#64405 and #76455 implement the same canonical profile_host_key() correction; #76455 is the more complete duplicate because it also preserves legacy-key compatibility and supplies regression coverage.

Suggested consolidation

Keep #76455 open with its complete fix and regression suite as the recorded best fix for #76414; its current diff addresses the visible contributor keep_open review by routing lookup through _host_block() and testing the legacy fallback. Close #64405 as duplicate of #76455, since its narrower diff retains the compatibility gap identified in its own keep_open review.

Cross-PR triage: Reviewed 2 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 7 kB of PR diffs, 8 kB of issue/PR text, 6 kB of discussion (8 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/memory Memory subsystem: store, providers, sync, background reviews area/profiles Multi-profile isolation, HERMES_HOME scoping comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/memory Memory tool and memory providers type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants