Skip to content

Analyze Change Impact

Before refactoring a function, use impact to understand the blast radius.

Basic Usage

axm-ast impact src/mylib --symbol my_function

Output:

๐Ÿ’ฅ Impact analysis for 'my_function' โ€” HIGH

  ๐Ÿ“ Defined in: core.utils (L42)
  ๐Ÿ“ž Direct callers (5): cli, core.engine, core.validator
  ๐Ÿ“„ Affected modules (3): cli, core.engine, core.validator
  ๐Ÿงช Tests to rerun (4): test_utils, test_engine, test_cli, test_validator
  ๐Ÿ“ฆ Re-exported in (2): mylib, core

Understanding the Score

Score Criteria
LOW 0-1 callers, no re-exports, no coupled files
MEDIUM 2-4 callers or 1+ affected modules or coupled files
HIGH 5+ callers, re-exported, many affected modules, or many coupled files

Find Callers First

For just the call-site list without full impact analysis:

axm-ast callers src/mylib --symbol my_function
๐Ÿ“ž 5 caller(s) of 'my_function':

  cli:89 in main()
    my_function(args)
  core.engine:42 in process()
    my_function(data)

Exclude Test Modules

Use --exclude-tests to focus the analysis on production code only, filtering out test modules from callers and affected modules:

axm-ast impact src/mylib --symbol my_function --exclude-tests

This is useful when you want a clean view of production blast radius without test files inflating the caller count or affected module list. Test files are still listed under test_files โ€” they are only removed from the callers/affected-modules sections.

JSON for CI

axm-ast impact src/mylib --symbol my_function --json
{
  "symbol": "my_function",
  "score": "HIGH",
  "definition": {"module": "core.utils", "line": 42, "kind": "function"},
  "callers": [{"module": "cli", "line": 89, "context": "main"}],
  "affected_modules": ["cli", "core.engine", "core.validator"],
  "test_files": ["test_utils.py", "test_engine.py"],
  "reexports": ["mylib", "core"],
  "git_coupled": [
    {"file": "src/mylib/config.py", "strength": 0.75, "co_changes": 6},
    {"file": "src/mylib/schema.py", "strength": 0.45, "co_changes": 4}
  ]
}

Git Change Coupling

impact enriches its analysis with git change coupling โ€” files that historically co-change with the symbol's file. This reveals hidden dependencies invisible to static analysis (e.g., config files, schemas, docs that always change together).

Formula: coupling(A, B) = co_changes(A, B) / max(changes(A), changes(B)) over the last 6 months of git history.

Only files with coupling strength โ‰ฅ 0.3 and โ‰ฅ 3 co-changes are included.

{
  "git_coupled": [
    {"file": "src/mylib/config.py", "strength": 0.75, "co_changes": 6}
  ]
}

Graceful degradation

If the project is not in a git repo or uses a shallow clone, git_coupled is simply an empty list โ€” no error is raised.

Import-Based Test Heuristic

When no test files reference a symbol by name (common for dataclasses, config models, or newly added symbols), impact falls back to an import-based heuristic: it scans tests/ for files that import the module containing the symbol.

Results appear in a separate key to distinguish them from direct matches:

{
  "test_files": [],
  "test_files_by_import": ["test_models.py", "test_config.py"]
}

When does the heuristic run?

Only when test_files is empty and the symbol has a known definition. If direct test matches exist, the heuristic is skipped to avoid noise.

Workspace: Cross-Package Impact

For uv workspaces with multiple packages, impact automatically performs cross-package analysis:

axm-ast impact /path/to/workspace --symbol ToolResult
๐Ÿ’ฅ Impact analysis for 'ToolResult' โ€” HIGH (workspace)

  ๐Ÿ“ Defined in: axm::tools.base (L15) [package: axm]
  ๐Ÿ“ž Direct callers (12): axm_mcp::server, axm_ast::tools.context, ...
  ๐Ÿงช Tests to rerun (5): test_tools, test_server, ...
  ๐Ÿ“ฆ Re-exported in (3): axm, axm_ast, axm_mcp

Automatic detection

No flag needed โ€” if the path contains a pyproject.toml with [tool.uv.workspace], workspace mode activates automatically.

Workflow: Safe Refactoring

  1. Check impact before changing a symbol:

    axm-ast impact src/mylib --symbol old_function
    
  2. Run only affected tests after your change:

    pytest tests/test_utils.py tests/test_engine.py
    
  3. Verify no callers remain if removing a symbol:

    axm-ast callers src/mylib --symbol old_function