撰寫與管理 Spec

憲章先行,規格要可驗證且持續更新,檔案結構清楚、模板可擴充。

spec.md 的標準結構

一份合格的 spec.md 不是備忘錄,而是驅動整個開發流程的契約——從任務拆解、程式實作到測試驗收,全程以它為依據。 規格文件必須遵循固定模板,讓 AI Agent 與人類協作者都能快速定位資訊,不需要閱讀完整文件就能理解範圍與驗收條件。 Spec Kit 預設的標準模板包含以下七個核心區塊,每個區塊各有明確職責,缺少任何一塊都會讓下游的計畫與任務生成出現品質缺口。

# 功能名稱

## 背景與目標
說明為什麼要做這個功能,解決什麼使用者痛點,
以及成功後對業務或產品帶來什麼具體、可量化的價值。
盡可能附上成功指標(KPI / OKR)。

## 範圍(Scope)
### 本次包含
- 明確列出本次迭代要實現的功能邊界

### 本次排除
- 明確列出不做的項目,並標注後續計畫編號(如 Phase 2 / FEAT-xxx)
- 防止需求蔓延(scope creep)

## 使用者故事(User Stories)
- As a [角色], I want [行為], so that [價值].

## 驗收標準(Acceptance Criteria)
- [ ] Given … When … Then …(Gherkin 格式,逐條可獨立測試)

## 技術限制與非功能需求
- 效能:API 回應 ≤ 500 ms(p95)
- 資安:所有端點需通過 JWT 驗證
- 可及性:符合 WCAG 2.1 AA

## 開放問題(Open Questions)
- 待釐清的疑問,標記 Owner 與截止日期

## 附錄
- 線框圖連結、API 文件、設計稿連結、相關 ADR
為何「本次排除」與「本次包含」同等重要: 明確寫下不做什麼,可防止需求蔓延(scope creep)。當 AI Agent 在生成任務時,它會參考排除清單,避免自行補充超出範圍的工作。同理,人工審查 PR 時,也能以此為基準拒絕超範圍的提交。養成習慣在排除清單中加入「另立 spec」或「Phase N」的說明,可讓未來規劃更加清晰,也能在 Backlog 追蹤中快速找到對應的後續議題。

好規格的三大特質

無論功能大小,一份優秀的規格必須具備以下三項核心特質,缺一不可。這三點也是 speckit.clarify 在審查規格時所依循的評估框架——若有任何一點不足, 它就會產生對應的澄清問題,要求撰寫者補充說明後才推進至計畫與任務階段。

1. 具體(Concrete)

規格必須描述可觀察的行為,而非主觀感受或模糊意圖。避免「系統應該很快」,改為量化指標;避免「使用者」,改為明確的角色描述,讓讀者不需要猜測。

2. 可驗證(Verifiable)

每一條需求都必須能被測試——不論是自動化測試、QA 手測或使用者訪談,都必須有明確的判斷準則。沒有測試方法的需求,等同於沒有需求;它只是一個願望,無法成為驗收的依據。

快速驗證法:把需求句子交給另一位工程師,請他當場寫一個測試案例。若對方需要猜測或追問才能動筆,這條需求就不夠具體,必須修訂。這個練習同樣適用於與 AI 協作——模糊的需求會讓 AI 做出不可預測的假設,導致實作方向偏差,最終在驗收階段才發現問題,代價極高。

3. 邊界清晰(Well-Bounded)

規格應同時涵蓋正常流程(happy path)與所有重要的異常流程(edge case / error path)。邊界不清的規格是 bug 的溫床,也是開發者之間最常發生認知落差的根源,更是 AI 自行腦補、做出不符預期行為的主因。

User Story 格式與範例

User Story 是規格中最常見的需求描述格式,採用固定語法結構,強迫撰寫者從使用者視角出發,明確表達行為背後的業務動機,而非直接描述技術實作。這個格式也讓非技術背景的產品經理與設計師能夠參與規格審查,確保需求來自真實的使用者問題:

As a [角色],
I want [要執行的行為或達到的目標],
so that [背後的業務或使用者價值].

好的 User Story 必須符合 INVEST 原則Independent(可獨立部署)、 Negotiable(範圍可協商)、 Valuable(對使用者有實質價值)、 Estimable(可合理估算工作量)、 Small(夠小,一個 Sprint 可完成)、 Testable(有明確的驗收條件)。 違反任何一點都應重新審視是否需要拆分或合併。過大的 Story 容易讓 AI 在任務拆解時產生過於籠統的任務清單,失去可執行性。

範例:登入功能的 User Stories

As a 已註冊的一般會員,
I want to 使用電子郵件與密碼登入系統,
so that 我可以存取個人化內容與歷史訂單,
         而不需要依賴 Google 等第三方帳號。

