src/index.ts — CodeGraph class

對外唯一入口:library、CLI、MCP server 全部驅動這一個 class
檔案:src/index.ts · 分層 pipeline 的「總電源開關」

大方向

src/index.ts 定義 CodeGraph class,把四層接起來:db → extraction → resolution → graph/context,並 re-export 全部型別與底層積木(DatabaseConnectionQueryBuilderFileWatcher…)。constructor 是 private,一律用 static factory(init/open/recreate)。關鍵設計:同一份 API 給 library 用、也給 CLI 與 MCP server 用,所以這裡的每個方法你都能在 CLI 指令與 MCP 工具上看到對應。


1. 生命週期:init / open / recreate / close

CodeGraph.init / open static建新專案(可含初始索引)或開既有專案(可含 sync)。

initinitGrammars() 載入 tree-sitter grammars → 檢查是否已初始化(是則 throw)→ createDirectoryDatabaseConnection.initialize 建 .codegraph/codegraph.db → 依 options.index 決定要不要立刻 indexAll

open:先 validateDirectory 驗證結構,再 DatabaseConnection.open,依 options.sync 決定要不要先增量同步。一個先後差異:init 預設不索引,open 預設不 sync——都要明確傳旗標。

教學重點:這解釋了 CLI 的 codegraph init 為何「建目錄 + 建圖一步完成」——init 呼叫內部會傳 { index: true }
reopenIfReplaced src/index.ts在途修復「.codegraph 被刪重建」後的陳舊 DB handle。

如果 .codegraph/ 被移除又在同一路徑重建(git worktree 移除重加、rm -rf .codegraph + codegraph init),我們開著的 fd 指向已 unlink 的 inode,永遠看不到新索引。此方法偵測到就先開新檔(失敗則舊 handle 留著、下次再試),成功後在途交換,MCP daemon 的既有 connection 不用重啟就自癒。POSIX-only(Windows 上已開檔無法 unlink)。

close src/index.ts釋放資源:unwatch、release file lock、close db。

三個動作依序:停止 watcher → 釋放跨 process 的 file lock → 關 SQLite。順序很重要——先停 watcher 才不會在 close 過程中又觸發 sync。

2. 索引:indexAll / sync

indexAll src/index.ts全量索引——用 mutex + file lock 防並發,WAL 延遲 checkpoint 提速。

核心流程(大量工程細節都藏在這裡):

  • 並發防護indexMutex(in-process)+ fileLock(跨 process,CLI/MCP/git hooks 共用)——拿不到 lock 就回傳「另一 process 正在索引」的錯誤結果。
  • WAL 延遲 checkpoint:預設 1000-page 的 autocheckpoint 在大量寫入時會重寫熱頁(實測 ~95% 的磁碟 I/O)。WalCheckpointValve 在 worker thread 背景被動 checkpoint,runMaintenance 收尾。CODEGRAPH_NO_WAL_DEFER=1 可關。
  • Fast-init:全新 DB 時暫時用 journal_mode=MEMORY + synchronous=OFF 換速度(可棄置,crash 就重跑)。
  • 階段順序:標記 index_state=indexing → bulk parse(FTS trigger 延後重建)→ resolver re-init + runPostExtract → batch resolution → chained/conformance 第二輪 → 重算節點數 → 標記 complete/partial/failed
  • 完整性對帳:discovered ≠ indexed+skipped+errored 時標 partial 並附警告。
教學重點:`index_state` metadata 讓 codegraph status 能分辨「完整索引」vs「被 kill 的截斷索引」,不會靜默提供部分結果。
sync src/index.ts增量同步——只處理變動檔,含 failed-ref 重試與 orphan 清掃。

與 indexAll 同鎖、同 WAL 延遲策略。差異在範圍:

  • git fast path:有 git 資訊時只載 變動檔案的 unresolved refs 來解析;沒 git 就全量 batch。
  • failed-ref 重試(#1240):變動檔新增了 symbol,讓沒變動的檔先前解析失敗的 refs 現在能成——依變動檔的 symbol 名查回並重解析。
  • CG-33 rebind:定義增減會讓「沒被 sync 碰到」的檔的邊失效——用 definitionDelta 復活 stale resolution edges(CODEGRAPH_NO_REBIND=1 可關)。
  • orphan 清掃(#1187):被 kill 的解析 pass 留下 pending rows;healthy index 上這只是一次 COUNT query。
教學重點:sync 不是「重新掃描」,是「只補變動」+「重試失敗」+「修復側邊影響」三件事。

3. 查詢與上下文

searchNodes / getCallers / getImpactRadius src/index.ts對 GraphQueryManager / GraphTraverser 的高階包裝。

這些方法把底層查詢包成簡潔 API:searchNodes(name) 走 FTS5;getCallers(id)/getCallees(id) 走 traverser;getImpactRadius(id, depth) 算影響半徑。MCP 的 codegraph_node/callers/impact 工具與 CLI 同名指令就是它們的薄殼。

buildContext src/index.ts把圖變成「給 AI 讀的上下文」(markdown/JSON)。

組出回答某個任務需要的相關節點原始碼 + 關係,格式可由參數選(markdown/JSON)。這是 codegraph explore 輸出的資料來源——「一次呼叫拿到相關符號原始碼 + 呼叫路徑 + blast radius」的組裝點。

4. 檔案監看

watch / unwatch src/index.ts用原生 OS 檔案事件自動同步;watch 回呼把 sync 結果回傳。

watchFileWatcher(FSEvents/inotify/RDCW)並接一個 async 回呼:事件 → sync({ paths }) → 回傳變動數與耗時。特別處理「sync 回傳零 shape = lock 拿不到」→ throw LockUnavailableError,讓 watcher 保留 pending files 並重排。getPendingFiles() 就是 MCP 工具附加 staleness banner 的資料來源。

看完這頁你應該能說出:constructor 為什麼是 private(全走 static factory)、init 與 open 的預設行為差異、indexAll 的 WAL 延遲與 fast-init 兩個加速、sync 比「重新掃描」多了哪三件事、以及 watch 回呼如何處理 lock 失敗。