feat: resolution_gaps — rank index blind spots and explain how to improve them #36

Closed
opened 2026-07-20 22:45:36 +02:00 by buildagent · 1 comment
Member

Product

Make unresolved-reference telemetry queryable so users know where graph answers are weak and maintainers know which extractor/resolver improvement buys the most coverage.

Queries

  • summary by language, file, reference kind, role, qualifier presence, and candidate count
  • top unresolved names weighted by frequency, enclosing-symbol importance, and boundary/test role
  • classify likely cause with reason codes: missing receiver/type binding, missing import edge, ambiguous candidates, external dependency, dynamic/framework dispatch, parser omission, or no candidate
  • estimate the number of edges each proposed resolver rule could unlock
  • before/after comparison across an index run or commit when history exists
  • export minimal source examples/handles for regression fixtures

Why

Graph features are only as trustworthy as resolution coverage. Current evidence already identifies a dominant actionable gap: method calls resolve at ~6.8% versus ~31.7% for plain calls; 2,619 unresolved method calls have exactly one in-repo name candidate and 590 more need receiver disambiguation (#29). Today those measurements require bespoke SQL.

This tool creates a virtuous loop: expose blind spots → prioritize extraction work → add fixtures → measure recovered edges → improve every graph product.

Boundaries

  • candidate counts are diagnostic, never permission to guess a target
  • external/dynamic references remain honestly unresolved
  • high-frequency generated/vendor files must be suppressible
  • privacy-safe snippets follow existing read_code boundaries and project routing

Acceptance

  • project overview gains a compact coverage summary and links/handles into this report
  • classifications are deterministic and carry supporting counts
  • report distinguishes unresolved-qualified, unresolved-bare, and ambiguous in-project refs
  • rankings can exclude tests/generated paths and can focus on a language/file
  • #29’s expected unlock can be reproduced from the public output
  • regression fixture demonstrates that an extractor improvement reduces its target gap without increasing ambiguous/incorrect resolutions
## Product Make unresolved-reference telemetry queryable so users know where graph answers are weak and maintainers know which extractor/resolver improvement buys the most coverage. ### Queries - summary by language, file, reference kind, role, qualifier presence, and candidate count - top unresolved names weighted by frequency, enclosing-symbol importance, and boundary/test role - classify likely cause with reason codes: missing receiver/type binding, missing import edge, ambiguous candidates, external dependency, dynamic/framework dispatch, parser omission, or no candidate - estimate the number of edges each proposed resolver rule could unlock - before/after comparison across an index run or commit when history exists - export minimal source examples/handles for regression fixtures ## Why Graph features are only as trustworthy as resolution coverage. Current evidence already identifies a dominant actionable gap: method calls resolve at ~6.8% versus ~31.7% for plain calls; 2,619 unresolved method calls have exactly one in-repo name candidate and 590 more need receiver disambiguation (#29). Today those measurements require bespoke SQL. This tool creates a virtuous loop: expose blind spots → prioritize extraction work → add fixtures → measure recovered edges → improve every graph product. ## Boundaries - candidate counts are diagnostic, never permission to guess a target - external/dynamic references remain honestly unresolved - high-frequency generated/vendor files must be suppressible - privacy-safe snippets follow existing `read_code` boundaries and project routing ## Acceptance - project overview gains a compact coverage summary and links/handles into this report - classifications are deterministic and carry supporting counts - report distinguishes unresolved-qualified, unresolved-bare, and ambiguous in-project refs - rankings can exclude tests/generated paths and can focus on a language/file - #29’s expected unlock can be reproduced from the public output - regression fixture demonstrates that an extractor improvement reduces its target gap without increasing ambiguous/incorrect resolutions
Author
Member

Shipped in v0.5.20 (I029 Track D) as the resolution_gaps MCP tool + a per-language resolution block in project_overview.

Deterministic reason codes (external, missing_receiver_single_candidate/_ambiguous, no_candidate, unreachable_unique, ambiguous) computed against the SAME candidate universe the resolver uses (kind-aware, same-language, impl/assoc-item-excluded pools); example handles decode from a single aggregated key so they always name a real ref site (review-caught: the naive MIN(path)+MIN(line) fabricated locations); full ORDER BY tiebreaks for cross-build determinism; unknown lang rejected with did_you_mean instead of confident zeros (the D3 trap).

It already did its job: the tool corrected #29's unlock estimate — the brainstorm's 2,619 was lang-blind; the resolver-faithful measurement is 757 single-candidate + 597 receiver-disambiguable method calls (reproducible from public output, per this issue's acceptance). The 7-language e2e asserts per-lang rows and that reason-code aggregates account for exactly the unresolved remainder, end to end through the RPC/serde/tool layers.

Shipped in **v0.5.20** (I029 Track D) as the `resolution_gaps` MCP tool + a per-language `resolution` block in `project_overview`. Deterministic reason codes (`external`, `missing_receiver_single_candidate`/`_ambiguous`, `no_candidate`, `unreachable_unique`, `ambiguous`) computed against the SAME candidate universe the resolver uses (kind-aware, same-language, impl/assoc-item-excluded pools); example handles decode from a single aggregated key so they always name a **real** ref site (review-caught: the naive MIN(path)+MIN(line) fabricated locations); full ORDER BY tiebreaks for cross-build determinism; unknown `lang` rejected with `did_you_mean` instead of confident zeros (the D3 trap). **It already did its job**: the tool corrected #29's unlock estimate — the brainstorm's 2,619 was lang-blind; the resolver-faithful measurement is **757 single-candidate + 597 receiver-disambiguable** method calls (reproducible from public output, per this issue's acceptance). The 7-language e2e asserts per-lang rows and that reason-code aggregates account for exactly the unresolved remainder, end to end through the RPC/serde/tool layers.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
h-dv/code-index#36
No description provided.