治理:單一權威與「摘要不具權威」
CT 不追求「每一份文件都寫對」,而是讓每條規則只在一個地方完整定義,其他地方只放一句摘要和連結,並且明說摘要不具權威。你正在讀的 Portal,也照這條規則運作。
「看起來完整」本身就是一種失效模式
CT 的治理規則,多半不是新功能,而是從真實失誤裡長出來的。其中最有代表性的一次是這樣的:
塔台 SKILL.md 裡有一行派工指令範例,讀起來像一份完整的旗標清單,實際上漏了兩個必要旗標。塔台照著它逐字派工,於是派工出錯。
直覺的修法是「把漏掉的旗標補上」。CT 的診斷剛好相反:
補上漏掉的那個旗標,只會把失誤移到下一個旗標。缺陷不在某個旗標,而在於摘要看起來是完整的。
任何摘要都會再次過時,所以修法不是把摘要補齊,而是改變摘要的地位:在它旁邊標明「非權威」,規定要執行某個動作時,去讀旁邊指名的 reference,照那裡的指令表逐字使用。這就是「摘要授權規則」。
CT 也因此沒有禁止 SKILL.md 寫指令範例:範例對路由有幫助,問題只在把它當成權威。Portal 頁尾那句「摘要不具權威」,就是同一條規則用在這個網站上。
每條規則只有一個權威定義
v5.0.6 之前,CT 內部對「工單編號能不能帶前綴」有五處敘述、兩種相反的立場。一處說只能是 T 加數字,另一處說跨專案時強制帶前綴。每一處單獨讀都說得通,放在一起卻互相矛盾。
這個矛盾有實際代價:某個專案沒有設定前綴,熱區裡卻有好幾張帶前綴的跨塔台工單;派其中一張時,下游的驗證器只認不帶前綴的編號,派工被擋下,塔台只好繞道。
CT 的結論是:逐處改寫,只會讓下一次再度發散;收斂成一處定義,才是修法。
- 規則只在一個地方完整定義,並標明「本節是唯一事實來源」。
- 其他地方只寫交叉引用,不複述判斷條件。
- 要把規則組合進更大的規則時,用名稱指稱它,而不是就地展開成字面值。
最後一條也有實例:yolo 斷點 A 用來比對 Worker 回報的正則,曾經就地寫死不帶前綴的形式,於是帶前綴的「完成」回報被誤判成非預期回報。就地展開就是複製一份定義,下次改動時必然漏改一處。
v5.0.4 到 v5.2.3 的修正,大多都是在治這個病:工單編號格式、Layer 1 的寫入範圍、決策日誌檔名、狀態值清單、各 reference 複述的設定預設值,逐一收斂到一處。v5.2.4 之後的新機制則是一出生就先指定權威小節,例如合併流程的權威在 merge-workorder.md,Worker 向塔台提問的權威在 yolo-mode.md。
SKILL.md 改成路由器
到 v5.0.2,8 個 SKILL.md 合計 4,938 行,每次 skill 觸發都要整份讀進 context,而大部分內容和當下的動作無關。v5.0.3 把它們改成只寫三件事:角色、Hard Boundaries、路由表;細節全部移到 references/,需要時才載入。總行數降到 865 行。
SKILL.md | reference | |
|---|---|---|
| 內容 | 角色、硬邊界、什麼時候讀哪份 reference | 完整規格、指令表、流程 |
| 權威性 | 摘要,指令範例可能省略必要旗標 | 它負責的那個動作的事實來源 |
| 載入時機 | skill 啟動時 | 當前動作需要時才讀 |
這同時是在省 context(見 認知作業系統),也讓「摘要」和「權威」在檔案結構上就分開了。
版號治理與 SemVer
版號也只有一個事實來源。Codex 的 skill 驗證會把 frontmatter 裡的未知欄位視為錯誤,所以 frontmatter 只放 name 和 description,版號改寫在內文的第一個註解:
<!-- control-tower-version: X.Y.Z -->H1 標題、塔台面板、_tower-state.md 都是它的鏡像;要讀版號時先讀註解,標題只是備援,不得要求 frontmatter 有 version:。
版號採 SemVer:
| 觸發條件 | 版號變動 |
|---|---|
| 不相容的工作流程或 metadata schema 變更 | MAJOR |
| 新指令、新設定、新的向下相容能力 | MINOR |
| 文件補完、BAT 規則修正、觸發描述調整 | PATCH |
CHANGELOG 記錄的 72 個正式版本裡,升過兩次主版號:v5.0.0,工單的事實來源從內文表格搬到 frontmatter(見 檔案即真相來源);v6.0.0,加入方法論轉接,BUG/PLAN/EXP 預設改開啟、工單模板的方法論段落改名(見功能總覽 › 方法論轉接)。
棄用條款:寫明棄用什麼、理由是什麼
規則改了,AI 的記憶不一定跟著改。CT 發現,單點禁令「嚴禁 X」在 LLM 的權重裡很弱,常被記憶中累積多次的「以前都這樣做」蓋過去。所以當新規則反轉了舊行為時,要寫成棄用條款:
| 寫法 | 效果 |
|---|---|
| 單點禁令:「嚴禁 X」 | 權重低,容易被記憶中的舊慣例蓋過 |
| 棄用條款:「舊版允許 X,自某版起棄用,改用 Y」 | 權重高,AI 看到的是規則演進,而不是一條沒有脈絡的禁令 |
這不是多寫字,而是在不改變語意的前提下提高訊號強度。工單的 memory_overrides 欄位用同一個格式,在派工時再說一次:「AI 記憶中有 X 這個舊做法 → 本工單不採用 → 理由」。skill 和工單雙重明示。
什麼時候不該用:第一次建立的規則(沒有歷史可對比,硬寫棄用條款等於製造假歷史)、極低頻的非核心規則,以及純新功能的規範。判斷標準是:同一條規則在兩次以上工單被違反,就該改寫成棄用條款格式。
這些護欄的共同點
| 護欄 | 共同的設計選擇 |
|---|---|
| 落點檢查 | 用外部訊號(工單的 repo 欄位)回答「我在不在對的 repo」,不用代理指標(路徑存不存在) |
| 摘要授權規則 | 不追求摘要永遠正確,而是明定摘要不具權威 |
| 單一權威定義 | 不追求每一處都改對,而是讓規則只存在一處 |
| Layer 1 寫入機制 | 不只給禁令,還寫出機制,讓「上次沒事」無法成為反證 |
| 不做 workspace 一致性檢查 | 不加一道會亂叫的警報;只記錄,不阻斷 |
| 合併護欄 | 每次推進 main 都有可比對的 SHA 證據;資料缺漏就不推進 |
共同點是:每道護欄都先問「這種失效會以什麼形式再次發生」,再選一個讓它無法以同樣形式發生的結構,而不是只修眼前這一個實例。
還有一個貫穿各處的取捨:會亂叫的警報終究會被忽略。 落點檢查不退回誤報率高的判定法、不加 workspace 比對,都是同一個理由:一道常常誤報的護欄,代價比它換來的保護更長久。落點檢查的完整設計見 落點檢查。
延伸閱讀
control-tower-guide/references/governance.md§ 摘要授權規則:「看起來完整」本身就是失效模式、§ 單一權威定義+交叉引用、§ 版本治理、§ 棄用條款:為什麼要寫明「棄用什麼、理由」、§ 這些護欄的共同點control-tower-guide/references/ecosystem.md§ SKILL.md 是路由器,reference 才是權威control-tower/references/skill-writing-conventions.md§ 棄用條款寫法規範control-tower/references/version-governance.md§ 版號事實來源、§ SemVer 慣例- 演進史 § 5.0.3:SKILL.md 改成路由器、§ 5.0.4 之後:一條規則只寫一處(見 演進史)
Portal 是摘要,不具權威。內容與 CT reference 有出入時,以 reference 為準。