Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions plugins/memory/holographic/retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ def search(
# Strip raw HRR bytes — callers expect JSON-serializable dicts
for fact in results:
fact.pop("hrr_vector", None)

# Increment retrieval_count for all matched facts so usage metrics
# (dreaming, trust adjustments) have accurate signal. Covers both
# the prefetch() and fact_store(action='search') code paths.
if results:
ids = [r["fact_id"] for r in results]
placeholders = ",".join(["?"] * len(ids))
try:
self.store._conn.execute(
f"UPDATE facts SET retrieval_count = retrieval_count + 1 "
f"WHERE fact_id IN ({placeholders})",
ids,
)
self.store._conn.commit()
except Exception:
pass # Non-critical — don't fail search over a counter update

return results

def probe(
Expand Down
87 changes: 87 additions & 0 deletions tests/plugins/memory/test_holographic_retrieval_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Test that retrieval.search() increments retrieval_count (#17899)."""

from __future__ import annotations

import sqlite3
import types
from unittest.mock import MagicMock

import pytest


@pytest.fixture()
def _memory_store(tmp_path):
"""Create a minimal in-memory MemoryStore-like object with a real SQLite DB."""
db_path = tmp_path / "facts.db"
conn = sqlite3.connect(str(db_path))
conn.execute("CREATE VIRTUAL TABLE IF NOT EXISTS facts_fts USING fts5(content, tags, fact_id UNINDEXED)")
conn.execute(
"""CREATE TABLE IF NOT EXISTS facts (
fact_id TEXT PRIMARY KEY,
content TEXT,
tags TEXT DEFAULT '',
category TEXT DEFAULT 'general',
trust_score REAL DEFAULT 0.8,
retrieval_count INTEGER DEFAULT 0,
helpful_count INTEGER DEFAULT 0,
created_at TEXT,
updated_at TEXT,
hrr_vector BLOB DEFAULT NULL
)"""
)
# Insert a test fact
conn.execute(
"INSERT INTO facts (fact_id, content, tags, category, trust_score, retrieval_count) "
"VALUES (?, ?, ?, ?, ?, ?)",
("fact-1", "Python is a programming language", "python coding", "general", 0.9, 0),
)
conn.execute(
"INSERT INTO facts_fts (fact_id, content, tags) VALUES (?, ?, ?)",
("fact-1", "Python is a programming language", "python coding"),
)
conn.commit()

store = MagicMock()
store._conn = conn
return store


def test_search_increments_retrieval_count(_memory_store):
"""retrieval.search() must increment retrieval_count for returned facts."""
from plugins.memory.holographic.retrieval import FactRetriever

retriever = FactRetriever(store=_memory_store)

# Patch _fts_candidates to return our test fact directly
retriever._fts_candidates = lambda query, category, min_trust, limit: [
{
"fact_id": "fact-1",
"content": "Python is a programming language",
"tags": "python coding",
"category": "general",
"trust_score": 0.9,
"retrieval_count": 0,
"helpful_count": 0,
"created_at": None,
"updated_at": None,
"fts_rank": 0.8,
"hrr_vector": None,
}
]

results = retriever.search("Python programming")
assert len(results) == 1
assert results[0]["fact_id"] == "fact-1"

# Verify retrieval_count was incremented in the DB
row = _memory_store._conn.execute(
"SELECT retrieval_count FROM facts WHERE fact_id = ?", ("fact-1",)
).fetchone()
assert row[0] == 1, f"Expected retrieval_count=1, got {row[0]}"

# Search again — should increment to 2
results = retriever.search("Python programming")
row = _memory_store._conn.execute(
"SELECT retrieval_count FROM facts WHERE fact_id = ?", ("fact-1",)
).fetchone()
assert row[0] == 2, f"Expected retrieval_count=2, got {row[0]}"
Loading