Summary
I'd like to contribute a graphify impact capability: git-diff blast radius with severity scoring. Given a diff, it maps changed lines onto graph nodes, traverses to find what the change actually reaches, and scores each hit HIGH/MEDIUM/LOW.
Before opening a PR I wanted to check whether you want it, and in what shape — you have a lot of open issues and I'd rather not drop 1k unsolicited lines on you.
What it does
$ graphify impact --diff HEAD~1 --top 3
Impact analysis: 3 affected node(s)
------------------------------------------------------------
[HIGH] main() (depth=1, via calls)
graphify/__main__.py:L2090
score=7 reasons: god-node, high fan-in (35)
[MEDIUM] test_install.py (depth=2, via imports)
tests/test_install.py:L1
score=4 reasons: god-node
[MEDIUM] FileChange (CHANGED, via changed)
graphify/git_risk.py:L44
score=3 reasons: high fan-in (10)
The pipeline is parse_git_diff → find_changed_nodes → blast_radius → score_severity → format_impact, with run_impact() as the one-call entry and get_diff_text() for working / staged / ref diff modes. Text and JSON output.
Severity blends traversal depth with graph position — god-node membership and fan-in raise the score, leaf nodes drop it. Weights live in a impact_config.toml so they're tunable rather than magic numbers, and every hit carries its reasons list, so a score is always explainable rather than an oracle.
Why it fits graphify specifically
It is built entirely on what you already have: graphify.affected.affected_nodes() does the traversal, load_graph() reads the graph. It adds no new dependency and changes no existing file — it's additive:
graphify/git_risk.py | 582 +++++++++
graphify/impact_config.toml | 41 ++++
tests/test_git_risk.py | 452 +++++++++
3 files changed, 1075 insertions(+)
git diff --stat v0.9.16..<branch> — the three files apply cleanly on top of v0.9.16 with zero conflicts, and all 30 tests pass against pristine v0.9.16.
The use case it serves: an AI coding assistant reviewing a change wants the affected subgraph, not the repo. query/path/explain answer "what is X"; this answers "what does this change touch", which is the question a diff raises and the graph is uniquely able to answer.
Open questions for you
- Do you want it in graphify at all, or would you rather it stay a downstream package importing
graphify.affected? Both work for us — we run it as a separate package today precisely because graphify.affected is a clean public seam.
- CLI wiring. The version we run predates your
dispatch_install_cli / dispatch_command refactor, so my __main__.py hook is stale. If you want the feature, tell me how you'd like impact registered in the current dispatch and I'll wire it your way rather than guessing.
.py-only today. Node matching is via source_file + line ranges from the graph, so it should generalise to any language your extractors cover, but I've only exercised it on Python.
Happy to open the PR if this is welcome. If you'd rather not carry it, no hard feelings — closing this is a perfectly good answer and I'll keep it downstream.
Version tested: graphify v0.9.16, Python 3.12, Linux.
Summary
I'd like to contribute a
graphify impactcapability: git-diff blast radius with severity scoring. Given a diff, it maps changed lines onto graph nodes, traverses to find what the change actually reaches, and scores each hit HIGH/MEDIUM/LOW.Before opening a PR I wanted to check whether you want it, and in what shape — you have a lot of open issues and I'd rather not drop 1k unsolicited lines on you.
What it does
The pipeline is
parse_git_diff→find_changed_nodes→blast_radius→score_severity→format_impact, withrun_impact()as the one-call entry andget_diff_text()forworking/staged/refdiff modes. Text and JSON output.Severity blends traversal depth with graph position — god-node membership and fan-in raise the score, leaf nodes drop it. Weights live in a
impact_config.tomlso they're tunable rather than magic numbers, and every hit carries itsreasonslist, so a score is always explainable rather than an oracle.Why it fits graphify specifically
It is built entirely on what you already have:
graphify.affected.affected_nodes()does the traversal,load_graph()reads the graph. It adds no new dependency and changes no existing file — it's additive:git diff --stat v0.9.16..<branch>— the three files apply cleanly on top of v0.9.16 with zero conflicts, and all 30 tests pass against pristine v0.9.16.The use case it serves: an AI coding assistant reviewing a change wants the affected subgraph, not the repo.
query/path/explainanswer "what is X"; this answers "what does this change touch", which is the question a diff raises and the graph is uniquely able to answer.Open questions for you
graphify.affected? Both work for us — we run it as a separate package today precisely becausegraphify.affectedis a clean public seam.dispatch_install_cli/dispatch_commandrefactor, so my__main__.pyhook is stale. If you want the feature, tell me how you'd likeimpactregistered in the current dispatch and I'll wire it your way rather than guessing..py-only today. Node matching is viasource_file+ line ranges from the graph, so it should generalise to any language your extractors cover, but I've only exercised it on Python.Happy to open the PR if this is welcome. If you'd rather not carry it, no hard feelings — closing this is a perfectly good answer and I'll keep it downstream.
Version tested: graphify v0.9.16, Python 3.12, Linux.