feat: retrieval-utility logging + history-based deletion (Closes #1480) - #1483
Conversation
Add structured retrieval-utility logging on the existing memory retrieval infrastructure and a history-based deletion function that removes records retrieved >=n times with average downstream utility below a threshold. - agent/retrieval_utility.py: sidecar JSON log with record_retrieval(), record_outcome(), compute_utility(), delete_low_utility_records() - agent/memory_manager.py: wire prefetch_all → record_retrieval, sync_all → record_outcome (uses existing friction signals) - hermes_cli/config.py: memory.retrieval_utility config section - Tests: 25 unit tests + 7 integration tests Closes #1480 Co-Authored-By: Hermes Evolution <evolution@hermes.ai>
Two privacy issues found reviewing this PR. Both are small, and neither costs the feature anything. 1. record_retrieval persisted retrieval_context[:500] — up to 500 characters of the user's query, on disk, per retrieval. It was WRITE-ONLY: compute_utility scores outcomes alone and never reads it, so the text served no downstream purpose. Now accepted but not stored; the parameter stays in the signature so callers need no change and a future consumer can opt into a redacted form deliberately rather than by default. 2. retrieval_utility.enabled defaulted True, so every memory/skill hit in every ordinary session wrote a record to disk unasked. Now False, matching the opt-in HERMES_EVOLUTION_CAPTURE precedent from #1363 — where the same question came up and was settled the same way. The existing test asserted the stored context, so it is updated to pin the new behaviour, plus a test that the query text does not appear anywhere in the persisted entry. 26 passing in test_retrieval_utility.py, 31 with the memory-manager suite. Ruff clean.
|
Reviewed and pushed two privacy fixes to this branch ( 1. It was write-only: 2. The existing test asserted the stored context, so it now pins the new behaviour, plus a test that the query text appears nowhere in the persisted entry. On the other PR#1482 closes the same issue with a different approach — it logs retrieval utility for ERL heuristics ( #1480 asks for memory/skill retrieval specifically, so this PR is the one that matches. Merging both would create two parallel utility stores — one under Merging this one; closing #1482 with the suggestion that if heuristic-retrieval utility is wanted, it should write to this store rather than a second one. 26 passing in |
The memory.retrieval_utility.enabled config flag defaults to False (opt-in), but _record_retrieval_utility and _record_retrieval_outcomes in MemoryManager ran unconditionally — writing a per-retrieval record to disk on every memory hit in every session despite the user never opting in. This adds a _retrieval_utility_enabled() check that reads the config flag via load_config_readonly() and gates both methods. When disabled (the default), no sidecar file is written and no pending retrievals accumulate. Identified in PR #1483 code review. Issue #1480 was closed as completed but the privacy gate fix was never landed — PR #1485 is stuck in a conflicting state. This is the minimal standalone fix. Co-authored-by: Hermes Evolution <evolution@hermes.ai>
Automated evolution PR for issue #1480 (child of #1270).
Summary
Add structured retrieval-utility logging on the existing memory retrieval infrastructure and a history-based deletion function that removes records retrieved ≥n times with average downstream utility below a threshold. The ACL 2026 memory-management paper proves selective addition + history-based deletion beats add-all by 22-25 points.
Changes
agent/retrieval_utility.py (new): Sidecar JSON log module with:
record_retrieval()— log when memory/skill context is retrievedrecord_outcome()— log downstream outcome (helpful/neutral/harmful) derived from friction signalscompute_utility()— aggregate avg downstream utility per recorddelete_low_utility_records()— identify records eligible for history-based deletion (retrieved ≥n times, avg utility < floor)agent/memory_manager.py: Wire retrieval logging into existing infrastructure:
prefetch_all()calls_record_retrieval_utility()when a provider returns contextsync_all()calls_record_retrieval_outcomes()after scoring friction signals_pending_retrievalslisthermes_cli/config.py: Add
memory.retrieval_utilityconfig section (enabled,min_retrievals,utility_floor)Tests: 25 unit tests + 7 MemoryManager integration tests (all passing)
Design notes
tools/skill_usage.py— operational telemetry stays out of user-authored contentget_hermes_home()Closes #1480