feat: persistent cross-file edge overlays#357
Open
chris-asmussen wants to merge 1 commit intosafishamsi:v4from
Open
feat: persistent cross-file edge overlays#357chris-asmussen wants to merge 1 commit intosafishamsi:v4from
chris-asmussen wants to merge 1 commit intosafishamsi:v4from
Conversation
Add cross_edges.json support so manually curated or LLM-generated cross-file edges survive AST-only rebuilds. This addresses the problem where _rebuild_code() drops edges between two code nodes, leaving multi-file codebases with hundreds of isolated 1-node communities. Changes: - watch.py: inject cross_edges.json edges into _rebuild_code() after semantic preservation, skipping stale/duplicate edges - __main__.py: add `graphify edges` CLI with list/add/remove/prune subcommands for managing cross-file edges - tests/test_cross_edges.py: 13 tests covering rebuild injection, staleness handling, malformed JSON resilience, and all CLI commands Closes safishamsi#298
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cross_edges.jsonsupport so manually curated or LLM-generated cross-file edges survive AST-only rebuilds (_rebuild_codeinwatch.py)graphify edgesCLI withlist,add,remove, andprunesubcommands for managing cross-file edgesProblem
_rebuild_code()preserves semantic nodes/edges where neither endpoint is a code node, but drops cross-file edges between two code nodes. This means community detection produces hundreds of isolated 1-node communities for multi-file codebases in Ruby, TypeScript, Go, etc. where AST extraction can't resolve cross-file calls.Approach
A persistent
graphify-out/cross_edges.jsonoverlay file stores edges that should survive rebuilds. After the existing semantic preservation logic in_rebuild_code(), the new injection block merges these edges into the result dict -- skipping edges where either node no longer exists and deduplicating against edges already present from AST extraction.The
graphify edgesCLI provides CRUD operations for managing the overlay without hand-editing JSON.Complements #315 (global symbol table) -- the symbol table handles statically resolvable calls, while this overlay handles framework conventions (Rails
has_many, Django ForeignKey), dynamic dispatch, and user knowledge about architectural intent.Closes #298
Test plan
test_preserves_cross_edges-- cross edges with valid nodes are injectedtest_skips_stale_cross_edges-- edges referencing deleted nodes are silently skippedtest_no_cross_edges_file-- rebuild works identically without cross_edges.jsontest_malformed_cross_edges-- invalid JSON does not crash rebuildtest_no_duplicate_injection-- existing AST edges are not duplicatedtest_edges_add/test_edges_add_duplicate-- CLI add with deduptest_edges_remove/test_edges_remove_not_found-- CLI removetest_edges_list_empty/test_edges_list_shows_edges-- CLI listtest_edges_prune-- removes edges where nodes no longer exist in graphtest_edges_help-- usage output on missing subcommand