fix(memory/holographic): wire retrieval_count into all retrieval paths via locked store helper - #73901
fix(memory/holographic): wire retrieval_count into all retrieval paths via locked store helper#73901ar-nim wants to merge 5 commits into
Conversation
fa20625 to
cf56f24
Compare
…s via locked store helper Fix a dead-code bug where retrieval_count was permanently zero. The counter increment lived in store.search_facts() which has zero callers; the actual retrieval path (FactRetriever.search()) bypassed it via _fts_candidates(). Changes: - Add MemoryStore.increment_retrieval_count() under the shared re-entrant lock so all writes respect the serialized-access contract. - Call it from every FactRetriever path that returns results: search(), probe(), related(), reason(), and _score_facts_by_vector(). - Reuse the helper from store.search_facts() to eliminate duplicated SQL. - Add tests for keyword search (FTS5) and structural paths (HRR probe, related, reason) with entity-bound facts, including selectivity checks for non-returned facts. Closes: NousResearch#17899
cf56f24 to
6ec315f
Compare
After increment_retrieval_count, bump each result dict's retrieval_count by 1 so the response matches what the DB now holds. Previously the dict contained the pre-increment value, always one behind.
…s DB after increment
…rieval-count # Conflicts: # tests/plugins/memory/test_holographic_retrieval.py
…al_count
increment_retrieval_count now returns {fact_id: new_count} via SQLite
RETURNING clause, so the dict sync is atomic — no race window between
UPDATE and read-back even under concurrent multi-session access.
Previously the dict sync used f.get('retrieval_count', 0) + 1 which
assumed no concurrent increment happened between the SELECT and UPDATE.
With multiple sessions reading the same fact, the dict could drift from
the true DB value.
|
Thanks for tracing this through the active provider paths. On current main, The PR's locked helper and coverage for keyword and structural result paths fit the existing shared-connection design. The target files are unchanged on current main since the PR base, and GitHub reports the branch mergeable. Automated hermes-sweeper review. |
What does this PR do?
Fixes a dead-code bug where retrieval_count was permanently zero for all facts.
The plugin has two FTS5 search paths. They were written in the same commit (924bc67, PR #4623). They were never connected to each other.
retrieval.py was ported from a separate codebase ("KIK memory_agent.py" per its docstring) with its own FTS5 pipeline, duplicating the store-level search without inheriting the counter. The same gap existed in probe(), related(), and reason() — they also returned facts without recording retrievals.
The fix adds MemoryStore.increment_retrieval_count() under the shared self._lock and calls it from all 5 retrieval paths. Writing _conn directly would bypass MemoryStore's shared connection contract (one connection + one RLock for serialized access across coexisting provider instances). The helper centralizes the counter SQL so every caller uses the same serialized path.
After increment, each result dict is bumped by 1 so the response matches the DB (was always one behind — read 0 from DB, incremented DB to 1, returned 0).
Related Issue
N/A — small bug fix with clear root cause documented above.
Type of Change
Changes Made
How to Test
Checklist
Code
Documentation & Housekeeping
Screenshots / Logs
pytest tests/plugins/memory/test_holographic_retrieval.py -v
============================== 16 passed in 0.69s ==============================