analyze.py(749 行)· report.py(300 行)圖建好、分好群之後,analyze 負責「找出這張圖值得說的事」,report 負責把它排版成 GRAPH_REPORT.md——也就是你的 AI 助手會先讀的那份摘要。
「god node = 最高度數節點」這個直覺很簡單,但實作關鍵在「排除誰」:
_is_file_node)排除——它們機械式地累積 import/contains 邊,不代表真正的架構抽象。_is_concept_node)與 JSON key 節點排除。_BUILTIN_NOISE_LABELS 排除——這是 0.8.33 修的 bug:str、int、MagicMock 等內建型別節點曾灌爆度數、把真正的抽象擠出 god-node 排名。「驚喜連線」是報告最有趣的一段。策略依語料規模分流:
is_multi_source):找「跨檔的實體之間」的邊,排序 AMBIGUOUS → INFERRED → EXTRACTED(越不確定越值得看)。概念節點被排除——它們是刻意加入的,不是被發現的。
問題來源有四種,每個都帶 type / question / why 三個欄位:
X 和 Y 的確實關係是什麼?」(因為那條邊被標不確定)。這種「由圖結構自動生成問題」的能力,正是報告「4-5 個建議問題」的來源——也是 Graphify 最有產品感的輸出之一。
回傳「N 檔循環」,供報告的 Import Cycles 章節使用。只對含程式碼的語料有意義——文件語料沒有 import,那一段會是純噪音,所以 report.py 會先檢查圖裡有沒有 code 才輸出。
段落式說明:以 (u, v, relation) 為邊 key 做集合差異,算出新增/移除的節點與邊。這是 graphify update / PR 影響分析背後的差集工具。
300 行的純函數:generate() 接收所有分析結果,回傳一份 markdown 字串。章節順序即報告的閱讀順序:
built_at_commit(0.7.0 加入,讓團隊能查圖是否過期)。--obsidian 時輸出 wikilink,否則純清單(避免預設輸出一堆斷鏈)。.graphify_learning.json 來的學習覆蓋層(0.9.x 新功能)。段落式說明:
_safe_community_name(label) — 把社群名變成安全檔名(與 export 的 safe_name 同步),確保 hub 檔名與報告 wikilink 一致。_learning_section(lines, learning, top_n) — 附加「Work-memory lessons」章節:preferred 來源(過去 session 證實有用)與 dead_ends(帶到死路的問題)。都沒有時整個章節省略。load_learning_for_report(graph_path) — 讀取 .graphify_learning.json 覆蓋層與 memory docs,best-effort(永遠不 raise,失敗就回 None)。前面是「理解 god nodes 怎麼算」;這次是把 analyze 變成決策工具:你的團隊要在 dedup.py 重構前,先回答「這會影響哪些社群、哪些跨檔邊」。
graphify extract .,存一份 graph-before.json(含 built_at_commit)。graphify update . 增量建圖,存 graph-after.json。graph_diff(G_old, G_new) 或對應 CLI——得到新增/移除的節點與邊(以 (u,v,relation) 為 key 的集合差)。graph_diff 看到的是「這條依賴斷了、這個社群被波及」——結構層的影響是文字 diff 看不見的。而且它與報告的「稽核性質」一致:每個「影響」都可回溯到具體的節點/邊,不是 LLM 的推測。analyze 頁兩個函數最值得深挖:
_BUILTIN_NOISE_LABELS(str/int/MagicMock…)——最後一項是 0.8.33 修掉的真實 bug:內建型別灌爆度數、把真抽象擠出排名。這說明「找核心抽象」的問題定義(什麼算雜訊)比演算法(sort by degree)難得多。--obsidian 才輸出 wikilink 的 Community Hubs,避免預設報告一堆斷鏈。報告會「知道什麼時候該閉嘴」。errors.py 的 exception 類別可能度數很高(人人 import),但它是協議細節不是核心流程。更隱晦的:degree 是無向的,把 calls 的方向資訊丟了;一個「被 50 個檔呼叫」的 util 與「呼叫 50 個函數的 orchestrator」度數相同,但架構意義完全不同。讀 god nodes 時要回到有向圖查 direction。| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| god nodes 出現預期外的工具類/設定類節點 | 排除清單沒覆蓋(新語言型別、設定 key 未被視為 JSON key 節點) | 檢查 _BUILTIN_NOISE_LABELS 與 _is_concept_node/_is_json_key_node 的判定 |
| surprising connections 全是不重要的邊 | 多檔語料下「跨檔實體邊」太多,排序被 AMBIGUOUS 灌滿 | 調整 top_n;對照單檔語料改用跨社群橋樑策略 |
graph_diff 回報大量假性新增/移除 | 節點 ID 不穩定(hash 型 ID 或順序依賴)導致同節點被算成不同 | 確認 ID 用穩定規範({parent_dir}_{stem});排除順序差異造成的噪音 |
| 報告出現「沒有 import 的 Import Cycles」 | 文件語料仍輸出了 code 專屬章節 | 確認 report.py 的「圖裡有沒有 code」檢查有生效(升級版本) |
| 建議問題(suggested questions)問不到重點 | 問題由結構啟發(AMBIGUOUS 邊、橋樑節點),不是語意啟發 | 把它當「結構提議」而非「領域問題」;用 path/explain 人工補足語意深度 |