Skip to content
Open
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
28 changes: 0 additions & 28 deletions src/hooks/shared/recall-gate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,32 +134,4 @@ export const RECALL_THRESHOLD: number = (() => {
return Number.isFinite(n) && n > 0 && n <= 1 ? n : DEFAULT_RECALL_THRESHOLD;
})();

// Common words carry no recall signal — matching them would surface noise.
const STOPWORDS = new Set([
"the", "and", "for", "are", "but", "not", "you", "your", "with", "this", "that",
"have", "has", "had", "was", "were", "can", "could", "should", "would", "will",
"does", "did", "what", "why", "how", "when", "where", "which", "who", "into",
"from", "they", "them", "then", "than", "there", "here", "out", "get", "got",
"use", "using", "used", "make", "made", "want", "need", "please", "let", "add",
"fix", "run", "set", "all", "any", "our", "its", "his", "her", "now", "new",
"some", "more", "most", "such", "only", "also", "just", "like", "able", "via",
]);

/**
* Extract salient lower-cased keywords from a prompt for the lexical fallback.
* Keeps identifier-ish tokens (snake_case, dotted, paths), drops stopwords and
* sub-3-char tokens, de-dupes, and caps the count.
*/
export function extractKeywords(prompt: string | undefined | null, max = 8): string[] {
const raw = (prompt ?? "").toLowerCase().match(/[a-z0-9][a-z0-9_./-]{2,}/g) ?? [];
const out: string[] = [];
const seen = new Set<string>();
for (const tok of raw) {
const w = tok.replace(/[._/-]+$/, ""); // trim trailing separators
if (w.length < 3 || STOPWORDS.has(w) || seen.has(w)) continue;
seen.add(w);
out.push(w);
if (out.length >= max) break;
}
return out;
}
20 changes: 0 additions & 20 deletions tests/shared/recall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { describe, it, expect, vi } from "vitest";
import {
shouldRecall,
passesThreshold,
extractKeywords,
proactiveRecallDisabled,
parsePositive,
RECALL_THRESHOLD,
Expand Down Expand Up @@ -492,25 +491,6 @@ describe("recallTopHit — focused semantic query", () => {
});
});

describe("extractKeywords — lexical fallback keyword extraction", () => {
it("keeps salient/identifier tokens, drops stopwords and short tokens", () => {
const kw = extractKeywords("why does the parser throw a TypeError in column_streamers.hpp?");
expect(kw).toContain("parser");
expect(kw).toContain("typeerror");
expect(kw).toContain("column_streamers.hpp");
expect(kw).not.toContain("the");
expect(kw).not.toContain("why"); // stopword
});
it("de-dupes and caps the count", () => {
const kw = extractKeywords("cache cache cache redis redis storage storage provider bucket byoc extra", 4);
expect(kw.length).toBe(4);
expect(new Set(kw).size).toBe(kw.length);
});
it("returns few/no keywords for terse input (can't meet the lexical bar)", () => {
expect(extractKeywords("ok go").length).toBeLessThan(2);
});
});

describe("recordRecallEvent — always-on JSONL sink", () => {
let home: string;
beforeEach(() => { home = mkdtempSync(join(tmpdir(), "recall-ev-")); setFakeHome(home); });
Expand Down