Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
2c49da2
feat: graphify clone <github-url> — clone any repo and run full pipel…
safishamsi Apr 23, 2026
2faeed9
feat: cross-repo merge-graphs; fix #527 CLAUDE_CONFIG_DIR; fix #524 g…
safishamsi Apr 23, 2026
df9b7ec
fix #479 #451: build_merge(), pre-write shrink guard, label dedup, ch…
safishamsi Apr 23, 2026
8bed332
release: bump to v0.5.0 — clone, merge-graphs, shrink guard, dedup, b…
safishamsi Apr 23, 2026
3ff7188
feat: add cross-language edge contexts and context-aware queries
TheFedaikin Apr 23, 2026
770d7f5
Add The Memory Layer book badge to README
safishamsi Apr 25, 2026
c3ba79f
feat(tree): graphify tree — D3 v7 collapsible-tree HTML emitter
dsremo Apr 26, 2026
a523509
fix(tree): escape title, header, and JSON blob in emit_html
dsremo Apr 27, 2026
6175e0a
fix #547 #559 #570: expand ~ in hooksPath, fix gitignore inline comme…
safishamsi Apr 27, 2026
4563b04
Fix 6 bugs: ID collisions, path portability, alias resolution, HTML c…
safishamsi Apr 27, 2026
a566bfb
Bump to v0.5.1
safishamsi Apr 27, 2026
a1dc610
feat(extract): add dynamic import() extraction for JS/TS
Yalkowni Apr 27, 2026
88e2b83
fix: drop Python <3.14 upper bound
Yalkowni Apr 27, 2026
563ee80
fix(extract): skip dynamic template literals in import() args
Yalkowni Apr 27, 2026
ee1df22
Fix PreToolUse hook for Claude Code v2.1.117+ (Glob|Grep → Bash matcher)
safishamsi Apr 27, 2026
7359cda
Fix AST/semantic cache namespace collision breaking graphify update (…
safishamsi Apr 28, 2026
dd86271
Fix SSRF DNS rebinding TOCTOU and yt-dlp URL bypass (#591, #592)
safishamsi Apr 28, 2026
eceaaad
Add v0.5.4 release notes to README
safishamsi Apr 28, 2026
5904081
Add Kimi K2.6 backend, fix phantom god nodes (#598), fix concept file…
safishamsi Apr 29, 2026
59cbad3
Fix Go package-call false-negative and llm.py robustness
safishamsi Apr 29, 2026
f9c344b
Remember scan root so graphify update works without a path arg
safishamsi Apr 29, 2026
a4ad901
Update v0.5.5 release notes in README
safishamsi Apr 29, 2026
71d1b39
fix NameError in Kimi tip: use module-level os import instead of _os
safishamsi Apr 29, 2026
c750582
fix SyntaxWarning: use raw string for shell glob pattern with backsla…
safishamsi Apr 29, 2026
7448271
update product site: fix pip install package name to graphifyy, updat…
safishamsi Apr 29, 2026
44fc32e
add product-site as part of graphify repo (was separate submodule)
safishamsi Apr 29, 2026
326c03e
remove product-site from graphify repo
safishamsi Apr 29, 2026
28b17d3
remove Python upper bound to support 3.14+ (fixes #607)
safishamsi Apr 29, 2026
a9946fb
Merge remote-tracking branch 'upstream/v5' into v5
TheFedaikin Apr 29, 2026
f755aca
fix kimi temperature 400 error and community label deletion on cleanu…
safishamsi Apr 29, 2026
4360f96
move changelog out of README into CHANGELOG.md, add yt-dlp legal notice
safishamsi Apr 29, 2026
abb1450
docs: add Docker MCP Toolkit + SQLite MCP runbook
chronicgiardia Apr 29, 2026
97099ed
bump to v0.5.6
safishamsi Apr 30, 2026
4e871ad
swap downloads badge to shields.io for cache refresh
safishamsi Apr 30, 2026
3755fdc
swap downloads badge back to pepy.tech
safishamsi Apr 30, 2026
cc5c545
feat(llm): pack chunks by token budget, parallelise, accept tiktoken
jasonm4130 Apr 30, 2026
2d13a17
feat(llm): split and retry chunks that hit max_completion_tokens trun…
jasonm4130 Apr 30, 2026
5aaa268
add yaml/yml to DOC_EXTENSIONS so k8s/kustomize corpora are indexed (…
safishamsi Apr 30, 2026
47a994a
bump to v0.5.7
safishamsi Apr 30, 2026
0999822
update README: add yaml/yml to file type table and feature description
safishamsi Apr 30, 2026
7d604e8
v6: SQL AST extractor + xlsx structural extraction utility (fixes #349)
safishamsi May 1, 2026
ad1e11a
update README: add SQL support to file type table and feature descrip…
safishamsi May 1, 2026
17fb524
bump to v0.6.0
safishamsi May 1, 2026
6b68de1
stop .graphifyignore walk at any VCS root or home dir, not just .git …
safishamsi May 1, 2026
8a6306f
make .graphifyignore hermetic: stop at VCS root, not project boundari…
safishamsi May 1, 2026
7f336ac
fix .graphifyignore: correct gitignore semantics + hermetic non-VCS s…
safishamsi May 1, 2026
14fd14a
combine what+when in skill description
safishamsi May 1, 2026
2dc759a
bump to v0.6.1
safishamsi May 1, 2026
5dbbcf7
feat: add VB.NET (.vb) language support via tree-sitter
rrangraj May 1, 2026
e73b606
fix #590 #628 #629 #630 #619 #617: directed graph, negation patterns,…
safishamsi May 1, 2026
3fdae8f
fix #623 #621 #605 #638 #589 #586 #593: kimi thinking, manifest, inli…
safishamsi May 1, 2026
be83a8c
bump to v0.6.2
safishamsi May 1, 2026
af15e33
feat: add extraction support for VB.NET files
rrangraj May 2, 2026
0fc2dc6
feat: implement parallel AST extraction using ProcessPoolExecutor wit…
hanzala-sohrab May 2, 2026
c8969ed
Fix semantic node preservation on incremental rebuild and detach git …
safishamsi May 2, 2026
028f585
Fix ambiguous cross-file call resolution inflating god_nodes and guar…
safishamsi May 2, 2026
a4149df
Bump version to 0.6.3
safishamsi May 2, 2026
8c9ee18
Fix Codex PreToolUse hook failing on Windows
safishamsi May 2, 2026
a61b25c
Bump version to 0.6.4
safishamsi May 2, 2026
c3ddace
Update README git hooks description to reflect detached background re…
safishamsi May 2, 2026
71423a1
Kotlin call-walker: accept both simple_identifier and identifier (#659)
michalharakal May 2, 2026
8e01d68
feat: replace show/hide buttons with checkbox-based multi-select cont…
hanzala-sohrab May 2, 2026
ca48092
Add --force flag and GRAPHIFY_FORCE env var to graphify update
safishamsi May 2, 2026
e02c7cc
Fix Codex PreToolUse hook on Windows by delegating to graphify hook-c…
safishamsi May 2, 2026
d40e1c0
Bump version to 0.6.5
safishamsi May 2, 2026
36e894a
v0.6.6: Windows skill bash rewrite, wiki fixes, rationale-node fix, h…
safishamsi May 2, 2026
47ca922
security: add usedforsecurity=False to MD5/SHA1 hashes used for file …
safishamsi May 2, 2026
5a342e3
fix(extract): emit symbol-level edges for TS/JS named imports
RubenAAA May 2, 2026
763a935
Add Pi coding agent support and tighten wheel packaging
safishamsi May 2, 2026
893219d
docs: add Pi coding agent to README platform table and install docs
safishamsi May 2, 2026
58271fb
docs: add Pi to pyproject.toml description and keywords
safishamsi May 2, 2026
9ab4f39
Merge pull request #662 from RubenAAA/fix/ts-named-import-symbol-edges
safishamsi May 2, 2026
996e82b
test: add regression test for ambiguous cross-file call resolution (#…
safishamsi May 2, 2026
d04e487
Merge branch 'safishamsi:v6' into feat/parallel-ast-extraction
hanzala-sohrab May 2, 2026
7237cd3
feat: add VB.NET (.vb) language support via tree-sitter (#648)
safishamsi May 2, 2026
66e61c7
docs: add Docker MCP Toolkit + SQLite MCP runbook (#620)
safishamsi May 2, 2026
24808ef
merge PR #625: token-aware chunking with split-and-retry on truncation
safishamsi May 2, 2026
9881d7c
merge PR #557: graphify tree — D3 v7 collapsible-tree HTML view of gr…
safishamsi May 2, 2026
28047b5
merge PR #573: cross-language edge context filters in MCP query tool
safishamsi May 2, 2026
bfe18f0
fix: add context=import to JS/TS named-import edges (caught by PR #57…
safishamsi May 2, 2026
2ca3a59
merge PR #579: dynamic import() extraction for JS/TS
safishamsi May 2, 2026
1e84845
remove VB.NET support: tree-sitter-vbnet only has Windows wheels, no …
safishamsi May 2, 2026
0a99a46
chore: update project dependencies and metadata in pyproject.toml
hanzala-sohrab May 2, 2026
bd92ab6
docs: remove VB.NET from README language count and file type table
safishamsi May 2, 2026
d819827
fix #655 #656 #657 #658: cache dir crash, sanitize_label None, ration…
safishamsi May 2, 2026
e484282
bump version to 0.6.7
safishamsi May 2, 2026
ba41258
merge PR #663: parallel AST extraction with ProcessPoolExecutor (1.66…
safishamsi May 2, 2026
cf7ce3a
fix #651: hook-check exits silently instead of emitting unsupported a…
safishamsi May 2, 2026
96267ad
fix #651: resolve absolute graphify path at codex install time for VS…
safishamsi May 2, 2026
893acb1
Fix #664: filter thin communities from GRAPH_REPORT.md by default
safishamsi May 2, 2026
f065933
Fix #676 #678 #681: graphifyignore negation, Antigravity slash comman…
safishamsi May 3, 2026
d753413
bump version to 0.6.8
safishamsi May 3, 2026
b11a8a7
simplify README, move technical details to docs/how-it-works.md
safishamsi May 3, 2026
de268a0
fix Penpax waitlist link to graphifylabs.ai
safishamsi May 3, 2026
f61bb27
Fix #688: stricter VS Code Copilot instructions to enforce GRAPH_REPO…
safishamsi May 3, 2026
6df69dc
Fix #683: normalize source_file path separators + two-phase cohesion …
safishamsi May 3, 2026
8e81720
Fix #686 #652: GRAPHIFY_OUT env var for worktrees, Antigravity instal…
safishamsi May 3, 2026
f81e3bc
bump version to 0.6.9
safishamsi May 3, 2026
64b9515
fix(antigravity): use .agent instead of .agents for Antigravity paths
gavy0037 May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,146 @@

Full release notes with details on each version: [GitHub Releases](https://github.com/safishamsi/graphify/releases)

## 0.6.9 (2026-05-03)

- Fix: `source_file` path separators normalized to forward slashes at graph ingestion — same physical file emitted with backslashes (Windows AST extractor) and forward slashes (semantic subagents) now merges into one node instead of splitting into two disconnected components (#683)
- Fix: two-phase cohesion re-clustering — communities with cohesion < 0.05 and ≥ 50 nodes are re-split, preventing doc-hub nodes (e.g. `CLAUDE.md`) from merging unrelated subsystems into one giant community (#683)
- Fix: VS Code Copilot instructions rewritten to be prescriptive — agent's first tool call must read `GRAPH_REPORT.md`, explicit trigger list, narrow allowlist for raw source reads (#688)
- Feat: `GRAPHIFY_OUT` env var overrides the output directory — accepts a relative name or absolute path, wires through `cache.py`, `watch.py`, and the CLI; useful for sharing one graph across multiple git worktrees (#686)
- Fix: `graphify antigravity install` now auto-updates stale rules and workflow files on re-run instead of silently skipping them (#652)
- Docs: README simplified — less dense, plain language; technical pipeline details moved to `docs/how-it-works.md`

## 0.6.8 (2026-05-03)

- Fix: `.graphifyignore` negation patterns (`!src/**`) now work correctly — when any `!` pattern is present, directory pruning is deferred to per-file checks so negated files inside ignored directories are reached (#676)
- Fix: Antigravity slash command `/graphify` now appears in the command dropdown — workflow file now includes YAML frontmatter with `name: graphify` required for Antigravity discovery (#678)
- Fix: Gemini CLI BeforeTool hook replaced `[ -f ... ] && echo` (bash-only) with cross-platform `python -c` using `json.dumps` — fixes hook failure on Windows CMD and Git Bash (#681)
- Fix: Codex hook-check exits silently — resolves `additionalContext` rejection on Codex Desktop PreToolUse (#651)
- Fix: `graphify install --platform codex` now writes absolute path to `graphify` executable — fixes PATH resolution in VS Code extension on Windows (#651)
- Fix: thin communities (fewer than 3 concept nodes) are now omitted from the Communities section in `GRAPH_REPORT.md` by default; report header shows `(N total, M thin omitted)` and Knowledge Gaps collapses thin communities to one summary line (#664)

## 0.6.7 (2026-05-02)

- Feat: `graphify tree` — self-contained D3 v7 collapsible-tree HTML view of `graph.json`; expand/collapse controls, depth-based colours, hover inspector; XSS-safe (#557)
- Feat: token-aware chunking with split-and-retry on truncation (#625)
- Feat: cross-language edge context filters in MCP `query_graph` tool (#573)
- Feat: dynamic `import()` extraction for JS/TS (#579)
- Fix: `save_semantic_cache` crashed with `IsADirectoryError` when a node's `source_file` was a directory path — `p.exists()` → `p.is_file()` (#655)
- Fix: `sanitize_label(None)` raised `TypeError` crashing `to_html` on graphs with null `source_file` rationale nodes — return `""` early (#656)
- Fix: chunk-extraction prompt omitted `rationale` from valid `file_type` values — model hallucinated `concept` on every doc/paper run; explicit merge step added to all skill variants (#657)
- Fix: `cost.json` always reported 0 tokens — chunk JSONs have placeholder zeros; orchestrator now globs and sums real token counts before merging (#658)
## 0.6.6 (2026-05-02)

- Fix: `skill-windows.md` rewritten from PowerShell to bash — Claude Code on Windows uses git-bash so PowerShell syntax (`$null`, `$LASTEXITCODE`, `Select-Object`, `& (Get-Content ...)`, `Remove-Item`) caused exit code 49 failures; now mirrors `skill.md` structure with `python` added as fallback after `python3` for Windows Conda (#39)
- Fix: wiki `to_wiki()` now clears stale articles before regenerating, preventing orphan .md accumulation (#558)
- Fix: `_safe_filename()` in wiki.py now strips Windows-reserved characters (`< > : " / \ | ? *`) and caps length at 200 chars (#594)
- Fix: rationale-node leakage in cross-file INFERRED call resolution — rationale nodes now excluded from name lookup; edge direction (`calls`, `rationale_for`) preserved correctly at JSON export (#576)
- Feat: `.graphifyinclude` hidden path allowlist — opt specific hidden dirs into traversal (e.g. `.hermes/plans/**/*.md`) (#583)
- Feat: `--no-viz` flag wired in `cluster-only`; `GRAPHIFY_VIZ_NODE_LIMIT` env var overrides 5000-node HTML threshold (#565)
- Fix: stray colon SyntaxError in `skill-trae.md` `--cluster-only` block (#603)
- Docs: skill INFERRED confidence score guidance changed to discrete rubric (0.55/0.65/0.75/0.85/0.95) backed by calibration data (#546)
- Docs: skill `--update` prune output clarified — splits no-drift vs drift cases (#544)
- Docs: skill `--update` merge step now calls `save_manifest` to prevent deleted files reappearing (#545)
- Feat: `graphify tree` — self-contained D3 v7 collapsible-tree HTML view of `graph.json`; expand/collapse controls, depth-based colours, hover inspector; XSS-safe via `html.escape()` and `_js_safe()` (#557)

## 0.6.5 (2026-05-02)

- Fix: Kotlin call-walker now accepts both `simple_identifier` and `identifier` node types — PyPI's `tree_sitter_kotlin` grammar uses `identifier` while older forks use `simple_identifier`, causing zero `calls` edges to be emitted (#659)
- Feat: community sidebar now uses checkbox-based multi-select instead of show/hide buttons — supports indeterminate "select all" state (#647)
- Feat: `graphify update --force` and `GRAPHIFY_FORCE=1` env var — bypass the node-count safety check after refactors that legitimately shrink the graph (#639)
- Fix: Codex PreToolUse hook on Windows — replaced `python3 -c "..."` inline command (fails on Conda where only `python` exists, and breaks PowerShell JSON parsing) with `graphify hook-check`, a new shell-agnostic subcommand. Re-run `graphify codex install` to regenerate the hook (#651, #522)

## 0.6.4 (2026-05-02)

- Fix: Codex PreToolUse hook failed on Windows — `[ -f ]` is bash-only and crashes on `cmd.exe`; replaced with a cross-platform Python one-liner (`pathlib.Path.exists()`) (#651)

## 0.6.3 (2026-05-02)

- Fix: incremental rebuild (`graphify update`, post-commit hook) dropped INFERRED/AMBIGUOUS semantic nodes extracted from code files — node preservation now filters by ID membership in the new AST output instead of `file_type`, so LLM-extracted call/data-flow edges survive code-only rebuilds (#653)
- Fix: post-commit and post-checkout hooks blocked `git commit` for the full rebuild duration (hours on large repos) — rebuilds now detach via `nohup & disown`, git returns in ~100ms, log written to `~/.cache/graphify-rebuild.log` (#650)
- Fix: cross-file INFERRED `calls` resolution used a last-write-wins name map, causing common short names (`log`, `execute`, `find`) to accumulate hundreds of spurious edges and dominate god_nodes ranking — resolution now skips any callee name that matches 2+ candidates (ambiguous, no import evidence to pick the right target) (#543)
- Fix: `cluster-only` command crashed on graphs with >5000 nodes due to unguarded `to_html` call — now wrapped in try/except ValueError matching the watch/hook path (#541)

## 0.6.2 (2026-05-01)

- Fix: Kimi K2.6 reasoning mode consumed entire token budget leaving `content` empty — thinking now disabled on Moonshot calls so graphs actually populate (#623)
- Fix: `graphify update` / `graphify watch` never persisted the manifest, so every subsequent `--update` re-extracted all files — manifest now saved after each rebuild (#621)
- Fix: inline comments in `.graphifyignore` (e.g. `vendor/ # legacy`) now stripped correctly — whitespace + `#` suffix is treated as a comment, `path#hash.py` preserved (#605)
- Fix: `graphify query "FunctionName"` now returns the exact matching node first instead of high-degree hub modules hijacking the output — 100-point exact-match bonus + seeds render before BFS expansion (#638)
- Fix: concurrent AST extractors raced on a shared `.tmp` cache file — each writer now gets a unique tempfile via `mkstemp`, eliminating cache corruption under parallel extraction (#589)
- Fix: `_clone_repo` branch names starting with `-` could be interpreted as git flags — validation added, `--` separator inserted before positional args (#589)
- Fix: replaced `html2text` (GPL-3.0) with `markdownify` (MIT) — removes the only copyleft dependency from a MIT project (#586)
- Fix: `--update` re-extracted files whose mtime was bumped by sync tools (Obsidian, Nextcloud) without content changes — manifest now stores content hash alongside mtime; mtime bump triggers an MD5 check before re-extraction (#593)
- Feat: R language support — `.r` files classified as code and processed via LLM semantic extraction (#617)
- Feat: extensionless shell scripts now detected via shebang (`#!/bin/bash`, `#!/usr/bin/env python3`, etc.) and included as code (#619)
- Fix: cross-language INFERRED `calls` edges (e.g. Python→TypeScript name collision) no longer appear as top surprising connections in GRAPH_REPORT.md (#630)
- Fix: `cluster-only` CLI silently flipped directed graphs to undirected — `directed` flag now read from graph.json and preserved through re-clustering (#590)
- Fix: Windows UNC / extended-length paths (`\\?\C:\...`) now normalize to consistent cache keys (#629)
- Fix: `.graphifyignore` negation patterns (`!src/lib/secrets.ts`) now work — full last-match-wins evaluation with `!` un-ignore support (#628)

## 0.6.1 (2026-05-01)

- Fix: `.graphifyignore` discovery now uses correct gitignore semantics — outer rules are loaded first so inner (closer) rules always win via last-match-wins, matching standard gitignore behavior (#643)
- Fix: without a VCS root, `.graphifyignore` discovery is now hermetic to the scan folder — no leakage across sibling projects in a shared workspace (#643)
- Fix: anchored patterns (leading `/`) in a parent `.graphifyignore` now correctly apply only relative to their own directory, not the scan root (#643)
- Fix: trailing spaces in patterns are now handled per gitignore spec — unescaped trailing spaces are stripped, `vendor\ ` (escaped) is preserved (#643)

## 0.6.0 (2026-05-01)

- Feat: SQL AST extractor — `.sql` files now processed deterministically via tree-sitter. Extracts tables, views, functions/procedures, foreign key references, and FROM/JOIN reads_from edges. No LLM needed. Requires `pip install 'graphifyy[sql]'` (#349)
- Feat: `xlsx_extract_structure()` utility — extracts sheet names, named tables, and column headers from .xlsx files as structural nodes

## 0.5.7 (2026-04-30)

- Feat: YAML/YML files now indexed for semantic extraction — Kubernetes, Kustomize, Helm, and any YAML corpus now picked up automatically (#633)

## 0.5.6 (2026-04-30)

- Fix: `NameError: name '_os' is not defined` crash after `graphify update` — this was fixed in v5 branch but not released to PyPI (#618, #612)

## 0.5.5 (2026-04-29)

- Feat: Kimi K2.6 backend — `pip install 'graphifyy[kimi]'` + `MOONSHOT_API_KEY` routes semantic extraction through Kimi K2.6. 3-6x richer relation extraction at ~3x lower cost. Claude remains default; Kimi is opt-in.
- Fix: phantom god nodes (#598) — member-call callees (`this.logger.log()` → `log`) no longer cross-file resolved. Go package-qualified calls (`pkg.Func()`) correctly preserved. Affects JS/TS, Go, Rust, Swift, Kotlin, Scala, PHP, C++, C#, Zig, Elixir.
- Fix: `concept` file_type no longer triggers validation warnings (#601)
- Fix: `graphify update` remembers scan root via `graphify-out/.graphify_root` — no path argument needed on subsequent runs
- Fix: Kimi K2.6 temperature 400 error — temperature param is now skipped for Kimi backends (model enforces its own fixed value) (#610)
- Fix: community labels deleted in Step 9 cleanup — `.graphify_labels.json` is now preserved so wiki/obsidian/HTML retain human-readable names after re-cluster (#608)
- Fix: `NameError: name '_os' is not defined` in `graphify update` Kimi tip (#612)
- Fix: `SyntaxWarning` in `__main__.py` for shell glob pattern with backslash escapes
- Fix: Python upper bound removed — `requires-python = ">=3.10"` now supports Python 3.14+ (#607)

## 0.5.4 (2026-04-28)

- Fix: SSRF DNS rebinding — `safe_fetch` now patches `socket.getaddrinfo` for the full request duration (#591)
- Fix: yt-dlp SSRF bypass — `download_audio` now calls `validate_url` before handing URL to yt-dlp (#592)

## 0.5.3 (2026-04-27)

- Fix: cache namespace — AST and semantic entries now live in `cache/ast/` and `cache/semantic/` subdirectories; flat entries read as migration fallback

## 0.5.2 (2026-04-26)

- Fix: PreToolUse hook now matches on `Bash` instead of `Glob|Grep` for Claude Code v2.1.117+

## 0.5.1 (2026-04-25)

- Fix: node ID collision for same-named files in different directories
- Fix: `source_file` paths relativized before return so `graph.json` is portable
- Fix: desync guard — `to_json()` returns bool; report only written on successful JSON write
- Feat: TypeScript `@/` path aliases resolved via `tsconfig.json`
- Feat: Show All / Hide All buttons in HTML community panel

## 0.5.0 (2026-04-24)

- Feat: `graphify clone <github-url>` — clone and graph any public repo
- Feat: `graphify merge-graphs` — combine multiple `graph.json` outputs into one cross-repo graph
- Feat: `CLAUDE_CONFIG_DIR` support in `graphify install`
- Feat: shrink guard — `to_json()` refuses to overwrite with a smaller graph
- Feat: `build_merge()` for safe incremental updates
- Feat: duplicate node deduplication via `deduplicate_by_label()`
- Fix: `graphify-out/` excluded from source scanning

## 0.4.23 (2026-04-18)

- Fix: stale skill version warning persists after running `graphify install` when multiple platforms were previously installed — `graphify install` now refreshes `.graphify_version` in all other known skill directories so the warning clears across the board (#178)
Expand Down
Loading