文章

寫出 AI 代理驗得過的驗收標準

驗收標準(AC,acceptance criteria)是一項變更要算作完成之前,必須為真的條件。Given/When/Then 是 Gherkin 裡的步驟寫法。Cucumber 用這種語言做行為驅動開發(BDD,behaviour-driven development):Given 是起始狀態,When 是發生一個動作,Then 是接著出現、可以觀察到的結果。產品需求文件(PRD,product requirements document)是一段散文,點出問題,也點出打算做的產品。規範驅動開發(SDD,spec-driven development)把結構化的規範,而不只是那段散文,當成核對實作的依據。EARS(Easy Approach to Requirements Syntax)用來約束一條需求句子,讓其中的子句維持固定順序。持續整合(CI,continuous integration)會對每一項提議中的變更自動做一次檢查;本站在 驗證器頁面 說明 SpecScore 的兩項檢查。本頁說明如何寫出人工智慧(AI)程式開發代理驗得過的驗收標準,並給出驗收標準範例,以及 SpecScore 命令列介面(CLI,command-line interface)實際檢查什麼。

更新於 2026年11月3日。

驗收標準是什麼

一條驗收標準回答的是「什麼必須為真」。它點出審閱者、測試或代理能夠接受或拒絕的條件。它不點出要呼叫的函式,也不點出要改的檔案。那些選擇屬於實作。

需求是規則。在 SpecScore 的 需求規範 裡,需求是功能中的一個 #### REQ: 標題:一項義務,自帶識別碼。驗收標準把相關需求收成一個條件。情境是一個具體案例,用來表明該條件成立。驗收標準規範 是這樣說的:標準回答「什麼必須為真」,情境回答「如何證明」。

PRD 可以把同樣的意圖寫進段落。段落幫得上人。代理仍然得猜測哪一句才是通過或失敗的檢驗。把標準寫成自己的一句話,就不用再猜。

什麼讓驗收標準可以驗證

AI 程式開發代理能照著一條標準做,前提是事後的讀者能指出證據,並說出通過或失敗。五個習慣讓這件事變得可能。沒有一個是句子範本。它們是可以套到任何範本上的檢查,Given/When/Then 和檢查清單都算在內。

可觀察

結果是外人看得到的東西:頁面上的一則訊息、一筆存下來或沒存下來的紀錄、一次重新導向、一份被拒絕的表單。「系統理解購物者」無法觀察。「頁面在電子郵件欄位旁邊顯示 Enter a valid email address」可以觀察。

具體

點出行為者、輸入和結果。「壞的輸入會被處理」沒有說是哪一種輸入、哪一種處理。「購物者送出電子郵件 not-an-email」說了。具體不是要你把每個正式環境的值都貼上來。而是讀者能自己準備一筆測試資料,並且知道該發生什麼。

一個行為

一條標準,一個行為。「購物者可以登入、重設密碼,並看到鎖定訊息」是一句話裡的三條標準。實作了第一條、略過第三條的代理,仍可以說這句話做完了。把它們拆開。

通過或失敗

可驗證的驗收標準只有兩種結局。「表單應該感覺很快」是程度問題,不是一個結果。如果需要一條界線,就把界線寫出來:「結帳頁顯示錯誤,而且不再向伺服器送出進一步的請求。」如果說不出失敗長什麼樣子,這句話還不是標準。

拿掉含糊的詞

拿掉把結果藏起來的詞:優雅、直覺、穩健、好用、無縫、快、應該、適當。把每一個換成你願意接受的證據。「優雅地處理錯誤」變成「在欄位旁邊顯示 Enter a valid email address,而且不要成立訂單」。

Given/When/Then 和檢查清單

團隊真正留得下來的驗收標準範例,大多是兩種形態。Given/When/Then 是一個情境。檢查清單是一串結果。狀態、動作、結果的順序要緊時,用情境。要列出同一個動作各自獨立的結果時,用檢查清單。

Cucumber 的 Gherkin 參考 給步驟配上關鍵字 Given、When、Then、And 和 But。這份參考使用英文;Gherkin 也有這些關鍵字的譯文。關鍵字後面的文字,會在 Cucumber 執行檔案時對上稱為步驟定義(step definition)的程式碼。SpecScore 不用那一層。下面的例子是 Gherkin,好讓形態看起來眼熟。它不是 SpecScore 檔案。

Given/When/Then
Scenario: Reject an email that is not a valid address
  Given the shopper is on the checkout form
  When the shopper submits the email "not-an-email"
  Then the page shows "Enter a valid email address" beside the email field
  And the order is not placed
檢查清單
- Submitting the email "not-an-email" shows "Enter a valid email address" beside the email field.
- The order is not placed.

When 只留一個。第二個動作就是第二個情境。And 延續同一個關鍵字:另一個 Given,或另一個 Then。不要用 And 夾帶第二個行為。

檢查清單是同一個約定,只是沒有關鍵字。每一行仍然是一個可觀察的結果。上面的檢查清單就是情境的 Then,寫成一項項檢查。

這和 EARS 需求的關係

