Fix #252: Automatic fact trust calibration from usage feedback
Some checks failed
Forge CI / smoke-and-build (pull_request) Failing after 53s

fact_feedback tool existed but was never called automatically. Trust
scores never changed after initial assignment. Facts lived forever
regardless of accuracy.

Changes:
- MemoryProvider: add get_prefetched_fact_ids() for feedback loop
- HolographicMemoryProvider: track fact IDs returned by prefetch()
- MemoryManager: auto_calibrate_feedback() detects corrections and
  applies helpful/unhelpful feedback automatically
- Correction detection: regex patterns for 'no', 'wrong', 'actually',
  'i said', 'correction:', 'undo', etc.
- MemoryManager: get_pruning_candidates() for below-threshold facts
- Wired into run_agent.py: calibration runs after prefetch, before tool loop

Trust mechanics:
- Successful interaction: trust += 0.05 per fact (helpful)
- Correction detected: trust -= 0.10 per fact (unhelpful)
- Trust clamped to [0.0, 1.0]
- Facts below threshold (default 0.15) are pruning candidates

Tests: 23 new tests, all passing. 139 total memory tests green.

Refs: Timmy_Foundation/hermes-agent#252
This commit is contained in:
Alexander Whitestone
2026-04-13 18:22:58 -04:00
parent f8f4678ee4
commit f3fd5142ac
5 changed files with 370 additions and 0 deletions

View File

@@ -119,6 +119,7 @@ class HolographicMemoryProvider(MemoryProvider):
self._store = None
self._retriever = None
self._min_trust = float(self._config.get("min_trust_threshold", 0.3))
self._last_prefetch_ids: List[int] = []
@property
def name(self) -> str:
@@ -205,11 +206,14 @@ class HolographicMemoryProvider(MemoryProvider):
def prefetch(self, query: str, *, session_id: str = "") -> str:
if not self._retriever or not query:
self._last_prefetch_ids = []
return ""
try:
results = self._retriever.search(query, min_trust=self._min_trust, limit=5)
if not results:
self._last_prefetch_ids = []
return ""
self._last_prefetch_ids = [r["fact_id"] for r in results if "fact_id" in r]
lines = []
for r in results:
trust = r.get("trust_score", r.get("trust", 0))
@@ -217,8 +221,12 @@ class HolographicMemoryProvider(MemoryProvider):
return "## Holographic Memory\n" + "\n".join(lines)
except Exception as e:
logger.debug("Holographic prefetch failed: %s", e)
self._last_prefetch_ids = []
return ""
def get_prefetched_fact_ids(self) -> List[int]:
return list(self._last_prefetch_ids)
def sync_turn(self, user_content: str, assistant_content: str, *, session_id: str = "") -> None:
# Holographic memory stores explicit facts via tools, not auto-sync.
# The on_session_end hook handles auto-extraction if configured.