Skip to main content

AST call graph analyzer — what breaks if I change this file?

Project description

blast-radius

What breaks if I change this file?

blast-radius builds an incremental AST call graph for your Python project and answers the question instantly. It indexes imports and symbol definitions into SQLite (SHA-256 cached — only changed files are re-indexed) and resolves transitive dependents in milliseconds.

pip install blast-radius

PyPI version Python 3.10+ License: MIT CI


Quickstart

# Build the graph (incremental — only re-indexes changed files)
blast-radius --build

# What breaks if I change src/utils.py?
blast-radius --query src/utils.py

# Output a Mermaid diagram (renders in GitHub READMEs / PRs)
blast-radius --query src/utils.py --mermaid

# Watch mode — auto-rebuild on every save
blast-radius --watch

# Raw JSON output (pipe to jq, scripts, CI)
blast-radius --query src/utils.py --json

Terminal output (with Rich)

src/utils.py  ⚡ GOD NODE
├── 📄 src/api/routes.py
├── 📄 src/models/user.py
├── 🧪 tests/test_utils.py
└── 🧪 tests/test_api.py
  14 file(s) affected · in-degree 47 · 2 test file(s)

Install Rich for colored output:

pip install blast-radius[rich]

Mermaid diagram (renders in GitHub)

from blast_radius import build_graph, get_blast_radius, to_mermaid

build_graph()
result = get_blast_radius("src/utils.py")
print(to_mermaid(result))

Paste the output into any GitHub issue, PR, or README:

graph TD
    utils_py["src/utils.py"]
    utils_py --> routes_py["src/api/routes.py"]
    utils_py --> user_py["src/models/user.py"]
    utils_py --> test_utils_py["tests/test_utils.py"]
    style test_utils_py fill:#22c55e,color:#fff
    %% total affected: 3 | in-degree: 0

Python API

from blast_radius import build_graph, get_blast_radius, to_mermaid, watch

# Build the import graph (incremental — re-indexes only changed files)
n = build_graph()
print(f"{n} files indexed")

# Query blast radius
result = get_blast_radius("src/mymodule.py")
print(result["total_affected"])   # int
print(result["direct_dependents"])  # list of file paths
print(result["test_files"])         # files that start with tests/

# Mermaid output
diagram = to_mermaid(result)

# Watch mode (blocking — runs until Ctrl+C)
watch(interval=2.0)

Configuration

All paths are configurable — no hardcoded assumptions:

# Scan only specific directories
blast-radius --build --scan src tests

# Use a custom DB path (useful in CI)
blast-radius --build --db /tmp/my-graph.db

# Adjust watch poll interval
blast-radius --watch --interval 1.0

Or via Python API:

from pathlib import Path
build_graph(scan_dirs=["src", "tests"], db_path=Path("/tmp/my-graph.db"))
get_blast_radius("src/utils.py", db_path=Path("/tmp/my-graph.db"))

GitHub Action — comment blast radius on PRs

# .github/workflows/blast-radius.yml
name: Blast Radius
on: [pull_request]

jobs:
  blast-radius:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {python-version: "3.11"}
      - run: pip install blast-radius
      - name: Compute blast radius
        id: br
        run: |
          blast-radius --build
          echo "mermaid<<EOF" >> $GITHUB_OUTPUT
          blast-radius --query "${{ github.event.pull_request.head.sha }}" --mermaid >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
      - uses: marocchino/sticky-pull-request-comment@v2
        with:
          message: |
            ## Blast Radius

            ${{ steps.br.outputs.mermaid }}

Graphify god-node detection (optional)

If you have graphify installed and have run graphify update . in your repo, blast-radius will enrich results with transitive centrality data and flag god nodes (files imported by 30+ modules):

result = get_blast_radius("src/core.py")
if result.get("graphify", {}).get("god_node"):
    print("WARNING: this is a god node — change it carefully")

Installation

# Core (no dependencies)
pip install blast-radius

# With Rich colored output
pip install blast-radius[rich]

# With watchdog file watching (faster than polling)
pip install blast-radius[watch]

# Everything
pip install blast-radius[all]

Part of the LexiPro Sovereign OS

blast-radius is extracted from LexiPro — a local-first agentic OS where it powers the pre-edit safety gate: before any agent touches a kernel file, get_blast_radius() checks if it's a god node. Agents touching files with in-degree ≥ 30 must acquire a hard mutex first.


License

MIT — see LICENSE.

Built by Broken Arrow Entertainment LLC · Sovereign Intelligence Systems Group


OS Integration — God-Node Gate

blast-radius wires into pre-edit safety gates to enforce a hard stop before any agent touches a high-centrality file. This is the v9.6 integration pattern used in the LexiPro Sovereign OS:

# tool_hook_pipeline.py — _hook_guardian_path_guard (v9.6)
from blast_radius import get_blast_radius, rebuild_if_stale

async def pre_edit_gate(file_path: str) -> dict:
    rebuild_if_stale(max_age_seconds=300)
    br = get_blast_radius(file_path)

    # Hard block — god-node writes require explicit mutex acquisition
    if br.get("graphify", {}).get("god_node"):
        in_deg = br["graphify"]["in_degree_sum"]
        return {
            "allowed": False,
            "error": (
                f"GOD_NODE_PROTECTED: {file_path} has in_degree_sum={in_deg}. "
                f"Acquire hard mutex before editing god-node files."
            ),
        }

    # High blast radius — warn + emit contention pheromone
    if br["total_affected"] >= 10:
        emit_contention_pheromone(file_path, strength=br["total_affected"] / 50.0)

    return {"allowed": True, "warning": f"{br['total_affected']} dependents affected"}

God-node threshold: files with in_degree_sum >= 30 (via Graphify) require explicit mutex acquisition before any write. Without Graphify, the gate still warns on total_affected >= 10.

Pheromone broadcast: high-blast-radius edits emit a WRITE_CONTENTION signal to the NeuralBus so other agents observe the contested resource and can defer non-critical writes.

Run graphify update . in your repo root to generate graphify-out/graph.json and enable god-node detection.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

impact_radius-1.0.0.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

impact_radius-1.0.0-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file impact_radius-1.0.0.tar.gz.

File metadata

  • Download URL: impact_radius-1.0.0.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for impact_radius-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0025416539a7329f28f3e42181b70a080c2a0de1aeb5206b758fdbd8c66a36d3
MD5 03c77a7a79cfe3e363a2057a93093c6a
BLAKE2b-256 4ed476b6a4968181269de3057cd383329b922c7fd9243500a6ad306a44a8fd9c

See more details on using hashes here.

File details

Details for the file impact_radius-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: impact_radius-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for impact_radius-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cbbbf429d25a1b257ce5f509fc3519f4d9c6ecac68df5ae04b96e74a93b7c8b2
MD5 d3b70fc1e708d9a7da7dc71a1e07769d
BLAKE2b-256 738cf9cb08830de4d4f77350079d8f0b05a6f8a808296e04a36c3f46e36e3399

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page