Files
graphify/tests
Lenin Herrera a67e7060b0 fix(build): ghost-merge nodes whose source_file is the referencing doc, not the referenced file
The #1145-extended ghost-merge (build_from_json) keys exclusively on
(source_file, label). When a semantic pass reads a document that only
*mentions* a real file by name (a saved graphify-out/memory/*.md query
answer, a runbook like "see App.tsx"/"backup.sh does X"), the new node
it mints gets source_file = the document being read, not the file
actually named in the prose. That wrong source_file means the key can
never match the real AST node's, so the ghost survives every rebuild.

Add a conservative label-only fallback pass reusing the existing
_is_file_node_label() predicate (already used for file-node label
disambiguation) against every AST file-self node collected in Pass 1.
Only remaps when the match is unique across the graph — 0 or 2+
candidates (e.g. two different index.ts files) are left alone, same
conservatism the existing (source_file, label) key already applies via
_loc_collisions.

Verified against a real ~4600-node project graph: 10 long-standing
ghost nodes removed across two unrelated documents (a memory query
file and an ops runbook), confirming this is a general failure mode of
the "document mentions a file by name" pattern, not a narrow edge
case. Both hyperedges that had cited the phantoms now correctly cite
only real, AST-backed nodes.

Fixes #3344
2026-09-04 21:17:37 -05:00
..