You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Version: graphifyy 0.9.19 · Windows 11 · Python 3.14 · TS/TSX corpus (~540 code files)
Symptom
After an incremental update (re-extracting only changed files, then build_merge), the graph silently loses every cross-file edge from a changed file to an unchanged file. In our repo a utility imported by ~every component (v2/src/lib/cn.ts, byte-identical import { cn } from "@/lib/cn" across files) dropped from ~100 edges to 4, and its neighborhood became a disconnected island. ~610 edges were lost in one update.
The failure signature is exact and makes the cause easy to confirm:
edge
outcome
changed → changed (case-detail.tsx → text.ts)
survives
unchanged → unchanged (Kbd.tsx → cn.ts)
survives
changed → unchanged (case-detail.tsx → cn.ts)
deleted
Root cause
extract() resolves cross-file imports only against the batch it is given (_augment_symbol_resolution_edges(paths, ...)). When the update batch contains only changed files, imports of unchanged files resolve to nothing — those edges are simply never produced.
build_merge's replace-on-re-extract then drops the changed file's old (complete) edge set and replaces it with the new (gutted) one.
Each behavior is individually reasonable; combined they guarantee edge loss on every incremental update of a codebase.
Minimal repro
frompathlibimportPathfromgraphify.extractimportextractfromgraphify.buildimportbuild_merge# A.ts imports { b } from "./B"r_full=extract([Path("A.ts"), Path("B.ts")], cache_root=None) # A→B edge presentr_incr=extract([Path("A.ts")], cache_root=None) # A→B edge absent (B not in batch)# build_merge([r_incr], graph_path=...) replaces A's edges → A→B edge deleted from graph.json
Suggested fix
Since AST extraction is deterministic and cheap (~30 s for 500 files, no LLM), the update path could always run structural extraction over the full corpus and be incremental only for semantic (LLM) extraction. Alternatively, _augment_symbol_resolution_edges could resolve against the existing graph.json node index in addition to the batch.
Secondary finding: dangling edges to never-created node ids
In a full, clean extraction of the same corpus, ~356 edge endpoints reference node ids that no node pass ever creates:
Barrel re-exports: imports of Button/Surface/Input through v2/src/design/primitives/index.ts emit edges to e.g. ..._primitives_index_button, but no such node exists (the components live in Button.tsx as ..._primitives_button_button).
Wrapper consts: re-exported consts like const Dialog = DialogPrimitive.Root get edges (..._ui_dialog_dialog) but no node.
Some of these ids also carry an absolute-path prefix (c_users_<user>_dev_<repo>_v2_src_...) that escaped the relativization/id-remap pass, so they can't even be suffix-matched to real nodes.
Happy to provide the full dangling-id list or run diagnostics against a branch.
I’m reproducing this against the current v8 head and investigating a focused fix that preserves changed-to-unchanged cross-file edges without forcing full-corpus re-extraction.
This looks fixed on the v8 branch by 4e7e6b1f (fix(extract,watch): C# assembly-aware partial merge, incremental edge preservation, extract crash recovery; bump to 0.9.33). Could a maintainer confirm and close?
Activity
aryanbonigala commentedon Aug 3, 2026
I’m reproducing this against the current v8 head and investigating a focused fix that preserves changed-to-unchanged cross-file edges without forcing full-corpus re-extraction.
omsenjalia commentedon Oct 18, 2026
This looks fixed on the
v8branch by 4e7e6b1f (fix(extract,watch): C# assembly-aware partial merge, incremental edge preservation, extract crash recovery; bump to 0.9.33). Could a maintainer confirm and close?