change_impact affirmatively reports "no test-role dependents" for all 1,750 symbols of the one crate whose 70 test files structurally cannot produce an edge #286

Open
opened 2026-09-17 16:16:46 +02:00 by buildagent · 0 comments
Member

What the tool says

Seeding change_impact with plan_queries and batch_entry — the batching
planner shipped in v0.30.0, which has six dedicated tests — returns:

{"seeds":[931271,931272],"total_affected":2,"production_count":2,"test_count":0,
 "test_role_files":[],"no_test_role_dependents":[931271,931272],
 "graph_semantics":"resolved_dependencies; test-role results are static proxies, not runtime coverage"}

test_role_files is described as "the file-level test run-set, which is the
point of the tool". Here it is empty, and no_test_role_dependents names both
seeds affirmatively. The honest reading a caller takes from that is "nothing to
run". The correct answer is crates/mcp-server/tests/batch_queries_e2e.rs,
six tests written specifically for those two functions.

The mechanism is structural, not a resolver gap

crates/mcp-server is the workspace's only bin-only crate:

[[bin]]
name = "code-index-mcp"
path = "src/main.rs"

There is no src/lib.rs. A Rust integration test in tests/ cannot link a
bin-only crate, so it cannot reference its items. Measured:

integration-test files in crates/mcp-server/tests 70
of those that name code_index_mcp:: 0
rust symbols in crates/mcp-server/src 1,750

Every one of those 1,750 symbols — argcheck (82), eligibility (40),
errors (38), gitdiff (68), main (55), provenance (37), server
(1,368), stdio (46), tokens (16) — is a seed for which change_impact
returns an empty test set, for a reason that has nothing to do with whether
the symbol is tested. crates/mcp-server/src/server.rs alone holds the
implementation of all 23 tools.

Positive control, so this is not a claim about a broken traversal:
seeding plan_agent_rules (crates/cli/src/rules.rs, a lib crate) returns
test_count: 3, test_role_files: ["crates/cli/src/rules.rs"], and
omits no_test_role_dependents entirely. The mechanism works; it is the
edge that does not exist.

The wider class

Bin-only is where it is provably total, but the general case is any test that
drives the code under test across a process boundary — which is this
product's dominant e2e style. batch_queries_e2e.rs imports exactly
serde_json::{json, Value} and mcp::{Mcp, build_bin, call_tool, initialize, pre_index, tool_body}: a harness that spawns the binary and speaks stdio.
121 of the workspace's 337 integration-test files mention a process-spawn
construct. Those edges are invisible by construction, in lib crates too.

Why the existing disclosure does not cover it

The payload does carry graph_semantics: "... static proxies, not runtime coverage", and the tool description says these fields are "STATIC DEPENDENCY
PROXIES, not runnable-test or runtime-coverage claims". That warns a reader
that the set may be incomplete. It does not let them tell the two states
apart:

  • test_role_files: [] because the symbol genuinely has no tests, and
  • test_role_files: [] because no test in this crate can have an edge.

Those are the same payload today, and they warrant opposite actions.
no_test_role_dependents is the sharper half of the problem: unlike an empty
list, it is an affirmative, per-seed assertion, and it is emitted exactly
when the count is zero — i.e. precisely in the case that is unreliable.

Shape of a fix (structural, not per-case)

Report the denominator alongside the set, so an empty set describes
itself. test_role_files: [] beside "the seed's package contains 70
test-role files, 0 of which the closure reached" is self-explaining;
[] of 0 and [] of 70 are the two states above, distinguished by one
count that the index already holds.

That rests on a structural fact (test-role files under the seed's package
root, a population the indexer already labels) rather than on detecting
spawn harnesses, and it stays language-neutral — no Cargo-target special
case, and it degrades correctly for a repo with no test-role files at all.

Found by dogfooding v0.30.0 (1a9079d) — the tool was asked which tests to
run for code this session had just shipped, and answered "none".

