What shipped.
Every release, straight from the repository, newest first. Nothing is written twice: this is the note that went out with the tag.
- v0.9.88
Oct 12, 2026
v0.9.88
The full note0.9.88 (2026-10-12)
Twenty community pull requests: language-extraction and call-resolution fixes (Java, C/C++, Python, Swift, Go, PowerShell, C#, JS/EJS), dedup/shrink-guard hardening, and query/graph.html ergonomics. The AST cache schema is bumped, so the first build after upgrading re-extracts.
- Feature: Java a call on a chained,
newor cast receiver (factory.builder().size(3).build(),new Builder().size(1),((Builder) o).build()) now resolves through the declared return types on the method chain, binding only on a single unambiguous target (#4306, #4307, thanks @rohit-jsfreaky). - Fix: Java a bare call or field receiver inherited from a supertype in another file now resolves to the nearest declaring supertype (class wins over an interface default; a tie binds nothing), instead of dangling (#4304, #4305, thanks @rohit-jsfreaky).
- Fix: C/C++ a quoted cross-directory include (
#include "../lib/foo.h", STM32Core/SrctoCore/Inc) now resolves to the right header by a unique longest-shared-directory-prefix match, fail-closed on ties and never guessing for./,../, absolute or angle-bracket includes (#4354, #4392, thanks @hopstreax). - Fix: Python a
@name.setter/.getter/.deleterdecorator no longer mints a sourceless stub node (#4380, #4385, thanks @rajatnagda45). - Fix: Python a
Self(PEP 673) type annotation (-> Self,: Self,typing.Self) no longer mints a sourcelessselfstub (#4381, #4386, thanks @rajatnagda45). - Fix: Swift a
Selftype annotation no longer mints a sourcelessselfstub (#4382, #4387, thanks @rajatnagda45). - Fix: Go generic type parameters (
[T any]) in signatures, struct fields and interface methods no longer mint sourcelesst/rstubs (#4383, #4388, thanks @rajatnagda45). - Fix: Python a class type-hinted before it is defined (a forward reference) no longer mints a bare stub that collides with and swallows the file node (#4334, #4343, thanks @Mpasha17).
- Fix: C# extraction now recovers members declared after a verbatim interpolated string that ends in an escaped quote (
$@"a""{e}"""), instead of silently dropping the rest of the file; the fix masks only the offending bytes and discards the rewrite unless it re-parses clean (#3376, #3612, thanks @rohit-jsfreaky). - Fix: PowerShell dot-sourced includes with quoted or
$PSScriptRootpaths now emit import edges, and script-scope commands (outside any function) are now collected as calls (#4356, #4369, thanks @FabioRueda).
- Feature: Java a call on a chained,
- v0.9.87
Oct 12, 2026
v0.9.87
The full note0.9.87 (2026-10-12)
Eighteen community pull requests: language-extraction fixes (PHP, C#, Python, TypeScript, Julia), retrieval and watch hardening, and skill/benchmark correctness.
- Fix: PHP a
Class::method()static call now resolves to the called method rather than binding to the class node, and no longer stalls at INFERRED confidence for a same-namespace call that needs nouseimport.self/static/parentand lowercase class receivers route through the PHP resolver, fail-closed on any ambiguous or off-corpus receiver (#3872, #3874, thanks @rikurunico). - Fix: C# nested and generic
partialtypes now merge by their full type path (Outer\1.Inner), so a two-file nested partial is unified whileFooandFoo<T>` stay distinct; a cross-file unqualified call binds to the caller's own merged type when it is the single own-type candidate, and a sourceless placeholder base is dropped when a real same-named base exists on the partial (#4363, #4364, thanks @JensD-git). (The AST cache schema is bumped, so the first build after upgrading re-extracts.) - Feature: Python a read of a
@property(obj.prop, includingx.prop += v) now links to the property's getter, instead of being dropped as a bare attribute access (#4337, thanks @rohit-jsfreaky). (The AST cache schema is bumped, so the first build after upgrading re-extracts.) - Fix: TypeScript a public call
c.name()reaches a#name-labeled node only when the class declares a publicname, and a public call keeps its edge whenfooand#fooshare one node (#4298, thanks @rohit-jsfreaky). - Fix: Julia parametric and module-qualified functor (callable-struct) types are named by their type rather than the variable, and never fall back to the variable binding (#4351, thanks @ayarodionov).
- Fix: C# a
varis typed from the called method's return type, so downstream member calls on it resolve (#4266, #4268, thanks @Mpasha17). - Fix:
graphify affected <PR>now scopes graph impact to the requested PR instead of the repository default branch, and PR default-branch detection is isolated under test (#3829, thanks @hopstreax). - Fix:
updaterefuses to drop a saved semantic node id when the node total grows (treating it as an incomplete re-extract), while still letting a removed import stub go;exportkeeps an integer node id that is still in the graph (#4115, thanks @SrijanSriv). - Fix: the MCP
query_graphseed order no longer lets a weak match on an early-alphabet term lead a specific term's exact match: the per-term guaranteed seeds (#1445) are ordered by match strength (#4357, #4358, thanks @devkancheti4-design). - Fix: the update skill stamps
_originon the semantic tier so an AST-onlyupdatecannot delete semantic nodes it did not re-extract (#2843, #3110, thanks @abhay-codes07).
- Fix: PHP a
- v0.9.86
Oct 11, 2026
v0.9.86
The full noteEighteen community pull requests: language-extraction fixes, safety and determinism hardening, and CLI/query ergonomics.
- Safety:
graphify uninstall --purgenow refuses to delete the project (or home, or a filesystem root) whenGRAPHIFY_OUTis empty or., instead of silently removing the working tree (#4329, thanks @Hassannzidan). - Fix: Julia now extracts return-typed, qualified (
Base.show), operator (Base.:+) and functor (callable-struct) methods, and resolves broadcast (f.(xs)) and pipe (x |> f) calls (#4310, thanks @ayarodionov). - Fix: Rust grouped
usedeclarations (use a::{b, c::d}) now expand into one import binding per name, instead of a single edge to the common prefix (#4135, thanks @krishhgg). (The AST cache schema is bumped, so the first build after upgrading re-extracts.) - Fix: Scala 3
class Foo derives Barnow links the class to each derived typeclass (#2048, #4173, thanks @Mpasha17). - Fix: Codex semantic chunks are no longer clobbered by the shared B3 merge (each chunk is written to its own file, matching the other hosts), so semantic nodes/edges survive (#4311, #4312, thanks @vibhanshu-mishra).
- Fix:
affected <Symbol>now also walks callers of the supertype member that an overriding method overrides, so a change to an override surfaces users of the base contract (#4330, #4331, thanks @rohit-jsfreaky). - Fix: dedup keeps combining marks in label normalization, so distinct Indic-script words no longer collapse to one node (#4317, #4318, thanks @Suraj370).
- Fix: dedup ranks a relative
source_fileagainst the scan root rather than the CWD, so building from a subdirectory no longer strands an extension-renamed node's edges on the survivor (#4281, #4326, thanks @Deepjyoti-Sarmah). - Fix: the global (cross-repo) graph preserves stored edge direction on
global add, sopathand other direction-aware readers no longer follow reversed arcs (#4066, #4138, thanks @e4c5). - Fix: graphify now respects git's global ignore file (
core.excludesFile), with git-faithful precedence and~/XDG expansion (#4335, #4339, thanks @smngvlkz). - Fix: null token counts from a backend are coerced to 0 across all backends, instead of crashing a chunk with a
TypeError(#4325, #4340, thanks @rtmalikian). - Feature: built-in Ollama requests accept a sampling seed for reproducible extraction (#4168, thanks @oleksii-tumanov).
- Safety:
- v0.9.85
Oct 10, 2026
v0.9.85
The full noteA language-extraction and tooling batch: six extractor/exporter fixes picked from open issues, plus fourteen community pull requests.
- Fix: Julia functions with a
whereclause (long and short form) and parametric type definitions (struct Box{T},abstract type Shape{T},struct Sq{T} <: Shape{T}) are now extracted. The name sat inside awhere_expression/parametrized_type_expressionwrapper that the name lookup skipped, so the whole method/type was dropped; a declared type parameter (value::T) no longer leaks as a phantom field-type node (#4126, #4128). - Fix: Fortran a named generic
interfacenow gets a callable node and adispatches_toedge to each listedmodule procedure, so a call to the generic name resolves instead of dangling; unnamed and operator/assignment interfaces are unaffected (#4141, #4142, thanks @rajatnagda45). - Fix: Elixir
defdelegateis now extracted as a function definition, so the delegated function appears and same-module calls to it resolve (#4132). - Fix: Scala 3
given ... withinstance methods are scoped to the given instead of leaking to file scope (where they collided with the same-named trait type); an anonymousgiven Show[Int] withkeeps its members under a synthesized name (#4130). - Fix: graph.html a node label containing an unclosed
<!--then<scriptcan no longer break out of the embedded data script and blank the page; every<in the embedded JSON is escaped (#4124). - Fix: the incomplete-extraction message now explains a pure semantic omission (a smaller
--token-budgetis the lever) instead of always blaming truncation (#4101, #4280, thanks @ayushcodes10). - Fix: TypeScript
export type *star re-exports no longer trip a spurious syntax-error flag that skewed the health report (#3942, #4303, thanks @ayushcodes10). - Fix: Rust a cross-file reference to a type with impl blocks in other files now binds to the single declaration instead of a sourceless stub, fail-closed (#4283, #4284, thanks @Alin1233).
- Fix: distinct files that mint the same node id after the extension is dropped (
x.pyvsx.html) are kept as separate nodes instead of collapsing and losing one (#4281, #4282, thanks @bitwizard25). - Fix: the git hook now updates the graph for files whose names contain non-ASCII characters (
core.quotePath=falseplus C-quote decoding) (#4278, #4279, thanks @smngvlkz). - Fix: watch the rebuild lock no longer unlinks on release while a waiter holds it, closing a race that let two rebuilds run at once (POSIX) (#4273, #4277, thanks @ayushcodes10).
- Fix: an unanchored ignore pattern is now matched against the entry name only (so
*no longer crosses/and negations behave like git) (#4242, #4251, thanks @Yyunozor).
- Fix: Julia functions with a
- v0.9.84
Oct 10, 2026
v0.9.84
A correctness batch picked directly from open issues, plus an OpenCode plugin fix.
- Fix: PowerShell functions (and classes/enums) defined inside a file-scope
begin {}/process {}/end {}block are now extracted. These blocks parse as pseudo-commands rather than named blocks, so the walker returned before descending and dropped everything inside — the common[CmdletBinding()]advanced-function layout (#4270). - Fix: R every backtick-quoted binding now gets a collision-free id. A partially-symbolic name like
`%foo%`(or an S3 method`[.cls`, or a dotted`my.op`) normalized to the same id as an ordinary identifier and was silently dropped on merge; such names now use the reserved operator namespace (#4253). (The separate infinite-loop reported in that issue was already fixed in 0.9.83.) - Fix:
graphify pathand the MCPshortest_pathtool now fail closed on afile::symbolendpoint whose file defines no such symbol, instead of falling back to scoring the bare name and answering from a same-named symbol in another file; the refusal lists the files that do define it (#4264). - Fix: OpenCode the plugin now loads on OpenCode 2 (a default export with
setup()) while keeping the v1server()hook, andgraphify installrefreshes an already-installed v1-only copy, so the graph tools appear again for users upgraded past the v1 plugin contract (#3554, #3732, thanks @bercedev). - Fix: Python a bare
import loggingis no longer captured by a loose same-named module (scripts/logging.py) in a non-package directory — it resolves to the stdlib module. Guarded by a vendored, deterministic stdlib-name set across the module resolver, the sibling-repoint pass, and the build-time stem-alias index; a deliberate package shadow (logging/__init__.py) still resolves (#4261). - Fix: Python a qualified external annotation (
httpx.Response) no longer binds to an unrelated private local class (_Response). The stub-rewire match key now preserves underscores, so_ResponseandResponseare distinct identifiers (#4269). - Fix: C# an external type the corpus references but never declares (
List<T>,System.Type, Unity'sVisualElement) now gets one shared, name-keyed placeholder instead of a separate per-file stub (a_cs_list,b_cs_list), so a query returns one node and the files sharing the type connect through it (#4247). - Internal: added regression coverage locking in cross-module binding of a singly-defined type through re-export chains and the unique-stub rewire; the reported failure (#4262) no longer reproduces on this line.
- Fix: PowerShell functions (and classes/enums) defined inside a file-scope
- v0.9.83
Oct 9, 2026
v0.9.83
A C# resolution and determinism batch, plus Windows test-suite fixes.
- Fix: C# a generic and a non-generic type of the same name (
EffectvsEffect<T>) now get distinct node ids (arity folded into the id), so they no longer collapse into one node andEffect<T> : Effectno longer produces an inherits self-loop (#4255, #4249, thanks @ayushcodes10). - Fix: C# a call through a member chain (
a.b.C()), element access (xs[i].M()), or inside a constructor body now resolves to the right method, fail-closed to a single declared type per hop (collection element types only forT[]/List<T>), instead of being dropped (#4258, #4246, thanks @Mpasha17). - Fix: C# a bare call whose name matches an enum member (
Delegate(t)next to aDelegatecase) no longer binds to the enum member; case members are excluded from both the per-file and cross-file call-resolution maps, fail-closed (#4254, #4245, thanks @ayushcodes10). - Fix: C# a static factory that constructs its own type keeps its
methodmembership edge — an undirected collapse previously let the reversecallsedge overwrite it, hiding the member from every type walk (#4256, #4248, thanks @Mpasha17). - Fix: an unqualified call in Java/C#/Scala/C++ binds to the method on the caller's own class chain (own class, then in-file bases, then enclosing classes) instead of the last same-named method declared anywhere in the file; fail-closed on a tie, with free functions and constructors still resolving (#4252, thanks @Yyunozor).
- Fix: an unresolved re-export target id is now portable — it is minted in a dedicated namespace with a hash over the repo-relative path instead of the absolute checkout path, so a clone produces the same graph (#4257, thanks @andan0).
- Fix:
graphify's own skill runbook now reuses the persisted scan options (excludes and the gitignore flag) a prior build wrote, so a skill-driven update no longer drops opted-in files or re-adds explicitly excluded ones versus a CLI rebuild (#4250, #4240, thanks @deepanshupal). - Fix: the test suite passes on Windows —
_atomic_replacerefuses a read-only destination there instead of silently clobbering it (nt-only guard, no POSIX change), plus encoding, path-shape, and non-regular-file test guards (#4260, thanks @SoloDrex52). - Fix: C# nested types imported with
using staticnow resolve (using static Demo.Layer;reachingLayer.Inner), fail-closed on ambiguity, complementing the enclosing-namespace resolution also in this release (#4235, #4216, thanks @hopstreax). - Fix: the AST cache directory is now namespaced by the installed tree-sitter grammar versions (
...-g<fingerprint>), so upgrading a grammar within the same graphify release no longer serves stale or ABI-incompatible cached ASTs for unchanged files (#4239, #4236, thanks @nothariharan).
- Fix: C# a generic and a non-generic type of the same name (
- v0.9.82
Oct 9, 2026
v0.9.82
- Feature: after
graphify extractbuilds a graph, the CLI prints a short one-time pointer to Graphify Cloud (faster indexing, fewer tokens, cross-repo search, PR review, and an always-current view of your SDLC at app.graphify.com). It is shown only in an interactive terminal, once per project, and can be turned off withGRAPHIFY_NO_TIPSorGRAPHIFY_NO_CTA; CI, piped output, and the AI-assistant pipeline never see it. - Fix: Rust an in-file call now binds to the type that actually names it rather than any same-named function —
Type::new()/Self::f()/self.f()resolve through the owningimpl(unique-owner only, fail-closed), instead of mis-binding to an unrelatedfnwith the same last segment (#4238, #4237, thanks @rohit-jsfreaky). - Fix: SVG export strips XML-illegal control characters from node and legend labels, so a label carrying e.g. an ANSI escape no longer produces a malformed
graph.svg; valid whitespace and Unicode are preserved, and node identity is unchanged (#4244, thanks @Yyunozor).
- Feature: after
- v0.9.81
Oct 8, 2026
v0.9.81
The full noteA large resolution-accuracy and determinism batch across Python, TypeScript, C#, Elixir, and PHP, plus analysis-quality fixes and a portability regression guard.
- Fix: Python nested class identities are now qualified by their enclosing class, so
class Outer: class Innerno longer collides with a differentOuter2: Innerinto one node (and their methods no longer collapse together) (#4228, thanks @xiehuanyi). - Feature: Python
self/cls/super()calls now resolve to a base-class method defined in another file, fail-closed on multiple/opaque/out-of-corpus bases, withsuper(Cls, obj)forms excluded (#4222, #4221, thanks @rohit-jsfreaky). - Fix: Python typed-receiver resolution finds a nested function's file by climbing to the real file node, so a
self.x.m()/annotated-local call inside a nested def now resolves instead of failing the visibility check (#4227, #4226, thanks @rohit-jsfreaky). - Fix: Python an absolute import (
from werkzeug.wrappers import Request) no longer resolves onto a local same-named module (wrappers.py), which had rewired a class to inherit from itself; a same-named module in another package still resolves (#4225, #4224, thanks @rohit-jsfreaky). - Feature: TypeScript
this.fieldreceivers are typed from class field declarations (not only constructor-injected parameters), so a service'sthis.repo.find()resolves; fail-closed on static/array/union/generic field types (#4231, #4230, thanks @rohit-jsfreaky). - Fix: TypeScript a call on a receiver whose type name is declared in several files resolves to the one the caller actually imports, and a public call never binds to a
#privatemethod of the same name (#4233, #4232, thanks @rohit-jsfreaky). - Fix: C# types declared in an enclosing namespace now resolve from a nested namespace (
Demo.Innerreferencing a type inDemo), innermost-wins, additive over the existing scope resolution (#4204, #4196, thanks @hopstreax). - Fix: Elixir qualified and aliased remote calls (
App.Accounts.get_user,alias App.Accounts; Accounts.get_user) resolve to the right module's function, and a member call never mis-binds to a same-named local; cross-file targets link only to the single corpus module that defines the function (#4213, #4206, thanks @Mpasha17). - Fix: Elixir keyword-form definition bodies (
def f(x), do: g(x)) now have their calls extracted, not only thedo/endblock form (#4210, #4207, thanks @rtmalikian). - Fix: PHP 8.5
(void)casts and a cast applied to amatchexpression are parsed via a fail-safe pre-processing pass, so calls behind them are no longer dropped to a syntax error (#4211, #4202, thanks @Mpasha17). - Fix: plain AST declarations (TS type aliases, enum members, JSON keys) whose only edge is the structural
containsfrom their file are no longer flagged as weakly-connected knowledge gaps in the analysis output and GRAPH_REPORT.md (#4212, #4205, thanks @nothariharan). - Fix: low-confidence AMBIGUOUS edges are scaled down before community detection (on a copy, leaving the real graph untouched) so they no longer fuse independent clusters, and ambiguous suggested questions move to a separate low-confidence section;
GRAPHIFY_AMBIGUOUS_SCALE=1.0restores the prior behavior (#4214, #4199, thanks @JunoLee1).
- Fix: Python nested class identities are now qualified by their enclosing class, so
- v0.9.80
Oct 7, 2026
v0.9.80
The full noteMore clone-identical determinism, a large MCP retrieval speedup, and a batch of extractor and resolution fixes.
- Fix: more node ids and manifest keys stop leaking the local checkout path or OS username, so a clone keeps producing the same graph — a re-clone no longer keeps a previous checkout's absolute manifest keys (#4175, thanks @SrijanSriv), an AST cache hit whose import target has since been deleted is re-extracted instead of replaying the stale absolute-path id (#4185, #4184, thanks @rohit-jsfreaky), and
--no-clustergraph.json no longer shipsextract()'s run-only absolute source paths or undeclared/dangling endpoints (#4189, #4183, thanks @rohit-jsfreaky). - Fix: cross-drive scans no longer abort on a syntax-error warning — the remaining unguarded
os.path.relpathin the partial-extraction warning path falls back to a portable display path on Windows cross-drive files, completing the 0.9.78 #4106 fix (#4149, thanks @xiehuanyi). - Fix: an external import stub whose last referencing edge is gone is dropped on incremental rebuild instead of lingering as a zero-degree ghost a fresh build never has (#4181, thanks @rohit-jsfreaky).
- Fix: Python
self.<attr>.<method>()calls now resolve through the attribute's constructor/annotation type to the owning class, fail-closed on ambiguity (#4176, #2860, thanks @Mpasha17). - Fix: Python
obj.method()on a local or parameter whose class is known from an annotation (c: Client, includingOptional/union/string forms) or a constructor/withbinding now resolves to the owning class's method, fail-closed to a single in-file-or-imported class that owns it (#4198, thanks @rohit-jsfreaky). - Fix: Python imports under
if TYPE_CHECKING:are marked type-only so they no longer form impossible runtime import cycles (#4179, #3159, thanks @Yyunozor). - Fix: Java methods and the calls inside anonymous class bodies (
new Runnable() { public void run() {...} }) are now captured, mirroring the Kotlin object-literal handling (#4140, thanks @rajatnagda45). - Fix: markdown links to file names containing spaces or percent-encoding (
[x](<My Note.md>),[x](My%20Note.md)) resolve to the real file instead of a ghost target; wikilinks stay verbatim and external links stay excluded (#4178, thanks @Yyunozor). - Fix: a
re_exportsedge is kept for both files whose ids collide after separator normalization (a-b/x.tsanda/b/x.ts), removing an order-dependent dropped edge (#4143, thanks @Cintu07). - Fix: the Windows
graphifyconsole script now uses the multi-core extraction pool instead of silently falling back to single-core, since a non-file__main__.__file__no longer disables it (#4187, #4186, thanks @rohit-jsfreaky). - Perf: the MCP server builds the traversal view and shortest-path graphs once per loaded graph instead of rebuilding them on every call, keyed to the existing graph cache (~1.6x on
query_graph, up to ~300x onshortest_path); the two cached path graphs add a bounded, LRU-capped memory cost (#4192, #4191, thanks @rohit-jsfreaky). - Perf: the extraction id-remap and call tie-break resolve and parse each path once per run instead of recomputing it for every node and candidate (tens of thousands of redundant
Path.resolve()calls eliminated), with byte-identical graph.json output (#4195, thanks @rohit-jsfreaky).
- Fix: more node ids and manifest keys stop leaking the local checkout path or OS username, so a clone keeps producing the same graph — a re-clone no longer keeps a previous checkout's absolute manifest keys (#4175, thanks @SrijanSriv), an AST cache hit whose import target has since been deleted is re-extracted instead of replaying the stale absolute-path id (#4185, #4184, thanks @rohit-jsfreaky), and
- v0.9.79
Oct 6, 2026
v0.9.79
- Fix: incremental
graphify updateandwatchno longer re-cluster and re-render on every run after an unchanged rebuild. Theschema_version/graphify_versionmetadata added tograph.jsonin 0.9.78 (#4167) was being counted as a topology change by the watch unchanged-topology check, since the freshly-built candidate graph carries no such metadata; it is now excluded from the comparison.
- Fix: incremental
- v0.9.78
Oct 6, 2026
v0.9.78
A determinism and portability batch: node ids no longer leak the checkout path, OS username, or line endings into graph.json, so a clone produces the same graph everywhere. Plus encoding, C#, PowerShell, C++, and watch-reconcile correctness fixes.
- Fix: node ids no longer embed the local checkout path or OS username for unresolved targets — a missing
require('./x')(#4155, #4154), a missing Python relative importfrom .absent import x(#4157, #4156), and a.dmfelement keyed on its window (#4153, #4152) now mint portable, clone-identical ids; all three thanks @rohit-jsfreaky. - Fix: C# namespace scope ids are keyed on row/column instead of byte offset, so a CRLF checkout no longer writes different
scope_chainmetadata than an LF one (#4165, #4164, thanks @rohit-jsfreaky). - Fix: R symbol-only bindings (operators like
`%||%`) no longer collapse onto the file node and spinresolve_localforever; they get a stable, collision-free id (#4171, #4162, thanks @xiehuanyi). - Fix: source files are decoded before parsing — a UTF-16 file no longer yields zero nodes and a cp1252 name like
CaféOrderis no longer truncated; valid UTF-8 files are byte-for-byte unchanged, non-UTF-8 falls back deterministically (#4146, #4145, thanks @rohit-jsfreaky). - Fix: C# calls through a cast or an interface-typed property now resolve —
((IStore)x).Save(),(x as IStore).Save(), and a shadowedIStore Store => ...; Store.Save()bind to the interface's own method instead of being dropped or mis-bound to the concrete class (#4172, #3797, thanks @Mpasha17). - Fix: PowerShell member calls bind by receiver owner rather than method name alone —
$this.M()resolves to the enclosing class and[Type]::M()to a single unambiguous local class, fixing a same-name-method mis-bind; value, cast, dynamic, duplicate, and external receivers stay fail-closed (#4163, #4158, thanks @oleksii-tumanov). - Fix: C++ classes behind module export macros (
class MYLIB_EXPORT Foo : Base {}) are preserved — the ALL-CAPS macro is blanked before parsing (byte-length and newline preserving) so tree-sitter no longer error-recovers over the class and drops it (#3661, #3648, thanks @nikhilsaxena04). - Fix: incremental
graphify updatekeeps placeholder nodes for never-scanned referenced files, so an unchanged referrer's cross-file edges to an unresolved import or a.csproj/.slnreference are no longer dropped as if the target were deleted; genuinely deleted files are still reaped (#4161, #4160, thanks @rohit-jsfreaky). - Fix:
graph_diffkeeps edge direction, so a reversed edge (a→b becomes b→a) is reported as a change instead of cancelling out to "no changes"; the diff now loads the previous graph through the direction-preserving reader (#4170, #4067, thanks @Mpasha17). - Perf: the watch reconcile pass computes each stored source path's identity once per update instead of recomputing it for every node, edge, and hyperedge, cutting reconcile on graphify's own repo from 10.2s to 2.7s with graph.json byte-identical (#4151, #4150, thanks @rohit-jsfreaky).
- Feature:
graph.jsonnow carriesschema_versionandgraphify_versionmetadata for downstream consumers, written additively so existing readers and older graphs are unaffected (#4167, #3638, thanks @smngvlkz).
- Fix: node ids no longer embed the local checkout path or OS username for unresolved targets — a missing
- v0.9.77
Oct 5, 2026
v0.9.77
The full noteMore community language-structure coverage, two reload/incremental correctness fixes, and a batch of extractor tests.
- Feature: four more language extractors gained type coverage from @rajatnagda45 — Solidity enum values link via
case_ofinstead ofcontains(#4090), PowerShell enum members likewise (which also stops a member named like a type binding as a constructor) (#4092), Objective-C C-styleenumandtypedef enumdeclarations are extracted with their members (#4096), and a SQL trigger is linked to the function it executes with anexecutesedge (#4094). - Feature: Scala class-level context bounds (
class C[A: Ordering]) now resolve toreferencesedges, mirroring the method-level handling from 0.9.75 (#4085, #4080, thanks @Mpasha17). - Fix: Astro files terminate a trailing
//comment in one<script>block so it no longer swallows the next block on the same line; byte offsets and line numbers are preserved (#4083, #4072, thanks @Sourya-Prabaharan). - Fix: a zero-byte source file keeps its node but no longer claims a line-1 source location, so an empty
__init__.pyis still a real module without a misleading anchor (#4086, #4041, thanks @Mpasha17). - Fix: PHP calls to a method whose name collides with a cross-language builtin (
$this->list(),$this->open()) now resolve against the caller's own class instead of being dropped, while non-$thisreceivers and bare construct names stay fail-closed (#4119, refines #3975 and #3381, thanks @xiehuanyi). - Fix: JavaScript methods attached to an exported object (
res.format = function () {...}; module.exports = res) are now extracted as nodes, so calls inside them resolve across CommonJS/ESM module boundaries (#4121, #3778, thanks @harshaygadekar). - Fix: incremental
graphify updateon a subfolder no longer false-reports files in sibling folders as deleted; a shared single manifest now anchors stored paths to its base and scopes deletion detection to the scanned root (#4118, #3785, thanks @harshaygadekar). - Fix: reloading a saved
graph.jsonpreserves stored edge direction across the HTML, Cypher, Neo4j, FalkorDB, and Obsidian-canvas exporters, the watch HTML re-render, and the merge driver, instead of reversing edges whose target precedes their source in the node list (#4088, #4066, thanks @e4c5). - Fix: PowerShell method calls are now recorded —
$this.Method()and[Type]::Method()resolve to the method node by name, keyed only on method-labelled targets so a free function sharing the name is never bound, and unresolved names stay fail-closed (#3995, thanks @rajatnagda45). - Fix: Rust anonymous constants (
const _: () = assert!(...)) no longer collapse onto the file node and emit a self-loop; the anonymous item is skipped while named consts and statics keep their nodes (#4108, #4064, thanks @xiehuanyi). - Fix: a cleanly-parsed source file on a different drive from the scan root no longer aborts the whole extraction on Windows; the symbol-free-file warning falls back to an absolute display path instead of raising (#4106, #4059, thanks @xiehuanyi).
- Fix:
--no-dedupnow also disables the same-file ghost-merge pass inbuild_from_json, so two distinct non-AST nodes sharing a(source_file, label)are preserved when dedup is turned off; AST reconciliation and the default dedup path are unchanged (#4122, #4019, thanks @xiehuanyi).
- Feature: four more language extractors gained type coverage from @rajatnagda45 — Solidity enum values link via