# CIで仕様リンターを使って仕様をリントする

Canonical: https://specscore.md/ja/articles/lint-specs-in-ci/

最終更新: 2026年11月4日

仕様リンターは、仕様に構造上の誤りがないかを検査し、見つけると失敗を示す終了コードで終わるプログラムです。[継続的インテグレーション](https://specscore.md/ja/validators/)（CI、continuous integration）は、提案された変更のたびに走る自動検査です。継続的インテグレーションと継続的デリバリー（CI/CD、continuous integration and continuous delivery）は、その検査を実行し、通った変更をリリースできる状態に保つパイプラインです。[仕様駆動開発](https://specscore.md/ja/spec-driven-development/)（SDD、spec-driven development）は、コードの前に仕様を書き、仕様を真実の源として扱うやり方です。製品要求文書（PRD、product requirements document）は、問題と範囲を述べる散文です。[SpecScore](https://specscore.md/)では、要件（REQ）は機能の中の名前付き規則で、受け入れ基準（AC、acceptance criterion）は、それらの規則の一つ以上を指す任意の抽象的な条件です。検査は[コマンドラインインターフェース](https://specscore.md/ja/cli/)（CLI、command-line interface）のコマンド `specscore spec lint` で、その CLI は [specscore/specscore-cli](https://github.com/specscore/specscore-cli)（[Apache-2.0](https://github.com/specscore/specscore-cli/blob/main/LICENSE)）にあります。[EARS](https://specscore.md/ja/articles/ears-requirements/)（Easy Approach to Requirements Syntax）は要件の文型です。このリンターが検査するのは見出し、必須の節、参照です。英語の出来は採点しません。

## 仕様をリントするとは

仕様をリントすることは、コードをリントするのと同じ種類の検査です。決定的なプログラムがファイルを読み、規則違反を報告します。製品が良い考えかどうかは決めず、要件をより良い散文に書き直すこともしません。[バリデーターのページ](https://specscore.md/ja/validators/)は、その構造の検査と、人手による AI レビューとを分けています。`specscore spec lint` が構造の検査です。

コマンドの説明は、[internal/cli/spec.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/internal/cli/spec.go) の、CLI タグ v0.55.1 と、このリポジトリのワークフローがインストールする v0.39.1 タグにあります。仕様ツリーを構造上の規約違反について検証する、と書かれています。違反のない実行は `0 violations found` を印字して終了コード 0 です。違反を見つける実行は、発見ごとに1行を印字して終了コード 1 です。その終了コードが CI ジョブを失敗させます。無効な引数は終了コード 2 です。`specscore.yaml` がないと終了コード 3 で、メッセージは `specscore init` を実行するよう示します。

## 仕様リンターが検査すること

規則は CLI のもので、別のクラウドサービスではありません。生成されたカタログ [docs/lint-rules.md](https://github.com/specscore/specscore-cli/blob/v0.55.1/docs/lint-rules.md) は、タグ v0.55.1 で 183 件の規則を挙げます。このウェブサイトのワークフローがインストールするのは、より古いリリースである v0.39.1 です。より後のタグにだけある規則は、そのジョブが実行するものではありません。この節で名指しする規則は、両方のタグにあります。既定の `--severity` は `error` です。警告が印字されるのは、`--severity warning` または `info` を渡したときだけで、既定のコマンドは警告では失敗しません。カタログは `dogfood-version-bump` を警告と印しているので、ワークフローのピンがバイナリより遅れていても、既定のコマンドは失敗しません。

### 必須のファイルと節

規則 `readme-exists`（[readme_exists.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/readme_exists.go)）は、仕様の各ディレクトリに `README.md` を要求します。規則 `oq-section`（[oq_section.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/oq_section.go)）は、機能の README に `## Open Questions` 節があることを要求します。旧来の見出し `## Outstanding Questions` は別の発見で、`--fix` はその見出しをその場で書き換えます。下の例のメッセージ「Open Questions section not found」は、その節を取り除いた機能 README からの発見です。

### インデックスの行と子ディレクトリ

規則 `index-entries`（[index_entries.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/index_entries.go)）は、機能のインデックスをディスク上の子ディレクトリと照合します。一覧にない子は違反で、存在しない子をリンクが指す行も違反です。`--fix` は、実体のない行を消し、欠けている行を挿入できます。これはディレクトリとインデックスの整合です。散文の中のすべての URL をたどるものではありません。

### 受け入れ基準の見出しの形

規則 `ac-heading-format`（[ac_heading.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/ac_heading.go)）は、タイトルが `# Feature:` である機能 README に適用されます。受け入れ基準の見出しに見える行は、コロンの後に空白が一つ、id が kebab-case で、ちょうど `### AC: <id>` でなければなりません。`### AC: <id> (verifies ...)` の形の見出しも受け付けます。`--fix` が直すのは空白だけです。大文字やアンダースコアを含む id は報告され、人に残されます。この規則は `**Requirements:**` 行を要求せず、「graceful」や「fast」のような語を採点せず、散文に Given、When、Then が含まれても警告しません。基準そのものの書き方は [AIエージェントが検証できる受け入れ基準の書き方](https://specscore.md/ja/articles/acceptance-criteria/) にあります。

### それらの ID へのプランの参照

出典の機能を名指しするプランでは、[plan_rules.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/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 は呼び出しません。カタログはさらに別の族を名指しします。着想、決定、実体、プロパティ、教訓、issue、そして残りのプラン規則です。各規則は、自分が担当するファイルに適用されます。一覧はカタログです。このページは 183 件の説明をすべて繰り返しません。

## CI で specscore spec lint を実行する

コマンドは、作業ディレクトリから上へ `specscore.yaml` を探します。そのファイルがないと終了コード 3 で、`specscore init` を名指しします。したがって CI ジョブは、チェックアウトに設定ファイルを必要とします。[scripts/install.sh](https://github.com/specscore/specscore-cli/blob/v0.55.1/scripts/install.sh) は `SPECSCORE_VERSION` を読み、変数が未設定なら `latest` を使います。実行のたびに同じ規則が要るなら、タグをピンしてください。

このリポジトリの検査は [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml) です。`SPECSCORE_VERSION` を `v0.39.1` に設定して CLI をインストールし、その後、追加のフラグなしで `specscore spec lint` を、pull request と main への push で実行します。そのプロセスが非ゼロで終わると、GitHub Actions はステップを失敗にします。下の抜粋は、それらのインストールと lint のステップを残しています。ファイルはまた `permissions: contents: read`、並行性グループ、ピンが `latest` ではない理由のコメントも設定します。

### dogfood.yml のインストールと lint のステップ

```yaml
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 でも行の形は同じ）

```text
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)
```

### 違反のない報告

```text
0 violations found
```

各発見は `file:line [severity] rule: message` です。要約は `N violations found` に、`(3 errors)` のような括弧内の件数を足したものです。終了コードはプロセスの状態であり、報告の一行ではありません。上の三行は、Open Questions の節が取り除かれ、インデックスが空の子ディレクトリを省いていた機能に対し、specscore 0.55.0 で取得したものです。CLI のページが示すのと同じ報告です。`--format` が受け付けるのは `text`（既定）、`json`、または `yaml` です。`--rules` と `--ignore` は規則を選び、組み合わせることはできません。`--fix` は、修正器がある発見を書き換えます。Outstanding Questions の見出しも含まれます。dogfood ジョブは `--fix` を渡しません。

## CI でこの形式をリントしないツール

この CLI における要件品質の検査は、上の構造の検査です。散文の採点ではありません。他の仕様駆動のツールが公表している検査は別のものです。下の段落は、それらのプロジェクト自身のページが述べることだけを使います。[ツールまとめ](https://specscore.md/ja/spec-driven-development/tools/) は、同じページを 2026年10月30日に読んだと記録しています。例外は、2026年9月28日と印字されている Spec Kit の文書のホームと、2026年8月4日と印字されている Kiro の機能仕様のページです。

[GitHub Spec Kit](https://github.github.io/spec-kit/) は、Markdown の成果物を書くエージェントのワークフローです。[エージェント型 SDD のリファレンス](https://github.github.io/spec-kit/reference/agentic-sdd.html) は `/speckit.analyze` を、仕様、プラン、タスクのあいだの不整合の報告であり、ファイルは編集しない、と説明します。実行するのはエージェントの中です。文書のホームは、CI Guard と呼ばれるものを含むコミュニティ拡張も名指しし、それらは準拠のゲートを足します。それは SpecScore の機能 README をリントするコマンドではありません。

[OpenSpec](https://github.com/Fission-AI/OpenSpec) は構造の検査を公表しています。`openspec validate` は [CLI リファレンス](https://openspec.dev/docs/cli) に書かれており、OpenSpec の変更と仕様の構造を検査し、検証が失敗すると非ゼロで終わります。リファレンスには、CI ジョブが実行できるシェルの断片もあります。その検査は OpenSpec の形であり、`### AC:` 見出しや SpecScore のインデックスではありません。

[Kiroの機能仕様のページ](https://kiro.dev/docs/specs/feature-specs/) は、Analyze Requirements を、設計の前に Kiro の中で行う検査だと説明します。探すのは不整合、曖昧さ、衝突する制約、抜けです。`dogfood.yml` のコマンドではありません。Kiro が書く文型は [EARS要件構文](https://specscore.md/ja/articles/ears-requirements/) にあります。

[BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) の README は、その方法の成果物とエージェントのワークフローを説明します。CI で固定の仕様スキーマをリントするコマンドは記載していません。[Task Master](https://github.com/eyaltoledano/claude-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](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml) は、動作する GitHub Actions の例です。ピンは v0.39.1 です。

### 失敗する実行は何を印字しますか。

発見ごとに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` を実行します。

## 出典

CLI の挙動は 2026年11月4日、specscore-cli のタグ v0.55.1 と v0.39.1 に対して確認しました。他のプロジェクトのページは下にリンクしたものです。ツールまとめは、ページ自身が日付を印字している場合を除き、2026年10月30日に読んだと記録しています。

- [specscore/specscore-cli](https://github.com/specscore/specscore-cli)
- [specscore-cli — Apache-2.0 ライセンス](https://github.com/specscore/specscore-cli/blob/main/LICENSE)
- [specscore/specscore](https://github.com/specscore/specscore)
- [specscore-cli v0.55.1 — lint 規則カタログ（183 件）](https://github.com/specscore/specscore-cli/blob/v0.55.1/docs/lint-rules.md)
- [specscore/specscore — dogfood.yml（CLI v0.39.1）](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml)
- [specscore-cli — install.sh（SPECSCORE_VERSION）](https://github.com/specscore/specscore-cli/blob/v0.55.1/scripts/install.sh)
- [specscore-cli v0.55.1 — readme-exists](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/readme_exists.go)
- [specscore-cli v0.55.1 — oq-section](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/oq_section.go)
- [specscore-cli v0.55.1 — index-entries](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/index_entries.go)
- [specscore-cli v0.55.1 — ac-heading-format](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/ac_heading.go)
- [specscore-cli v0.55.1 — プラン規則 P-001 と P-002](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go)
- [SpecScore が検証するもの](https://specscore.md/ja/validators/)
- [AIエージェントが検証できる受け入れ基準の書き方](https://specscore.md/ja/articles/acceptance-criteria/)
- [EARS要件構文を例で説明する](https://specscore.md/ja/articles/ears-requirements/)
- [GitHub Spec Kit の文書（ページの日付 2026年9月28日）](https://github.github.io/spec-kit/)
- [GitHub Spec Kit — エージェント型 SDD のリファレンス（/speckit.analyze）](https://github.github.io/spec-kit/reference/agentic-sdd.html)
- [OpenSpec の CLI リファレンス — openspec validate](https://openspec.dev/docs/cli)
- [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec)
- [Kiro — 機能仕様（2026年8月4日更新）](https://kiro.dev/docs/specs/feature-specs/)
- [bmad-code-org/BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD)
- [eyaltoledano/claude-task-master](https://github.com/eyaltoledano/claude-task-master)
- [仕様駆動開発ツール](https://specscore.md/ja/spec-driven-development/tools/)

## 関連

- [Claude Code と Cursor による仕様駆動開発](https://specscore.md/ja/articles/claude-code-specs/)
- [AIコーディング向けMarkdownのPRDテンプレート](https://specscore.md/ja/articles/feature-spec-template/)
- [AIエージェントが検証できる受け入れ基準の書き方](https://specscore.md/ja/articles/acceptance-criteria/)
- [EARS要件構文を例で説明する](https://specscore.md/ja/articles/ears-requirements/)
- [SpecScore が検証するもの](https://specscore.md/ja/validators/)
- [CLI](https://specscore.md/ja/cli/)
- [CLI をインストール](https://specscore.md/ja/cli/install/)
- [仕様駆動開発](https://specscore.md/ja/spec-driven-development/)
- [仕様駆動開発ツール](https://specscore.md/ja/spec-driven-development/tools/)
- [機能仕様](https://specscore.md/feature-specification)
- [受け入れ基準の仕様](https://specscore.md/acceptance-criteria-specification)
