Summary
TS/JS references to ECMAScript built-in globals (Date, and any other builtin whose casefolded name matches a user symbol) collapse onto a same-named user declaration, producing a huge false "god node". In a real 3,368-file corpus, a module-local, non-exported const DATE in one frontend file accumulated 469 false cross-file references edges (degree 472, betweenness 0.435, bridging ~130 communities) — every new Date() call site in the repo resolved to it.
Call edges are already guarded against this; the type/new-reference path is not.
Root cause
Two things combine:
-
normalize_id() casefolds (ids.py). The ECMAScript global Date and a user const DATE both normalize to date, so they are indistinguishable to the label/id index.
-
The reference-resolution path does not consult _LANGUAGE_BUILTIN_GLOBALS. Call edges do — every call-edge site guards on it, e.g.:
# extract.py:16730
if callee in _LANGUAGE_BUILTIN_GLOBALS:
... # skip
But ensure_named_node(name, line) (extract.py:3580, and its 6 sibling closures) has no such guard. When a new Date() / Date reference is walked, it creates a sourceless stub (id: date, label: Date) and draws a references edge (context="call", confidence=EXTRACTED, score 1.0). The corpus-level rewire/dedup step then collapses that stub onto the single real declaration whose norm-id matches — the user's const DATE.
Net: Date ∈ _LANGUAGE_BUILTIN_GLOBALS (so calls are skipped), yet the references/context="call" path still emits edges to a user symbol.
Proposed fix
Guard the reference path the same way call edges are guarded — the natural chokepoint is ensure_named_node: if name in _LANGUAGE_BUILTIN_GLOBALS, do not create a stub/edge (return a sentinel the callers skip, mirroring the existing if target_nid != func_nid skip pattern). Apply consistently to all ensure_named_node closures.
Optionally, as defense in depth, normalize _BUILTIN_NOISE_LABELS membership tests through normalize_id so casefold collisions (DATE vs Date) are still filtered from god-node reporting.
Environment
graphifyy 0.9.9
- Python 3.12.3, Linux
Summary
TS/JS references to ECMAScript built-in globals (
Date, and any other builtin whose casefolded name matches a user symbol) collapse onto a same-named user declaration, producing a huge false "god node". In a real 3,368-file corpus, a module-local, non-exportedconst DATEin one frontend file accumulated 469 false cross-filereferencesedges (degree 472, betweenness 0.435, bridging ~130 communities) — everynew Date()call site in the repo resolved to it.Call edges are already guarded against this; the type/
new-reference path is not.Root cause
Two things combine:
normalize_id()casefolds (ids.py). The ECMAScript globalDateand a userconst DATEboth normalize todate, so they are indistinguishable to the label/id index.The reference-resolution path does not consult
_LANGUAGE_BUILTIN_GLOBALS. Call edges do — every call-edge site guards on it, e.g.:But
ensure_named_node(name, line)(extract.py:3580, and its 6 sibling closures) has no such guard. When anew Date()/Datereference is walked, it creates a sourceless stub (id: date,label: Date) and draws areferencesedge (context="call",confidence=EXTRACTED, score 1.0). The corpus-level rewire/dedup step then collapses that stub onto the single real declaration whose norm-id matches — the user'sconst DATE.Net:
Date ∈ _LANGUAGE_BUILTIN_GLOBALS(so calls are skipped), yet thereferences/context="call"path still emits edges to a user symbol.Proposed fix
Guard the reference path the same way call edges are guarded — the natural chokepoint is
ensure_named_node: ifname in _LANGUAGE_BUILTIN_GLOBALS, do not create a stub/edge (return a sentinel the callers skip, mirroring the existingif target_nid != func_nidskip pattern). Apply consistently to allensure_named_nodeclosures.Optionally, as defense in depth, normalize
_BUILTIN_NOISE_LABELSmembership tests throughnormalize_idso casefold collisions (DATEvsDate) are still filtered from god-node reporting.Environment
graphifyy0.9.9