From 6adcfdff128390a6d4d40b2bbb274ba2e5fe1c96 Mon Sep 17 00:00:00 2001 From: Silong Tan Date: Thu, 16 Apr 2026 22:08:01 -0400 Subject: [PATCH] fix: rank symbols by fuzzy score instead of line order in Stage 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stage 1 file→symbol expansion was selecting symbols by start_line (insertion order) instead of fuzzy relevance score, dropping MRR@3 from ~0.54 to ~0.39. Preserve match_score from validate_symbols and use it as the within-file ranking key. Aggregate MRR@3: 0.39 → 0.58. Co-Authored-By: Claude Opus 4.6 (1M context) --- adapters/code_locator.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/adapters/code_locator.py b/adapters/code_locator.py index 45325b65..7f69f4ff 100644 --- a/adapters/code_locator.py +++ b/adapters/code_locator.py @@ -212,11 +212,14 @@ def _ground_single( # collapses to BM25-only. # 2. Rank symbols within each qualifying file (relevant ones # come first). - matched_ids: set[int] = set() + matched_scores: dict[int, float] = {} if tokens: try: validated = self._validate_with_threshold(tokens, fuzzy_threshold) - matched_ids = {v["symbol_id"] for v in validated if v.get("symbol_id")} + for v in validated: + sid = v.get("symbol_id") + if sid: + matched_scores[sid] = max(matched_scores.get(sid, 0), v["match_score"]) except Exception as exc: logger.debug("[ground] fuzzy validate failed for '%s': %s", description[:60], exc) @@ -225,10 +228,12 @@ def _ground_single( try: rows = db.lookup_by_name(name) for row in rows: - matched_ids.add(row["id"]) + matched_scores[row["id"]] = max(matched_scores.get(row["id"], 0), 100.0) except Exception as exc: logger.debug("[ground] symbol name lookup failed for '%s': %s", name, exc) + matched_ids = set(matched_scores) + # Stage 1: multi-file fused retrieval (FC-2 fix, v0.4.6). # Previously this stage took only the top-1 BM25 hit via next(), # which collapsed multi-file features to a single anchor — the @@ -273,7 +278,7 @@ def _ground_single( relevant_ids = matched_ids & file_symbol_ids ranked = sorted( file_symbols, - key=lambda r: (r["id"] not in relevant_ids, r["start_line"]), + key=lambda r: (r["id"] not in relevant_ids, -matched_scores.get(r["id"], 0)), ) for row in ranked[:per_file_budget]: code_regions.append({ @@ -294,8 +299,9 @@ def _ground_single( # Unchanged from v0.4.5 semantics. if not code_regions and matched_ids: try: + score_ranked_ids = sorted(matched_scores, key=matched_scores.get, reverse=True) code_regions = self._regions_from_symbol_ids( - sorted(matched_ids)[:max_symbols], db, description, + score_ranked_ids[:max_symbols], db, description, ) except Exception as exc: logger.warning("[ground] fuzzy fallback failed: %s", exc)