fix(honcho): surface the peer notice and audit the injection on the recall sync path

With recallSync on, prefetch popped only the auth notice and returned without writing the injection log. A session whose init failed for a missing user peer never told the model that memory was off, and the audit file stayed empty for every turn. The recall sync branch now pops the peer notice the way the async branch does and records each turn as injected or recall-sync-empty.
This commit is contained in:
Erosika
2026-09-08 16:10:58 -04:00
committed by kshitij
parent d532d83eca
commit 4b916022ab
3 changed files with 29 additions and 4 deletions
+3 -3
View File
@@ -563,9 +563,9 @@ class HonchoMemoryProvider(DialecticMixin, MemoryProvider):
if self._recall_sync:
from plugins.memory.honcho.recall_sync import prefetch_sync
notice = self._pop_auth_notice()
result = prefetch_sync(self, query)
return "\n\n".join(part for part in (notice, result) if part)
notice = self._pop_auth_notice() or self._pop_peer_notice()
payload = "\n\n".join(part for part in (notice, prefetch_sync(self, query)) if part)
return self._log_injection("injected" if payload else "recall-sync-empty", payload)
first_turn_base_deadline = (time.monotonic() + self._first_turn_wait(self._FIRST_TURN_BASE_TIMEOUT)
if self._turn_count <= 1 else None)
+1 -1
View File
@@ -34,7 +34,7 @@ def prefetch_sync(provider, query: str) -> str:
if provider._init_thread is not None:
provider._init_thread.join(timeout=max(0.0, deadline - time.monotonic()))
if not provider._session_ready():
return provider._pop_auth_notice()
return provider._pop_auth_notice() or provider._pop_peer_notice()
manager = provider._manager
if (generation is not provider._recall_generation or session != provider._session_key
or turn != provider._turn_count or time.monotonic() >= deadline):
+25
View File
@@ -1,4 +1,5 @@
"""Opt-in current-query alignment and bounded late-worker isolation."""
import json
import threading
import time
@@ -127,3 +128,27 @@ def test_timeout_keeps_single_flight_and_late_result_cannot_publish():
provider._manager.get_prefetch_context = superseded
assert provider.prefetch("Plan the garden") == ""
assert provider._last_context_turn == provider._last_dialectic_turn == -999
def test_missing_peer_notice_surfaces_once():
provider = HonchoMemoryProvider()
provider._config = HonchoClientConfig(timeout=0.05)
provider._recall_sync = True
provider._init_peer_failure = "No runtime identity or peerName"
first = provider.prefetch("What did we decide about the schema?")
assert "Honcho memory is off" in first
assert "hermes honcho peer --user" in first
assert provider.prefetch("And the index?") == ""
def test_prefetch_writes_the_injection_log(tmp_path):
provider = make_provider()
provider._injection_log_path = str(tmp_path / "injection.log")
provider.on_turn_start(1, "Plan the garden")
result = provider.prefetch("Plan the garden")
assert "base:Plan the garden" in result
assert provider.prefetch("Plan the garden") == ""
records = [json.loads(line) for line in (tmp_path / "injection.log").read_text().splitlines()]
assert [r["reason"] for r in records] == ["injected", "recall-sync-empty"]
assert records[0]["payload"] == result and records[0]["turn"] == 1
assert records[1]["payload"] == "" and records[1]["bytes"] == 0