Mar 2026 - May 2026 · Solo build
TraceScope
A Go CLI that predicts the blast radius of any pull request.
TraceScope turns a pull request into a risk map. Instead of guessing what a diff might break, it resolves the real call graph, traces impact outward, and ships the result as a CI gate that comments directly on the PR.
Architecture
The problem. A reviewer can see the lines a pull request changes, but not what those changes might break elsewhere. The risk lives in the call graph, where it is invisible on a diff.
Resolve the real graph. Rather than text heuristics, TraceScope resolves SCIP symbol occurrences into a typed call graph, so call, import, and inheritance edges are accurate across files.
Trace impact deterministically. A reverse breadth-first traversal walks outward from the changed functions to everything that transitively depends on them, then scores each by depth, fan-in, and exports. Same diff in, same ranking out.
Make it a gate. The result ships as a CI gate with risk-tiered exit codes and a GitHub PR comment that flags the high-risk functions and their owners, so the warning lands where the review happens.
What I built
- Maps any pull-request diff to its changed functions and ranks the downstream code most likely to break.
- Derives the dependency graph by resolving SCIP symbol occurrences into typed cross-file call, import, and inheritance edges.
- Implements a deterministic impact traversal as a reverse BFS across the call graph, scoring risk by depth, fan-in, and exports.
- Ships as a CI gate with risk-tiered exit codes and a GitHub PR comment that flags high-risk functions and their owners.
Under the hood
The stack, the data structures, and the decisions that matter, for engineers.
Two graph backends, one model
The dependency graph is built two ways behind one interface. The SCIP backend decodes a Protocol Buffers index from scip-go and emits only EXACT edges; the parser backend builds the graph from go/ast plus go/types for Go and tree-sitter for JS, TS and Python, tagging uncertain edges HEURISTIC. Both produce the same serializable GraphData, two flat slices of nodes and edges with adjacency rebuilt per query so the model stays JSON-friendly, and a validate-scip command diffs the two by stable content signatures to quantify how far the heuristic graph drifts from the exact one.