Follow-up to #2213. The target_file-stamp fix (shipped in 0.9.28) resolves the dangling absolute-id edges on incremental runs. This tracks the remaining, larger half.
Problem. Cross-file symbol resolution (_augment_symbol_resolution_edges and the raw_calls pass in extract()) resolves only against nodes extracted in the current batch (symbol_nodes / callable_nids are built from this run's nodes). On an incremental run that re-extracts only a changed file, its INFERRED cross-file edges to symbols defined in an unchanged neighbor (e.g. from .exc import BadData; raise BadData() where exc.py isn't re-extracted) are not regenerated, and the merge correctly drops the graph's old copies because the source file was replaced. Net: those INFERRED calls/imports edges disappear until a full rebuild.
This is pre-existing and affects BOTH the clustered and --no-cluster incremental paths identically (it is not specific to the #2169 change).
Fix direction (from the #2213 deep-dive). In extract(), parse the in-root import-target "context files" of the batch (the same set the #2169 remap loop already discovers) for resolution FACTS only: let their nodes/edges flow through _augment_symbol_resolution_edges / _merge_decl_def_classes / the id remap / callable_nids, then filter out every node and edge whose source_file is a context file before assembling the result, so ownership stays with the unchanged files and the merge carries their existing contributions forward untouched. One hop of context is enough; do not add context files' raw_calls.
Test. Two-module corpus (A relative-imports and calls a symbol of B) -> full extract -> touch A -> incremental extract -> assert the normalized edge set equals the full-scan edge set, for both --no-cluster and clustered.
Follow-up to #2213. The
target_file-stamp fix (shipped in 0.9.28) resolves the dangling absolute-id edges on incremental runs. This tracks the remaining, larger half.Problem. Cross-file symbol resolution (
_augment_symbol_resolution_edgesand the raw_calls pass inextract()) resolves only against nodes extracted in the current batch (symbol_nodes/callable_nidsare built from this run's nodes). On an incremental run that re-extracts only a changed file, its INFERRED cross-file edges to symbols defined in an unchanged neighbor (e.g.from .exc import BadData; raise BadData()whereexc.pyisn't re-extracted) are not regenerated, and the merge correctly drops the graph's old copies because the source file was replaced. Net: those INFERREDcalls/importsedges disappear until a full rebuild.This is pre-existing and affects BOTH the clustered and
--no-clusterincremental paths identically (it is not specific to the #2169 change).Fix direction (from the #2213 deep-dive). In
extract(), parse the in-root import-target "context files" of the batch (the same set the #2169 remap loop already discovers) for resolution FACTS only: let their nodes/edges flow through_augment_symbol_resolution_edges/_merge_decl_def_classes/ the id remap /callable_nids, then filter out every node and edge whosesource_fileis a context file before assembling the result, so ownership stays with the unchanged files and the merge carries their existing contributions forward untouched. One hop of context is enough; do not add context files'raw_calls.Test. Two-module corpus (A relative-imports and calls a symbol of B) -> full extract -> touch A -> incremental extract -> assert the normalized edge set equals the full-scan edge set, for both
--no-clusterand clustered.