Skip to content

explore: a query whose words are not in the code returns a bare "No relevant code found" — no diagnosis, no vocabulary to retry with #1904

Description

@iacore

Concept

Query matching is lexical, and a miss never says so. A query is tokenized and every token is OR-prefix-matched against symbol name / qualified name / signature / docstring (bm25(nodes_fts, 0, 20, 5, 1, 2), src/db/queries.ts), with a LIKE-substring pass, a bounded-edit-distance name pass, and a word→identifier-segment lookup (name_segment_vocab) on top. A natural-language question therefore works exactly as far as its words overlap text the index holds — and when none of them do, the whole response is:

No relevant code found for "<query>"

The caller cannot distinguish this codebase has no such concept from your words differ from the code's words, and it is handed no vocabulary to retry with. The next move is Read/Grep — the fallback this tool exists to prevent.

Repro (1.6.0; one temp project, 5 symbols)

src/users.py: RegistrationService.create_account, RateLimiter.check_limitsrc/orders.py: OrderStateMachine.transition, cancel_order

$ codegraph explore "how do we stop users signing up too fast"
No relevant code found for "how do we stop users signing up too fast"

$ codegraph query "signup throttle"
ℹ No results found for "signup throttle"

# the same shape works whenever the words DO overlap identifiers:
$ codegraph query "how do we register a new user account"
method      create_account
  src/users.py:3

# one literal token rescues an otherwise-synonym query:
$ codegraph explore "throttle signup limit"
→ 2 symbols, matched on the word `limit` in `check_limit`

Why the miss has exactly this shape

Proposal — reuse the response shape the tool already has

  1. Report which query tokens occur anywhere in the index (name / signature / docstring / segment vocab) and which do not — e.g. signup, throttle: absent; limit: 1 symbol name.
  2. When at least one token exists, return up to ~8 candidate names for those tokens (segment vocab + searchNodes + fuzzy fallback), labeled as candidates, not answers.
  3. When no token exists, say that in those words — "none of these words appear in any indexed name, signature, comment, or path" — and name the likely cause. Optionally list the project's most central indexed symbols so the caller can orient.
  4. State the contract in one line: names, file names and code terms match; prose matches where it is a leading comment or docstring.

Precedent for the shape: a missing symbol name already answers with > **Note:** no symbol named "X". Did you mean: A, B? (src/graph/named-symbol-flow.ts), and the CLI prints Symbol "X" not found — did you mean: …?. This is the same treatment one level up, at the query. Success-shaped response, no isError, no instruction/description text.

Relationship to existing reports

This closes none of them — the root causes are different, verified: #1642 is an index shortfall (the default build/ ignore hides Java package paths), #1372 is the ASCII-only query splitter dropping pure-CJK terms (PR #1377), #1830 is the false-positive path (a path-shaped token treated as free text), and #1831/#1836 is a different surface (node's file-not-indexed message). They are all one family though: a miss and a real absence are byte-identical, and no response names its own cause. This is the query-level half of that family.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions