Skip to content

fix(honcho): restore profile fallback and backfill memory files#13375

Closed
stephenschoettler wants to merge 3 commits into
NousResearch:mainfrom
stephenschoettler:fix/honcho-profile-fallback-backfill-v2
Closed

fix(honcho): restore profile fallback and backfill memory files#13375
stephenschoettler wants to merge 3 commits into
NousResearch:mainfrom
stephenschoettler:fix/honcho-profile-fallback-backfill-v2

Conversation

@stephenschoettler

@stephenschoettler stephenschoettler commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes Honcho profile recall and memory-file migration for existing sessions.

honcho_profile could return an empty profile even when Honcho session context already had a populated peer card. Existing non-per-session Honcho sessions also did not import USER.md, MEMORY.md, or SOUL.md if those sessions were created before the migration path ran.

This PR adds fallback lookup through session-context peer-card data and backfills local memory files into existing non-per-session Honcho sessions once per content hash.

Related to #17124. This PR is broader than #17124 because it includes the memory-file backfill path in addition to profile fallback behavior.

Related Issue

No linked GitHub issue.

Related PR: #17124

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • plugins/memory/honcho/__init__.py
    • Make honcho_profile fall back to session context before returning an empty profile result.
  • plugins/memory/honcho/session.py
    • Fall back to session-context peer-card data when direct peer-card lookup is empty.
    • Backfill USER.md, MEMORY.md, and SOUL.md into existing non-per-session Honcho sessions.
    • Persist a local content-hash marker so the same memory content is not imported repeatedly.
  • tests/honcho_plugin/test_session.py
    • Add regression coverage for peer-card fallback and existing-session memory backfill behavior.

How to Test

  1. Run the Honcho session test module:

    source venv/bin/activate
    python -m pytest tests/honcho_plugin/test_session.py -q -o 'addopts='
  2. Confirm profile fallback behavior:

    honcho_profile returns session-context facts when direct peer-card lookup is empty.
    
  3. Confirm existing-session backfill behavior:

    Existing non-per-session Honcho sessions import local memory files once for a given memory-file hash.
    
  4. Optional live harness:

    source venv/bin/activate
    python - <<'PY'
    from plugins.memory.honcho.client import HonchoClientConfig, get_honcho_client
    from plugins.memory.honcho.session import HonchoSessionManager
    
    cfg = HonchoClientConfig.from_global_config()
    client = get_honcho_client(cfg)
    mgr = HonchoSessionManager(honcho=client, config=cfg)
    session = mgr.get_or_create(cfg.resolve_session_name(cwd='/home/w0lf'))
    print(mgr.get_peer_card(session.key, peer='user')[:8])
    PY

Validation Status

  • Targeted regression coverage was added for this bug.
  • Original focused validation command: python -m pytest tests/honcho_plugin/test_session.py -q.
  • GitHub checks are not currently all green.
  • Current merge state: conflicting with main.
  • Failed check: test.
  • Full-suite checklist is not marked complete because this branch needs rebasing on a green main before merge validation.

Checklist

Code

Documentation and Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior or N/A

For New Skills

N/A. This PR does not add a skill.

Screenshots / Logs

Live verification harness from the original PR description:

source venv/bin/activate
python - <<'PY'
from plugins.memory.honcho.client import HonchoClientConfig, get_honcho_client
from plugins.memory.honcho.session import HonchoSessionManager

cfg = HonchoClientConfig.from_global_config()
client = get_honcho_client(cfg)
mgr = HonchoSessionManager(honcho=client, config=cfg)
s = mgr.get_or_create(cfg.resolve_session_name(cwd='/home/w0lf'))
print(mgr.get_peer_card(s.key, peer='user')[:8])
PY

- fall back to session context when direct peer-card lookup is empty
- backfill USER.md, MEMORY.md, and SOUL.md into existing sessions once per content hash
- add regression tests for both paths
@stephenschoettler