這些句式寫在EARS 需求語法詳解與範例。

Alistair Mavin 的指南 把 EARS(Easy Approach to Requirements Syntax)定義成一種溫和地約束文字需求的機制。子句維持同一個順序。指南給出的通用形態是:While <optional pre-condition>, when <optional trigger>, the <system name> shall <system response>。一條需求有零個或多個前置條件、零個或一個觸發、一個系統名稱,以及一個或多個系統回應。

那句話是義務:系統應當滿足的規則。驗收標準是這項義務要算作已滿足時必須為真的條件。一個 Given/When/Then 情境是這個條件的一個具體案例。需求可以寫成 EARS 句子,標準仍然可以不含範例輸入。

在 SpecScore 的功能裡,需求可以是 #### REQ: 標題下的一句 EARS 風格的話。標準維持抽象條件。情境帶著範例。EARS 兩者都不取代。它只約束需求那一句。

驗收標準範例:含糊的和可驗證的

點出證據

含糊

The checkout form should handle bad input gracefully and feel fast.

可驗證

When the shopper submits the email "not-an-email", the checkout page shows "Enter a valid email address" beside that field and does not place the order.

含糊的那一行藏著兩項要求(錯誤與速度),也沒有證據。可驗證的那一行有一個動作,以及人或代理都能核對的兩個結果。範例維持英文,因為格式的關鍵字是英文。

一個行為

含糊

Users can sign in, reset a password, and see an error if the account is locked.

可驗證

When a visitor submits a known email and the matching password, the app sets a session cookie and redirects to /dashboard.

登入、重設和鎖定是三個行為。可驗證的那一行只留下登入。重設和鎖定各自得到自己的標準,帶著自己的輸入和結果。

寫結果,不寫函式名

含糊

The handler returns 400 from validateEmail().

可驗證

When the shopper submits an email that is not a valid address, the checkout page shows "Enter a valid email address" and does not place the order.

函式名和狀態碼把標準綁在今天的程式碼上。檢查挪到另一個函式,結果仍然成立。當狀態碼本身就是你承諾的行為時,把它留下來,並且寫成可觀察的結果。

SpecScore 如何儲存它們,以及 CI 檢查什麼

SpecScore 在 specscore/specscore 儲存庫發布格式,在 specscore/specscore-cli 發布 CLI。兩份文件描述驗收標準時,形態並不完全一樣。兩份都還在用。這一節先說明哪一份是哪一種,然後說明 specscore spec lint 實際拒絕什麼。

這份驗收標準規範,也就是該 URL 上提供的功能 README,把標準寫在功能 README 裡面。每個功能都有一節 ## Acceptance Criteria。每條標準是一個 ### AC: {slug} 標題。slug 使用小寫,並用連字號連接。下一行是 **Requirements:**,按下面的形式列出它所收攏的需求:{feature-id}#req:{slug}。後面是散文,也就是合成後的條件。規範說,這段散文維持抽象。它不得包含 Given/When/Then 步驟、範例輸入或實作細節。還沒有標準時,這一節讀作「Not defined yet.」,Open Questions 一節寫「Acceptance criteria not yet defined for this feature.」。標準是可選的分組:規範說,收攏兩條或更多需求時加一條,若只會複述單條需求就省掉。

具體的證明是功能的 _tests/ 目錄下的情境檔案。情境規範 要求有一個 # Scenario: 標題、一節 ## Steps、大寫的 GIVEN、WHEN、THEN 和 AND,並且恰好一個 WHEN。可選的 **Validates:** 行把情境連到 {feature-path}#ac:{slug},或連到一條需求。## Rehearse 一節可以在 rehearse 圍欄裡放一段可執行的腳本,腳本以 shebang 開頭。

CLI 也讀取精簡的標準檔案,每條標準一個,位於 _acs/<slug>.ac.md。登入範例 和 Rehearse 指南 記錄了這種形態:# AC: <slug>,可選的 **Status:**、**Verifies:** 和 **Applies-to:**(這三項都可選),以及 ## Statement 下面的條件。specscore rehearse acs <feature-dir> 根據這些檔案印出一張摘要表。specscore rehearse acs --write 用這張表,外加一則說明該節是產生出來的、不要手改的註解,替換功能 README 裡的 Acceptance Criteria 一節。沒有 # AC: 標題的檔案,會被該命令報為錯誤。

本儲存庫的 CI 是 dogfood 工作流程。它安裝 CLI v0.39.1,並在拉取請求上、以及推向 main 時執行 specscore spec lint。2026年11月3日核對過,該發行版和 CLI 的預設分支都包含下面這些規則。檢查器查的是結構。它不為英文打分。

