Skip to content

Commit 1745ffe

Browse files
committed
fix: address bot review feedback (AND-vs-OR comment, test coverage)
- Document intentional AND-join semantics in hybrid mode vs OR in FTS-only mode (vector search covers broad recall). - Split misleading "falls back" test into two: one for AND-join of multiple keywords, one for genuine fallback on all-stop-word input. Made-with: Cursor
1 parent dc2c742 commit 1745ffe

2 files changed

Lines changed: 21 additions & 4 deletions

File tree

extensions/memory-core/src/memory/manager.hybrid-query-expansion.test.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,31 @@ describe("hybrid query expansion improves FTS recall", () => {
134134
expect(expandedResults.length).toBeGreaterThanOrEqual(rawResults.length);
135135
});
136136

137-
it("falls back to original query when no keywords are extracted", async () => {
137+
it("AND-joins multiple extracted keywords in hybrid mode", async () => {
138138
const keywords = extractKeywords("API PostgreSQL");
139-
// Pure keywords without stop words — extractKeywords returns them as-is
140139
expect(keywords.length).toBeGreaterThan(0);
141140

142141
const results = await runSearch({
143142
rows: indexedRows,
144143
query: keywords.join(" "),
145144
});
146-
// "API" AND "PostgreSQL" — only row 1 has "API" but not "PostgreSQL",
147-
// so this may return 0. The point is the code doesn't break.
145+
// "API" AND "PostgreSQL" — row 1 has "API" but not "PostgreSQL",
146+
// row 2 has "PostgreSQL" but not "API". AND semantics → 0 results.
147+
// This is intentional: vector search provides broad recall in hybrid mode.
148+
expect(results).toHaveLength(0);
149+
});
150+
151+
it("falls back to original query when all tokens are stop words", async () => {
152+
const keywords = extractKeywords("what is the");
153+
expect(keywords).toHaveLength(0);
154+
155+
// When extractKeywords returns empty, the code falls back to the raw query.
156+
// Verify the search doesn't throw and returns a defined result.
157+
const fallbackQuery = keywords.length > 0 ? keywords.join(" ") : "what is the";
158+
const results = await runSearch({
159+
rows: indexedRows,
160+
query: fallbackQuery,
161+
});
148162
expect(results).toBeDefined();
149163
});
150164
});

extensions/memory-core/src/memory/manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem
380380
// Extract meaningful keywords for better FTS matching on conversational queries
381381
// (e.g. "that thing we discussed about the API" → "discussed API").
382382
// In hybrid mode, vector search handles semantics; FTS benefits from focused keywords.
383+
// Note: unlike FTS-only mode which searches each keyword independently (OR semantics),
384+
// hybrid mode AND-joins the extracted keywords via buildFtsQuery for higher precision,
385+
// since vector search already provides broad semantic recall.
383386
const keywords = extractKeywords(cleaned, {
384387
ftsTokenizer: this.settings.store.fts.tokenizer,
385388
});

0 commit comments

Comments
 (0)