domain-map 的 bundle 界定表是測試策略、任務派發、對齊度分析的權威依據——表上列了什麼 bundle,下游就對什麼 bundle 建測試、開工作項目。這張表如果混入了程式碼中不存在的概念,下游產出的工作項目在執行時才會發現目標不存在,整條工作鏈從分析到建票到派發全部白費。

本章處理的判準:bundle 界定表的每一列是否對應到程式碼中實際存在的結構。與組裝層的可達性互補——組裝層可達性守的是「已實作的功能有沒有接到入口」,本章守的是「文件宣告的結構有沒有在程式碼中存在」。兩者的共同根因是宣告與現況的落差,差別在觀察面:前者從程式碼往入口看,後者從文件往程式碼看。

一個 bundle 的失敗鏈

一個專案建立了九份 domain-map,其中 synchronization domain 的 bundle 界定表列出了 PassthroughMergeTagTreeMerge 兩個 bundle——來源是規格文件中描述的合併策略分類。分析代理人拿這張表比對測試目錄,發現這兩個 bundle 沒有對應的 unit test,列為測試缺口,建了一張補測試的工作項目。

執行代理人認領這張工作項目後,用 grep 搜尋目標類別——程式碼中不存在 PassthroughMergeTagTreeMerge。實際的合併邏輯在 SyncMergeService 裡,沒有拆成獨立的策略類別。代理人花了 97k tokens 嘗試後回報失敗。

事後追溯,失敗鏈有三個斷點:

階段發生了什麼應該做的驗證
產出 domain-map從規格描述反推 bundle 名稱,沒有 grep 驗證對應類別是否存在ls lib/domains/synchronization/ 確認目標路徑
消費 domain-map直接消費 bundle 清單比對測試目錄,沒有二次驗證 bundle 對應的程式碼結構存在grep -r "PassthroughMerge" lib/ 確認類別存在
建立工作項目從分析報告的缺口清單建票,沒有對 where.files 的目標做存在性確認test -f lib/domains/synchronization/passthrough_merge.dart

三個斷點獨立發生——任何一個做了驗證都能攔截。但三個都沒做,背後是同一個信任假設:bundle 界定表列出的就是已實作的程式碼結構。

根因:一張表兩種語意

bundle 界定表有兩種語意混在同一張表裡:

語意含義下游用法
(a) 已實作對應的類別、目錄、模組在程式碼中存在可以建測試、分析覆蓋度、派發實作任務
(b) 規劃中規格描述的概念分層,程式碼中尚未拆為獨立結構不可建測試缺口工作項目;要先建實作工作項目

表上沒有區分 (a) 和 (b) 時,下游消費者的合理預設是全部為 (a)——bundle 界定表被定位為「程式碼結構的權威依據」,讀者沒有理由懷疑上面的條目不存在。

這個混合不是文件「過期」。過期是指文件產出時正確、之後程式碼改了文件沒跟上。這裡的情況是文件產出時就沒驗證——規格描述的概念被直接搬進 bundle 界定表,從來沒有對應過程式碼。漂移在產出階段就發生了。

判準:產出端驗證與消費端驗證

產出端:每個 bundle 附程式碼路徑並驗證存在

bundle 界定表的每一列寫目標路徑後,跑一次驗證:

1# 驗證 bundle 目標路徑存在
2ls lib/domains/synchronization/services/sync_merge_service.dart
3# 存在 → 已實作
4
5ls lib/domains/synchronization/services/passthrough_merge.dart
6# 不存在 → 標「規劃中」

驗證的對象是目標路徑欄位已經寫好的路徑——不需要額外設計,只需要對已填寫的路徑跑一次 lsgrep

加一欄:實作狀態

在 bundle 界定表加一欄「實作狀態」,值只有兩種:「已實作」或「規劃中」。

1| Bundle | 分類 | 目標路徑 | 測試層 | 實作狀態 |
2|---|---|---|---|---|
3| SyncMergeService | domain service | `lib/domains/sync/services/` | unit | 已實作 |
4| PassthroughMerge | domain service | `lib/domains/sync/strategies/` | unit | 規劃中 |
5| TagTreeMerge | domain service | `lib/domains/sync/strategies/` | unit | 規劃中 |

這一欄讓消費者在讀表時就能區分,不需要自己去驗證。

