From eeadde4cffe29112ae6c63548e47dfaf14d649c1 Mon Sep 17 00:00:00 2001 From: sciapanCA Date: Thu, 10 Sep 2026 23:42:31 +0200 Subject: [PATCH 1/3] Add call sites --- src/tests/test_tool_metadata.py | 19 +++++++++++++++++++ src/tools/artifact_relationships.py | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/tests/test_tool_metadata.py b/src/tests/test_tool_metadata.py index 3be8832..1902b7c 100644 --- a/src/tests/test_tool_metadata.py +++ b/src/tests/test_tool_metadata.py @@ -79,3 +79,22 @@ def test_server_advertises_codealive_version_and_compact_instructions(): assert len(mcp.instructions.split()) <= 150 assert "DISCOVER → SEARCH → READ → EXPAND" in mcp.instructions assert "chat only when the user explicitly requests" in mcp.instructions.lower() + +@pytest.mark.asyncio +async def test_relationships_description_states_the_call_site_contract(): + """The three call-site rules are only enforceable through the tool description: the backend can + omit positions for a repository indexed before call sites shipped, and a model that reads a + missing position as "no call" draws the opposite conclusion from the truth.""" + # Arrange / Act + async with Client(mcp) as client: + tools = await client.list_tools() + + # Assert + description = {tool.name: tool for tool in tools}["get_artifact_relationships"].description + assert description is not None + assert "call_sites" in description + assert "call_site_count" in description + # Missing position means "not indexed yet", never "no call". + assert "never" in description.lower() + # No parameter enables them, so the model must not go hunting for one. + assert "no parameter" in description.lower() diff --git a/src/tools/artifact_relationships.py b/src/tools/artifact_relationships.py index 545a2db..c8cc565 100644 --- a/src/tools/artifact_relationships.py +++ b/src/tools/artifact_relationships.py @@ -33,6 +33,17 @@ async def get_artifact_relationships( This is a graph expansion tool, not a search tool. Use identifiers returned by semantic_search, grep_search, fetch_artifacts, read_file, or prior relationship results. + + Call relationships also carry `call_sites` — the file and 1-based line where + each call is actually written — plus `call_site_count` for how many exist in + total. Read those exact lines instead of fetching the whole caller. There is + no parameter for this: positions come back whenever they are known, so do not + look for a flag. A call item with no `call_sites` means the position is not + indexed yet (the repository was indexed before call sites shipped, or that one + edge could not be located); it never means the call does not happen — the item + being listed at all is what says the call exists. A `confidence` on a site + appears only when the position is approximate; its absence means exact. For + incoming calls the file shown is the caller's file, not this artifact's. """ tool_name = "get_artifact_relationships" require_text(identifier, tool_name, "identifier") From a57a89c687c57fcc6334d402fb417e6b976a1d77 Mon Sep 17 00:00:00 2001 From: sciapanCA Date: Sat, 12 Sep 2026 19:37:31 +0200 Subject: [PATCH 2/3] Replace CallSite file+line with position --- src/tools/artifact_relationships.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/artifact_relationships.py b/src/tools/artifact_relationships.py index c8cc565..8327c76 100644 --- a/src/tools/artifact_relationships.py +++ b/src/tools/artifact_relationships.py @@ -34,11 +34,11 @@ async def get_artifact_relationships( by semantic_search, grep_search, fetch_artifacts, read_file, or prior relationship results. - Call relationships also carry `call_sites` — the file and 1-based line where - each call is actually written — plus `call_site_count` for how many exist in - total. Read those exact lines instead of fetching the whole caller. There is - no parameter for this: positions come back whenever they are known, so do not - look for a flag. A call item with no `call_sites` means the position is not + Call relationships also carry `call_sites` — each one a `position` written as + `path:line`, where the call is actually written — plus `call_site_count` for + how many exist in total. Read those exact lines instead of fetching the whole + caller. There is no parameter for this: positions come back whenever they are + known, so do not look for a flag. A call item with no `call_sites` means the position is not indexed yet (the repository was indexed before call sites shipped, or that one edge could not be located); it never means the call does not happen — the item being listed at all is what says the call exists. A `confidence` on a site From 03129a9eafe4733e4a780da2618a85920d68f596 Mon Sep 17 00:00:00 2001 From: sciapanCA Date: Thu, 24 Sep 2026 21:00:48 +0200 Subject: [PATCH 3/3] build(deps): bump anyio to 4.15.1 for security advisories Fixes GHSA-5p39-cfhj-2xmp, GHSA-82r6-8w77-94w6 and GHSA-3w57-8xmc-8v26 reported by uv audit. Co-Authored-By: Claude Opus 5.5 (1M context) --- uv.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uv.lock b/uv.lock index 4f12639..70b136b 100644 --- a/uv.lock +++ b/uv.lock @@ -48,15 +48,15 @@ wheels = [ [[package]] name = "anyio" -version = "4.14.1" +version = "4.15.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.15'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" }, + { url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" }, ] [[package]]