前兩篇看過 Spectra 的基本流程,以及指引、文件檢查與歸檔的安排。這篇接著看 apply 前後:規劃文件準備好了,AI 開始實作時,還會遇到哪些問題?
例如,change 放了幾天才繼續做,原本的規劃可能已經跟不上 codebase;實作途中遇到 Bug,需要先找出原因;有好幾項工作想同時進行時,也得避免彼此影響。Spectra 為這些情況提供了一些輔助功能,我們先看看它們分別會在什麼時候用到,再逐一介紹。
這篇使用哪個版本? 以下延續前兩篇,仍以 Spectra 2.3.1 的 Skills、設定與 CLI 行為為準。
| 出現的時機 | 功能或設定 | 主要在處理什麼? |
|---|---|---|
| 開始或恢復 apply 前 | drift | change 建立後,codebase 是否已經出現足以影響原計畫的變動。 |
| 實作途中遇到 Bug | debug | 問題能不能重現、發生在哪裡,以及真正原因是什麼。 |
| apply 或 debug 真正修改 code 時 | TDD | 用 Red → Green → Refactor 安排測試、實作與重構的順序。 |
| apply 執行彼此獨立的 tasks 時 | parallel_tasks |
透過 [P] 標記,讓支援平行執行的 Agent 環境同時處理。 |
| 多個 changes 準備同時進入 apply 時 | Worktree | 替每個 change 準備不同的工作目錄,避免未完成的修改直接混在一起。 |
| 每一項 task 完成時 | touched files | 記下這項工作碰過哪些檔案,不只留下 checkbox。 |
其中,前一篇的 validate、這一篇的 drift、debug 與 TDD,可以直接放回主要 workflow 的不同位置:

圖中的 drift、debug 與 TDD 會在不同情況下用到:change 放了一段時間,可以先用 drift 檢查;遇到 Bug 時使用 debug;TDD 則需要先從 .spectra.yaml 啟用。至於 parallel_tasks、Worktree 與 touched files,分別處理工作能不能一起做、工作目錄怎麼分開,以及完成後留下哪些紀錄,因此沒有畫成接續執行的步驟。
接下來,我們就從開始或恢復 apply 前的 drift 看起。假設這份 change 已經放了幾天,期間 codebase 又有其他修改,原本的 tasks 還能直接照著做嗎?
規劃這份 change 時,AI 參考的是當時的程式碼。如果中間先完成了其他工作,原本打算修改的檔案可能已經搬到別的位置,或某個功能已經換了一種寫法。這時候,tasks 雖然還沒做完,裡面寫的作法卻可能已經不適用了。
drift 就是用來檢查這份規劃是否還適合繼續做。AI 使用 drift Skill 時,會先呼叫下面的 CLI 指令,取得檢查結果:
spectra drift <change-name> --json
CLI 會從【Day - 10】看過的 .openspec.yaml 讀取建立日期,確認 change 已經放了多久,也會檢查 design 提到的檔案、函式或型別是否還存在,以及其他 commit 是否改到了尚未完成的 tasks 涉及的內容,再把變動程度分成 Light、Medium 或 Heavy。接著,AI 會依照 drift Skill 的指引,先說明這個 change 是否適合直接繼續,再列出原因與建議的下一步:變動很輕時可以直接 apply;需要重新調整時,可以先透過 ingest 更新;偏離太多時,則會建議刪除舊的 change,再重新建立一份。
drift 只負責檢查與提出建議,不會自己修改 artifacts,也不會直接替我們執行下一步。最後還是由我們自行決定要繼續、先更新,還是暫停。
apply 會自己執行 drift 嗎? 會,但不是每一次。當時的 apply Skill 會在 change 建立超過 5 天,而且 change 目錄最近 3 天沒有 commit 時,先產生 drift report,再讓我們選擇直接繼續、回到 ingest 更新,或先停下來。這項檢查只是提醒,不會強制擋住 apply。
確認規劃還跟得上 codebase,或透過 ingest 更新後,就可以繼續實作了。不過,實作途中如果碰到 Bug,還是得先把真正的原因找出來!
我們是不是很常看到這種情況:AI 一看到錯誤,就立刻猜一個原因、改一個地方,也沒有先確認這個修改會影響哪些地方。改錯了,就換另一種作法繼續試。這樣一路循環下去,原本的 Bug 不只沒有修好,修補的過程還可能再延伸出幾個新的 Bug。
debug Skill 想避免的就是這種狀況,所以它不會一開始就讓 AI 動手修改,而是先把除錯拆成四個階段:

