fix: Improve Python resolution accuracy and context relevance

Eliminate cross-language false positives in name resolution and deprioritize
test files in context building. Benchmarked on a Python+Rust codebase where
37% of edges were false positives from Python built-in methods resolving to
Rust functions (e.g., list.extend → Rust extend).

Resolution fixes (index-time):
- Filter Python built-in type method calls (list.extend, dict.update, etc.)
- Filter bare Python built-in method names (append, extend, pop, keys, etc.)
- Add language boundary checks to matchMethodCall strategies 1, 2, and 3
- Penalize cross-language matches: -80 points in findBestMatch (was 0)
- Reduce confidence for single cross-language exact matches (0.5 vs 0.9)
- Prefer same-language candidates in matchFuzzy

Context relevance fixes (query-time):
- Add isTestFile() utility detecting test files across Python/JS/TS/Go/Rust/Java
- Deprioritize test files in scorePathRelevance (-15 penalty)
- Reduce test file scores to 30% in context builder result merging
- Both skip deprioritization when query mentions "test" or "spec"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Colby McHenry
2026-04-03 12:29:21 -05:00
co-authored by Claude Opus 4.6
parent 5d5e715dec
commit 8b541be894
4 changed files with 204 additions and 11 deletions
+42
View File
@@ -375,6 +375,17 @@ export class ReferenceResolver {
this.queries.insertEdges(edges);
}
// Clean up resolved refs from unresolved_refs table so metrics are accurate
if (result.resolved.length > 0) {
this.queries.deleteSpecificResolvedReferences(
result.resolved.map((r) => ({
fromNodeId: r.original.fromNodeId,
referenceName: r.original.referenceName,
referenceKind: r.original.referenceKind,
}))
);
}
return result;
}
@@ -426,6 +437,37 @@ export class ReferenceResolver {
return true;
}
// Python built-in method calls (e.g., list.extend, dict.update, self.xxx)
if (ref.language === 'python') {
const dotIdx = name.indexOf('.');
if (dotIdx > 0) {
const receiver = name.substring(0, dotIdx);
// self.method and cls.method are internal calls, not built-in — let them resolve
// But receiver types that are built-in types should be filtered
const pythonBuiltInTypes = new Set([
'list', 'dict', 'set', 'tuple', 'str', 'int', 'float', 'bool',
'bytes', 'bytearray', 'frozenset', 'object', 'super',
]);
if (pythonBuiltInTypes.has(receiver)) {
return true;
}
}
// Also filter bare method names that are common Python built-in methods
// These get extracted as unresolved refs when called on arbitrary objects
const pythonBuiltInMethods = new Set([
'append', 'extend', 'insert', 'remove', 'pop', 'clear', 'sort', 'reverse', 'copy',
'update', 'keys', 'values', 'items', 'get',
'add', 'discard', 'union', 'intersection', 'difference',
'split', 'join', 'strip', 'lstrip', 'rstrip', 'replace', 'lower', 'upper',
'startswith', 'endswith', 'find', 'index', 'count', 'encode', 'decode',
'format', 'isdigit', 'isalpha', 'isalnum',
'read', 'write', 'readline', 'readlines', 'close', 'flush', 'seek',
]);
if (pythonBuiltInMethods.has(name)) {
return true;
}
}
// Pascal/Delphi built-ins and standard library units
if (ref.language === 'pascal') {
// Standard RTL/VCL/FMX unit prefixes — these are external dependencies