As a 忘記密碼的使用者,
I want to 透過電子郵件接收密碼重設連結,
so that 我不需要聯絡客服即可自助恢復帳號存取。

As a 資安敏感的使用者,
I want to 在帳號遭受暴力破解嘗試時收到通知,
so that 我能及時採取行動(如修改密碼或聯絡客服)保護帳號安全。
拆分原則:一個 User Story 只描述一件事。「使用者可以登入並查看訂單」應拆成兩個 Story——登入功能與訂單查看功能分開管理,讓每個 Story 各自獨立規劃、測試與部署,避免功能耦合造成的進度阻塞。當某個 Story 難以用一句話概括 so that 的價值時,往往是需要拆分的訊號。

驗收標準(Acceptance Criteria)寫法

驗收標準(AC)是規格中與測試最直接掛鉤的部分,也是開發者動筆實作前必須優先閱讀的區塊。推薦使用 Given / When / Then(Gherkin 格式)撰寫: Given 描述前置條件與環境狀態,When 描述使用者的觸發動作,Then 描述系統的預期回應。 這個格式讓開發者、測試人員與 AI 都能以相同方式解讀同一條需求,消除歧義,並可直接作為自動化測試的描述骨架。

## 驗收標準

### AC-1:成功登入
- Given 使用者已在登入頁面,且帳號狀態為「已啟用」
- When  使用者輸入正確的電子郵件與密碼,點擊「登入」按鈕
- Then  系統在 1 秒內重定向至使用者首頁,頂端導覽列顯示使用者姓名

### AC-2:密碼錯誤
- Given 使用者在登入頁面,帳號存在且狀態正常
- When  使用者輸入正確電子郵件但錯誤密碼,點擊「登入」
- Then  頁面原地顯示錯誤訊息「電子郵件或密碼錯誤」,
         不透露究竟是哪一項輸入有誤(防止帳號枚舉攻擊)

### AC-3:帳號鎖定
- Given 使用者已連續 5 次輸入錯誤密碼
- When  第 6 次(或更多次)嘗試登入
- Then  帳號鎖定 15 分鐘,頁面顯示「帳號已暫時鎖定,剩餘 X 分 Y 秒」

### AC-4:記住我功能
- Given 使用者勾選「記住我」後成功登入
- When  使用者關閉瀏覽器並於 30 天內重新開啟同一網站
- Then  系統自動維持登入狀態,無須重新輸入帳密

### AC-5:登出清除 Session
- Given 使用者處於已登入狀態
- When  使用者點擊「登出」按鈕
- Then  Session 與 Cookie 立即失效,頁面重導至登入頁,
         按瀏覽器「上一頁」無法恢復已登入狀態
最佳實踐:每個 AC 都是一個獨立可測試案例,命名建議加上編號(AC-1、AC-2…)。這樣可以在 PR 描述、Issue 追蹤、任務清單與程式碼註解中交叉引用,形成完整的可追溯鏈(traceability chain)。當發現 bug 時,也能直接對應到哪一條 AC 失敗,加速根因分析。測試案例的描述建議直接複製 AC 標題,讓測試報告與規格保持一對一對應。

技術限制與非功能需求

功能需求(Functional Requirements)描述「做什麼」; 非功能需求(Non-Functional Requirements,NFR)描述「做得多好」。 NFR 最容易在早期需求討論中被略過,卻往往是線上事故、效能瓶頸與資安漏洞的根源。 在規格中明確寫出 NFR,等於提前與整個團隊(包含 AI)對齊技術標準,避免各自實作時採用不同的品質基準。

常見 NFR 類別與範例數值

架構技巧:NFR 應先在 constitution.md(憲章)中定義全域預設值,再於個別 spec.md 中針對特定功能覆寫或強調差異。這樣可以避免每份規格重複相同的通用要求,同時讓特殊需求(例如:金融交易頁面有更嚴格的回應時間要求)能夠清楚凸顯,不被淹沒在大量重複的標準條款中。

常見規格缺陷

以下列出實務中最常見的規格撰寫錯誤,以及對應的診斷方式與修正方向。這些缺陷也是 speckit.clarify 最常觸發問題的場景——識別並修正這些問題,是提升 AI 協作品質最直接有效的手段:

缺陷一:模糊動詞與不可測形容詞

「系統應支援多種語言」、「介面應該友善」、「回應速度應該夠快」——這些詞彙無法被測試,因此等同於沒有寫。使用模糊動詞的規格不僅無法驅動開發,還會讓 AI 在任務生成時填入它自己的假設值,造成實作結果與期望大幅偏離。

