工單系統
一句話:工單是塔台和 Worker 之間唯一的合約。它有固定的編號格式、一張只交一個交付物,元資料讓塔台在派工前就能算出風險,回報後再以工單檔為準把進度對齊。
CT 的每一件事都從一張工單開始。Worker 不靠對話記住任務,只讀工單檔;塔台也不靠記憶判斷進度,只看工單檔的狀態欄位。所以工單系統的設計重點不在「怎麼寫得漂亮」,而在三件事:編號能不能被所有工具一致辨識、粒度能不能讓中斷後接得回來,以及元資料能不能讓塔台在派工前就先擋下衝突。
工單 ID:一個權威正則
工單 ID 的格式只在一個地方定義,權威正則是:
^(?:[A-Z]{2,4}-)?T\d+$也就是「可選的 2–4 位大寫英文前綴加連字號」,後面接 T 和純數字流水號。檔名再接 -<簡短描述>.md,描述用小寫英文、以 - 分隔,例如 T0015-fix-auth-bug.md。
| 合法 | 不合法 |
|---|---|
T0115(單專案標準形式) | cp-T0113(前綴必須大寫) |
CP-T0113(跨塔台交辦慣例前綴) | PROJX-T0001(前綴超過 4 字元) |
LC-T0001(project-prefix 自動加上) | T-0115、TASK0115(主體不是 T + 數字) |
PROJ-T0001(前綴 4 字元,上限) | C-T0001(前綴少於 2 字元) |
前綴有兩個來源:一是 project-prefix 設定,設了之後塔台派工一律自動加;二是跨塔台交辦的既有慣例(例如 CP-),由別的塔台或人工建立,不經 project-prefix 產生。所以沒有設 project-prefix 的專案,一樣可能看到帶前綴的 ID,任何「沒設前綴就只會有 T####」的假設都是錯的。
為什麼要收斂成一處?因為這條規則有實際代價。早期版本裡,「工單 ID 能不能帶前綴」散在好幾份文件,兩種立場彼此牴觸:有的說只能 T 加數字,有的說跨專案一定要帶前綴。每一處各自自洽,合起來就衝突,結果帶前綴的工單被下游驗證器擋下。逐處修改只會讓下次再發散,收斂成單一定義才是根治。
這個正則同時是防注入白名單:它不允許空白、引號、路徑分隔字元或任何 shell 元字元,因此可以直接用來驗證 BAT 派工參數 --workorder、回收參數 --close-worker,以及 *sync/*archive 掃描時辨識工單檔。其他文件要把工單 ID 組進更大的正則(例如比對 Worker 回報字串)時,一律用具名片段 <WORKORDER_ID>,不准就地展開成字面正則。展開等於複製一份定義,下次改規則時一定會漏改一處。
BUG、PLAN、EXP 單據有自己的編號規則,不適用這個正則(見 BUG/PLAN/EXP 與研究型工單)。
粒度:一個交付物、可中斷、可恢復
一張工單等於一個 BMad 工作流程,或一個明確的交付物。具體有三條:
- 單一職責:不把多個工作流程塞進同一張工單。
- 完整可交付:Worker 做完要有明確產出,塔台能驗收。
- 可中斷可恢復:中途停下回報
PARTIAL時,可以根據已完成的部分開接續工單。
粒度切得太大,中斷時沒有乾淨的接續點;切得太小,塔台光是派工與收單就吃掉大半注意力。「一個交付物」是兩者之間最容易判斷的界線:只要說得出「這張單交出什麼」,粒度通常就對了。
模板欄位與它們的設計依據
工單模板的元資料除了編號、狀態、時間之外,還有幾個欄位不是裝飾,而是各自對應一個協調風險。v5.0.0 起這些欄位以 YAML frontmatter 為機器事實來源,正文的元資料表是給人看的鏡像。
| 欄位 | 用途 | 沒填時 |
|---|---|---|
intervention_type | 標明 Worker 的互動策略:fire-and-forget(全程自動)、context-dependent(缺 context 時可問一次)、decision-requiring(到分叉點停下等決策) | 視為 fire-and-forget |
affects_files | Worker 預期會寫入、修改或刪除的檔案清單,只列寫入目標,不列讀取的檔 | 視為 *(全專案),平行派工一律警告 |
memory_overrides | 工單指示與 Worker 歷史慣例衝突時,明文宣告覆蓋哪一條、理由是什麼 | 不填;但有衝突卻沒寫,Worker 有照舊慣例做的風險 |
repo | 落點檢查 C-0 的承重欄位,值是 repo 根目錄名稱 | 落點檢查改用啟發式判斷(見 落點檢查) |
intervention_type 的視角值得多說一句。傳統的 agent 分類看 agent 內部構造(有沒有記憶、有沒有目標),CT 看的是「這個 Worker 對塔台的介入成本」:fire-and-forget 幾乎不佔使用者的注意力,decision-requiring 中途會打斷好幾次。有了這個欄位,塔台可以讓前者多張並行、讓後者序列執行,也能在工單鏈裡看到 decision-requiring 時先預告使用者「等一下要做架構決策」。
派工前,塔台還會對工單做「規格層級自問」(spec_level_check):目標是執行、設計還是研究?Worker 有沒有權自行決定技術方案、檔案位置、命名與介面?只讀工單和前置檔案夠不夠獨立完成?走錯方向的回頭成本有多大?有沒有和既有記憶衝突?背後的原則是規格應停在架構邊界層:產品意圖太淺,Worker 只能猜;寫到實作細節又太深,奪走了 Worker 的判斷空間。答案是「研究」就改開研究型工單,回頭成本是「整個子系統重設計」就先升級成 meta-PLAN。
派工前 overlap check
多張工單平行執行時,兩張改到同一個檔案就會互相覆蓋或產生 merge conflict。塔台在派工前,拿新工單的 affects_files 逐一比對所有 IN_PROGRESS 工單:
| 判定 | 條件 | 塔台動作 |
|---|---|---|
| 🚨 BLOCK | 有完全相同的檔案路徑 | 列出衝突清單;使用者要明確輸入「確認接受衝突」才繼續,否則取消派工 |
| ⚠️ WARN(wildcard) | 任一方是 *,或沒有宣告 | 顯示警告,[Y/N] 決定是否繼續 |
| ⚠️ WARN(same_dir) | 同目錄、不同檔案(只在目錄層標註時觸發) | 同上 |
| ✅ PASS | 沒有交集 | 正常派工 |
這個檢查刻意做成靜態:只比對工單宣告的字面內容,不在執行期間監看 Worker 實際動了哪些檔。理由是執行期的檔案監看要長駐程序和行程間通訊,成本高,而且「碰到同一個檔」不等於「邏輯衝突」,誤報比例也高。靜態比對用集合交集就能涵蓋大多數典型衝突,剩下的語意衝突本來就需要人判斷。Worker 實際動的檔案超出宣告範圍,不算這個機制的責任,這類落差會留給 *evolve 事後歸納。
單人單 session 工作時沒有 IN_PROGRESS 工單,這個檢查永遠 PASS,不會增加任何負擔。
Story 與 Dev 之間的品質檢查點
用 BMad 時,Story 產生後、Dev 實作前,塔台依情況決定要不要插入獨立審查:
bmad-create-story是保留的 shim;Story 拆分走bmad-spec的 Story Breakdown,審查在bmad-build的 Review Triage。不能因為用了 story 就省略審查:用bmad-build時看 spec 的## Review Triage Log,沒跑就照下面的條件另派審查工單。- 高風險 Story(安全、金流、資料遷移)或跨多個子專案、影響共用模組的 Story,派一張獨立審查工單,在不同 session 執行,避免確認偏誤。
- 沒用 BMad 的自訂流程,塔台主動提議審查步驟。
- 使用者明確跳過時,記進決策日誌。
審查回報裡有 CRITICAL 或 HIGH 發現時,塔台強制先派修正工單,修完才派開發(bmad-build)工單。這就是「審查 → 修正 → 交付」三步。
回報處理與進度同步
使用者在塔台輸入 T0001 完成(或 BAT 通知自動送達)時,塔台不採信字串本身,而是讀工單檔的回報區:完成狀態、產出摘要、遭遇問題。接著依序做品質閘門檢查、更新進度表、靜默記一筆學習,然後依狀態決定下一步:
DONE→ 派下一張,或宣布階段完成FAILED→ 啟動 Debug 策略BLOCKED→ 記下卡點,評估有沒有可以並行的工單PARTIAL→ 先判斷卡點是否還在;塔台一裁示剩下的部分怎麼處理(另開接手單,或判定不需再做),當下就補正為DONE(v5.13.0 起),並保留原始回報
PARTIAL 是某個時間點的未完成狀態,不應該永久掛在待辦清單上。補正時不覆寫歷史結論,而是在原工單文末加一段〈塔台收尾補記〉,寫明剩下的部分由哪張工單完成,或依哪個決策不需再做;接手單完成後塔台再回頭確認。只有真的在等外部條件(廠商、客戶、環境)的才保留 PARTIAL 或改 BLOCKED。
進度同步用「雙重保障」:Worker 在工單指示裡被要求更新 sprint-status.yaml,塔台每次收單時再複查補漏。需要全面對齊時執行 *sync:塔台列出所有工單檔,交叉比對塔台記憶、工單檔與 sprint-status.yaml 三方,以工單檔為唯一事實來源修正差異。
收單之後還有兩個附帶動作,都是 BAT 環境下才會做:worker_auto_close: done 時回收已完成的 Worker 分頁;要對同一張工單重派 Worker 之前,先回收舊分頁,避免同一張單同時開著兩個 Worker。這兩個動作的失敗都不影響收單結果。分頁回收的細節見 派工:auto-session 與 BAT。
命令範例
本頁的正則、表格與命令都是摘要,完整參數以 reference 為準。
延伸閱讀
control-tower/references/work-order-system.md§ 工單編號規則(含「工單 ID 格式(權威定義)」)、§ 工單粒度原則、§ Story → Dev 之間的品質檢查點、§ 派發前 overlap check(v4.4.0+)、§ 回報處理流程、§ PARTIAL 當下收尾(含 resolvedPARTIAL補正)、§ sprint-status.yaml 同步control-tower/references/work-order-template.md§ 填寫intervention_type指引、§ 填寫affects_files指引、§ 填寫memory_overrides指引、§ Sprint 2 transition — YAML frontmatter SoT (v5.0.0+)control-tower/references/doctrine.md§intervention_type/affects_files/spec_level_check的設計依據- 本站:一張工單的一生、檔案即真相來源
摘要不具權威
Portal 是摘要,不具權威,與 reference 有出入時以 reference 為準。