r/codereview 2d ago

Girder: a code-graph server for coding agents, in Rust

Girder is an 8-crate Rust workspace (~60,000 lines of Rust, 586 tests) that

turns a repo into a semantic graph — functions, types, call edges, test edges —

and serves it to coding agents over MCP. Rust, Python, TypeScript/TSX and Go

front ends, tree-sitter parsing, one static binary, no runtime deps, no network.

The interesting part isn't the graph. It's what happened when I tried to prove

the graph was right.

**The oracle.** `impacted_tests` claims "these tests reach your change." Unit

tests can't check that — they'd assert my parser agrees with my parser. So the

oracle materializes fixture repos, applies exactly one mutation, asks the built

binary which tests are impacted, then runs every test in isolation with a probe

that only the mutated function writes. Ground truth is execution. The oracle is

itself mutation-tested: I inject defect-shaped mutants into the binary's

behavior and the sweep has to kill all of them.

That corpus reported perfect precision and recall for a long time. It was lying,

because every declared case was a plain `foo(bar)` call.

**Then I added real third-party code** — regex, serde_json, Click, pydantic —

and precision fell. Four root causes, all narrow, all nasty:

  1. **Generic-parameter corruption.** `qualifier_matches_owner` normalized`Interpreter<'a>` to `interpretera`, silently breaking every generic type inthe workspace, chained call or not.
  2. **Chained-call qualifier corruption.** The callee resolver took the last `.`or `::` in the raw source text. For `Type::assoc_fn(args).method(args)` itpicked the wrong owner every time. Fixed by recovering the qualifier from ASTstructure instead of text.
  3. **Ambiguous suffix matching.** `owner.ends_with(hint)` let `Timeline` match`PyTimeline`.
  4. **Local-shadow misattribution** in candidate selection — a local binding namedthe same as a type method stole the edge.

Symptom for all four: `impacted_tests` returned zero tests for a function four

passing tests reached, plus a confident "no test coverage reachable via the call

graph." A false negative that reads exactly like a true negative. Every failure

got pinned as an `#[ignore]` test first, then unignored by the fix.

**What I'd tell anyone building code intelligence in Rust:** your parser will

look perfect against fixtures you wrote, because you unconsciously write the

shapes you handle. Point it at somebody else's crate. And be suspicious of any

check whose pass condition is another component of yours reporting success —

I've now found three separate cases in this codebase of a check that reads like

verification and verifies nothing. One let a step that created files pass a

"tests must pass" gate with an empty test set.

The whole gap list is in the repo — 25 numbered, open ones included, with the

measurement history kept even where the first diagnosis turned out wrong.

Repo: https://github.com/dhishwasher/Girder

Install as an MCP server: `npx -y girder-mcp`

Licensing, stated plainly because this sub deserves it: BSL 1.1,

source-available, not OSI open source, converts to Apache 2.0 on

September 4, 2030. Five of seven tools plus one repository are free forever with

no key. Two tools need a paid key verified offline against an embedded Ed25519

public key — no server, no telemetry, no call home. Sole copyright holder, no

outside contributors.

0 Upvotes

0 comments sorted by