v0.9.95

Graphify-Labs/graphifyv0.9.95Oct 23, 2026by safishamsi

Upgrading?

Release notes summary

Graphify 0.9.95 incorporates twenty-one community pull requests, with a strong focus on extraction correctness across Python, Go, C++, Rust, C#, Objective-C, SQL, and JSON configuration. It also hardens install and export security, improves merged-graph tree export and Windows cache handling, and adds structural YAML extraction for Helm, Kubernetes, and CI files. The AST cache schema is bumped, so the first build after upgrading will re-extract.

Key Highlights

  • Security hardening for skill installs using randomly named O_EXCL temp files to prevent symlink redirection attacks.
  • Explicit type aliases and Rust union items are now extracted as type nodes across Python, Go, C++, and Rust, improving reference resolution.
  • C# method overloads now receive distinct nodes and calls bind by argument count across in-file, cross-file, partial-class, and interface-dispatch cases.
  • Merged multi-repo graph tree export now gives each repo its own root, and Windows extended-length cache paths avoid deep-path extraction failures.
  • YAML/YML files are now structurally extracted as code, with safeguards for multi-document streams, data-heavy YAML, safe parsing, and bounded output.

New Features

  • Structural extraction for .yaml/.yml files, including file nodes and contains edges to keys, with classification as code.
  • Explicit type alias extraction for Python, Go, C++, and Rust, plus Rust union item extraction.
  • Per-overload C# method nodes with argument-count-based call binding.
  • package.json dependency manifest entries now link to the resolved import/reference node.
  • Per-repo root handling in graphify export tree for merged multi-repo graphs.

Full Release Notes

Twenty-one community pull requests. A security pass on install: the skill-install writes go through randomly-named temp files instead of predictable ones, so a pre-planted symlink can no longer redirect a write. Extraction: Python, Go, C++ and Rust explicit type aliases (and Rust `union` items) are extracted as type nodes so references resolve instead of minting sourceless stubs, each C# method overload gets its own node bound by argument count, and a package.json dependency's manifest entry links to the node that references it. Plus a one-root-per-repo tree on merged graphs, extended-length cache paths on Windows, and binary media no longer counted as text. The AST cache schema is bumped, so the first build after upgrading re-extracts.

