fix(honcho): restore profile fallback and backfill memory files#13375
fix(honcho): restore profile fallback and backfill memory files#13375stephenschoettler wants to merge 3 commits into
Conversation
- 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
|
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. |
# Conflicts: # plugins/memory/honcho/__init__.py
|
Updated against current green What changed on the branch:
Focused local validation:
Current CI notes:
|
|
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. |
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
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
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
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#
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
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
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
What does this PR do?
Fixes Honcho profile recall and memory-file migration for existing sessions.
honcho_profilecould return an empty profile even when Honcho session context already had a populated peer card. Existing non-per-session Honcho sessions also did not importUSER.md,MEMORY.md, orSOUL.mdif 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
Changes Made
plugins/memory/honcho/__init__.pyhoncho_profilefall back to session context before returning an empty profile result.plugins/memory/honcho/session.pyUSER.md,MEMORY.md, andSOUL.mdinto existing non-per-session Honcho sessions.tests/honcho_plugin/test_session.pyHow to Test
Run the Honcho session test module:
Confirm profile fallback behavior:
Confirm existing-session backfill behavior:
Optional live harness:
Validation Status
python -m pytest tests/honcho_plugin/test_session.py -q.main.test.mainbefore merge validation.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation and Housekeeping
docs/, docstrings) or N/Acli-config.yaml.exampleif I added/changed config keys or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows or N/AFor New Skills
N/A. This PR does not add a skill.
Screenshots / Logs
Live verification harness from the original PR description: