feat: add deterministic Python call linking during graph merge#580
Open
ParitKansal wants to merge 1 commit into
Open
feat: add deterministic Python call linking during graph merge#580ParitKansal wants to merge 1 commit into
ParitKansal wants to merge 1 commit into
Conversation
Preserve import alias metadata in Python extraction and link unambiguous same-file and imported function calls when assembling the knowledge graph. Also handles from-import submodule calls and skips ambiguous bindings.
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.
Why this is needed
Understand Anything already extracts Python call sites (via tree-sitter) and builds a knowledge graph, but many obvious, structurally certain function-to-function relationships never become
callsedges.Today those edges mostly depend on the LLM file-analyzer noticing and emitting them. In practice that means:
Meanwhile the hard part of the data is already available: call-graph records and import bindings from structural extraction. We just were not turning unambiguous cases into graph edges during assembly.
This PR fills that gap for Python — only where the callee can be resolved uniquely — so the graph becomes a more reliable map of real call flow without inventing edges the linker cannot prove.
Problem
Two concrete gaps made deterministic linking impossible today:
Import aliases were dropped after extraction.
Patterns like
from pkg import run as executeorimport pkg.helpers as helperslost the local→original binding, so later stages could not resolve call sites that use the alias.No assembly-time call linker.
Extraction produced
callGraphdata, butmerge-batch-graphs.pynever converted unambiguous caller/callee pairs intocallsedges. Coverage depended on the LLM.Solution
Preserve import alias metadata in Python structural extraction / extract-structure results (
aliases?: Record<string, string>— local binding → original name). Non-aliased imports stay unchanged.Add a deterministic Python call linker in
merge-batch-graphs.pythat runs after node deduplication and before edge dedup /tested_bylinking.It creates a
callsedge only when:from module import name,as),import mod as m; m.fn()/import pkg.mod; pkg.mod.fn()),from package import helper; helper.fn());Safety rule: prefer a missing edge over a wrong one. Skipped (no edge) when:
obj.method()), builtins, wildcards, etc.This mirrors the existing philosophy of the deterministic
tested_bylinker: structural truth first, LLM for semantic judgment.What this does not try to do
Changes
packages/core/src/types.ts— optionalaliaseson import recordspython-extractor.ts— emit alias maps (null-prototype safe for keys like__proto__)extract-structure-result.mjs— forward imports + aliases into extraction artifactsmerge-batch-graphs.py—link_python_calls(), module path resolution, import rebinding, artifact loader, merge report counterstest_merge_batch_graphs.pyMerge report gains a section like:
How to review
link_python_calls/_active_python_import/_resolve_imported_python_targetsinmerge-batch-graphs.py— especially the “skip when ambiguous” paths.Test plan
Locally verified against the same commands as CI:
pnpm lintpnpm --filter @understand-anything/core buildpnpm --filter @understand-anything/skill buildpnpm --filter understand-anything-viewer buildpnpm --filter @understand-anything/core testpnpm testpython3 -m unittest tests.skill.understand.test_merge_batch_graphs tests.skill.understand.test_merge_subdomain_graphs tests.skill.knowledge.test_parse_knowledge_base -v__proto__alias keys, artifact load failuresSuggested reviewer check:
/understand --fullon any small/medium Python repo and confirm the merge report includesPython call linker:counts, and that a few known same-file / imported calls appear ascallsedges without dangling endpoints.Compatibility
callsedges are kept; linker only adds missing unique ones and dedupesHappy to adjust naming, weights, or report wording if maintainers prefer a different convention.