From 29b3f9126d9347dcf40993f2f3c4101b1f3d4ab4 Mon Sep 17 00:00:00 2001 From: safishamsi Date: Sat, 4 Jul 2026 12:55:35 +0100 Subject: [PATCH] release: 0.9.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 19 fixes/features since 0.9.5. Highlights: - Ruby: module/Struct.new/Class.new/Data.define container nodes (#1640) and constant-receiver singleton-call resolution (#1634) — Rails/Zeitwerk graphs now get real cross-file edges. - Kill cross-language phantom imports_from edges from unresolved bare npm imports (#1638); harden semantic extraction against malformed LLM chunks (#1631); deterministic graph.json node/edge ordering for parallel semantic backends (#1632). - Contributor extractor fixes: Apex interface multiple inheritance (#1645), Kotlin `by` delegation (#1644). Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19634a8..a5b7765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Full release notes with details on each version: [GitHub Releases](https://github.com/safishamsi/graphify/releases) -## Unreleased +## 0.9.6 (2026-07-04) - Fix: Ruby plain modules and `Struct.new` / `Class.new` / `Data.define` constant assignments now get container nodes (#1640, thanks @krishnateja7). The extractor only created nodes for `class Foo`, so `module Foo` (utility/`module_function` modules), `Foo = Struct.new(...) do ... end`, `Foo = Class.new(StandardError)`, and `Result = Data.define(...)` produced no node at all — their methods hung off the file via `contains` with dot-less labels, and no edge could ever target them. `module` is now a container type (methods attach via `method` like a class, nested modules included), and a constant assignment whose RHS is one of those factories synthesizes a class node named after the constant, attaches block-defined methods to it, and emits an `inherits` edge for `Class.new(Super)`. Plain constant assignments (`MAX = 100`, `X = Foo.new`) are untouched. - Fix: Ruby constant-receiver singleton calls now resolve cross-file (#1634, thanks @krishnateja7). `Service.call`, `Model.where`, `SomeJob.perform_async` — the dominant Rails idiom — emitted no `calls` edge, so with Zeitwerk autoloading (no `require`s) a Rails app had essentially no cross-file edges and `affected`/`path` came up empty. `resolve_ruby_member_calls` now handles a capitalized (constant) receiver with any callee: it binds to the class's singleton/instance method when one is owned (`def self.call`, which the extractor indexes), else to the class node itself so inherited/dynamic class methods (ActiveRecord `where`/`find_by`) still give correct blast-radius. Namespaced receivers (`Billing::Processor.call`) resolve by the bare class name. The single-owning-class god-node guard is kept throughout — an ambiguous receiver resolves to nothing rather than a wrong edge. diff --git a/pyproject.toml b/pyproject.toml index 876602b..30d2a6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "graphifyy" -version = "0.9.5" +version = "0.9.6" description = "AI coding assistant skill (Claude Code, CodeBuddy, Codex, OpenCode, Kilo Code, Cursor, Gemini CLI, Aider, OpenClaw, Factory Droid, Trae, Hermes, Kiro, Pi, Devin CLI, Google Antigravity) - turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph" readme = "README.md" license = { file = "LICENSE" }