Skip to content

Releases: Graphify-Labs/graphify

v0.9.76

Choose a tag to compare

@safishamsi safishamsi released this 04 Oct 20:03

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 a case_of edge (#4050), C++ union specifiers are extracted as class-like type nodes with their members (#4052), VB.NET enum members link via case_of instead of contains (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 $schema declaration plus a structural marker ($defs/definitions/$id) so real manifests that merely reference a schema are unaffected (#4048, #2255).
  • Fix: Elixir import/use call 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 a calls edge 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 path and the MCP shortest_path tool resolve a path::symbol or 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: graphify no 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 own graphify-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 install refuses a core.hooksPath that resolves outside the repository (resolving both sides, symlink-safe), falling back to the in-repo .git/hooks instead 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

Choose a tag to compare

@safishamsi safishamsi released this 04 Oct 01:20

Intra-class call binding across five languages, new language-structure coverage, and a batch of resolution/build/cache fixes.

  • Feature: self/this/super member 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 the extends chain 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) with case_of edges (#4026), Elixir defmacro/defmacrop/defguard/defguardp definitions (#4027), and Rust macro_rules! definitions with local invocation resolution (std macros like println! fail closed, no fabrication) (#4028).
  • Feature: three Scala type-reference fixes from @Faisal-Fayaz — file-scope val/var type annotations now emit references edges (#4036, #2054), type alias/definition right-hand sides are walked (including opaque type and match types) (#4037, #2049), and context bounds (def f[A: Ordering]) resolve to references edges (#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 an invokes edge; a $VAR/path command word is not mistaken for an interpreter (#4007, thanks @ayushcodes10).
  • Feature: Dart part files 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 calls edges; one split partial class anywhere in a repo used to erase every recursive self-loop graph-wide (#4017, thanks @rohit-jsfreaky).
  • Fix: graphify path (CLI and the MCP shortest_path tool) now routes through a contains edge 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.json with 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 --previous file now errors cleanly instead of crashing (#4006, #3858, thanks @ayushcodes10).
  • Fix: cluster-only/label no 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_ctx setting is merged into extra_body instead of replacing it, so a GRAPHIFY_DISABLE_THINKING body set on the same backend is no longer silently clobbered (#4029, #3988, thanks @Agnik47).
  • Fix: the hook-guard reminder names the effective graph.json path when GRAPHIFY_OUT is customized, instead of always naming the default graphify-out/graph.json (#4042, #4040, thanks @DeepanshuPal).
  • Fix: graphify extract refuses to overwrite an existing graph with a dedup-shrunk one unless --allow-dedup-shrink is 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

Choose a tag to compare

@safishamsi safishamsi released this 02 Oct 16:20
  • Feature: four more language extractors gained structural depth. Ruby paren-less self-sends (do_thing with 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). TypeScript abstract method 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 a calls edge to a references/constructor edge (#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-notes vs artifacts/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 exports path to the legacy main/module fields (#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-self receiver fails closed with no cross-file member fabrication (#3994, thanks @rajatnagda45).
  • Feature: Erlang local fun references (fun Name/Arity, as in lists:map(fun helper/1, L)) are now recorded as indirect_call edges to the arity-matched local function; remote fun Mod:Name/Arity and 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 as receiver.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

Choose a tag to compare

@safishamsi safishamsi released this 30 Sep 19:53
  • Feature: enum members are now extracted as nodes with case_of edges in four more languages — Rust enum variants (#3938), Zig enum members (#3940), C++ enum/enum class enumerators 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 the inherits chain, 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 and MyBase. 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 --push path 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 status reports hooks written by an older release as out of date (run graphify hook install to 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.md etc.) 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

Choose a tag to compare

@safishamsi safishamsi released this 29 Sep 18:42
  • Feature: after a package upgrade, graphify refreshes stale installed skills automatically (the SKILL.md + references sidecar it manages) so the version-mismatch warning no longer requires a manual graphify install. It runs on any non-install CLI command when a skill is stale, backs up local edits to SKILL.md.bak, never touches your marker-bounded CLAUDE.md/AGENTS.md/GEMINI.md sections, and can be disabled with GRAPHIFY_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 an UnboundLocalError that 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: docx sidecar 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/--exclude and resolves an article-named index without overwriting the generated index.md hub — two independent wiki/markdown fixes (#3818, thanks @breken-ai; escaped-alias parsing [[target\|alias]] #3772, thanks @zagushka).
  • Fix: the community listing in GRAPH_REPORT.md reuses the shared real-node filter, so rationale/concept nodes 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 pdf extra (pypdf) is not installed, instead of silently producing no text (#3710, #3702, thanks @shobhitagnihotri69).
  • Chore: graphify / graphify --help now shows the logo banner and a link to the hosted platform at app.graphify.com.

v0.9.71

Choose a tag to compare

@safishamsi safishamsi released this 28 Sep 08:28
  • Feature: SQL CREATE TRIGGER statements are now extracted and linked to their table (ON <table>), including OR REPLACE/OR ALTER, INSTEAD OF, and procedural BEGIN…END bodies that previously landed in a parser-error node and were dropped (#3863, thanks @rajatnagda45).
  • Feature: Groovy enum declarations and their constants are extracted, with members linked to the enum via case_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() and private$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) using posixpath/ntpath rather 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.com appearing in the path or query is no longer corrupted (#3880, thanks @Dakshcore).
  • Chore: graphify install shows the refreshed graphify logo banner (#3892, thanks @rajarshidattapy).

v0.9.70

Choose a tag to compare

@safishamsi safishamsi released this 27 Sep 18:19
  • Security: the Fortran capital-F cpp step no longer allows an untrusted .F/.F90 source to read arbitrary host files. -nostdinc -I /dev/null did not stop cpp from resolving absolute (#include "/etc/passwd") or traversing (#include "../../../secret") includes, which inlined host-file contents into graph.json/GRAPH_REPORT.md and the LLM context on the default offline path. Every #include directive 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 --watch snippet no longer interpolates the agent-substituted INPUT_PATH into a shell command — it now reads the trusted graphify-out/.graphify_root written 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 value paired with a secret-named name in name/value pair lists (environment = [{ name = "DB_PASSWORD", value = "…" }], ECS valueFrom included), where the sensitive signal is the sibling name literal rather than a key (#3870, #3787, thanks @breken-ai).
  • Fix: graphify watch now serializes concurrent rebuilds on Windows via msvcrt byte-range locking instead of a no-op lock, closing a WinError 32 race between overlapping rebuilds; the POSIX fcntl path 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 to Count/Name); only the element types are referenced (#3877, #3796, thanks @KaiyiQuan).
  • Feature: JSX component usage now produces calls edges — <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 x when the scan root is Team/) now resolve to the local module by projecting the namespace prefix onto the scan-root layout (#3867, #3843, thanks @nikhilsaxena04).

v0.9.69

Choose a tag to compare

@safishamsi safishamsi released this 26 Sep 13:06
  • Feature: five language extractors gained structural depth — OCaml classes now emit their methods (via the method relation) and instance variables (#3838, thanks @rajatnagda45); Elixir defprotocol/defimpl are extracted as containers holding their functions, with a same-file implements link (#3839, thanks @rajatnagda45); Fortran derived-type contains blocks link type-bound procedures to the type, resolving the => impl target (#3840, thanks @rajatnagda45); Julia macro definitions and @enum types are extracted, including valued (red = 1) and typed (Color::UInt8) enum forms, with members using the case_of relation (#3841, thanks @rajatnagda45); Kotlin annotations (class/function/property, use-site targets) and val/var primary-constructor properties now produce edges (#3848, #3842, thanks @nikhilsaxena04).
  • Fix: a TypeScript "solution" tsconfig.json that only carries references (no paths of its own) now resolves path aliases declared in the referenced project configs, so alias imports in a tsc -b layout no longer dangle (#3753, #3745, thanks @abhay-codes07).
  • Fix: extraction now skips the process pool up front when the spawn start method can't re-import __main__ (stdin, python -c, REPL, embedded callers), falling back to a correct sequential run instead of a wall of BrokenProcessPool tracebacks (#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: ingest classifies a URL by its parsed host, not by text anywhere in the URL, so example.com/article-about-youtube is no longer mistaken for a YouTube link; subdomains and youtu.be still match, path-based extension detection is unchanged (#3831, thanks @L4XB).
  • Fix: graphify update on a destination outside the scan root no longer leaks a stat-index cache into the corpus — the incremental detection path now forwards cache_root like 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, and RELEASING.md, refreshed issue/PR templates, and corrected factual drift in SECURITY.md (supported version, network/XSS boundaries), ARCHITECTURE.md (shared-state), and AGENTS.md (scoped-query workflow) (#3845, thanks @nikhilsaxena04).

v0.9.68

Choose a tag to compare

@safishamsi safishamsi released this 25 Sep 15:33
  • Security: the /graphify add ... --watch reference no longer passes the raw, agent-substituted INPUT_PATH placeholder 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 trusted graphify-out/.graphify_root that Step 1 resolves, so there is no path to substitute (#3742, #3642, thanks @ayushcodes10). The identical placeholder still appears in the Aider/Devin monolith --watch snippet and is tracked separately.
  • Fix: incremental updates (update/extract --code-only/watch) now preserve a cross-file imports/calls/uses edge 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 a contains edge 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.xml ingestion resolves a dependency's inherited groupId/version from the local <parent> block and substitutes ${property} / ${project.*} placeholders (offline, one level), so previously-dangling depends_on edges 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.execvpe is a true process replacement only on POSIX; on Windows it spawned a new process and let the parent race ahead unpinned, crashing update/extract/cluster-only/label. The Windows path now spawns via subprocess.run and 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 variable default and output value — the secret's name lives in the block label, so the literal sat under the generic default/value key that the key-name check never flagged (variable "db_password" { default = "…" } reached graph.json verbatim). Redacted when the label names a secret or the block sets sensitive = 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 PERFORM edge was silently dropped, leaving only the file and program nodes (#3813, thanks @abhay-codes07).
  • Fix: PERFORM A THRU/THROUGH Z now links both endpoints of the range, not just the entry paragraph, so the range-end no longer lacks an inbound calls edge; 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

Choose a tag to compare

@safishamsi safishamsi released this 23 Sep 19:25
  • Fix: the PYTHONHASHSEED determinism pin (0.9.66) now re-execs via python -m graphify instead of replaying argv[0], fixing a Windows regression where update/extract/cluster-only/label failed to re-launch through the console-script .exe launcher (#3780, thanks @ayushcodes10).
  • Feature: PHP closures are now extracted — an anonymous function(){…}, an arrow fn()=>…, 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 semantic VERB /path name (composing nested group() 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 a pkg.py module) 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: export no 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).