文章

在 CI 中用規格檢查器檢查規格

規格檢查器是一支程式,它檢查規格裡的結構錯誤,發現錯誤時以失敗碼結束。持續整合(CI,continuous integration)是對每一項提議變更的自動檢查。持續整合與持續交付(CI/CD,continuous integration and continuous delivery)是執行這項檢查、並讓通過的變更保持可發行的流水線。規範驅動開發(SDD,spec-driven development)是在寫程式之前寫下規格,並把規格當作事實來源。產品需求文件(PRD,product requirements document)是陳述問題和範圍的散文。在 SpecScore 裡,需求(REQ)是功能內部一條有名字的規則,驗收標準(AC,acceptance criterion)是可選的抽象條件,指向其中一條或多條規則。這項檢查是命令列介面(CLI,command-line interface)命令 specscore spec lint,來自 specscore/specscore-cli(Apache-2.0)裡的 CLI。EARS(Easy Approach to Requirements Syntax)是一條需求的句式。這個檢查器檢查標題、必要的小節和參照。它不為英語打分。

最近更新:2026年11月4日

檢查一份規格是什麼意思

檢查一份規格,和檢查程式碼是同一類檢查。一支確定性的程式讀取檔案並報告規則違規。它不判斷產品是不是個好主意,也不把需求改寫成更好的散文。驗證器頁面把那項結構檢查和藉助 AI 的人工復查分開。specscore spec lint 就是那項結構檢查。

命令的說明寫在 internal/cli/spec.go,位於 CLI 標籤 v0.55.1,以及本儲存庫工作流程所安裝的 v0.39.1 標籤。說明寫的是:對照結構約定的違規來驗證規格樹。一次乾淨的執行印出 0 violations found 並以 0 結束。發現違規的執行為每筆發現印出一行,並以 1 結束。這個結束碼會讓 CI 作業失敗。無效參數以 2 結束。缺少 specscore.yaml 時以 3 結束,訊息要你執行 specscore init。

規格檢查器檢查什麼

規則屬於 CLI,不是另一項雲端服務。產生的規則一覽 docs/lint-rules.md 在標籤 v0.55.1 列出 183 條規則。本網站的工作流程安裝的是較舊的發行 v0.39.1,因此只存在於較晚標籤裡的規則,並不是那個作業所執行的。本節所點名的規則,兩個標籤裡都有。預設的 --severity 是 error。只有在傳入 --severity warning 或 info 時才會印出警告,預設命令不會因此失敗。規則一覽把 dogfood-version-bump 標為警告,所以當工作流程的釘選落後於二進位檔時,預設命令不會失敗。

必要的檔案和小節

規則 readme-exists(readme_exists.go)要求規格的每個目錄裡都有 README.md。規則 oq-section(oq_section.go)要求功能 README 包含 ## Open Questions 小節。舊式標題 ## Outstanding Questions 是另一筆發現,--fix 會就地改寫該標題。下面範例裡的訊息「Open Questions section not found」,是從一份拿掉了該小節的功能 README 得到的發現。

索引列與子目錄

規則 index-entries(index_entries.go)把功能索引和磁碟上的子目錄相對照。未列入的子目錄是違規,連結指向一個不存在的子目錄的列也是違規。--fix 可以刪掉那條幽靈列,並插入缺少的列。這是目錄和索引的完整性。它不是去爬散文裡的每一個 URL。

驗收標準標題的形態

規則 ac-heading-format(ac_heading.go)適用於功能 README,也就是標題為 # Feature: 的檔案。看起來像驗收標準標題的一行,必須恰好是 ### AC: <id>,冒號後有一個空白,id 為 kebab-case。### AC: <id> (verifies ...) 這種標題也被接受。--fix 只修復空白。帶大寫字母或底線的 id 會被報告,並留給人來處理。這條規則不要求 **Requirements:** 行,不為「graceful」或「fast」這類詞打分,散文裡出現 Given、When 或 Then 時也不警告。標準本身怎麼寫,見寫出 AI 代理驗得過的驗收標準。

計畫對這些識別碼的參照

在點名了來源功能的計畫上,plan_rules.go 讀取該功能 README 裡的 ### AC: 標題。規則 P-002 報告:任務的 **Verifies:** 值沒有解析到這些標題之一的 <feature-slug>#ac:<ac-slug>、空的 **Verifies:** 行、缺少或無法辨識的來源行,或者來源功能沒有解析到一份功能 README。規則 P-001 報告:沒有任何任務涵蓋、並且沒有列在 ## Deferred AC Coverage 之下的標題。以來源為構想的計畫(**Source:** idea:<slug>)和帶有 **Source:** none 的計畫免於這些規則,處於終態處置狀態的計畫也同樣免除。P-002 在規則一覽裡的一行文字是「valid dependency references」;那個檔案裡的檢查器,就是剛才描述的 AC 參照檢查。

一次通過的檢查不是什麼

同一條命令不判斷一條需求是否解決了所陳述的問題,不判斷一個名字是否說得通,也不判斷兩個功能是否在意義上互相矛盾。驗證器頁面把這些列在 CLI 檢查器之外。它也不檢查情境步驟的關鍵字。specscore rehearse 執行情境檔案。本儲存庫的工作流程執行 specscore spec lint,並不呼叫 rehearse。規則一覽還點出更多類別——構想、決策、實體、屬性、教訓、議題,以及其餘的計畫規則——每條規則適用於它負責的檔案。規則一覽就是那份清單。本頁不重述全部 183 條說明。

在 CI 中執行 specscore spec lint

命令從工作目錄向上尋找 specscore.yaml。沒有這個檔案時以 3 結束,並點名 specscore init。因此 CI 作業需要取出的內容裡有這份設定檔。scripts/install.sh 讀取 SPECSCORE_VERSION,變數未設定時預設使用 latest。如果希望每次執行都是同一套規則,就釘住一個標籤。

