Blast-radius impact analysis for code review, powered by the GitLab Knowledge Graph (Orbit).
orbit-impact is an MCP server that gives AI
agents the one question every reviewer actually asks β "if I change this, what
breaks?" β answered from a real call graph, not a text search.
It turns GitLab Orbit (the Knowledge Graph) into high-level impact tools, and ships with a GitLab Duo Agent Platform flow that posts the answer straight onto your merge request.
Built for the GitLab Transcend hackathon (Showcase track).
When you change a function, the dangerous question is who depends on it?
Today reviewers answer this with grep and vibes:
grepover-matches β every comment, string, and unrelated same-named symbol.grepunder-matches β it can't follow the call graph two hops out, so the scary indirect callers (the ones that actually break in prod) stay invisible.- LLM reviewers hallucinate dependents because they only see the diff, not the whole repository's structure.
Orbit already knows the truth: it parses your repo into a property graph with
real CALLS edges between definitions. But Orbit Local only exposes a raw
run_sql interface, and agents are bad at writing correct recursive graph SQL.
orbit-impact wraps Orbit's graph into five typed tools an agent can actually
use, with the recursive call-graph traversal baked in:
| Tool | What it answers |
|---|---|
analyze_diff |
Give it a raw MR diff β it resolves the exact changed definitions itself and returns a ready-to-post impact report. No hand-naming, no ambiguity. |
analyze_change |
Same report, but for symbols you name by hand. |
blast_radius |
Every definition that directly or transitively calls a symbol β the true impact set, with a risk rating. |
find_symbol |
Where is this symbol defined? (disambiguation) |
index_repo |
Build/refresh the Orbit graph for a repo. |
Because it reads Orbit's CALLS edges, the answer is exact: no false
positives from same-named symbols, and it follows the call chain as many hops as
you ask for.
A reviewer (or an agent reviewing an MR) already has the diff. analyze_diff
parses it, intersects the changed line ranges with Orbit's definition spans, and
picks the innermost enclosing definition for each change β so you analyze
exactly what the MR touched, pinned to one file and line. The name-ambiguity
problem just disappears.
Real example β the requests library. A diff that edits one line inside
Session.send:
git diff | orbit-impact diffResolved 1 changed definition across 1 file directly from the diff. Overall risk: π΄ high β 40 dependent definitions across 2 filesβ¦
The name send matches 5 definitions in requests (two in adapters.py,
two in sessions.py, one in a test). A plain grep send drowns you in matches;
naming the symbol by hand is ambiguous. The diff pins it to exactly
sessions.py:752 and walks the real call graph from there β catching indirect
callers many hops out that grep never shows, and flagging every test in the
radius π§ͺ.
orbit-impact-demo is a
tiny billing app whose tests cover the pricing layer but not the
order/invoice layer. Editing order_total and running orbit-impact diff:
Overall risk: π‘ medium β 3 dependent definitions across 2 files.
Dependent Location Hops create_invoiceshopfast/invoicing.py:61 checkoutshopfast/orders.py:121 monthly_statementshopfast/invoicing.py:122
β οΈ No test files appear anywhere in the blast radius β this change is effectively untested.
monthly_statement is two hops out β an indirect caller β and the tool proves
the change is untested. That's the answer reviewers actually need.
βββββββββββββββββββββββββββ
git repo β GitLab Orbit (local) β tree-sitter parse β DuckDB property graph
ββββββββββΊ `orbit index` β nodes: gl_definition / gl_file β¦
β `orbit sql` (CALLS) β edges: gl_edge (relationship_kind='CALLS')
βββββββββββββ¬ββββββββββββββ
β read-only SQL (stdin)
βββββββββββββΌββββββββββββββ
β orbit-impact (MCP) β recursive blast-radius + risk scoring
β index_repo find_symbol β
β blast_radius analyze_* β
βββββββββββββ¬ββββββββββββββ
β MCP tools
βββββββββββββΌββββββββββββββ
β GitLab Duo Agent /Flow β "Orbit Impact Analyzer" (AI Catalog)
β β posts MR comment β performs an action, not just chat
βββββββββββββββββββββββββββ
curl -fsSL "https://gitlab.com/gitlab-org/orbit/knowledge-graph/-/raw/main/install.sh" | bash
export PATH="$HOME/.local/bin:$PATH"
orbit --versiongit clone <this-repo> orbit-impact && cd orbit-impact
npm install
npm run buildorbit index /path/to/your/repo # or use the index_repo toolThe fastest way to feel it β pipe a diff straight in:
git diff main | node dist/index.js diff # β the Markdown impact report
node dist/index.js analyze order_total # by symbol name
node dist/index.js blast send src/requests/sessions.py
node dist/index.js helpAdd --json for structured output, --max-depth N to control traversal depth.
Claude Code / Cursor / any MCP client β add to your MCP config:
{
"mcpServers": {
"orbit-impact": { "command": "node", "args": ["/abs/path/orbit-impact/dist/index.js"] }
}
}GitLab Duo (IDE) β drop the same block into .gitlab/duo/mcp.json in your
project. See catalog/ for the published agent + flow definitions.
npm run smoke -- send # impact report for a symbol in the indexed repoanalyze_diff(diff, max_depth?)
The headline tool. Parses a unified diff, resolves the innermost enclosing
definition for every changed line (so a one-method edit in a big class reports
the method, not the class), and blast-radiuses each. Returns changed (the
resolved definitions), perSymbol, a rollup, and a markdown report ready to
post on an MR. No symbol names required, and no ambiguity β the diff pins each
change to one file and line.
blast_radius(symbol, file_path?, max_depth?)
Returns the resolved definition(s), the transitive caller set (impacted, each
with a depth), and a summary with a risk rating
(none/low/medium/high), files_touched, test_callers, and an
untested flag (callers exist but none live in test files). max_depth
defaults to 5 (max 25).
analyze_change(symbols[], max_depth?)
Runs blast_radius for each changed symbol, rolls them up, and returns a
markdown field ready to post as a merge-request comment.
| Env var | Default | Purpose |
|---|---|---|
ORBIT_BIN |
orbit |
Path to the Orbit binary. |
ORBIT_DB |
Orbit's default | Override the DuckDB graph path. |
- Impact is computed from Orbit's
CALLSedges, which are resolved per the languages Orbit supports (Python, TS/JS, Go, Ruby, Java, Rust, C/C++, C#, PHPβ¦). Dynamic dispatch and reflection aren't statically resolvable β same caveat as any call-graph tool. - Common symbol names can resolve to multiple definitions; the report flags this
as ambiguous and
file_pathdisambiguates. - Orbit Local indexes a single repo's code; cross-repo impact needs Orbit Remote.
MIT Β© 2026 Ali Zulfiqar. See LICENSE.