feat(search): semantic_query MCP tool via TF-IDF Option A (closes #11)#146
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
416db63 to
428ad15
Compare
Add a new semantic-query CLI command + codelens_semantic_query MCP tool that ranks symbols by cosine similarity to a natural-language query, using zero-dependency TF-IDF over symbol names + signatures + kinds + file paths. Implements Option A from issue #11 (Option B/C remain future work for embedding-model-based search). New files: - scripts/semantic_search_engine.py — TF-IDF engine: tokenize, build vocabulary + IDF, compute sparse doc vectors, rank by cosine sim. Cached per (db_path, mtime) so re-scans auto-invalidate the index. Named semantic_search_engine (not semantic_engine) to avoid colliding with the pre-existing deprecated taint-analysis semantic_engine.py from PR #140. - scripts/commands/semantic_query.py — CLI command registered as 'semantic-query'. Auto-exposed as codelens_semantic_query MCP tool via the dynamic tool discovery path. Also added an explicit static tool definition in _TOOL_DEFINITIONS so the JSON schema is documented. - tests/test_semantic_search_engine.py — 31 tests covering tokenizer, end-to-end query behavior, cache invalidation, graceful degradation, and TF-IDF ranking signal (rare-vs-common terms, multi-term queries). Modified files (auto-synced by sync_command_count.py --apply): - README.md, SKILL.md, SKILL-QUICK.md, pyproject.toml, skill.json, scripts/graph_model.py, scripts/mcp_server.py — command count 68->70, MCP tool count 66->68. Tests: 1401 passed, 80 skipped, 1 pre-existing failure unrelated (test_codelensignore::test_actual_target_dir_is_ignored — fails on clean HEAD too, environmental issue with the 'target' ignore pattern).
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Closes #11
Summary
Implements Option A from issue #11: a zero-dependency, pure-Python TF-IDF semantic search engine exposed as a new
semantic-queryCLI command andcodelens_semantic_queryMCP tool.Agents can now call:
and get back ranked symbols by cosine similarity — so a query for
"auth"surfacesverify_jwt_claims(matching via theauth/jwt.pyfile path) even when no symbol literally contains"auth"in its name.What was added
scripts/semantic_search_engine.py(db_path, mtime)so a re-scan auto-invalidates the index.scripts/commands/semantic_query.pysemantic-query. Auto-exposed ascodelens_semantic_queryMCP tool via dynamic tool discovery.scripts/mcp_server.py_TOOL_DEFINITIONSfor documented JSON schema (query, workspace, top).tests/test_semantic_search_engine.pyREADME.md,SKILL.md,SKILL-QUICK.md,pyproject.toml,skill.json,scripts/graph_model.pysync_command_count.py --apply: CLI 68->70, MCP 66->68.Naming note
The module is named
semantic_search_engine.py(notsemantic_engine.py) to avoid colliding with the pre-existing deprecated taint-analysissemantic_engine.pyfrom PR #140 / issue #49 phase-1. The two modules share the "semantic" prefix but have no other relationship.Why Option A first
Per the issue:
Option A (TF-IDF) is non-breaking, zero-dependency, deterministic, and good enough for the majority of agent "find the right file" queries. Option B (sentence-transformers embeddings) remains future work — it would require bundling an ~80 MB model and is better added as an optional install behind a feature flag.
Non-breaking by design
symbolstable populated bypersistent_registry— no new index file to keep consistent.Tests
Result on this branch: 1401 passed, 80 skipped, 1 failed.
The 1 failure (
test_codelensignore::TestBackwardCompat::test_actual_target_dir_is_ignored) is pre-existing and unrelated — it fails identically on cleanorigin/main(verified viagit stash+ re-run). Environmental issue with thetargetdirectory ignore pattern in the sandbox.Limitations (documented, not bugs)
"authentication"will not match"auth". The module docstring documents this and explains the trade-off (Option B would handle it). Workaround: agents query with"auth"directly.persistent_registry.symbolsschema doesn't store docstrings, so the TF-IDF document is built fromname + signature + kind + language + file_path + extra_json. Future enhancement: store docstrings during scan and add them to the document text.(db_path, mtime)so it's rebuilt only when the registry changes.