本儲存庫的檢查是 dogfood.yml。它把 SPECSCORE_VERSION 設為 v0.39.1 來安裝 CLI,然後不加額外旗標執行 specscore spec lint,觸發於 pull request 以及向 main 的 push。該行程以非零結束時,GitHub Actions 讓這個步驟失敗。下面的摘錄保留了那些安裝和檢查步驟。該檔案還設定 permissions: contents: read、一個並行群組,以及一條說明為何釘選不是 latest 的註解。

dogfood.yml 裡的安裝與檢查步驟
name: Dogfood lint

on:
  push:
    branches: [main]
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
      - name: Install specscore CLI (pinned)
        env:
          SPECSCORE_VERSION: v0.39.1
        run: |
          curl -fsSL https://specscore.md/install/get-cli | \
            SPECSCORE_INSTALL_DIR="$HOME/.local/bin" sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"
          specscore --version
      - name: Lint spec tree
        run: specscore spec lint
失敗報告(specscore 0.55.0,v0.39.1 的行形態相同)
features/apply-discount/README.md:0 [error] oq-section: Open Questions section not found
features/apply-discount/README.md:0 [error] index-entries: Child directory not listed in index: refunds
features/apply-discount/refunds:0 [error] readme-exists: README.md not found

3 violations found (3 errors)
乾淨的報告
0 violations found

每筆發現都是 file:line [severity] rule: message。摘要是 N violations found,再加上括號裡的計數,例如 (3 errors)。結束碼是行程狀態,不是報告裡的一行。上面三行取自 specscore 0.55.0,當時一份功能的 Open Questions 小節已被移除,索引也漏了一個空的子目錄。它們和 CLI 頁面展示的是同一份報告。--format 接受 text(預設)、json 或 yaml。--rules 和 --ignore 用來選擇規則,不能同時使用。--fix 會改寫帶有修復器的發現,包括 Outstanding Questions 標題。dogfood 作業不傳入 --fix。

不在 CI 中檢查這種格式的工具

在這個 CLI 裡,需求品質檢查就是上面的結構檢查。它不是給散文打分。其他規範驅動的工具公布的是不同的檢查。下面各段只用那些專案自己的頁面所說的內容。工具彙整 把同樣的頁面記為 2026年10月30日讀過,例外是印著 2026年9月28日的 Spec Kit 文件首頁,以及印著 2026年8月4日的 Kiro 功能規範頁。

GitHub Spec Kit 是一套代理工作流程,寫出 Markdown 產出物。代理式 SDD 參考 把 /speckit.analyze 描述為跨規格、計畫和任務的不一致報告,並且不編輯檔案。你在代理裡執行它。文件首頁還點名社群擴充,其中包括一個叫 CI Guard 的擴充,它們加上合規閘門。那不是一條會檢查 SpecScore 功能 README 的命令。

OpenSpec 的確公布了一項結構檢查。openspec validate,記載於CLI 參考,檢查 OpenSpec 的變更和規格結構,驗證失敗時以非零結束,參考裡還包含一段 CI 作業可以執行的 shell 片段。那項檢查是 OpenSpec 的形態,不是 ### AC: 標題,也不是 SpecScore 的索引。

Kiro 的功能規範頁 把需求檢視(Analyze Requirements)描述為 Kiro 內部、設計之前的一項檢查,尋找不一致、歧義、互相衝突的約束和缺口。它不是 dogfood.yml 裡的命令。Kiro 所寫的句式在EARS 需求語法。

BMAD Method 的 README 描述該方法的產出物和代理工作流程。它沒有記載一條在 CI 裡檢查固定規格綱要的命令。Task Master 的 README 描述用 task-master parse-prd 把 PRD 解析成任務。它沒有描述那個 PRD 的檢查器。PRD 仍然可以是 SpecScore 功能的輸入,而隨後檢查該功能檔案的是 specscore spec lint。

常見問題

什麼是規格檢查器?

規格檢查器讀取規格檔案並報告結構違規。specscore spec lint 就是針對 SpecScore 樹的那條命令。在所選嚴重程度下什麼都沒發現時以 0 結束,發現違規時以 1 結束。

規格檢查器會從用字判斷需求品質嗎?

不會。ac-heading-format 檢查的是 ### AC: 標題。它不為「graceful」或「fast」這類詞打分,一條標準裡出現 Given、When 或 Then 時也不警告。用字是寫作的工作。驗證器頁面把那項確定性檢查和藉助 AI 的人工復查分開。

怎樣在 CI 裡檢查規格?

安裝 CLI 時把 SPECSCORE_VERSION 設為一個發行標籤,然後執行 specscore spec lint。取出的內容需要一份 specscore.yaml。dogfood.yml 是一個能用的 GitHub Actions 範例。它釘住 v0.39.1。

失敗的一次執行會印出什麼?

每筆發現一行,file:line [severity] rule: message,然後是類似 3 violations found (3 errors) 的摘要。行程以 1 結束。一棵乾淨的樹印出 0 violations found 並以 0 結束。

其他規範驅動的工具會在 CI/CD 裡驗證規格嗎?

OpenSpec 的 openspec validate 可以讓 CI 作業失敗,它檢查的是 OpenSpec 自己的變更結構。Spec Kit 的 /speckit.analyze 在代理的工作階段裡執行。Kiro 的需求檢視(Analyze Requirements)在 Kiro 內部執行。BMAD Method 和 Task Master 的 README 沒有記載給 CI 用的格式檢查器。SpecScore 的 dogfood 工作流程在 SpecScore 樹上執行 specscore spec lint。

在 CI 裡檢查規格。

Have an idea how to improve this page?