# Линтовать спецификации в CI линтером спецификаций

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

Обновлено: 4 ноября 2026

Линтер спецификаций — это программа, которая проверяет спецификацию на структурные ошибки и завершается кодом ошибки, когда их находит. [Непрерывная интеграция](https://specscore.md/ru/validators/) (CI, continuous integration) — автоматическая проверка каждого предлагаемого изменения. Непрерывная интеграция и непрерывная доставка (CI/CD, continuous integration and continuous delivery) — это пайплайн, который выполняет эту проверку и сохраняет прошедшее изменение готовым к выпуску. [Разработка по спецификациям](https://specscore.md/ru/spec-driven-development/) (SDD, spec-driven development) — практика писать спецификацию до кода и считать спецификацию источником правды. Документ требований к продукту (PRD, product requirements document) — проза, которая называет проблему и рамки. В [SpecScore](https://specscore.md/) требование (REQ) — именованное правило внутри функции, а критерий приёмки (AC, acceptance criterion) — необязательное абстрактное условие, которое указывает на одно или несколько таких правил. Проверка — команда [интерфейса командной строки](https://specscore.md/ru/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)). [Easy Approach to Requirements Syntax](https://specscore.md/ru/articles/ears-requirements/) (EARS) — шаблон предложения для требования. Этот линтер проверяет заголовки, обязательные разделы и ссылки. Он не оценивает английский.

## Что значит линтовать спецификацию

Линтовать спецификацию — проверка того же рода, что и линтинг кода. Детерминированная программа читает файлы и сообщает о нарушениях правил. Она не решает, хороша ли идея продукта, и не переписывает требование более удачной прозой. [Страница валидаторов](https://specscore.md/ru/validators/) отделяет эту структурную проверку от ручной проверки ИИ. `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. Этот код выхода и роняет job 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, более ранний выпуск, поэтому правило, которое есть только в более позднем теге, — не то, что выполняет этот job. Правила, названные в этом разделе, есть в обоих тегах. `--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)) применяется к README функции, файлу, чей заголовок — `# Feature:`. Строка, которая выглядит как заголовок критерия приёмки, должна быть в точности `### AC: <id>` с одним пробелом после двоеточия и id в kebab-case. Заголовок вида `### AC: <id> (verifies ...)` тоже принимается. `--fix` чинит только пробелы. Id с прописными буквами или подчёркиваниями сообщается и оставляется человеку. Правило не требует строки `**Requirements:**`, не оценивает слова вроде «graceful» или «fast» и не предупреждает, когда проза содержит Given, When или Then. Как написать сам критерий — в статье [как писать критерии приёмки](https://specscore.md/ru/articles/acceptance-criteria/).

### Ссылки плана на эти идентификаторы

В плане, который называет функцию-источник, [plan_rules.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go) читает заголовки `### AC:` в README этой функции. Правило `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.

### Чем прошедший lint не является

Та же команда не решает, закрывает ли требование названную проблему, имеет ли имя смысл и противоречат ли две функции друг другу по смыслу. Страница валидаторов относит это за пределы линтера CLI. Она также не проверяет ключевые слова шагов сценария. `specscore rehearse` выполняет файлы сценариев. Воркфлоу этого репозитория выполняет `specscore spec lint` и не вызывает rehearse. Каталог называет дальнейшие семейства — идеи, решения, сущности, свойства, уроки, issues и остальные правила планов — и каждое правило применяется к файлам, которые ему соответствуют. Каталог и есть список. Эта страница не повторяет все 183 описания.

## Запуск specscore spec lint в CI

Команда ищет `specscore.yaml` вверх от рабочего каталога. Без этого файла она завершается с кодом 3 и называет `specscore init`. Job CI поэтому нужен файл конфигурации в checkout. [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). Он устанавливает CLI с `SPECSCORE_VERSION`, равным `v0.39.1`, и затем выполняет `specscore spec lint` без дополнительных флагов, на pull requests и на push в main. GitHub Actions помечает шаг как неуспешный, когда процесс завершается ненулевым кодом. Фрагмент ниже сохраняет эти шаги установки и lint. Файл также задаёт `permissions: contents: read`, группу конкурентности и комментарий о том, почему закрепление — не `latest`.

### Шаги установки и lint из dogfood.yml

```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)`. Код выхода — это статус процесса, а не строка отчёта. Три строки выше сняты со specscore 0.55.0 на функции, из которой убрали раздел Open Questions и чей индекс пропускал пустой дочерний каталог. Это тот же отчёт, который показывает страница CLI. `--format` принимает `text` (по умолчанию), `json` или `yaml`. `--rules` и `--ignore` выбирают правила и не сочетаются. `--fix` переписывает замечания, у которых есть исправитель, включая заголовок Outstanding Questions. Job dogfood не передаёт `--fix`.

## Инструменты, которые не линтуют этот формат в CI

Проверка качества требований в этой CLI — это структурная проверка выше. Это не оценка прозы. Другие инструменты разработки по спецификациям публикуют иные проверки. Абзацы ниже используют только то, что говорят собственные страницы этих проектов. [Обзор инструментов](https://specscore.md/ru/spec-driven-development/tools/) записывает те же страницы как прочитанные 30 октября 2026 года, кроме домашней страницы документации Spec Kit, которая печатает 28 сентября 2026 года, и страницы спецификаций функций Kiro, которая печатает 4 августа 2026 года.

[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, которые добавляют ворота соответствия. Это не команда, которая линтует README функции SpecScore.

[OpenSpec](https://github.com/Fission-AI/OpenSpec) структурную проверку всё же публикует. `openspec validate`, описанный в [справочнике CLI](https://openspec.dev/docs/cli), проверяет структуру изменения и спецификации OpenSpec, завершается ненулевым кодом, когда проверка не проходит, и справочник включает фрагмент shell, который может выполнить job CI. Эта проверка — форма OpenSpec, а не заголовки `### AC:` и не индекс SpecScore.

[Страница спецификаций функций Kiro](https://kiro.dev/docs/specs/feature-specs/) описывает Analyze Requirements как проверку внутри Kiro, до проекта, которая ищет несогласованности, неоднозначность, конфликтующие ограничения и пробелы. Это не команда в `dogfood.yml`. Шаблоны предложений, которые пишет Kiro, — в статье [синтаксис требований EARS](https://specscore.md/ru/articles/ears-requirements/).

README [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) описывает артефакты метода и воркфлоу агентов. Он не документирует команду, которая линтует фиксированную схему спецификации в CI. README [Task Master](https://github.com/eyaltoledano/claude-task-master) описывает разбор PRD в задачи командой `task-master parse-prd`. Он не описывает линтер для этого PRD. PRD по-прежнему может быть входом функции SpecScore, и `specscore spec lint` — это то, что затем проверяет файл функции.

## Вопросы и ответы

### Что такое линтер спецификаций?

Линтер спецификаций читает файлы спецификации и сообщает о структурных нарушениях. `specscore spec lint` — эта команда для дерева SpecScore. Она завершается с кодом 0, когда ничего не находит на выбранной серьёзности, и с кодом 1, когда находит нарушения.

### Оценивает ли линтер качество требований по формулировке?

Нет. `ac-heading-format` проверяет заголовок `### AC:`. Он не оценивает слова вроде «graceful» или «fast» и не предупреждает, когда критерий содержит Given, When или Then. Формулировка — это задача письма. Страница валидаторов отделяет этот детерминированный lint от ручной проверки ИИ.

### Как линтовать спецификации в CI?

Установите CLI с `SPECSCORE_VERSION`, закреплённым на теге выпуска, и выполните `specscore spec lint`. В checkout нужен `specscore.yaml`. [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/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` может уронить job CI, и она проверяет собственную структуру изменения OpenSpec. `/speckit.analyze` Spec Kit выполняется в сессии агента. Analyze Requirements у Kiro выполняется внутри Kiro. README BMAD Method и Task Master не документируют линтер формата для CI. Воркфлоу dogfood у SpecScore выполняет `specscore spec lint` по дереву SpecScore.

## Источники

Поведение CLI проверено 4 ноября 2026 года по тегам v0.55.1 и v0.39.1 specscore-cli. Страницы конкурентов — те, что связаны ниже; обзор инструментов записывает их как прочитанные 30 октября 2026 года, кроме страниц, которые печатают собственную дату.

- [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/ru/validators/)
- [Как писать критерии приёмки, которые проверит ИИ-агент](https://specscore.md/ru/articles/acceptance-criteria/)
- [Синтаксис требований EARS с объяснением и примерами](https://specscore.md/ru/articles/ears-requirements/)
- [Документация GitHub Spec Kit (дата страницы 28 сентября 2026)](https://github.github.io/spec-kit/)
- [GitHub Spec Kit — справочник агентного SDD (/speckit.analyze)](https://github.github.io/spec-kit/reference/agentic-sdd.html)
- [Справочник CLI OpenSpec — openspec validate](https://openspec.dev/docs/cli)
- [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec)
- [Kiro — спецификации функций (обновлено 4 августа 2026)](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/ru/spec-driven-development/tools/)

## Связанное

- [Разработка по спецификациям с Claude Code и Cursor](https://specscore.md/ru/articles/claude-code-specs/)
- [Шаблон PRD в Markdown для программирования с ИИ](https://specscore.md/ru/articles/feature-spec-template/)
- [Как писать критерии приёмки, которые проверит ИИ-агент](https://specscore.md/ru/articles/acceptance-criteria/)
- [Синтаксис требований EARS с объяснением и примерами](https://specscore.md/ru/articles/ears-requirements/)
- [Что проверяет SpecScore](https://specscore.md/ru/validators/)
- [CLI](https://specscore.md/ru/cli/)
- [Установить CLI](https://specscore.md/ru/cli/install/)
- [Разработка по спецификациям](https://specscore.md/ru/spec-driven-development/)
- [Инструменты разработки по спецификациям](https://specscore.md/ru/spec-driven-development/tools/)
- [Спецификация функции](https://specscore.md/feature-specification)
- [Спецификация критериев приёмки](https://specscore.md/acceptance-criteria-specification)
