A multi-word PascalCase query token — typically a project name a user includes (`SuperBizAgent backend routes`) — splits into sub-tokens (superbizagent / super / biz / agent) that ALL match the same path segment, so path relevance summed +5 four times for one concept. In a mixed-stack repo that ~doubled every score of the lexically-matching stack's file, burying the stack the query was about. Score path relevance per original query WORD instead: a word matches a path level if any of its sub-tokens do, and counts once — while still splitting the word (via extractSearchTerms on the original case) so it matches across naming conventions (`getUserName` → `get_user_name`). Distinct words each still contribute. Partial fix: this removes the dominant path over-counting (backend rises from absent-in-top-6 to parity on the reporter's repro). The residual lexical edge from the project name in the FTS class-name match + dir match is a deeper down-weighting change, tracked separately. No re-index needed (query-time). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5b3f5e36db
commit
afec1282e1
@@ -16,7 +16,7 @@ import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import CodeGraph from '../src/index';
|
||||
import { LOW_CONFIDENCE_MARKER } from '../src/context';
|
||||
import { isDistinctiveIdentifier } from '../src/search/query-utils';
|
||||
import { isDistinctiveIdentifier, scorePathRelevance } from '../src/search/query-utils';
|
||||
|
||||
describe('isDistinctiveIdentifier', () => {
|
||||
it('treats plain dictionary words as non-distinctive', () => {
|
||||
@@ -39,6 +39,31 @@ describe('isDistinctiveIdentifier', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// A single PascalCase query word (notably a project name a user naturally
|
||||
// includes) splits into sub-tokens that all match the SAME path segment; summed
|
||||
// per sub-token it boosted that path 4×, burying the rest of the query's stack
|
||||
// (#720). Path relevance must count each original WORD once per level, while
|
||||
// still splitting it for cross-convention matching.
|
||||
describe('scorePathRelevance per-word scoring (#720)', () => {
|
||||
it('counts a single PascalCase word once per path level, not once per sub-token', () => {
|
||||
// "SuperBizAgent" → super/biz/agent/superbizagent all hit the dir, but it's
|
||||
// one concept: +5 (dir) once, not +20.
|
||||
expect(scorePathRelevance('SuperBizAgentFrontend/app.js', 'SuperBizAgent')).toBe(5);
|
||||
});
|
||||
|
||||
it('still splits a word so it matches across naming conventions', () => {
|
||||
// getUserName must still match a snake_case path via its sub-tokens.
|
||||
expect(scorePathRelevance('get_user_name.go', 'getUserName')).toBeGreaterThanOrEqual(10);
|
||||
});
|
||||
|
||||
it('still credits distinct query words matching different path segments', () => {
|
||||
// auth (dir) and handler (filename) are separate concepts — each counts.
|
||||
expect(scorePathRelevance('src/auth/login_handler.go', 'auth handler')).toBeGreaterThan(
|
||||
scorePathRelevance('src/auth/login_handler.go', 'auth')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Context ranking — common-word precision & confidence', () => {
|
||||
let testDir: string;
|
||||
let cg: CodeGraph;
|
||||
|
||||
Reference in New Issue
Block a user