它另外訂了一條限制:同一個假設最多嘗試修正三次。第三次還是失敗,就要先停下來,記錄已經試過什麼,重新檢查 root cause,而不是繼續替同一個猜測換不同寫法。
前三個階段都還在重現問題、縮小範圍與確認真正原因,直到 Fix 才會開始修正程式。不過,debug 不會讓 AI 找到原因後就直接動手,而是要求先建立能重現問題的測試,確認它真的會因為目前的 Bug 失敗。
這一步也剛好把我們帶到 TDD(Test-Driven Development,測試驅動開發):先用失敗的測試把預期行為固定下來,再完成最小實作與重構。如果 .spectra.yaml 已經啟用 TDD,debug 會再取得完整的 TDD instructions,接著依照 Red → Green → Refactor 修正。
現在有什麼不同? Spectra 3.0.0 的 debug Skill 更明確要求先執行測試、重播紀錄或可重複的實驗,讓問題真的出現,再依證據排列可能原因。Fix 後也多了 Integration:如果修正屬於某份 change,就把結果接回對應的 task;獨立的 Bug 則視需要建議建立 proposal。它新增的是修正後怎麼接回 workflow,TDD 仍然放在 Fix 裡。
那麼,Spectra 是怎麼把 TDD 接進 apply 與 debug 的呢?
.spectra.yaml 怎麼把 TDD 接進 apply 與 debug?前面提到,debug 找到原因、準備修正時,可以依照 TDD 的順序進行。Spectra 把這個設定放在 .spectra.yaml,apply 實作功能時也能使用:
tdd: true
啟用後,AI 會依照 apply 或 debug Skill 的指引,另外呼叫 Spectra CLI,取得完整的 TDD instructions:
spectra instructions --skill tdd
這份指引會要求 AI 按照 Red → Green → Refactor,也就是先寫測試、完成實作、最後重構的順序修改程式。在 apply 裡,如果 specs 已經有具體的 Example,AI 還會被要求優先把 GIVEN/WHEN/THEN 轉成第一批測試。tasks 描述要完成什麼,TDD instructions 則補上每項工作要怎麼做。
這個設定對我來說很方便,因為在改用 Spectra 以前,我就已經要求 AI 先寫測試。搭配寫清楚的規格後,我確實覺得實作穩定不少:specs 提供輸入、操作與預期結果,AI 寫測試時就有內容可以依照。不過,規格漏寫的情境,也可能沒有對應測試,先寫測試並不會自動補齊這些缺漏。
使用 OpenSpec 的那段時間,我會把 TDD 相關要求分別放在 .claude/CLAUDE.md 與 openspec/config.yaml。.claude/CLAUDE.md 會先放一份整個專案共用的 TDD 提醒:
### TDD 開發
所有開發一律採用 TDD 流程,使用 `tdd-workflow` 技能引導:
- 先寫測試 → 再寫實作 → 最後重構
- 目標覆蓋率 80% 以上(unit、integration、E2E)
config.yaml 的 rules.tasks 則負責告訴 AI,產生 tasks.md 時要怎麼拆出這個順序:
rules:
tasks:
- 嚴格遵循 TDD 順序:先寫測試 → 再實作 → 最後重構,禁止先實作後補測試
- 格式範例:「1.1 撰寫 XXX 測試」→「1.2 實作 XXX 功能」→「1.3 重構 XXX」
- 每個階段結束須包含編譯或測試驗證步驟
最後產生的 tasks.md,大概會長這樣:
## 1. TDD:撰寫紅燈測試
- [ ] 1.1 先寫測試,確認目前會失敗
## 2. 綠燈:完成實作
- [ ] 2.1 修改程式,讓前面的測試轉綠
## 3. 重構與整合驗證
- [ ] 3.1 整理程式,再執行完整測試
這些設定會讓產生的 tasks 帶上 TDD 順序,CLAUDE.md 則提供專案共用的提醒。換到 Spectra 後,我就不用在兩個地方重複交代這個順序,只要啟用 tdd: true,AI 進入 apply 或 debug 的修正階段時,就會依照 Skill 指引另外取得完整的 TDD 步驟。
為了確認開啟 TDD 後有什麼差別,我請 AI 準備兩個獨立的小專案,使用相同的 change、specs 與 tasks,一個開啟 TDD,另一個不開啟。需求很簡單,就是讓 sum(2, 3) 得到 5。
先讓兩邊執行 spectra instructions apply --change <change-name> --json,結果拿到的工作清單、進度與操作指示都一樣。差別出現在下一步:開啟 TDD 的那組,AI 會依照 Skill 指引,再取得一份 TDD 的操作步驟。
接著讓兩組完成這個功能。開啟 TDD 的那組先寫測試,確認測試失敗後才修改程式,最後再重構;未開啟的那組則刻意安排成先寫程式、再補測試,方便比較。兩組最後都完成了 task,也通過【Day - 11】介紹的文件格式檢查。不過,未開啟那組的順序是這次對照刻意安排的,不是 Spectra 規定要這樣做的。