## What the tool says Seeding `change_impact` with `plan_queries` and `batch_entry` — the batching planner shipped in v0.30.0, which has six dedicated tests — returns: ```json {"seeds":[931271,931272],"total_affected":2,"production_count":2,"test_count":0, "test_role_files":[],"no_test_role_dependents":[931271,931272], "graph_semantics":"resolved_dependencies; test-role results are static proxies, not runtime coverage"} ``` `test_role_files` is described as "the file-level test run-set, which is the point of the tool". Here it is empty, and `no_test_role_dependents` names both seeds affirmatively. The honest reading a caller takes from that is "nothing to run". The correct answer is `crates/mcp-server/tests/batch_queries_e2e.rs`, six tests written specifically for those two functions. ## The mechanism is structural, not a resolver gap `crates/mcp-server` is the workspace's only **bin-only** crate: ```toml [[bin]] name = "code-index-mcp" path = "src/main.rs" ``` There is no `src/lib.rs`. A Rust integration test in `tests/` cannot link a bin-only crate, so it **cannot** reference its items. Measured: | | | |---|---| | integration-test files in `crates/mcp-server/tests` | **70** | | of those that name `code_index_mcp::` | **0** | | rust symbols in `crates/mcp-server/src` | **1,750** | Every one of those 1,750 symbols — `argcheck` (82), `eligibility` (40), `errors` (38), `gitdiff` (68), `main` (55), `provenance` (37), `server` (1,368), `stdio` (46), `tokens` (16) — is a seed for which `change_impact` returns an empty test set, for a reason that has nothing to do with whether the symbol is tested. `crates/mcp-server/src/server.rs` alone holds the implementation of all 23 tools. Positive control, so this is not a claim about a broken traversal: seeding `plan_agent_rules` (`crates/cli/src/rules.rs`, a lib crate) returns `test_count: 3`, `test_role_files: ["crates/cli/src/rules.rs"]`, and **omits** `no_test_role_dependents` entirely. The mechanism works; it is the edge that does not exist. ## The wider class Bin-only is where it is provably total, but the general case is any test that drives the code under test **across a process boundary** — which is this product's dominant e2e style. `batch_queries_e2e.rs` imports exactly `serde_json::{json, Value}` and `mcp::{Mcp, build_bin, call_tool, initialize, pre_index, tool_body}`: a harness that spawns the binary and speaks stdio. 121 of the workspace's 337 integration-test files mention a process-spawn construct. Those edges are invisible by construction, in lib crates too. ## Why the existing disclosure does not cover it The payload does carry `graph_semantics: "... static proxies, not runtime coverage"`, and the tool description says these fields are "STATIC DEPENDENCY PROXIES, not runnable-test or runtime-coverage claims". That warns a reader that the set may be *incomplete*. It does not let them tell the two states apart: * `test_role_files: []` because the symbol genuinely has no tests, and * `test_role_files: []` because no test in this crate *can* have an edge. Those are the same payload today, and they warrant opposite actions. `no_test_role_dependents` is the sharper half of the problem: unlike an empty list, it is an affirmative, per-seed assertion, and it is emitted *exactly* when the count is zero — i.e. precisely in the case that is unreliable. ## Shape of a fix (structural, not per-case) Report the **denominator** alongside the set, so an empty set describes itself. `test_role_files: []` beside "the seed's package contains 70 test-role files, 0 of which the closure reached" is self-explaining; `[] of 0` and `[] of 70` are the two states above, distinguished by one count that the index already holds. That rests on a structural fact (test-role files under the seed's package root, a population the indexer already labels) rather than on detecting spawn harnesses, and it stays language-neutral — no Cargo-target special case, and it degrades correctly for a repo with no test-role files at all. Found by dogfooding v0.30.0 (`1a9079d`) — the tool was asked which tests to run for code this session had just shipped, and answered "none".
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
h-dv/code-index#286
No description provided.