Статьи

Линтовать спецификации в 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, из CLI в specscore/specscore-cli (Apache-2.0). Easy Approach to Requirements Syntax (EARS) — шаблон предложения для требования. Этот линтер проверяет заголовки, обязательные разделы и ссылки. Он не оценивает английский.

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

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

Линтовать спецификацию — проверка того же рода, что и линтинг кода. Детерминированная программа читает файлы и сообщает о нарушениях правил. Она не решает, хороша ли идея продукта, и не переписывает требование более удачной прозой. Страница валидаторов отделяет эту структурную проверку от ручной проверки ИИ. specscore spec lint — это структурная проверка.

Описание команды в 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 на теге v0.55.1 перечисляет 183 правила. Воркфлоу этого сайта устанавливает v0.39.1, более ранний выпуск, поэтому правило, которое есть только в более позднем теге, — не то, что выполняет этот job. Правила, названные в этом разделе, есть в обоих тегах. --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. Как написать сам критерий — в статье как писать критерии приёмки.

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

В плане, который называет функцию-источник, 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 читает SPECSCORE_VERSION и, если переменная не задана, берёт latest. Закрепите тег, если хотите одни и те же правила на каждом запуске.

Проверка этого репозитория — 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
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. Job dogfood не передаёт --fix.

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

Проверка качества требований в этой CLI — это структурная проверка выше. Это не оценка прозы. Другие инструменты разработки по спецификациям публикуют иные проверки. Абзацы ниже используют только то, что говорят собственные страницы этих проектов. Обзор инструментов записывает те же страницы как прочитанные 30 октября 2026 года, кроме домашней страницы документации Spec Kit, которая печатает 28 сентября 2026 года, и страницы спецификаций функций Kiro, которая печатает 4 августа 2026 года.

GitHub Spec Kit — это воркфлоу агента, который пишет артефакты Markdown. Справочник агентного SDD описывает /speckit.analyze как отчёт о несогласованностях между спецификацией, планом и задачами, без правки файлов. Его запускают в агенте. Домашняя страница документации также называет расширения сообщества, включая одно под именем CI Guard, которые добавляют ворота соответствия. Это не команда, которая линтует README функции SpecScore.

OpenSpec структурную проверку всё же публикует. openspec validate, описанный в справочнике CLI, проверяет структуру изменения и спецификации OpenSpec, завершается ненулевым кодом, когда проверка не проходит, и справочник включает фрагмент shell, который может выполнить job CI. Эта проверка — форма OpenSpec, а не заголовки ### AC: и не индекс SpecScore.

Страница спецификаций функций Kiro описывает Analyze Requirements как проверку внутри Kiro, до проекта, которая ищет несогласованности, неоднозначность, конфликтующие ограничения и пробелы. Это не команда в dogfood.yml. Шаблоны предложений, которые пишет Kiro, — в статье синтаксис требований EARS.

README BMAD Method описывает артефакты метода и воркфлоу агентов. Он не документирует команду, которая линтует фиксированную схему спецификации в CI. README 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 — рабочий пример 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 года, кроме страниц, которые печатают собственную дату.

Линтуйте спецификацию в CI.

Нашли ошибку в переводе или знаете как улучшить эту страницу?