feat(graph): Cypher-subset query engine -- query-graph command + MCP tool (closes #9)#151
Closed
Wolfvin wants to merge 1 commit into
Closed
feat(graph): Cypher-subset query engine -- query-graph command + MCP tool (closes #9)#151Wolfvin wants to merge 1 commit into
Wolfvin wants to merge 1 commit into
Conversation
…tool (closes #9) Issue #9 — Cypher-like graph query engine for MCP tool query_graph. Agents can now express structural questions in a single expressive query instead of chaining trace + impact + context tool calls. One query replaces 3-5 tool calls for typical structural questions (estimated 60-80% reduction in tool calls for structural questions per issue #9). Supported Cypher subset (per issue 'minimal viable' scope): - Clauses: MATCH, WHERE, RETURN, LIMIT - Predicates: =, !=, <, >, <=, >=, CONTAINS, IS NULL, IS NOT NULL, EXISTS { pattern }, NOT EXISTS { pattern }, AND, OR, NOT - Node labels: Function, Class, File, Module, Route, Type, Interface - Edge types: CALLS, IMPORTS, DEFINES, INHERITS, IMPLEMENTS, USES_TYPE - Read-only (no CREATE/SET/DELETE/MERGE clauses) - Default LIMIT 100, hard cap 1000 to prevent runaway queries Example queries (from issue #9): MATCH (f:Function)-[:CALLS]->(g) WHERE f.name = 'handleRequest' RETURN g.name, g.file MATCH (c:Class)-[:INHERITS]->(p) WHERE p.name = 'BaseModel' RETURN c.name MATCH (f:Function) WHERE NOT EXISTS { ()-[:CALLS]->(f) } RETURN f.name -- dead code Architecture: - scripts/cypher_query_engine.py: tokenizer + recursive-descent parser + AST-to-SQL translator + executor. All user-supplied literals are parameterized (? placeholders) -- no SQL injection. Identifiers (var names, prop names, labels, edge types) validated against allow-lists at parse time. Correlated EXISTS subqueries translate to SQL EXISTS with WHERE correlation (not redundant JOIN). - scripts/commands/query_graph.py: CLI command with --explain flag (shows translated SQL without executing). Registered as 'query-graph'. - scripts/mcp_server.py: static MCP tool definition 'query-graph' with full description, query/workspace/explain parameters. Tool name codelens_query_graph (hyphens to underscores). - tests/test_cypher_query.py: 66 tests covering tokenizer, parser validation, SQL translation (placeholder/param count), end-to-end execution against test database, error handling, CLI command, MCP tool registration. Security: - All string/number literals in WHERE predicates are passed as SQL parameters (? placeholders) -- no string interpolation into SQL. - Identifiers (variable names, property names) validated against allow-lists (_NODE_PROPERTIES, _EDGE_PROPERTIES) at parse time. - Node labels validated against _LABEL_TO_NODE_TYPE map at parse time. - Edge types validated against _VALID_EDGE_TYPES set at parse time. - Write clauses (CREATE/SET/DELETE/MERGE/REMOVE/DROP/INSERT/UPDATE/DETACH) rejected with clear 'read-only' error. - SQL injection test case included in test suite (test_sql_injection_safe). Command count: 69 -> 70 (query-graph added). sync_command_count.py --apply updated README.md, SKILL.md, SKILL-QUICK.md, skill.json, pyproject.toml, scripts/graph_model.py. MCP tools: 67 -> 68 (55 static + 13 dynamic). Verified: - 66/66 cypher query tests pass - 185/185 pass on focused subset (test_cypher_query + test_command_count + test_command_registry + test_version_consistency + test_cli + test_codelens + test_graph_model + test_graph_incremental), 35 skipped (optional deps) - CLI: 'codelens query-graph --explain' produces correct SQL + params - End-to-end: all 3 issue #9 example queries return expected results against test database with 6 nodes + 3 edges
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Owner
Author
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 #9
Catatan: Race condition dengan PR #149. Saya claim issue ini pada 2026-07-01T11:56:55Z (~14 detik setelah claim comment worker lain di 11:56:41Z). Saat saya cek issue state sebelum claim, belum ada comment apapun. PR ini competing approach dengan PR #149 — BOS putuskan.
Summary
Implementasi Cypher-subset graph query engine sesuai issue #9 "minimal viable" scope. Agents dapat ekspresikan pertanyaan struktural dalam satu query ekspresif sebagai pengganti chaining 3-5
trace+impact+contexttool calls (estimasi 60-80% reduction in tool calls per issue #9).Supported Cypher subset
=,!=,<,>,<=,>=,CONTAINS,IS NULL,IS NOT NULL,EXISTS { pattern },NOT EXISTS { pattern },AND,OR,NOTExample queries (dari issue #9)
Architecture
scripts/cypher_query_engine.py— Tokenizer + recursive-descent parser + AST-to-SQL translator + executor. All user-supplied literals parameterized (? placeholders). Identifiers validated against allow-lists at parse time. Correlated EXISTS subqueries translate to SQL EXISTS with WHERE correlation (not redundant JOIN).scripts/commands/query_graph.py— CLI command dengan--explainflag (shows translated SQL without executing). Registered asquery-graph.scripts/mcp_server.py— Static MCP tool definitionquery-graphdengan full description + query/workspace/explain parameters. Tool namecodelens_query_graph.tests/test_cypher_query.py— 66 tests: tokenizer, parser validation, SQL translation (placeholder/param count verification), end-to-end execution against test database, error handling, CLI command, MCP tool registration, SQL injection safety.Security
_LABEL_TO_NODE_TYPEmap at parse time_VALID_EDGE_TYPESset at parse timeFiles
scripts/cypher_query_engine.py— new (~700 lines: tokenizer + parser + translator + executor)scripts/commands/query_graph.py— new (CLI command wrapper)scripts/mcp_server.py— modified (43 lines added: static tool definition)tests/test_cypher_query.py— new (66 tests)sync_command_count.py --apply(command count 69 -> 70, MCP tools 67 -> 68)Verified
codelens query-graph --explainproduces correct SQL + paramsquery_graph#9 example queries return expected results against test database (6 nodes, 3 edges)'x'; DROP TABLE graph_nodes; --'safely handled (table not dropped)Acceptance criteria status (from issue #9)
query_graphregistered (ascodelens_query_graph)query-graphregistered