Part of #82. Depends on #83 and #84.
Summary
Build the query-time resolver that turns raw edge target names into ranked candidate-set payloads, in the shared service layer.
Scope
- Resolver module (e.g.
app/search/references.py) joining edges.target_name against symbols.name: exact match primary, same-repo preferred with cross-repo fallback, ranking signals (kind match, same-file, same-repo). Use the two-query design from app/search/symbols.py — its docstring documents the SQLAlchemy auto-correlation hazard that a self-referencing join makes worse.
- Payload builders in
app/service.py (both MCP and webui consume these): candidate sets with (repo, path, line, edge_kind, enclosing_symbol, candidates[]), truncated/truncation_reason flags, deterministic ordering, keyset-friendly.
- Branch scoping byte-identical to
search_code: explicit branch: → branches @> ARRAY[:v]; otherwise the implicit default-branch conjunct (coalesce(default_branch, 'HEAD')).
- Quality measurement: record the unique/ambiguous/unresolved distribution on the indexed corpus against the deep-dive probe baseline (28.8% / 33.4% / 37.8% on the 4-repo sample).
Acceptance criteria
Part of #82. Depends on #83 and #84.
Summary
Build the query-time resolver that turns raw edge target names into ranked candidate-set payloads, in the shared service layer.
Scope
app/search/references.py) joiningedges.target_nameagainstsymbols.name: exact match primary, same-repo preferred with cross-repo fallback, ranking signals (kind match, same-file, same-repo). Use the two-query design fromapp/search/symbols.py— its docstring documents the SQLAlchemy auto-correlation hazard that a self-referencing join makes worse.app/service.py(both MCP and webui consume these): candidate sets with(repo, path, line, edge_kind, enclosing_symbol, candidates[]),truncated/truncation_reasonflags, deterministic ordering, keyset-friendly.search_code: explicitbranch:→branches @> ARRAY[:v]; otherwise the implicit default-branch conjunct (coalesce(default_branch, 'HEAD')).Acceptance criteria