Filter English stopwords out of graph scope's exact-match boost - #117
Filter English stopwords out of graph scope's exact-match boost#117emmahyde wants to merge 1 commit into
Conversation
taskTokens() in graph scope splits the free-text task string on
non-identifier chars and gave every token >=2 chars a flat 1.0
exact-name-match score whenever it collided with a real identifier in
the repo. Common function words and generic task-instruction verbs
("on", "to", "of", "up", "find") routinely collide with trivial
in-repo identifiers (Ruby DSL params, ActiveRecord's find) and buried
the actually relevant symbol under stopword noise -- in one repro, a
task mentioning "on" returned that literal identifier 5x at the top
of the ranking while the real target never appeared.
|
Confirmed the root cause over in #115 — the flat 1.0 boost lets stopword nodes take all six The filter is unconditional, so a symbol legitimately named one of the verb-tail entries can never take the exact-match boost. Two ways out, either is fine by me: A. Drop the verb tail. Remove B. Down-weight instead of filtering. Keep the full list, but give stopword exact-matches a reduced score (~0.4) rather than dropping them. They can no longer hijack the six seed slots, but a genuinely-named I lean A for minimality since it keeps the diff at its current size, but B is the more correct fix if you'd rather do it once. The regression test works unchanged under either. Non-blocking: |
What
graph scope's exact-match scoring insrc/graph/scope.tshad no stopword filtering.taskTokens()split the free-text task string on non-identifier characters and gave every token >=2 chars a flat1.0"exact-name-match" boost whenever it collided with any real identifier in the repo.In practice, task phrasing is full of English function words and generic task-instruction verbs ("on", "to", "of", "up", "find", "trace"...) that routinely collide with trivial in-repo identifiers — Ruby DSL params (
on:), block args, ActiveRecord'sfind— and those collisions outrank the actually relevant symbol.Repro (see #115 for the full writeup):
mex graph scope "find every call site that invokes mark_failed! on a model"returned the literal identifieronat score1.0five times as the top hits; the real target never made it into the top 10 at all.Fix
Added a
TASK_STOPWORDSset (English function words + generic task-instruction verbs) and filtered them out oftaskTokens()before the exact-match loop runs. Whole-task semantic search (bm25-ranked, viagraph.searchNodes(task, ...)) is untouched — this only scopes the flat-1.0 exact-match boost, which is the specific mechanism that was letting stopwords dominate.Verification
scope.test.ts) reproducing the exact collision.npx vitest run— 11/11 inscope.test.ts; full suite 376/377 (the one failure is the pre-existing, unrelatedtui.test.tsissue also called out in Add Ruby extraction via Prism, not tree-sitter #116).npx tsc --noEmit— clean.dist/and re-ran the three real repro queries against a ~1600-file Rails codebase: all three now surface the correct symbol at or near the top of the ranking with no stopword noise.Related