Copy link
Copy Markdown
Contributor Author

CI audit: the remaining failure is the shared Tests workflow, not the Honcho patch. This PR changes only plugins/memory/honcho/init.py, plugins/memory/honcho/session.py, and tests/honcho_plugin/test_session.py; targeted Honcho tests pass locally (117 passed). The failing workflow is also red on current main (run 24707349937), with unrelated failures in provider config / skills config / command guard tests. I also re-ran the four failing test nodes from this PR against a clean origin/main worktree and they passed in isolation, which points to broader suite instability rather than this patch.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers labels Apr 22, 2026
@stephenschoettler

Copy link
Copy Markdown
Contributor Author

Updated against current green main (49c3c2e0).

What changed on the branch:

  • Merged current main into fix/honcho-profile-fallback-backfill-v2.
  • Resolved the Honcho profile conflict by preserving the current _empty_profile_hint() behavior and keeping this PR's session-context card fallback.
  • PR is now mergeable.

Focused local validation:

  • python -m pytest tests/honcho_plugin/test_session.py -q -o addopts='': 118 passed
  • python -m compileall plugins/memory/honcho tests/honcho_plugin/test_session.py -q: passed
  • git diff --check origin/main...HEAD: passed

Current CI notes:

  • nix, e2e, attribution, and supply-chain checks are green.
  • ruff + ty diff is red because the advisory workflow tries to post a PR comment from a fork PR and GitHub returns 403 Resource not accessible by integration. The generated lint summary reports 0 ruff issues and no net new ty count.
  • test is red with broad failures outside this Honcho change set, including Bedrock, gateway restart, update, browser Chromium, delegate, and sandbox tests. Focused Honcho validation is clean.

@stephenschoettler

Copy link
Copy Markdown
Contributor Author

Closing this lane in favor of the narrower #17124.

Current Honcho is operational on my local setup without this broader backfill patch: memory status and honcho status are OK, honcho_search/context/reasoning return data, and the remaining profile-card gap is the narrower peer-card lookup path covered by #17124. If a distinct memory-file backfill regression still reproduces on current main, I will split/reopen that as a focused PR instead of keeping this broader overlapping branch alive.

erosika pushed a commit to erosika/hermes-agent that referenced this pull request May 27, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729
kshitijk4poor pushed a commit that referenced this pull request May 27, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to #13375, #17124, #20729
mathias3 pushed a commit to mathias3/hermes-agent that referenced this pull request May 28, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729
Bryce-huang pushed a commit to wbkunlun/hermes-agent that referenced this pull request May 29, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729

#AI commit#
mosaiq-systems pushed a commit to mosaiq-systems/hermes-agent that referenced this pull request May 29, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729
KKT-OPT pushed a commit to KKT-OPT/hermes-agent that referenced this pull request May 31, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
honcho_profile(peer="user") returned an empty card even when Honcho
held a populated peer card for the user. Two independent bugs combined
to produce the symptom:

1. Read path: get_peer_card() called _fetch_peer_card(observer, target=user),
   which hits GET /peers/{observer}/card?target={user} — the observer's local
   card of the user. On self-hosted Honcho v3 this slot is empty unless writes
   also use it. The peer card lives on the user peer itself
   (GET /peers/{user}/card). Add a fallback: when the observer-target slot is
   empty and a target exists, retry against the target peer's own card.

2. Write path: set_peer_card() resolved only the target peer and called
   user_peer.set_card(card). The read path uses the assistant peer as
   observer, so writes and reads addressed different Honcho card scopes.
   Align set_peer_card() with _resolve_observer_target() so writes go to
   assistant_peer.set_card(card, target=user_peer_id), matching the read.

Both paths now use the same observer/target resolution, and the read
path additionally falls back to the target's own card for compatibility
with deployments where cards were written directly to the peer.

Closes: related to NousResearch#13375, NousResearch#17124, NousResearch#20729
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P2 Medium — degraded but workaround exists 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.

2 participants