- Fix: **security** the skill install stages every write (version stamp, `SKILL.md`, references) through a randomly-named `mkstemp`/`mkdtemp` file created with `O_EXCL` and restrictive mode instead of a predictable `*.tmp` name, so a local attacker who pre-creates a symlink at that path can no longer redirect the write to clobber an arbitrary file; the final move stays atomic (#4513, thanks @Mahdifotohi).
- Fix: **python** an explicit module-level type alias (`X: TypeAlias = ...`, `type X = ...`, `NewType`) is extracted as a type node, so a field or parameter typed by the alias resolves to it instead of minting a sourceless stub; an implicit assignment, a local alias, or a re-export is left alone (#4578, thanks @madhusudanpatnaik).
- Fix: **go** a `type A = B` alias is extracted as a type node (tree-sitter parses it as a `type_alias`, not a `type_spec`), so references resolve to it; a re-export (`type Field = pkg.Field`) mints no node (#4579, thanks @madhusudanpatnaik).
- Fix: **cpp** a namespace-scope `using A = B;` or `typedef B A;` alias is extracted as a type node so references resolve; a member alias inside a class and a same-name re-export are excluded (#4580, thanks @madhusudanpatnaik).
- Fix: **rust** a `type` alias and a `union` item are extracted as type nodes (a union's fields reference their types like a struct), so references resolve instead of minting stubs; an impl-associated `type` is excluded (#4581, Refs #4285, thanks @madhusudanpatnaik; reported by @jonatasbcardio-boop).
- Fix: **csharp** each method overload gets its own node and source location instead of collapsing to one, and a call binds to the overload matching its argument count, across in-file, receiver-typed, bare-name cross-file, partial-class, and interface-dispatch resolution; a non-overloaded method keeps its id (#4584, #4591, thanks @Mpasha17; reported by @TerraVenil).
- Fix: **tree** `graphify export tree` on a merged multi-repo graph gives each repo its own root (keyed by the repo tag) instead of conflating same-path files from different repos; untagged nodes are not counted as a repo (#4524, #4525, thanks @AromalBiju1).
- Fix: **cache** AST cache entries are read and written through Windows extended-length (`\\?\`) paths, so a deep cache path over the 260-character limit no longer fails extraction with a `FileNotFoundError`; a no-op off Windows (#4542, thanks @omsenjalia).
- Fix: **detect** a binary media file (an image or audio/video) is no longer read and counted as text toward the corpus word total; an SVG stays counted as the XML text it is (#4548, thanks @kalkaran).
- Fix: **json_config** a `package.json` dependency's manifest entry links (`declares`) to the ref node that importing code resolves to, so the manifest entry and its importers share one node instead of being orphaned; the entry is relabelled `name@range` (#4569, #4572, thanks @Deepjyoti-Sarmah; reported by @BiSide).
- Feature: **yaml** `.yaml`/`.yml` files are now extracted structurally (a file node plus `contains` edges to keys) and classified as code rather than documents, so Helm charts, Kubernetes manifests, and CI pipelines contribute nodes to a code-only or `--update` run instead of nothing, matching how `.json` is handled. Multi-document streams (`---` separators) are walked per document; a data array, an OpenAPI/Swagger spec, a JSON-schema-in-YAML, and a flat data bundle are skipped so data-heavy YAML does not mint orphan nodes; parsing uses `safe_load` so a `!!python/...` tag never executes; output is bounded (1 MiB, 500 pairs, depth 6). The AST cache schema is bumped, so the first build after upgrading re-extracts (#2214, #4706, thanks @nothariharan; reported by @dchavezf).
- Fix: **extract** a bare call that resolves to a same-named symbol only because the caller imported that symbol's module (`from b import other`, then a call to a `_make_id` defined in both `a.py` and `b.py`) is no longer promoted to `EXTRACTED`; the edge is still emitted for connectivity but stays `INFERRED`, so a symbol that was never imported is not falsely certified. A real symbol import (`from a import _make_id`) still resolves `EXTRACTED` (#2945, #4707, thanks @nothariharan; reported by @TotalUnitManagement).
- Fix: **security** the SSRF guard blocks a host that resolves to a multicast address (`224.0.0.0/4`, `ff00::/8`), closing a gap alongside the existing private/reserved/loopback/link-local checks (#4708, thanks @Dextheking1).
- Fix: **security** the Obsidian export sanitizes a node's file-type and confidence before emitting them as frontmatter `tags`, so a crafted value cannot break out of the YAML list into a sibling key, matching how community tags are already sanitized (#4709, thanks @Dextheking1).
- Fix: **security** the Google Workspace shortcut sidecar escapes a file id or url through full YAML double-quoted-scalar escaping (tab, C0/DEL controls, and the Unicode line breaks U+2028/U+2029/U+0085), so a hostile shortcut file cannot inject frontmatter keys (#4710, thanks @Dextheking1).
- Fix: **affected** `graphify affected <path>` resolves a path whose file-node label was disambiguated by the shared-basename suffix pass (for example two `hooks.py` from different directories), reusing the canonical file-label predicate instead of a bare basename match (#4698, #4713, thanks @Deepjyoti-Sarmah; reported by @karsan8119).
- Fix: **build** a raw (`--no-cluster`) build resolves an import endpoint through the same old-stem alias index the clustered build uses, and mints an external stub only after resolution, so the raw graph no longer freezes an import onto a stub when the clustered graph resolves it (#4670, #4676, thanks @nothariharan; reported by @xiongjianxu).
- Fix: **cross-repo** an Objective-C class declared in one repo's header and implemented in another repo's `.m` binds a member call to the implementation, the cross-repo analog of the same-repo split-dir fix; two same-named classes that both define the selector stay ambiguous (#4690, #4691, thanks @xiongjianxu).
- Fix: **hooks** the rebuild hook runs from the checkout's top level (derived from the git common dir, falling back to `--show-toplevel`), so a stray `graphify-out/` in a subdirectory can no longer root the rebuild at the wrong place and walk an enormous tree (#3258, #4689, thanks @jaimemartinez; reported by @dsfaccini).
- Fix: **objc** `NS_CLOSED_ENUM` declarations are extracted as enums with their cases, the same as `NS_ENUM`/`NS_OPTIONS`; the AST cache schema is bumped so the first build after upgrading re-extracts (#4705, thanks @Jvxoq).
- Fix: **sql** a `CREATE TABLE` whose column default the SQL grammar cannot parse (for example MySQL/MariaDB `DEFAULT current_timestamp()`) is recovered from the ERROR node instead of being dropped, so the table and its foreign-key references still resolve; the AST cache schema is bumped (#4613, #4677, thanks @08raviyadav; reported by @AirRunner).

Related Repositories