-
Fix: live PostgreSQL introspection (
--postgres) now emits foreign-keyreferencesedges under a read-only role (#1746, thanks @rithyKabir). The FK query readinformation_schema.referential_constraints, which is privilege-filtered — a role with only SELECT sees zero FK rows while tables/views/routines still appear, so everyreferencesedge silently vanished. It now reads the world-readablepg_catalog.pg_constraint(keyed by oid, which also fixes same-named constraints on sibling tables cross-matching in the old name-based joins), preserving composite-FK column order viaUNNEST ... WITH ORDINALITY. -
Fix:
json_configno longer emitsimports/extendsedges to node IDs it never creates (#1764, thanks @oleksii-tumanov).package.jsondependencies andtsconfig.jsonextends/$reftargets produced edges whose endpoint node was absent, sobuild_from_jsonsilently dropped them (the "no matching node id" case is filtered out of real errors) — losing dependency/extends structure on two of the most common files in any JS/TS repo. The extractor now creates the referenced target as aconceptnode before adding the edge. -
Fix:
graphify updateno longer deletes semantic hyperedges on every run (#1755, thanks @oleksii-tumanov). The AST-only rebuild treated every rebuilt corpus file as grounds to evict hyperedges anchored to it, but the AST pass never re-emits hyperedges, so doc-sourced hyperedges (exactly what semantic extraction produces) were permanently lost on the firstupdateafter a full build — even a no-op run. Hyperedge eviction is now scoped to genuinely deleted (or symlink-outside) sources, mirroring node/edge handling; replacement-by-id and dangling-member cleanup are unchanged. -
Fix: Java member calls resolve against the receiver's declared type instead of a bare method-name match (#1696/#1697, thanks @oleksii-tumanov).
gw.charge()wheregw: PaymentGatewaynow binds toPaymentGateway.charge, not a same-namedAuditLog.chargein another file. Explicit-type receivers andthisare exact; current-class fields, method parameters, and explicitly-typed locals resolve via a method-scoped type table; a missing, ambiguous, inherited, or chained receiver is skipped rather than guessed (same god-node guard as the C#/Swift/Ruby resolvers). Fully-qualified and nested-type receivers are deferred (they need package/nesting-aware type identity). -
Fix: output/cache artifacts no longer land in the scanned corpus or CWD when
--out/--graphpoint elsewhere (#1747, thanks @bbqboogiedwonsen).extract <corpus> --out <dir>correctly wrote the graph to<dir>butdetect()'s word-count/stat-index cache still created a straygraphify-out/cache/inside the corpus (it uses the scan root); it now honors the--outdir via a threadedcache_root. Andcluster-only --graph <elsewhere>/graphify-out/graph.jsonwroteGRAPH_REPORT.md/labels/analysis/re-clustered graph to the CWD instead of beside the input; it now writes beside--graphwhen that graph lives in agraphify-out/dir, while still restoring into the CWD for an archivedbackup/graph.json(#934). -
Fix:
imports/referencesedges no longer bind across a language boundary (#1749, thanks @philberndt). The spec already forbids cross-languagecalls, but an unresolved Pythonimport timecould still resolve by bare stem onto asrc/time.tsfile node — welding a polyglot repo's halves together at a phantom edge (in the reporter's repo, 3 such edges were the only thing bridging 2409 Python nodes to 1403 TS nodes, inflatingtime.tsbetweenness ~90x and making it the #1 "god node"). The build-time cross-language guard now coversimports/imports_from/referencesin addition tocalls, dropping an edge only when both endpoints are known code languages of different interop families (so a config/manifest → code reference is untouched). -
Fix: files whose extractor bailed out for a missing optional dependency no longer vanish without a trace (#1745, thanks @rithyKabir).
.sqlfiles (and other extra-gated languages) have a dispatch entry, so the #1689 no-extractor warning can't fire, andextract_sqlreturns an error result whentree-sitter-sqlis absent, so the #1666 zero-node warning skips it too — the graph built "successfully" while an entire SQL corpus contributed nothing.extract()now surfaces these grouped by extension, naming the extra that restores the language (e.g.pip install "graphifyy[sql]"). -
Fix:
build_from_jsonis deterministic across process runs again (#1753, thanks @erasmust-dotcom). The ghost-node merge iteratedset(G.nodes()), so which node survived a(basename, label)collision depended on CPython's per-process string-hash seed — rebuilding the same extraction JSON in a fresh process could silently pick a different canonical id (breaking the cluster→relabel workflow with aKeyErroron an id that vanished). The Pass 1/Pass 2 loops now iterate in sorted order. Additionally, two non-AST (semantic) nodes sharing a key but from different files are now treated as distinct concepts and both survive (mirroring the AST/AST ambiguity guard #1257) instead of one arbitrarily merging away; a genuine same-file duplicate still collapses. -
Fix: a Java field/parameter/return-type reference to a class whose simple name is shared by two modules no longer dangles on a sourceless phantom node (#1744, thanks @aviciot). Both same-named classes already survive as distinct path-scoped nodes, but the cross-module
referencesedge was left pointing at a bare no-source stub because_resolve_java_type_referencesre-pointedimplements/inherits/importsbut notreferences— so a query about the referenced class could miss it. The Java resolver now disambiguatesreferencesby the importing file'simportstatement (falling back to same-package), mirroring the C# resolver, and drops the orphaned phantom.