Hi, I'm
If you have boundary nodes, AI can answer "this API is also called from repo X" as a fact. Instead of asking AI to infer, you hand it a fact that's already been resolved.
Yes, there is inference during the extraction phase — TypeScript Compiler and Gemini both contribute. But the results are persisted as confirmed values in the graph, and a daily boundary-analysis cron (covered below) lets us notice drift the next morning. By the time AI consumes the graph, only verified facts flow to it.
AI has a tendency to answer "with whatever it can see" rather than saying "I don't know." That's where silent hallucinations creep in — wrong answers that neither AI nor the human catches. Boundary nodes are what physically prevents that. They give AI a verified place to stand.
Construction: tree-sitter Base, With TypeScript Compiler and Gemini Where Needed
Normal code structure (function calls, class inheritance, imports) is relatively straightforward to extract with tree-sitter. Walk the AST, turn functions / methods / classes / fields into nodes, connect references with edges. Just grind through it.
The catch is that while tree-sitter is great at building syntax trees, it's weak on type information and scope resolution. To accurately follow a field access chain like user.preferences.theme, you need to resolve what type the variable user is and where it's defined. tree-sitter alone can't reach that.
So for field-access resolution we use TypeScript Compiler API and Gemini in combination. tree-sitter extracts the structure → TypeScript Compiler resolves variables and types → for the dynamic cases that even that can't reach, Gemini infers. Three stages with distinct responsibilities, which is how we push field-access accuracy up.
Annotation-Based Won't Work for Production Systems
And no, you can't take the same approach for the production-side codebase that code-graph deals with:
- Annotating all 46 repos at once isn't realistic
- Long-running production systems, touched by multiple teams, with mixed frameworks
- The precondition "put annotations into the code" doesn't hold
So the choice was: keep code-graph (static analysis) as the base, and evolve by layering on additional graph layers to compensate.
How we're trying to solve the issues above, I'll cover separately in Part 2.
To Be Continued
That's it for Part 1. Part 2 will be about how we try to get past the issues above.
The real story is less "thrown away" and more "evolved."
Thanks for reading this far.
SOCIAL SHARE CARD GENERATOR