Releases: Graphify-Labs/graphify
Releases · Graphify-Labs/graphify
Release list
v0.9.76
More language-structure coverage, resolution/dedup correctness, and a security fix for the git-hook installer.
- Feature: four more language extractors gained type coverage from @rajatnagda45 — Zig tagged-union variants (
union(enum)) emit a node per variant with acase_ofedge (#4050), C++unionspecifiers are extracted as class-like type nodes with their members (#4052), VB.NET enum members link viacase_ofinstead ofcontains(which also stops a member named like a type binding as a constructor) (#4054), and Pascal enumerated types and their values are extracted (#4056). - Feature: three Scala type-reference fixes shipped together earlier in the day are followed here by @Faisal-Fayaz's extractor hardening — graphify now stops walking JSON Schema files as config manifests, keyed on a
$schemadeclaration plus a structural marker ($defs/definitions/$id) so real manifests that merely reference a schema are unaffected (#4048, #2255). - Fix: Elixir
import/usecall scoping is now per-module rather than per-file, so an unqualified call in one module no longer resolves against another module's imports in the same file (#4058, refines #4015). - Fix: track calls to external Python modules — a
module.func()call to a plainly-imported dependency now records acallsedge to that module, fail-closed (receiver-shadowing and non-unique bindings are skipped, builtins and unresolved locals are never fabricated) (#4043, #3793, thanks @oleksii-tumanov). - Fix: Svelte files now feed only their
<script>blocks to the AST pass (masking the template and style, preserving line numbers), so the markup no longer produces a parse error that dropped every symbol (#3984, #3928, thanks @Agnik47). - Fix: PHP language constructs (
isset,empty,list,eval, ...) no longer bind as calls to a user method that happens to share the name (#3975, #3830, thanks @Cintu07). - Fix: an unresolved base class whose only same-named definition lives in another language is kept unresolved instead of binding across languages; same-language cross-file inheritance still resolves (#4068, thanks @SrijanSriv).
- Fix: unstamped document nodes with the same heading in different files are no longer merged together during dedup; same-file document twins still merge (#4065, thanks @SrijanSriv).
- Fix:
graphify pathand the MCPshortest_pathtool resolve apath::symbolor raw node-id endpoint to the exact node before falling back to fuzzy scoring, and refuse an ambiguous endpoint instead of silently picking one (#3935, #3913, thanks @bercedev). - Fix: cross-repo resolver confidence scores are snapped to the canonical INFERRED rubric (a label-only change; no edge is added, dropped, or reclassified) (#4046, #4045, thanks @DeepanshuPal).
- Fix:
graphifyno longer indexes its own installed skill folders and whole-written rule/hook files when scanning a project, keyed on the exact install locations so a user's owngraphify-named folder is not skipped (#4062, #4057, thanks @Mpasha17). - Fix: the suggested questions in the analysis output are diversified across signal types with a round-robin, so one category no longer crowds out the others (#3972, #3849, thanks @azizur100389).
- Security:
graphify hook installrefuses acore.hooksPaththat resolves outside the repository (resolving both sides, symlink-safe), falling back to the in-repo.git/hooksinstead of writing an executable outside the checkout; legitimate in-repo custom hook paths, linked worktrees, and submodules still work (#3919, #3869, CWE-22, thanks @nothariharan). - Chore: the PyPI package page now points Homepage at graphify.com and adds a Documentation link to docs.graphify.com; Repository and Issues stay on GitHub (#4069, thanks @SyedFahad7).
v0.9.75
Intra-class call binding across five languages, new language-structure coverage, and a batch of resolution/build/cache fixes.
- Feature:
self/this/supermember calls now bind to the caller's own class chain instead of the file-wide last-definition, across Python (self./cls./super(), nearest ancestor in the in-file MRO) (#4011), JavaScript/TypeScript (this.m()to the caller's own class;super.m()fails closed since theextendschain is not known at that pass) (#4012), Swift (self/super, class vs struct/extension aware) (#4030), and Ruby (self-sends within the class chain, complementing the paren-less self-send extraction from 0.9.74) (#4031) — all thanks @Cintu07. Multiple-inheritance ties and unknown/external ancestors fail closed (no fabricated edge). - Feature: four more language extractors gained structural coverage from @rajatnagda45 — Zig error-set declarations and their members (
case_of) (#4025), PHP enum cases (pure and backed) withcase_ofedges (#4026), Elixirdefmacro/defmacrop/defguard/defguardpdefinitions (#4027), and Rustmacro_rules!definitions with local invocation resolution (std macros likeprintln!fail closed, no fabrication) (#4028). - Feature: three Scala type-reference fixes from @Faisal-Fayaz — file-scope
val/vartype annotations now emitreferencesedges (#4036, #2054),typealias/definition right-hand sides are walked (includingopaque typeand match types) (#4037, #2049), and context bounds (def f[A: Ordering]) resolve toreferencesedges (#4038, #2046). - Feature: single-implementer interface dispatch was lifted into a language-agnostic core (#4034) and reused to dispatch a Swift protocol requirement to its sole conformer (INFERRED), failing closed on 2+ conformers (#4035) — thanks @GAURAV-1313.
- Feature: Elixir unqualified calls now resolve to functions brought in by
import/use, scoped per module and fail-closed when no in-scope module defines the name (fixes a large god-node from corpus-wide bare-name binding) (#4015, thanks @Ayushraj06-bit). - Feature: a bash script's invocation of another script through a non-shell interpreter (
python3 build.py,node build.js,"$PYTHON" stage.py) is now recorded as aninvokesedge; a$VAR/path command word is not mistaken for an interpreter (#4007, thanks @ayushcodes10). - Feature: Dart
partfiles keep their own file node linked to the library (#4013, #4008), and a configurable import/export (import 'a.dart' if (...) 'b.dart';) now links every URI branch, not just the default (#4003, #4002) — thanks @brlumen. - Fix: C# partial-class merging no longer drops recursive/intra-class
callsedges; one splitpartial classanywhere in a repo used to erase every recursive self-loop graph-wide (#4017, thanks @rohit-jsfreaky). - Fix:
graphify path(CLI and the MCPshortest_pathtool) now routes through acontainsedge back out to a symbol's file, so a cross-file dependency that must pass through a shared symbol is found instead of reporting no path (#4004, #3878, thanks @ayushcodes10). - Fix: the AST cache rebinds its stat index when a later call names a different cache root, so a multi-project process writes each root's
stat-index.jsonwith only its own files instead of pooling them into the first root's file (#4005, #3989, thanks @ayushcodes10). - Fix:
merge-graphs --previous <merged-graph.json>restores the previous merged community assignment by node id, so cluster/label reuse stays stable across re-merges; a malformed--previousfile now errors cleanly instead of crashing (#4006, #3858, thanks @ayushcodes10). - Fix:
cluster-only/labelno longer drop parallel edges (two different relations between the same pair) when reloading and rewriting a graph; preserved links track node-id remaps so none are silently dropped on a legacy graph (#4010, #3999, thanks @ayushcodes10). - Fix: the Ollama
num_ctxsetting is merged intoextra_bodyinstead of replacing it, so aGRAPHIFY_DISABLE_THINKINGbody set on the same backend is no longer silently clobbered (#4029, #3988, thanks @Agnik47). - Fix: the hook-guard reminder names the effective
graph.jsonpath whenGRAPHIFY_OUTis customized, instead of always naming the defaultgraphify-out/graph.json(#4042, #4040, thanks @DeepanshuPal). - Fix:
graphify extractrefuses to overwrite an existing graph with a dedup-shrunk one unless--allow-dedup-shrinkis passed; the refusal reports the actual number of nodes dedup merged (#4014, #3774, thanks @SrijanSriv). - Feature: extraction warns once when a cleanly-parsed code file yields no symbols beyond its own file node (often a data literal), while staying silent on empty/whitespace-only files, no-extractor languages, and intentionally-skipped data (#4009, #3946, thanks @ayushcodes10).
v0.9.74
- Feature: four more language extractors gained structural depth. Ruby paren-less self-sends (
do_thingwith no receiver or parens) are now captured as calls, with a local-variable/parameter/block-parameter in scope correctly suppressing the call (fail-closed, no fabrication) (#3960, thanks @rajatnagda45). TypeScriptabstractmethod signatures in an abstract class are now extracted as callable method members and resolve as call targets (#3961, thanks @rajatnagda45). Scala deferred (abstract) method declarations in traits and abstract classes (def foo: Int, no body) are now extracted as methods (#3962, thanks @rajatnagda45). C++ a member-function declaration inside a class (void foo();, defined out-of-line) is now classified as a method rather than a field, including pure-virtual,const, operator, and destructor forms; real data members stay fields (#3963, thanks @rajatnagda45). - Fix: a Rust type used before it is declared in the same file now resolves to its local declaration instead of fabricating an external stub; resolution is a two-pass, order-independent scan, and a forward reference whose name collides with another same-id item is kept unresolved (fail-closed) (#3903, #3782, thanks @Yyunozor).
- Fix: Rust prelude types (
Option,Result,Vec,String,Box,Rc,Arc,HashMap, and friends) no longer accumulate spurious in-degree and surface as god nodes that distort community detection and ranking; they are filtered at extraction time, and a type the file defines itself is kept. Tuple-struct and unit-struct construction (ClientId(id)) is reclassified from acallsedge to areferences/constructoredge (#3973, thanks @liam-mcelhaney122). - Fix: an Obsidian-style wikilink to a note whose name contains a dot (
[[v1.2 release]],[[note.en]]) now resolves instead of being dropped by a premature extension strip; plain, explicit-extension, anchor, and alias wikilinks are unchanged, a literal indexed file beside the link keeps precedence, and a genuinely missing target is still not fabricated (#3905, #3904, thanks @Yyunozor). - Fix: a constructor call whose target is a same-file annotation stub (a source-less node minted by an earlier annotation or generic-argument reference) is kept for cross-file resolution and binds to the real definition when there is import or namespace/using-scope evidence, instead of being dropped; a genuinely external unresolved name is still not fabricated (#3901, thanks @bercedev).
- Fix: the CLI hook-guard that protects graphify's own output directory now resolves paths and checks real containment instead of substring matching, so a sibling directory sharing a name prefix (
artifacts/graphify-notesvsartifacts/graphify) is no longer wrongly treated as inside the output dir; symlinks,.., relative paths, and case-insensitive filesystems are handled (#3964, #3959, thanks @shobhitagnihotri69). - Fix: when resolving an import of a workspace package that ships both a source entry and a built dist, the graph now prefers the source file (so edges point at authored code) and falls back to the built artifact only when no source entry exists, generalizing the existing source-over-dist preference from the
exportspath to the legacymain/modulefields (#4000, #3834, thanks @Adityakk9031). - Feature: Verilog header files (
.vh) are now detected and extracted through the same tree-sitter-verilog grammar as.v/.sv, so macros, parameters, and modules declared in headers are captured (#3983, thanks @oleksii-tumanov). - Fix: an incremental update no longer drops a hyperedge from an untouched file when a re-extracted file emits a hyperedge with the same id; carried hyperedges are now keyed by
(id, source_file)so a same-id edge from a different, unchanged file is preserved while a genuine same-file re-emit still replaces (#3997, #3981, thanks @Ayushraj06-bit). - Feature: Kotlin class-literal references in annotation arguments (
@ManyToOne(targetEntity = Customer::class)) are now extracted as attribute references to the referenced type (#3965, #3835, thanks @hopstreax). - Fix: Lua colon-method calls (
obj:method(),self:method()) now resolve to the table-qualified method definition; a non-selfreceiver fails closed with no cross-file member fabrication (#3994, thanks @rajatnagda45). - Feature: Erlang local fun references (
fun Name/Arity, as inlists:map(fun helper/1, L)) are now recorded asindirect_calledges to the arity-matched local function; remotefun Mod:Name/Arityand anonymous funs are left as-is, and an undefined or arity-mismatched local fails closed (#3996, thanks @rajatnagda45). - Fix: C# null-conditional member calls (
receiver?.Method()) now resolve through the same typed-receiver path asreceiver.Method(), including the call-site generic-argument walk; chained and element-access forms fall through to bare-name resolution with no fabrication (#3976, #3797, thanks @Cintu07).
v0.9.73
- Feature: enum members are now extracted as nodes with
case_ofedges in four more languages — Rust enum variants (#3938), Zig enum members (#3940), C++enum/enum classenumerators including nested enums (#3939), and Scala 3 enum cases plus their methods (#3937) — all thanks @rajatnagda45. - Fix: Java calls to inherited methods and
super.method()now resolve to the declaring ancestor (walking theinheritschain, nearest declaration wins), instead of dangling; an unknown/external or ambiguous ancestor fails closed (#3932, thanks @janwaleed09). - Fix: semantic extraction warns once when a file exceeds the 20,000-character cap and is truncated, instead of silently dropping the tail (#3923, #3773, thanks @AK-Lmn).
- Feature: Solidity file-level free functions (Solidity 0.7+, declared outside any contract) and their calls are now extracted (#3906, thanks @rajatnagda45).
- Fix: VB.NET type/module-qualified calls (
MyModule.DoThing(),MyClass.SharedMethod()) resolve to the target method; value-receiver andMyBase.calls fail closed (#3909, thanks @rajatnagda45). - Fix: Astro files are parsed correctly — only the frontmatter and
<script>blocks are fed to the AST pass (the HTML template no longer produces parse errors), with line numbers preserved (#3902, thanks @Bosken85). - Fix: the "surprising connections" cross-repo/directory bonus now matches the reason it prints — two files at the scan root no longer falsely score as crossing repos (#3934, thanks @neo1777).
- Fix: under
--exclude-hubs, a node whose only neighbours are excluded hubs is kept with its hub's community instead of being severed into a singleton; the default path is unchanged (#3933, thanks @neo1777). - Perf: the Neo4j/FalkorDB
--pushpath creates a per-label id index before the node upsert loop, fixing the throughput collapse on large graphs (#3957, thanks @Yi-111-a). - Fix: community labeling keeps the labels it already named when a nested retry fails to parse, instead of discarding the whole batch (#3956, thanks @Vikram-Lex).
- Fix:
graphify hook statusreports hooks written by an older release as out of date (rungraphify hook installto refresh) (#3951, #3771, thanks @bercedev). - Fix: a Rust virtual-workspace-root
Cargo.toml(only[workspace], no[package]) is treated as skipped-by-design rather than warned as zero-node (#3930, #3910, thanks @Adityakk9031). - Fix: when the instructions file (
CLAUDE.mdetc.) is a symlink, install reports the real target it wrote to, and uninstall keeps the symlink (strips only the graphify section) instead of deleting the link (#3950, #3953, #3805, thanks @bercedev).
v0.9.72
- Feature: after a package upgrade,
graphifyrefreshes stale installed skills automatically (theSKILL.md+ references sidecar it manages) so the version-mismatch warning no longer requires a manualgraphify install. It runs on any non-install CLI command when a skill is stale, backs up local edits toSKILL.md.bak, never touches your marker-boundedCLAUDE.md/AGENTS.md/GEMINI.mdsections, and can be disabled withGRAPHIFY_NO_AUTO_REFRESH=1(#3895, #1805, thanks @bercedev). - Fix:
graph.html's Node Info panel now shows the real Type/Source/Community for each node instead of "Type: unknown / Source: -" (the panel read field names that did not match the emitted node schema); aggregated community nodes show a member count (#3918, #3914, thanks @hopstreax). - Fix: a Kotlin class property that is both annotated and has an inferred type (
@Volatile var x = 0) no longer crashes extraction with anUnboundLocalErrorthat dropped the whole file (#3915, thanks @nothariharan; #3899, thanks @harshaygadekar; #3884). - Fix: SQL DDL that appears before a PostgreSQL
DO $$ ... $$block is now extracted — the block node the parser produces for that span is walked instead of skipped (#3900, thanks @bercedev). - Fix: Razor extracts C# members from
@functions { }blocks (classic Razor Pages/MVC), not only Blazor@code { }blocks (#3908, thanks @rajatnagda45). - Feature: Blade templates now link a view to the layout it
@extends(#3907, thanks @rajatnagda45). - Fix: resolving an imported module name no longer binds to a same-named contained symbol (a class/module member); only genuine top-level module/file nodes are considered (#3898, #3887, thanks @harshaygadekar).
- Fix:
docxsidecar conversion now keeps tables in their document position (instead of dumping them after all prose) and reads all text, including tracked insertions, content controls, and text boxes, by walking the document body in order (#3833, thanks @L4XB). - Fix: label/signature sidecars are now published atomically and in a safe order (labels before signatures), so an interrupted rebuild can no longer leave stale community labels for a clustering that no longer exists (#3853, thanks @shashank-100).
- Fix: the markdown wikilink index respects
.graphifyignore/.gitignore/--excludeand resolves an article-namedindexwithout overwriting the generatedindex.mdhub — two independent wiki/markdown fixes (#3818, thanks @breken-ai; escaped-alias parsing[[target\|alias]]#3772, thanks @zagushka). - Fix: the community listing in
GRAPH_REPORT.mdreuses the shared real-node filter, sorationale/conceptnodes no longer inflate a community's node count or leak into the listing (#3836, #3794, thanks @ayushcodes10). - Fix: extraction now warns once (not per file) when a PDF is encountered but the
pdfextra (pypdf) is not installed, instead of silently producing no text (#3710, #3702, thanks @shobhitagnihotri69). - Chore:
graphify/graphify --helpnow shows the logo banner and a link to the hosted platform at app.graphify.com.
v0.9.71
- Feature: SQL
CREATE TRIGGERstatements are now extracted and linked to their table (ON <table>), includingOR REPLACE/OR ALTER,INSTEAD OF, and proceduralBEGIN…ENDbodies that previously landed in a parser-error node and were dropped (#3863, thanks @rajatnagda45). - Feature: Groovy
enumdeclarations and their constants are extracted, with members linked to the enum viacase_of(#3861, thanks @rajatnagda45). - Fix: R class definitions created via a namespace-qualified constructor (
R6::R6Class,methods::setRefClass) are now recognised, so the class body and its methods are no longer dropped (#3864, thanks @rajatnagda45). - Fix: R6 intra-class calls through
self$method()andprivate$method()now resolve to the sibling method instead of dangling;super$is left unresolved (single-file dispatch is not visible) (#3865, thanks @rajatnagda45). - Fix: the markdown wikilink index now respects
.graphifyignore/.gitignore/--exclude— it no longer descends huge ignored trees when building the[[link]]index, and a wikilink can no longer resolve into an ignored file (#3826, #3822, thanks @Abhirup0). - Fix: manifest re-anchoring keeps a foreign-platform key in its own path syntax (a POSIX key on Windows, a
C:\/UNC key on POSIX) usingposixpath/ntpathrather than the host's rules, fixing separator corruption introduced by the 0.9.69 portability work (#3879, thanks @Dakshcore). - Fix: normalizing a Twitter/X URL for the oEmbed fetch rewrites only the host, so
x.com/twitter.comappearing in the path or query is no longer corrupted (#3880, thanks @Dakshcore). - Chore:
graphify installshows the refreshed graphify logo banner (#3892, thanks @rajarshidattapy).
v0.9.70
- Security: the Fortran capital-F cpp step no longer allows an untrusted
.F/.F90source to read arbitrary host files.-nostdinc -I /dev/nulldid not stop cpp from resolving absolute (#include "/etc/passwd") or traversing (#include "../../../secret") includes, which inlined host-file contents intograph.json/GRAPH_REPORT.mdand the LLM context on the default offline path. Every#includedirective is now stripped before preprocessing and the source is fed to cpp on stdin; macro expansion is preserved (GHSA-pcc4-rvhr-2pr8, CWE-22/73/200). - Security: the Aider/Devin monolith
--watchsnippet no longer interpolates the agent-substitutedINPUT_PATHinto a shell command — it now reads the trustedgraphify-out/.graphify_rootwritten in Step 1, closing the last instance of the shell-injection class from #3642 (#3852, #3844, thanks @hopstreax). - Security: Terraform secret redaction now also covers a
valuepaired with a secret-namednamein name/value pair lists (environment = [{ name = "DB_PASSWORD", value = "…" }], ECSvalueFromincluded), where the sensitive signal is the siblingnameliteral rather than a key (#3870, #3787, thanks @breken-ai). - Fix:
graphify watchnow serializes concurrent rebuilds on Windows viamsvcrtbyte-range locking instead of a no-op lock, closing a WinError 32 race between overlapping rebuilds; the POSIXfcntlpath is unchanged (#3883, #3881, thanks @harshaygadekar). - Fix: C# type references no longer collect a named tuple's element names as type references (
(int Count, string Name)recorded a bogus ref toCount/Name); only the element types are referenced (#3877, #3796, thanks @KaiyiQuan). - Feature: JSX component usage now produces
callsedges —<MyButton/>and<_Row/>link to the component, while lowercase DOM tags (<div>) and member tags (<Nav.Item>) are conservatively skipped, so React component graphs capture render relationships (#3855, #3854, thanks @sinangumuskabak-sys). - Fix: absolute Python imports that spell the scan root's own nested namespace (
from Company.Apps.Team.lib import xwhen the scan root isTeam/) now resolve to the local module by projecting the namespace prefix onto the scan-root layout (#3867, #3843, thanks @nikhilsaxena04).
v0.9.69
- Feature: five language extractors gained structural depth — OCaml classes now emit their methods (via the
methodrelation) and instance variables (#3838, thanks @rajatnagda45); Elixirdefprotocol/defimplare extracted as containers holding their functions, with a same-fileimplementslink (#3839, thanks @rajatnagda45); Fortran derived-typecontainsblocks link type-bound procedures to the type, resolving the=> impltarget (#3840, thanks @rajatnagda45); Julia macro definitions and@enumtypes are extracted, including valued (red = 1) and typed (Color::UInt8) enum forms, with members using thecase_ofrelation (#3841, thanks @rajatnagda45); Kotlin annotations (class/function/property, use-site targets) andval/varprimary-constructor properties now produce edges (#3848, #3842, thanks @nikhilsaxena04). - Fix: a TypeScript "solution"
tsconfig.jsonthat only carriesreferences(nopathsof its own) now resolves path aliases declared in the referenced project configs, so alias imports in atsc -blayout no longer dangle (#3753, #3745, thanks @abhay-codes07). - Fix: extraction now skips the process pool up front when the
spawnstart method can't re-import__main__(stdin,python -c, REPL, embedded callers), falling back to a correct sequential run instead of a wall ofBrokenProcessPooltracebacks (#3754, #3669, thanks @abhay-codes07). - Fix: entity deduplication preserves a genuine pre-existing self-loop (a recursive call, a self-referential FK) while still dropping a self-loop newly created by a merge (#3825, thanks @Abhirup0).
- Fix:
ingestclassifies a URL by its parsed host, not by text anywhere in the URL, soexample.com/article-about-youtubeis no longer mistaken for a YouTube link; subdomains andyoutu.bestill match, path-based extension detection is unchanged (#3831, thanks @L4XB). - Fix:
graphify updateon a destination outside the scan root no longer leaks a stat-index cache into the corpus — the incremental detection path now forwardscache_rootlike the fresh-scan path (#3850, #3847, thanks @ayushcodes10). - Fix: manifest duplicate-key collapse breaks ties by last-seen time instead of arbitrary iteration order, so a stale duplicate can no longer win and under-report changed files; also re-anchors foreign-platform absolute keys and normalizes
../.segments so more duplicates actually collapse (#3781, #1964, thanks @ayushcodes10). - Docs: a community-health and contributor-guide overhaul — new
CONTRIBUTING.md,CODE_OF_CONDUCT.md, andRELEASING.md, refreshed issue/PR templates, and corrected factual drift inSECURITY.md(supported version, network/XSS boundaries),ARCHITECTURE.md(shared-state), andAGENTS.md(scoped-query workflow) (#3845, thanks @nikhilsaxena04).
v0.9.68
- Security: the
/graphify add ... --watchreference no longer passes the raw, agent-substitutedINPUT_PATHplaceholder unquoted into a shell command (… -m graphify.watch INPUT_PATH), where a scan root containing$(…), backticks, or;could execute — a follow-on to the Step 1 fix. The watcher now reads the trustedgraphify-out/.graphify_rootthat Step 1 resolves, so there is no path to substitute (#3742, #3642, thanks @ayushcodes10). The identical placeholder still appears in the Aider/Devin monolith--watchsnippet and is tracked separately. - Fix: incremental updates (
update/extract --code-only/watch) now preserve a cross-fileimports/calls/usesedge whose target symbol lives in an unchanged file — the symbol-resolution facts pass widens its target index with the read-only resolution context, so re-extracting one file no longer silently drops its edges into the rest of the graph; a genuinely removed edge is still pruned (#3812, #3776, thanks @hopstreax). - Fix: C# type references (
inherits/implements/parameter/return/base types) no longer resolve to a same-named non-type node — an enum member, property, field, or method sharing a type's name is excluded from the type-definition index, so a class inherits from the real base rather than a stray member; resolution of partial classes without acontainsedge is restored (#3815, #3795, thanks @hopstreax). - Fix: dedup now keeps the node with a real source location over a richer but source-less one when merging duplicates, so a merged entity points at real code instead of an inferred/external stub; the loser's attributes are still folded onto the survivor (#3786, #3775, thanks @ayushcodes10).
- Fix: Maven
pom.xmlingestion resolves a dependency's inheritedgroupId/versionfrom the local<parent>block and substitutes${property}/${project.*}placeholders (offline, one level), so previously-danglingdepends_onedges now connect (#3823, #3806, thanks @chiliec). - Fix: the PYTHONHASHSEED re-exec (0.9.67) now waits for and propagates the child's exit code on Windows instead of returning early —
os.execvpeis a true process replacement only on POSIX; on Windows it spawned a new process and let the parent race ahead unpinned, crashingupdate/extract/cluster-only/label. The Windows path now spawns viasubprocess.runand exits with the child's status; the POSIX path is unchanged (#3816, #3799, thanks @sinangumuskabak-sys). - Fix: Terraform secret redaction now also covers a secret-named
variabledefault andoutputvalue — the secret's name lives in the block label, so the literal sat under the genericdefault/valuekey that the key-name check never flagged (variable "db_password" { default = "…" }reachedgraph.jsonverbatim). Redacted when the label names a secret or the block setssensitive = true(#3817, #3644/#3762 follow-up, thanks @breken-ai). - Fix: fixed-format COBOL that carries a sequence NUMBER in columns 1-6 (not blanks) is now detected as fixed-format — previously it was misread as free-format, the sequence digits stayed in the code, and every paragraph and
PERFORMedge was silently dropped, leaving only the file and program nodes (#3813, thanks @abhay-codes07). - Fix:
PERFORM A THRU/THROUGH Znow links both endpoints of the range, not just the entry paragraph, so the range-end no longer lacks an inboundcallsedge; a dangling THRU target is skipped rather than fabricated (#3814, thanks @abhay-codes07). - Fix:
GRAPH_REPORT.md's Knowledge Gaps section only offers "undocumented components" as an explanation for an isolated node when the graph actually has a semantic layer (a document/paper/image node an LLM extracted meaning from) — a code-only graph no longer lists a possibility it can never have (#3828, #3801, thanks @ayushcodes10).
v0.9.67
- Fix: the PYTHONHASHSEED determinism pin (0.9.66) now re-execs via
python -m graphifyinstead of replayingargv[0], fixing a Windows regression whereupdate/extract/cluster-only/labelfailed to re-launch through the console-script.exelauncher (#3780, thanks @ayushcodes10). - Feature: PHP closures are now extracted — an anonymous
function(){…}, an arrowfn()=>…, or a closure passed as an argument now produces a node and its inner calls are captured, in all positions including file scope. Route-definition closures get a semanticVERB /pathname (composing nestedgroup()prefixes); other closures get a stable per-scope ordinal (#3461, #3409, thanks @nikhilsaxena04). - Fix: absolute Python package imports (
import pkg.sub,from pkg.sub import x) now resolve to the local package/module node within the scan root, reusing the canonical resolver (bounded walk, PEP 420 namespace handling); an ambiguous module name across scanned trees fails closed rather than binding arbitrarily (#3729, thanks @Ha1baraA11). - Fix: a package/module name collision (
pkg/package alongside apkg.pymodule) no longer produces a phantom import cycle — the spurious provisional edge is retracted while genuine package-init and submodule edges are preserved (#3784, #3777, thanks @hopstreax). - Fix: Terraform secret redaction now also covers secrets nested inside list values (
configs = [{ password = "…" }]), not just maps (#3762, #3644 follow-up, thanks @abhay-codes07). - Fix:
exportno longer rewrites unchanged wiki/Obsidian pages on every run — a page whose content is identical is left untouched (stable mtimes, clean git/Obsidian sync), while changed and new pages still write and orphaned pages are still swept (#3760, #3060, thanks @abhay-codes07).