❌ 模糊:系統應支援使用者管理功能。
✅ 具體:管理員可新增、停用、刪除一般會員帳號;
         操作結果須在 2 秒內反映於管理列表。

❌ 模糊:介面應讓使用者感到易用。
✅ 具體:新使用者在無說明文件的情況下,
         可在 5 分鐘內完成首次訂單建立(以可用性測試為準)。

❌ 模糊:API 應妥善處理錯誤。
✅ 具體:所有 API 端點在發生 4xx/5xx 錯誤時,
         回應 Body 必須包含 error_code(字串)
         與 message(人類可讀說明)欄位。
高風險模糊動詞清單:「支援」、「處理」、「管理」、「整合」、「優化」、「確保」——這些詞每次出現時,都應追問「具體行為是什麼?成功的判斷標準是什麼?」直到能用 Given/When/Then 描述為止,才算完成規格化。

缺陷二:遺漏邊界條件

規格只描述成功流程,忽略異常情境,導致開發者各自決定邊界行為,造成系統行為不一致,也讓測試人員找不到明確的測試依據。邊界缺失是線上事故中「預期之外的輸入」類問題的最主要成因。

四問自我檢查法:針對每個功能,逐一問自己—— 「如果輸入是空的?」「如果網路斷了?」「如果使用者重複點擊?」「如果資料超過上限?」 這四個問題能覆蓋大多數常被遺漏的邊界情境。建議在完成規格草稿後,逐項對照此清單確認,並在驗收標準中為每個邊界條件補充至少一條 AC。

缺陷三:隱含假設未明文化

規格撰寫者對系統現況有先備知識,卻沒有寫出來,導致 AI 或新進工程師基於錯誤假設實作。 例如:「使用者登入後可查看訂單」——但系統有哪些登入方式?訂單資料從哪個微服務取得?這些前置知識應明確寫在規格中,或以連結指向相關技術文件,不能依賴口頭傳遞的隱性知識。

識別隱含假設的方式:將規格交給一位對系統毫不了解的人(或一個全新初始化的 AI 對話),請他複述他對這個功能的理解。凡是他說錯或說不出來的部分,都是你的隱含假設,必須補充到規格中。這個練習也是最有效的規格品質自我審查方式。

完整 spec.md 範例:登入功能

以下是一份可直接作為參考基準的完整登入功能規格,涵蓋所有標準區塊,可複製後依實際需求調整。請注意每個區塊的撰寫密度——背景要說明業務動機,排除項目要標注後續規劃,AC 要有明確編號,NFR 要有量化數值,開放問題要標記負責人與截止日期:

# 登入功能(Email + Password)

## 背景與目標
目前系統僅支援 Google OAuth 登入。為擴大使用族群(尤其是企業用戶,
其 IT 政策可能禁止使用 Google 帳號登入第三方服務),需新增電子郵件
與密碼的傳統登入方式。

成功指標:新登入方式上線後 30 天內,非 Google 帳號的每日活躍使用者
(DAU)增加 15%。

## 範圍
### 本次包含
- 電子郵件 + 密碼登入
- 連續失敗鎖定機制(5 次失敗 → 鎖定 15 分鐘)
- 記住我(30 天 persistent session)
- 登入失敗的明確但不洩漏資訊的錯誤訊息
- 登入事件稽核日誌(成功、失敗、鎖定均記錄)

### 本次排除
- 忘記密碼 / 重設密碼(另立 spec:FEAT-042)
- 多因素驗證 MFA(Phase 2,另立 spec)
- SSO / SAML 企業登入(另立 spec:FEAT-055)

## 使用者故事
- As a 已註冊會員, I want to 用 Email 登入, so that 我可以不依賴 Google 使用服務。
- As a 資安敏感的使用者, I want to 看到帳號鎖定提示, so that 我知道有異常嘗試。

## 驗收標準
- [ ] AC-1:正確帳密 → 1 秒內跳轉首頁,頂部顯示使用者姓名
- [ ] AC-2:錯誤帳密 → 顯示「電子郵件或密碼錯誤」,不揭露哪項有誤
- [ ] AC-3:連續 5 次失敗 → 鎖定 15 分鐘,顯示剩餘解鎖倒數時間
- [ ] AC-4:記住我勾選 → 關閉再開瀏覽器後 30 天內自動登入
- [ ] AC-5:登出 → Session 與 Cookie 立即失效,無法以上一頁恢復

## 技術限制與非功能需求
- 效能:登入 API p95 ≤ 500 ms;鎖定狀態查詢 p99 ≤ 200 ms
- 資安:密碼 bcrypt hash(cost=12);rate limit 10 req/min per IP
- 合規:登入事件(成功/失敗/鎖定)須寫入稽核日誌,保留 90 天
- 可及性:登入表單可完全以鍵盤操作,錯誤訊息有 aria-live 標記