這個差別來自 AI 取得的指引。即使開啟 TDD,仍然要靠 AI 照著步驟執行;Spectra CLI 不會檢查測試是不是先寫的,AI 如果先改程式,也不會因此被擋下來。
現在有什麼不同? Spectra 3.0.0 在開啟 TDD 時,還會要求 AI 完成實作後,確認規格裡哪些情境已有測試、哪些還沒測到,以及哪些不需要測試,例如單一畫面的外觀細節。這仍然是要求 AI 執行的檢查,不會因為有缺漏就自動阻止 task 完成。
TDD 安排的是每一項 task 裡,測試與實作的先後順序。那如果有好幾項 tasks 彼此獨立,能不能一起做呢?
【Day - 10】提過,.spectra.yaml 有一個 parallel_tasks 開關。沒有啟用時,AI 會照著 tasks.md 的順序,一項做完再做下一項。設定成 true 後,propose 會先找出「不用等另一項工作完成,而且預計修改不同檔案」的 tasks,替它們加上 [P]:
- [ ] [P] 2.1 實作登入錯誤訊息
- [ ] [P] 2.2 補上 session 過期測試
[P] 表示這些工作可以考慮一起做,但還不是確定同時開工。進入 apply 後,AI 會依照 Skill 指引,再檢查連續標記 [P] 的 tasks:有沒有哪一項必須等另一項做完?會不會改到同一份檔案的同一個地方?如果有,就仍然一項一項做。
確認可以分開做,而且目前使用的 Agent 工具也支援同時派出多個 AI Agents,才會讓它們各自處理不同的 task。例如,圖中的 Task A 和 Task B 可以同時開始,Task C 則要等兩邊都完成。如果不符合這些條件,就照原本的順序執行。

