← Back to work

Mar 2026 - May 2026 · Solo build

TraceScope

A Go CLI that predicts the blast radius of any pull request.

GoSCIPStatic AnalysisCI/CD

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.

Built with
Go 1.25CobrazerologSCIP (scip-go)tree-sittergo/ast + go/typesProtocol Buffersgo:embedD3 v7gorilla/mux
01 / 06

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.