SWE-bench Verified · 500 real issues · twelve repositories
Better aim, for a fraction of the reading.
Each issue is pinned to the commit it was filed against. The question asked is the issue exactly as a human wrote it; the right answer is the set of files the accepted fix actually touched, test files excluded.
Bar length is drawn to the token figures. Better recall than reading ten whole files, for one eighteenth of the input. On Rust, across another 239 issues, 74.2%.
What it prints
A ranked answer, and why each line is in it.
Every entry says how it was reached. A name that resolved is not the same kind of evidence as a word matched in a docstring, and an agent that cannot tell them apart weighs them the same.
$ leangraph context "separability_matrix is wrong for nested CompoundModels" seed1.00fnseparability_matrix astropy/modeling/separable.py@2017 prose1.00fn_separable astropy/modeling/separable.py@8778 callee0.50fn_coord_matrix astropy/modeling/separable.py@5448 caller0.60fn_cstack astropy/modeling/separable.py@6916 path0.90fn_compute_n_outputs astropy/modeling/separable.py@3513 seed1.00method_calculate_separability_matrix astropy/modeling/core.py@30909 caller0.57fileastropy/modeling/tests/test_separable.py co-chg0.40fileastropy/modeling/functional_models.py
Illustrative — the shape is exactly what the command prints, the query is a
real issue. Add --source and it emits the code behind those
lines instead of their names.
Why it is quick
Loading is a memory map, not deserialization.
A graph is a file laid out so that querying it needs no parsing step. Opening one
is an mmap and a header check, which is why an agent can afford to ask.
How it works
Four passes, and everything after the first is an integer.
01 Discover
The repository's own ignore rules decide what counts as source. Nothing else is read.
02 Extract
One tree-sitter pass per file collects definitions, references — and the comments and docstrings, which are the only part of a repository written in the words its users actually use.
03 Resolve
Three tiers: lexical scope, explicit import, then a name match across the repository. Each edge keeps how it was found, so a proven call never weighs the same as a guess.
04 Persist
Adjacency in both directions, as CSR. callers() is two array reads and a slice — no descent, no decode, no allocation.
Where it loses
The part most tools leave out.
Every number here comes from a script in bench/ that you can run yourself.
So do these.
- It returns nothing useful on a seventh of issues. 14.4% of SWE-bench Verified, and plain keyword search beats it outright on another 5.2%.
- TypeScript is the weak language. 42.6% against Python's 81.8%. A third of the gap is the benchmark asking a harder question; the rest is a repository that ships its documentation as code, where a demo matches a bug report better than the implementation does.
- Edge precision is measured on one repository. 78.1% overall and 94.8% at the highest confidence tier, settled by running a real test suite and recording which call actually happened.
- A one-file change re-resolves the whole repository. Resolution is global: a definition added anywhere can change what a reference elsewhere binds to.