如果中途透過 ingest 更新 tasks.md,原本的 [P] 會保留,新加入的工作也會依照相同條件判斷能不能一起做。
這和 TDD 可以一起使用:parallel_tasks 處理不同 tasks 能不能同時進行,每一項 task 裡仍然可以按照先寫測試、再改程式、最後重構的順序完成。
現在有什麼不同? Spectra 3.0.0 的 propose Skill 不再替工作加上
[P],而是用[after: ...]寫清楚「這項工作要等誰完成,才能開始」。例如1.3 [after: 1.1, 1.2] 整合結果,就是 1.3 要等 1.1 和 1.2 都完成。到了 apply,再根據這些先後順序,找出可以一起做的工作;如果目前的 Agent 環境不支援平行執行,就依序處理。
前面處理的是同一個 change 裡的 tasks。那如果想同時進行好幾個 changes,要怎麼避免不同工作的修改混在一起呢?
即使替每個 change 分別開啟不同的 AI Agent 對話,只要它們還是共用同一個工作目錄,一邊修改的檔案也會立刻出現在另一邊。要把這些工作分開,還需要各自的工作目錄。
Git Worktree 可以讓同一個 repo 同時存在多個工作目錄(checkout),每個目錄各自使用不同的 branch。Spectra 把這項功能放進 Desktop,而且預設不會啟用;需要時,可以在 .spectra.yaml 打開開關並設定 Worktree 位置:
worktree: true
worktrees_dir: .spectra/worktrees
使用上面的設定後,每個 change 的 Worktree 會放在:
.spectra/worktrees/<change-name>
對應的 branch 則會使用 spx/<change-name>。透過 Desktop 建立 Worktree 後,Spectra 會把這份 change 的 artifacts 移進新的工作目錄,讓它和主要工作目錄裡的其他工作分開。
不過,artifacts 搬過去後,這份 change 並不會從主要工作目錄的畫面消失。Desktop 與 spectra list 仍然看得到它,也會顯示目前位於 Worktree;需要時,還可以透過 Desktop 把 artifacts 搬回主要工作目錄,或移除不再使用的 Worktree。
現在有什麼不同? Spectra 3.0.0 已移除自行管理 Git Worktree 的功能。前面這段是當時的操作方式;現在仍然可以透過 Git 分開工作目錄,只是不再由 Spectra Desktop 建立與搬動這些 Worktrees。
無論 change 最後在哪個工作目錄裡進行,apply 每完成一項 task,還是要更新對應的 checkbox。除了知道工作已經完成,我們還能回頭查到這項 task 改過哪些檔案嗎?
apply 完成一項 task 時,除了把 tasks.md 裡的 checkbox 打勾,也會透過 spectra task done,把這項工作改過的檔案記進 .spectra/touched/<change>.json。例如,下面這筆簡化的紀錄表示 task 1.1 修改了 src/sync.js 與 src/sync.test.js:
{
"change": "add-sync",
"touched": [
{
"task_id": "1.1",
"task_desc": "實作同步流程",
"files": ["src/sync.js", "src/sync.test.js"]
}
]
}
這樣就能查到每項 task 改過哪些檔案。不過,準備 archive 時,AI 會依照 Skill 指引先刪除這份暫存紀錄,再由 CLI 重新查看當下的 Git 變更,整理相關的程式與測試檔案,寫進【Day - 10】介紹的 @trace。
因此,@trace 並不是把每項 task 的檔案紀錄原封不動留下來。同一份 change 裡,不同 requirements 可能拿到相同的檔案清單。它可以幫我們找到相關檔案,但無法精確告訴我們「這個檔案是為了哪一條 requirement 修改的」。
現在有什麼不同? Spectra 3.0.0 的 apply Skill 會要求 AI 在開始 task 前,先用
task start記下當時的 Git 狀態。完成後,再根據這份紀錄,或由 AI 明確列出檔案,整理這項 task 改了哪些檔案。不過,如果不同 changes 都改到同一個檔案,還是需要確認各自改了哪些內容。
檔案紀錄能幫我們回查修改,但程式有沒有照著規格做好,還需要另外核對。等所有 tasks 都完成後,就可以視需要使用【Day - 9】介紹過的 verify。
從開始前檢查規劃,到實作途中處理 Bug、安排工作,再到完成後留下紀錄,這些都是 Spectra 在 apply 前後提供的協助。實際把這些功能用進開發工作後,我也開始思考哪些作法適合自己,哪些地方還想調整。
Spectra 後來成了我主要使用的 SDD 工具,而且一直用到現在。先用過 OpenSpec,再換到 Spectra,就更能感受到這些功能帶來的方便:規劃時可以透過 propose 一次準備好文件,中途改需求有 ingest 幫忙更新,AI 有時候也會提醒我接下來可以做什麼。原本需要自己處理的事情,現在有工具幫忙,真的輕鬆不少。
用久之後,我也開始有自己的想法。有些流程用得很順,想繼續保留;有些地方則會忍不住想:「如果改成這樣,會不會更符合我的習慣?」這不就跟龍哥當時想調整 OpenSpec 一樣嗎XD。於是,我也想試著做一套自己的 SDD workflow。不過,要先做哪些東西,才能真的拿來用呢?下一篇,就來看看我怎麼開始吧!