規則 ac-heading-format 是一則錯誤。在功能 README(標題為 # Feature: 的檔案)裡,看起來像驗收標準標題的一行必須恰好是 ### AC: <id>,冒號後一個空白,id 為 kebab-case。形如 ### AC: <id> (verifies ...) 的標題也被接受。--fix 只修復空白。帶大寫字母或底線的 id 會被回報,並留給人處理。這條規則不要求有 **Requirements:** 行,不要求「Not defined yet.」佔位,散文裡出現 Given、When 或 Then 時也不警告。規範裡為那則警告所寫的情境,並不是這支 CLI 裡的 lint 規則。

當一份計畫點名了來源功能時,檢查器會讀取該功能 Acceptance Criteria 一節裡的 ### AC: 標題。規則 P-002 回報任務的 **Verifies:** 值不是這些標題之一所對應的 <feature-slug>#ac:<ac-slug>。規則 P-001 回報沒有任何任務涵蓋、並且沒有列在 ## Deferred AC Coverage 下面的標題。這兩條規則不開啟 _acs/*.ac.md。rehearse acs --write 產生的摘要表沒有 ### AC: 標題,所以計畫規則看不到那些精簡檔案。

同一條 lint 命令不檢查情境步驟的關鍵字。specscore rehearse 執行情境檔案:Rehearse 指南在圍欄命令上方使用 ## Given 或 ## When 這樣的標題,並用 **Use:** 呼叫可重複使用的檢查。一個檔案裡有一個 Given 和數個 When 分支時,會作為各自獨立的案例執行。specscore rehearse new <feature-slug>#ac:<ac-slug> 讀取功能 README,並把該標準裡的 Given/When/Then 行抽到 spec/features/<feature-slug>/_tests/<ac-slug>.md。這些都不在 dogfood 工作流程裡執行。工作流程執行的是 specscore spec lint。

內嵌標準,出自驗收標準規範
## Acceptance Criteria

### AC: invalid-email-rejected

**Requirements:** checkout#req:reject-invalid-email

An email that is not a valid address is rejected, and the order is not placed.
精簡標準檔案,rehearse acs 讀取的形態
# AC: invalid-email-rejected

**Status:** accepted
**Verifies:** checkout#req:reject-invalid-email

## Statement

An email that is not a valid address is rejected, and the order is not placed.
情境檔案,出自情境規範
# Scenario: Reject an invalid email

**Validates:** [checkout#ac:invalid-email-rejected](../README.md#ac-invalid-email-rejected)

## Steps

GIVEN the shopper is on the checkout form
WHEN the shopper submits the email "not-an-email"
THEN the page shows "Enter a valid email address" beside the email field
AND the order is not placed
Rehearse 情境,Rehearse 指南裡的形態
# Rehearse: Reject an invalid email

## Given a submitted email that is not a valid address
```bash
printf 'email=not-an-email\n' > form.txt
```

## When the response is recorded
```bash
printf 'Enter a valid email address\n' > out.txt
```

## Then the message is the invalid-email text
```bash
grep -q 'Enter a valid email address' out.txt
```

這四份樣品用來說明那些形態。它們不是一棵完整的功能樹,本頁也不聲稱它們單獨就能通過 specscore spec lint。功能 README 還需要其他必要小節,那條命令才會乾淨。

如果想要一份問題清單,用來從含糊的請求裡把標準問出來,用 提出好問題。登入導覽把一條精簡標準 session-hardened 放在其他產物之中。

常見問題

什麼是驗收標準?

驗收標準(AC)是一項變更要算作完成之前必須為真的條件。在 SpecScore 的驗收標準規範裡,它們是抽象的:說明什麼必須為真,把具體步驟留給情境。

什麼是 Given/When/Then?

Given/When/Then 是 Gherkin 裡的步驟寫法:Given 是起始狀態,When 是發生一個動作,Then 是接著出現、可以觀察到的結果。Cucumber 在 Gherkin 參考裡記錄這些關鍵字。SpecScore 的情境規範使用大寫關鍵字 GIVEN、WHEN、THEN 和 AND,每個情境檔案恰好一個 WHEN。

怎樣為 AI 程式開發代理寫驗收標準?

寫一個可觀察的行為,帶上行為者、輸入和結果,並且不要含糊的詞。範例資料放進情境,不要放進抽象標準。代理就可以對著標準實作,並核對情境。

驗收標準和測試案例是同一回事嗎?

不是。標準陳述條件。測試案例,或 SpecScore 情境,是帶具體輸入的一次執行,用來表明條件成立或失敗。多個情境可以支撐同一條標準。

specscore spec lint 會評判含糊的用詞嗎?

不會。在 CLI v0.39.1,也就是本儲存庫 CI 所安裝的發行版裡,ac-heading-format 檢查 ### AC: 標題。它不為「graceful」或「fast」這類詞打分,標準裡出現 Given/When/Then 時也不警告。用詞是寫作的事。驗證器頁面 把那種決定性的 lint 和手動的 AI 審查分開。

Given/When/Then 步驟在 SpecScore 裡放在哪裡?

放在情境裡,不放在驗收標準裡。驗收標準規範禁止在標準內部寫 Given/When/Then 步驟。情境規範把它們放在 _tests/ 下的 ## Steps 裡。Rehearse 執行一種相關形態:_tests/ 下的標題和圍欄命令,記錄在 Rehearse 指南裡。檢查器不強制這些步驟關鍵字。

檢查你手上的規範。

Have an idea how to improve this page?