Theme / v0.9.73

Graphify

Codebase 知識圖譜

基礎觀念

v0.9.57 → v0.9.65:Terraform、外部 Stub 節點與增量重建正確性

理解 v0.9.57~v0.9.65 九個 patch 的重點:Terraform 模組拓撲與屬性(含 secret redaction)、Elixir/Go/Swift 語言擴充、dangling edge 終結者 external stub node,以及增量重建不再丟節點的系列修正。

為什麼這九個 patch 值得學

v0.9.57~v0.9.65(2026-09-09 至 2026-09-20)延續 Graphify 一貫的主題:知識圖譜的價值取決於邊的可信度。這批 patch 修的都是「圖看起來建好了,但內容默默地錯了」的問題——增量重建丟節點、 dangling edge 物化成幻影、合併時資訊較少的節點贏過較完整的。

Terraform 進圖(v0.9.62、v0.9.64)

兩個版本把 Terraform 從「文字檔」變成「拓撲」:

模組呼叫拓撲(v0.9.62,#3571)

module call 帶字面 local source(./… 或 ../…)時,現在解析到 directory-scoped module node,揭露 caller → implementation 的分層(例如 environment → application → base)。

保守邊界不變:remote 與 registry source、以及任何 source 運算式都不猜、不偽造目標。

屬性保留與 secret redaction(v0.9.64,#3644)

resource / data / module node 現在保留 block attributes(ami、instance_type、cidr_block、tags 等),帶型別(bool/number/list/map)、nested block 與直接屬性分開,可查詢可搜尋。

安全設計:secret 命名的屬性值在進入 graph.json 或模型之前先 redact——password、*secret*、*token*、*_key、連線字串都算。寫死在 .tf 檔裡的 credential 不會因為建圖而外洩。

升級既有 graph 後,跑一次 graphify update . 重建 Terraform id 與拓撲。

Dangling Edge 的終結者:External Stub Node(v0.9.63)

過去 graph.json 裡 imports / imports_from / re_exports 邊的端點可能指向外部模組(stdlib、第三方套件)——一個從未宣告過的節點。載入器(loader)會把這種 dangling endpoint 物化成沒有屬性的幻影節點。

v0.9.63 起:

  • 對外部模組的邊改為鑄造 typed external stub node(有類型的外部存根節點)
  • graph.json 裡每條邊的每個端點都保證是宣告過的節點
  • 跨 repo merge 把同一個外部模組統一成單一 global node

「不變式(invariant)寫進格式」比「載入器要記得處理例外」可靠——這是把正確性從慣例升級為結構。

增量重建不再丟節點(v0.9.57、v0.9.59、v0.9.65)

三個 patch 分別堵住三條靜默丟失路徑:

版本 問題 修法
v0.9.57(#3411) 重萃取一個 .csproj/.sln 會丟掉被參照專案的 package/framework 節點 AST-replacement set 改從實際萃取的檔案推導
v0.9.59(#3477) 增量重建丟掉未觸及檔案的 cross-file concept 節點 merge 時的 global dedup 保護未觸及檔案的既有節點
v0.9.65 eviction pass 剛報告「保留」的節點又被清除;moved-file/symlink layout 會把 shrink guard 卡死到拒絕每次 update eviction pass 重查 kept set

共同教訓:增量系統的 bug 通常不是「更新了不該更新的」,而是「以為自己沒動到的其實動到了」。

跨檔 Resolution 擴充(v0.9.58~v0.9.65)

這批語言層的改進全部遵循同一個原則:只在無歧義時才連邊。

  • Ruby:隱式 self 呼叫與已知型別 receiver 的 member call,可沿單一無歧義繼承鏈升級到 superclass method(#3569、#3585);mixin、reopened class、動態 superclass 一律不猜
  • Rust:self.method() 跨檔解析到 split-impl 同型別的 method(v0.9.63,#3602);v0.9.64 擴及簡單 generic impl(impl<T> Foo<T>),bounded / where / trait 形狀仍 fail-closed(#3653)
  • Kotlin:receiver 呼叫跨檔解析到另一檔宣告的 object / class / companion object(#3598)
  • C++:scope-qualified static call Foo::bar() 跨 translation unit 解析(#3613)
  • Go / Swift:interface 的 method requirements(type Foo interface { Bar() })與 protocol 的 func f() 附加到 interface / protocol 節點本身(#3672、#3673)
  • Elixir:alias / import / require / use 解析到 defmodule 節點,模組依賴圖不再是 dangling(#3603);僅頂層模組索引
  • Python:巢狀函式依 lexical scope 解析(#3410);PEP 420 namespace package 子模組 import(#3429);同層平目錄 bare-name import 模擬 sys.path[0](#3430)
  • JS/TS:let/const 綁定改為 block-scoped——block-local 綁定不再壓制同函式其他地方真實的 indirect_call 邊;var 維持 function-scoped(v0.9.65,#3688)
  • PHP:use Foo\Bar as Baz; 以 alias 為 key,後續 Baz 解析到真實 class(#3421);檔內 inline <script> 以 JS 索引並映射回真實行號(#3627)
  • Java / Verilog:enum body member 掛回 enum 節點、enum 內部呼叫可解析(#3674);module instantiation 連本地定義而非幻影重複(#3675)

Markdown 參考邊(v0.9.62,#3562)

文件裡的 inline code span(例如 `Widget.render`)在整個 corpus 恰有一個 callable 匹配時,發出 references 邊。generic 詞彙與歧義名稱不連——文件加入圖,而不產生假邊洪流。

另外:檔名是裸複數「tokens」的文件(如 TOKENS.md)不再被誤判為 credential dump(#3527)。

效能與可攜性

  • Python symbol resolution 快約 47%(v0.9.59):path resolution memoize、每檔跨兩個 pass 只解析一次、tree walk 改迭代式
  • Python 3.12 / 3.13:graphify.serve 可正常 import;chinese extra 自 3.12 起改 pin jieba-py(v0.9.61)
  • Python 3.14 支援(v0.9.60)
  • Windows:atomic write 在 WinError 17(跨磁碟區)正確 fallback(v0.9.60)
  • 可見性:無法分類的檔案以計數與 top extensions 呈現,不再從「成功」run 中消失(#3511)

安全(v0.9.65,#3698)

svg / all extras 對 Pillow 加下限 >=12.3.0,修 CVE-2026-54058(Pillow 經 matplotlib 間接被拉入)。

注意:Pillow 12.3.0 已不提供 glibc < 2.27 的 cp310 Linux wheel——老舊 glibc + Python 3.10 主機裝這兩個 extra 時會從 sdist 建置。

升級建議

情境 建議
有 Terraform 必跑 graphify update .(重建 module id 與拓撲)
依賴 Rust / Kotlin / Ruby 繼承鏈、Elixir module graph 建議 rebuild
svg / all extra + 老 glibc 注意 Pillow 可能從 sdist 建置
其他 一般升級即可,增量索引延續

來源:v0.9.57~v0.9.65