Describe the bug
wren memory index (LanceDB backend) treats knowledge/sql/*.md as upsert-only: it
never removes a query_history row whose natural-language query is no longer present
in the markdown. Deleting or renaming an example under knowledge/sql/ does not clear
it from the semantic index, so it keeps being recalled as few-shot context for SQL
generation.
wren memory check already detects this drift and calls it out as stale, but its own
suggested fix does not work:
2 user pair(s) indexed without markdown — stale index, run `wren memory index`.
Re-running wren memory index only upserts the pairs currently in the markdown; it
never forgets the ones that dropped out. The same gap exists in wren memory watch's
auto-reindex loop, whose own docstring says it keeps recall from serving stale
content.
To Reproduce
wren memory index # index two examples
rm knowledge/sql/count-orders.md # delete one example
wren memory check # -> "1 user pair(s) indexed without markdown"
wren memory index # per check's own advice
wren memory recall -q "count orders" # still returns the deleted example
Expected behavior
After deleting an example from knowledge/sql/ and re-running wren memory index
(or letting wren memory watch pick up the change), the deleted example is dropped
from query_history and no longer recalled.
Additional context
core/wren/src/wren/memory/store.py's load_queries(pairs, upsert=True) only
upserts rows whose nl_query is present in the current batch; it has no notion of
"rows that used to be there and now aren't." The three call sites that treat
knowledge/sql/*.md as the complete source of truth (cli.py's index and watch
commands, and index_backend.py's LanceDBIndex.rebuild) all inherit this gap, since
they all pass the current markdown pairs straight through the same upsert-only call.
Describe the bug
wren memory index(LanceDB backend) treatsknowledge/sql/*.mdas upsert-only: itnever removes a
query_historyrow whose natural-language query is no longer presentin the markdown. Deleting or renaming an example under
knowledge/sql/does not clearit from the semantic index, so it keeps being recalled as few-shot context for SQL
generation.
wren memory checkalready detects this drift and calls it out as stale, but its ownsuggested fix does not work:
Re-running
wren memory indexonly upserts the pairs currently in the markdown; itnever forgets the ones that dropped out. The same gap exists in
wren memory watch'sauto-reindex loop, whose own docstring says it keeps recall from serving stale
content.
To Reproduce
Expected behavior
After deleting an example from
knowledge/sql/and re-runningwren memory index(or letting
wren memory watchpick up the change), the deleted example is droppedfrom
query_historyand no longer recalled.Additional context
core/wren/src/wren/memory/store.py'sload_queries(pairs, upsert=True)onlyupserts rows whose
nl_queryis present in the current batch; it has no notion of"rows that used to be there and now aren't." The three call sites that treat
knowledge/sql/*.mdas the complete source of truth (cli.py'sindexandwatchcommands, and
index_backend.py'sLanceDBIndex.rebuild) all inherit this gap, sincethey all pass the current markdown pairs straight through the same upsert-only call.