Skip to content

Do not report unresolved exact-name graph fallback as confirmed callers or impact #5183

Description

@Widthdom

Summary

When an exact symbol query has zero indexed definitions but unresolved same-name reference rows, callers and impact promote that fallback evidence to confirmed or authoritative results.

For ExecuteTrackedReader, definition returns not found, while callers --count reports 110 callers with degraded: false and authoritative_count: true. impact reports the name-fallback traversal as confirmed, with heuristic: false.

This is a direct residual/regression of the confidence contract completed in #5084.

Environment

  • origin/main: c642bc4c3dda4ef659df8e6b699e10f61da3c836
  • cdidx v1.44.3, locally built
  • fresh, complete repository index; no reference-extraction cap hits
  • full net8.0 and net9.0 suites pass

Reproduction

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll definition \
  ExecuteTrackedReader --exact-name --strict-not-found \
  --db .cdidx/codeindex.db --json --no-progress

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll callers \
  ExecuteTrackedReader --exact-name --count \
  --db .cdidx/codeindex.db --json --no-progress

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll impact \
  ExecuteTrackedReader --exact-name --count --limit 20 \
  --db .cdidx/codeindex.db --json --no-progress

Current results:

definition: exit 2 / E018_QUERY_NOT_FOUND

callers:
  count: 110
  files: 44
  degraded: false
  authoritative_count: true

impact:
  count: 20
  confirmed_count: 20
  hint_count: 0
  heuristic: false
  degraded: true
  authoritative_count: false
  termination_reason: row_limit_truncated

inspect identifies the available reference evidence as graph_scope: query_fallback, and the underlying rows are unresolved.

Expected behavior

For an exact query with no resolved definition identity:

  • unresolved same-name rows must not become confirmed callers;
  • unresolved rows must not seed confirmed transitive impact traversal;
  • confirmed_count remains zero;
  • retained discovery evidence is labeled unresolved, heuristic, or hint;
  • authoritative caller counts are false or unavailable;
  • strict mode fails with a stable reason explaining that no identity-backed root exists.

Broad discovery may retain name-based fallback, but must not weaken the trust contract of exact or qualified queries.

Root-cause evidence

Relevant layers include:

  • src/CodeIndex/Database/DbReader.GraphQueries.cs;
  • src/CodeIndex/Database/DbReader.ImpactTraversal.cs;
  • caller aggregation and fallback selection;
  • src/CodeIndex/Cli/QueryCommandRunner.Dependencies.cs;
  • MCP impact projection in src/CodeIndex/Mcp/McpToolHandlers.ImpactAnalysis.cs.

The reference layer preserves resolution_state: unresolved; downstream caller/impact aggregation changes the confidence semantics after choosing a name fallback.

Focused PR scope

One PR should make the shared confidence contract consistent across:

  1. callers;
  2. impact;
  3. inspect caller summaries;
  4. hotspot/reference aggregation if it consumes the same fallback bucket;
  5. CLI and MCP projections of the same result.

Non-goals

  • Do not repair the missing method definition here; the extractor cutoff is tracked separately.
  • Do not discard unresolved evidence globally.
  • Do not require compiler-grade C# resolution.
  • Do not redesign selectors, overload identity, or partial-family identity.
  • Do not label a name-only row confirmed because its leaf name happens to be unique on one page.

Implementation guidance and cautions

  • A confirmed row must be backed by a resolved target symbol ID or another authoritative indexed identity.
  • Preserve resolution state through grouping and traversal.
  • Separate resolved roots from fallback/hint roots before BFS begins.
  • Never traverse a hint root into confirmed transitive results.
  • Keep bounded pagination, cycles, graph-completeness, and cap-hit metadata intact.
  • Give exact/qualified and broad discovery modes explicit, tested semantics.
  • Avoid count inflation when many unresolved rows share one display name.
  • Keep CLI and MCP counts and degradation flags synchronized.

Required tests

Use an isolated fixture that remains valid after the extractor bug is fixed:

  • an unresolved external call with no indexed definition;
  • a deliberately omitted definition file;
  • a resolved local symbol with the same leaf name;
  • two unrelated same-name methods;
  • exact and broad queries;
  • a transitive caller chain behind the unresolved row;
  • complete and capped/incomplete graph variants.

Assert parity across references, callers, inspect, impact, hotspots, and MCP. Confirm that hint roots never yield confirmed traversal and that strict mode returns the documented failure.

Acceptance criteria

  • An exact query with zero definitions returns zero confirmed callers and zero confirmed impact.
  • heuristic: false is never emitted for name-only unresolved traversal.
  • callers does not report authoritative_count: true for an unresolved fallback bucket.
  • Resolved same-name symbols remain navigable.
  • Broad discovery remains useful but visibly lower-confidence.
  • CLI and MCP agree.

Regression history

This is a direct residual/regression of #5084, which required unresolved same-name C# edges to remain heuristic and excluded from confirmed callers, impact, and hotspot counts. Regression tests and the bilingual changelog fragment should reference #5084.

Earlier related identity work includes #4569, #3894, #2819, and #151. No newer exact issue was found.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETPull requests that update .NET codebugSomething isn't workingdocumentationImprovements or additions to documentationtests

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions