Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,19 @@ jobs:
run: |
uv sync --extra treesitter-full --extra semantic --extra milvus --extra test --group dev

# evals/ too: the pre-commit hook checks it, so a type error there failed
# every local commit while this job stayed green (issue #3436).
- name: Run type checking
run: |
uv run ty check codebase_rag --exclude codebase_rag/tests/
uv run ty check codebase_rag evals --exclude codebase_rag/tests/

# Again with the optional `neo4j` extra installed: its package types
# every statement `LiteralString`, so a checkout with all extras saw
# errors the run above could never report (issue #2191).
- name: Run type checking with the neo4j extra
run: |
uv sync --extra treesitter-full --extra semantic --extra milvus --extra test --extra neo4j --group dev
uv run ty check codebase_rag --exclude codebase_rag/tests/
uv run ty check codebase_rag evals --exclude codebase_rag/tests/

test-unit:
name: Unit Tests (${{ matrix.os }}, py${{ matrix.python-version }}, shard ${{ matrix.shard }})
Expand Down
33 changes: 33 additions & 0 deletions codebase_rag/tests/test_eval_graph_node_exists.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# The in-memory store answers CYPHER_GRAPH_NODE_EXISTS for the unknown-target
# refusals in `cgr graph` and the MCP tools: a name counts as known when any
# node in any project carries it, and the answer is at most one row (#3436).
from __future__ import annotations

from codebase_rag import constants as cs
from codebase_rag import cypher_queries as cq
from codebase_rag.graph_query import node_exists
from evals.cgr_graph import _StatefulIngestor

QN = "other_project.pkg.mod.run"


def _store() -> _StatefulIngestor:
store = _StatefulIngestor()
# The same name under two labels: two nodes, so two candidate rows.
for label in (cs.NodeLabel.FUNCTION, cs.NodeLabel.METHOD):
store.ensure_node_batch(label.value, {cs.KEY_QUALIFIED_NAME: QN})
return store


def test_a_name_any_node_carries_is_found_as_one_row() -> None:
store = _store()
rows = store.fetch_all(cq.CYPHER_GRAPH_NODE_EXISTS, {cs.KEY_QN: QN})
assert rows == [{cs.KEY_QUALIFIED_NAME: QN}]
assert node_exists(store.fetch_all, QN)


def test_an_unknown_name_is_not_found() -> None:
store = _store()
missing = "other_project.pkg.mod.walk"
assert store.fetch_all(cq.CYPHER_GRAPH_NODE_EXISTS, {cs.KEY_QN: missing}) == []
assert not node_exists(store.fetch_all, missing)
5 changes: 3 additions & 2 deletions evals/cgr_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1376,11 +1376,12 @@ def fetch_all(
# Any node in any project: the unknown-target refusal asks
# whether the name is in the graph at all (issue #3244).
wanted = _str((params or {}).get(cs.KEY_QN))
return [
rows: list[ResultRow] = [
{cs.KEY_QUALIFIED_NAME: wanted}
for props in self.nodes.values()
if props.get(cs.KEY_QUALIFIED_NAME) == wanted
][:1]
]
return rows[:1]
case cq.CYPHER_CLAIM_PROJECT_ROOT:
return self._claim_project_root(params or {})
case cq.CYPHER_MARK_CLAIMED_PROJECT_INCOMPLETE:
Expand Down
Loading