## 開放問題
- [ ] 鎖定帳號時是否發送 Email 通知使用者?(Owner: @product,截止: 2026-04-10)
- [ ] 記住我的 session token 是否需要 rotation on use?(Owner: @security)
- [ ] 鎖定計時器是否於後端重置,還是允許前端計時顯示?(Owner: @frontend)

## 附錄
- 設計稿:Figma 連結(TBD)
- 相關規格:FEAT-042(重設密碼)、FEAT-055(SSO)
- 稽核日誌格式:參見 ADR-007

speckit.clarify 如何補全規格

當規格存在模糊地帶或遺漏資訊時,Spec Kit 的 speckit.clarify 指令會自動分析 spec.md 的內容,依照「具體性、可驗證性、邊界清晰度」三個維度評估品質缺口, 並針對最關鍵的不確定點提出至多 5 個精準的澄清問題。收到你的回答後,它會將答案直接編碼寫回 spec.md,確保規格始終是最新的唯一真相來源(Single Source of Truth),而非散落在對話紀錄或 Slack 訊息中。

建議使用時機:在執行 speckit.planspeckit.tasks 之前,先跑一次 speckit.clarify。清晰的規格可大幅減少 AI 在任務生成階段做出錯誤假設的機率,避免後期因規格不清而需要重新生成任務或修改實作。越早澄清,修正成本越低——規格階段修改一個字,等同於省下實作階段數小時的返工時間。

典型的澄清問題範例(以登入功能為例):

每個問題都聚焦在「如果沒有答案,任務就無法正確實作」的關鍵決策點。 speckit.clarify 會刻意避免問「可以之後再決定」的細節, 確保每次對話的澄清都直接提升規格品質,而不是增加規格複雜度。最理想的狀態是:跑完一輪 speckit.clarify 後,開放問題區塊中所有關鍵阻斷項目都已獲得答案,只剩非阻斷性的待定細節。

規格與任務的對應關係

在 Spec Kit 的工作流程中,spec.md 是整個功能開發的唯一需求來源 (Single Source of Truth)。plan.md 描述技術設計決策, tasks.md 則是從規格與計畫衍生出的可執行工作單元。 三份文件形成一條清晰的可追溯鏈,確保每一行程式碼都能追溯至一條使用者價值:

spec.md(要做什麼、成功條件、驗收標準)
    ↓ speckit.plan 分析規格,輸出技術設計
plan.md(怎麼做、技術架構、資料模型、API 設計)
    ↓ speckit.tasks 綜合規格與計畫,拆解任務
tasks.md(具體任務清單,含依賴順序與 AC 對應編號)
    ↓ speckit.implement 逐一執行任務
程式碼 Pull Request(每個 PR 標注對應的 AC 編號)

每個 tasks.md 中的任務都應能追溯至 spec.md 中的至少一個驗收標準(AC)。 若某個任務找不到對應的 AC,代表它可能是純粹的實作細節(應寫在 plan.md), 或者是多出來的範圍(應先確認是否需要補充到規格中,再決定是否執行)。 這個追溯規則同時也是防止 AI 自行增加未授權功能的護欄。

任務可追溯性範例: tasks.md 中的「實作登入失敗計數器(Redis INCR + TTL)」對應 AC-3; 「在 JWT payload 中加入 remember_me flag」對應 AC-4。 若有任務寫著「優化登入頁面排版」,卻找不到對應 AC, 則應判斷此項目是 plan.md 的範疇,或需要先在 spec.md 中補充對應的驗收標準,再決定是否納入本次迭代。

追溯關係不只是文件管理的形式要求,它是品質保證的核心機制。 當一條 AC 在最終測試中失敗時,可以立即找到所有相關任務與提交紀錄, 快速定位問題;當需求變更時,也能精確識別哪些任務受到影響, 避免局部修改造成全局不一致。這套機制的價值在大型 AI 協作專案中尤為明顯—— 當有十幾個 AI 任務並行實作時,清晰的追溯鏈是維持整體一致性的唯一可靠手段。

黃金法則:規格驅動任務,任務不應自行增加規格沒有的功能。若實作過程中發現規格遺漏,標準做法是:先暫停當前任務,更新 spec.md,執行 speckit.clarify 確認補充內容無歧義,再由 AI 重新生成受影響的任務。保持三份文件(spec → plan → tasks)的一致性,是 AI 協作開發能夠穩定運作的根本前提。任何繞過這個流程的「快速修改」,最終都會以更高的代價在整合或驗收階段浮現。