消費端:分析前過濾

消費 domain-map 做測試對齊或缺口分析時,前置步驟過濾掉「規劃中」的 bundle:

11. 讀取 bundle 界定表
22. 過濾:只保留「已實作」的 bundle
3   (或表中無實作狀態欄時,逐個 grep 驗證目標路徑存在)
43. 對過濾後的清單執行分析

消費端驗證是防禦性措施——產出端做對了就不需要;但產出端的驗證品質不由消費端控制,所以消費端保留自己的檢查。

兩個專案的規模差異

同一個框架的兩個專案在同一週內建立 domain-map:

維度專案 A(移動應用,v0.38)專案 B(瀏覽器擴充,v1.6)
bundle 總數~120113
「規劃中」數2(sync domain)0
false positive 工作項目1(97k tokens 白費)0

專案 B 的 113 個 bundle 全部驗證為已實作——這不代表驗證是多餘的。專案 B 是成熟專案,功能已全部實作;專案 A 是開發中專案,規格描述領先於實作,混合的機率更高。

驗證的成本與 bundle 數量成線性關係(每個 bundle 一次 ls),false positive 的成本是非線性的(整條分析、建票、派發、執行鏈白費)。成熟專案的驗證結果全是「已實作」、看起來像浪費,但這是驗證的正確結果而非多餘的步驟——跟測試全綠是正確結果而非多餘的測試同理。

一般化:設計文件與程式碼的漂移管理

domain-map 的 bundle 驗證是一個更普遍模式的特例:設計文件描述的結構與程式碼的現況之間存在漂移,漂移需要被管理而非假設不存在。

三個判準把這個模式從 domain-map 擴展到其他設計文件:

判準一:指向程式碼的宣告用工具驗證目標存在

「指向程式碼的宣告」包括 bundle 的目標路徑、spec 引用的類別名稱、架構圖標示的模組路徑。驗證手段是 lsgreptest -f——工具比印象可靠,因為印象的驗證是「我記得這個類別存在」,工具的驗證是「這個路徑在檔案系統中有沒有對應的 entry」。

判準二:文件產出時就驗證,不等消費時才驗證

漂移有兩種形態:產出時就不正確(本章的案例)、產出後程式碼改了文件沒跟上(過期問題)。產出端驗證攔第一種,定期重新驗證攔第二種。只在消費端驗證等於把品質責任推給讀者——讀者的數量遠大於作者的數量,在讀者端分散驗證的總成本高於在作者端集中驗證。

判準三:語意差異用顯式欄位區分,不靠讀者推斷

bundle 界定表的「已實作」和「規劃中」是兩種不同的語意,但原始設計沒有欄位區分。讀者需要自己去驗證才能區分——這是一個設計缺口,不是讀者的責任。加一欄讓語意顯式化,消除了讀者需要推斷的負擔。

邊界

本章的判準適用於被下游消費者當作「程式碼結構權威依據」的設計文件。不適用的情況:

  • 純概念文件(如技術提案、未來規劃):讀者預期內容是規劃而非現況,不需要驗證
  • 文件與程式碼完全解耦(如使用者手冊):指向的是操作流程而非程式碼結構
  • 產出與消費是同一人同一時間(如個人筆記):作者即讀者,隱含知識不會造成誤判

判準適用時,驗證的粒度跟文件的消費方式匹配:bundle 界定表被逐列消費,驗證就逐列做;架構圖被整體消費,驗證就對圖上每個模組做。

與其他章節的關係

  • 組裝層的可達性:組裝層守「程式碼到入口」的連通性,本章守「文件到程式碼」的一致性。兩者的共同上游判準是「宣告的東西要能被驗證為存在」
  • 不變式的強制層次:bundle 的實作狀態是一種文件層的不變式——「已實作」的 bundle 必須有對應的程式碼路徑。不變式的強制方式是產出時的 ls/grep 驗證,跟程式碼中不變式的強制方式(型別系統、建構子驗證)同源
  • 跨邊界參照與狀態所有權:bundle 名稱是 domain-map 對程式碼的參照,「程式碼有沒有這個名稱」是參照有效性的問題。判準一的驗證跟該章的「參照有效性三問」第一問(「對方的哪些操作會讓這個參照死亡?」)同源