概述
Graphify v0.9.74~v0.9.79(2026-10-02~10-06,六個 patch 無跳號)延續「抽取深度 + 解析正確性」的節奏,這批最亮眼的是 v0.9.78 的決定性 (determinism) 批次:
- 可攜的 node id:graph.json 不再洩漏 checkout 路徑、OS 使用者名或行尾——同 repo 的 clone 在任何機器產生相同的圖
- intra-class 綁定:
self/this/super成員呼叫綁到呼叫者自身的 class chain(Python/JS/TS/Swift/Ruby) - watch 修復:v0.9.78 引入的 metadata 被 watch 誤判為 topology change——v0.9.79 收尾
一、決定性與可攜性(v0.9.78)
Release notes 的定位:「node ids no longer leak the checkout path, OS username, or line endings into graph.json, so a clone produces the same graph everywhere.」
三個具體修復:
- unresolved target 的 id:missing
require('./x')、missing Python 相對 import、.dmfelement 等未解析目標,改鑄可攜、clone 相同的 id - CRLF vs LF:C# namespace scope id 改以 row/column 為 key——CRLF checkout 不再寫出與 LF 不同的
scope_chain - 編碼:原始檔解析前先解碼——UTF-16 檔不再 0 節點、cp1252 名稱(如
CaféOrder)不再截斷
同版加上的 schema_version/graphify_version metadata 是 additive——既有讀取器與舊圖不受影響……除了 watch(見第五節)。
二、intra-class 呼叫綁定(v0.9.75)
self/this/super 成員呼叫原本綁到「檔案級最後定義」——現在綁到呼叫者自身的 class chain:
| 語言 | 行為 |
|---|---|
| Python | self./cls./super(),in-file MRO 最近祖先 |
| JS/TS | this.m() 綁到呼叫者自己的 class;super.m() fail closed(extends 鏈在該 pass 未知) |
| Swift | self/super,class vs struct/extension 感知 |
| Ruby | class chain 內的 self-send(補上 v0.9.74 的 paren-less self-send) |
多重繼承平手與未知/外部祖先一律 fail closed(不編造邊)。同版另修 C# partial-class 合併丟失遞迴 self-loop 的問題——一個 repo 出現 partial class 曾把全圖的遞迴邊清光(#4017)。
三、語言結構覆蓋持續擴充(v0.9.74~77)
- Ruby paren-less self-send 成 call(局部變數遮蔽正確抑制)
- TS
abstract方法簽名、Scala deferreddef、C++ class 內成員函式宣告(含 pure-virtual/operator/destructor) - Zig tagged-union variants 與 error-set、PHP enum cases、Elixir
defmacro/defguard系列、Rustmacro_rules!(std macros fail closed) - Scala 型別引用:file-scope
val/var註記、type alias RHS(含opaque type)、context bounds(def f[A: Ordering])成references - SQL trigger 以
executes連到執行的函式;Verilog.vhheader;Kotlin 註解 class-literal;Erlang local fun(fun Name/Arity)成indirect_call - C# null-conditional(
?.)、cast 與 interface-typed 呼叫(((IStore)x).Save());PowerShell 方法呼叫以 receiver owner 綁定;bash 經非 shell 直譯器(python3 build.py)叫用腳本成invokes - Dart
part檔保有檔案節點;條件 import 的所有 URI 分支都連
解析正確性代表:Rust prelude 型別(Option/Vec…)抽取期過濾,不再成為扭曲社群偵測的 god nodes;tuple-struct 建構由 calls 改 references/constructor;PHP 語言結構(isset、eval)不再綁到同名 user method;跨語言同名基底類別保持 unresolved;Svelte 只把 <script> 餵 AST(先前 template 的 parse error 會丟掉全部符號)。
四、安全修復(v0.9.76,CWE-22)
graphify hook install 拒絕解析後落在 repo 外的 core.hooksPath(雙邊解析、symlink-safe),改回退至 repo 內 .git/hooks——不再把執行檔寫到 checkout 之外。合法的 in-repo 自訂 hook 路徑、linked worktrees 與 submodules 仍可運作。
五、incremental / reload / watch 正確性
- hyperedge 保存(v0.9.74):以
(id, source_file)為 key,同 id 不同檔的邊不再被增量更新丟掉 - 子資料夾 update(v0.9.77):不再把 sibling 資料夾的檔案誤報為刪除
- 邊方向保存(v0.9.77/78):重載 graph.json 在五種匯出器(HTML、Cypher、Neo4j、FalkorDB、Obsidian-canvas)與 watch re-render 保留方向;
graph_diff保留方向(反轉邊報為變更) - placeholder 節點(v0.9.78):未掃描的引用目標不再被當成已刪除而掉邊
- reconcile 效能(v0.9.78):每路徑一次 identity 計算,graphify 自家 repo 的 reconcile 從 10.2s 降到 2.7s(graph.json 逐位元組相同)
- watch 收尾(v0.9.79):v0.9.78 的
schema_versionmetadata 被 watch 的 unchanged-topology 檢查計為變更——不變重建後每次都重新分群與渲染;現在排除於比較之外
阿榮升到 v0.9.78 後發現 watch 每次跑完都在重新分群與渲染,即使程式碼沒變。他該怎麼辦?
💡 想先看個提示?
「不變重建卻重新分群」= 比較把不該算的東西算進去了。
六、CLI 與快取
- hook-guard 以真實路徑包含檢查取代子字串比對——
artifacts/graphify-notes不再被誤判在artifacts/graphify之內 - workspace package 同時有 source 與 dist 時優先 source(
main/module比照exports) graphify extract拒絕以 dedup 縮小的圖覆蓋既有圖(除非--allow-dedup-shrink,回報實際合併數)graphify path經contains邊回到符號所在檔案——跨檔依賴經共享符號可達- AST cache 多 root 各寫各的
stat-index.json;merge-graphs --previous以 node id 恢復前次社群分配 - Ollama
num_ctx併入而非覆蓋extra_body;graphify 不再索引自身安裝的 skill 資料夾
隨堂總結測驗
兩位工程師分別在自己的機器 clone 同一個 repo 並執行 graphify,比對兩份 graph.json 的 node id。v0.9.78 之後會看到什麼?
💡 想先看個提示?
「portable, clone-identical」是關鍵詞。
動手升級檢查清單
升級 v0.9.79:動手檢查清單
逐項勾選,確認你已完成升級必要的步驟(進度會保存在此瀏覽器)
延伸閱讀
- 官方 v0.9.79 release notes
- 官方 v0.9.78 release notes
- 上一課:
v0970-to-v0973-security-and-enums——v0.9.70~73 的安全修復與 enum 擷取 - 版本紀錄:本主題的 Changelog 頁有完整的 v0.9.74~v0.9.79 條目