# Lintar especificações na CI com um linter de especificações

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

Atualizado em 4 de novembro de 2026

Um linter de especificações é um programa que verifica uma especificação em busca de erros de estrutura e termina com um código de falha quando os encontra. A [integração contínua](https://specscore.md/pt-br/validators/) (CI, continuous integration) é uma verificação automática em cada mudança proposta. A integração contínua e a entrega contínua (CI/CD, continuous integration and continuous delivery) é o pipeline que executa essa verificação e mantém publicável uma mudança que passa. O [desenvolvimento guiado por especificação](https://specscore.md/pt-br/spec-driven-development/) (SDD, spec-driven development) é a prática de escrever a especificação antes do código e tratá-la como a fonte da verdade. Um documento de requisitos de produto (PRD, product requirements document) é a prosa que enuncia o problema e o escopo. No [SpecScore](https://specscore.md/), um requisito (REQ) é uma regra nomeada dentro de uma funcionalidade, e um critério de aceitação (AC, acceptance criterion) é uma condição abstrata opcional que aponta para uma ou mais dessas regras. A verificação é um comando da [interface de linha de comando](https://specscore.md/pt-br/cli/) (CLI, command-line interface), `specscore spec lint`, da CLI em [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/pt-br/articles/ears-requirements/) (EARS) é um padrão de frase para um requisito. Este linter verifica cabeçalhos, seções obrigatórias e referências. Não avalia o inglês.

## O que significa lintar uma especificação

Lintar uma especificação é o mesmo tipo de verificação que lintar código. Um programa determinístico lê os arquivos e informa violações de regras. Não decide se o produto é uma boa ideia, e não reescreve o requisito com prosa melhor. A [página de validadores](https://specscore.md/pt-br/validators/) separa essa verificação estrutural de uma revisão manual com IA. `specscore spec lint` é a verificação estrutural.

A descrição do comando, em [internal/cli/spec.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/internal/cli/spec.go) na tag v0.55.1 da CLI e na tag v0.39.1 que o fluxo deste repositório instala, diz que valida a árvore de especificações contra violações de convenções estruturais. Uma execução limpa imprime `0 violations found` e sai com 0. Uma execução que encontra violações imprime uma linha por achado e sai com 1. Esse código de saída é o que faz um job de CI falhar. Argumentos inválidos saem com 2. Se falta `specscore.yaml`, sai com 3 e a mensagem manda executar `specscore init`.

## O que o linter de especificações verifica

As regras são da CLI, não de um serviço separado na nuvem. O catálogo gerado [docs/lint-rules.md](https://github.com/specscore/specscore-cli/blob/v0.55.1/docs/lint-rules.md) na tag v0.55.1 lista 183 regras. O fluxo deste site instala v0.39.1, uma versão anterior, então uma regra que só existe numa tag posterior não é o que esse job executa. As regras nomeadas nesta seção estão nas duas tags. O `--severity` padrão é `error`. Um aviso só é impresso se você passa `--severity warning` ou `info`, e o comando padrão não falha por um aviso. O catálogo marca `dogfood-version-bump` como aviso, então o comando padrão não falha quando o pin do fluxo está atrás do binário.

### Arquivos e seções obrigatórios

A regra `readme-exists` ([readme_exists.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/readme_exists.go)) exige um `README.md` em cada diretório da especificação. A regra `oq-section` ([oq_section.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/oq_section.go)) exige que o README de uma funcionalidade contenha uma seção `## Open Questions`. Um cabeçalho herdado `## Outstanding Questions` é um achado à parte, e `--fix` reescreve esse cabeçalho no lugar. A mensagem do exemplo abaixo, “Open Questions section not found”, é o achado de um README de funcionalidade do qual a seção foi removida.

### Linhas do índice e diretórios filhos

A regra `index-entries` ([index_entries.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/index_entries.go)) confere um índice de funcionalidades contra os diretórios filhos no disco. Um filho que não está na lista é uma violação, e uma linha cujo link aponta para um filho que não está lá também é uma violação. `--fix` pode apagar a linha fantasma e inserir a que falta. Isso é integridade de diretórios e de índice. Não é um rastreamento de cada URL da prosa.

### Forma do cabeçalho de critérios de aceitação

A regra `ac-heading-format` ([ac_heading.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/ac_heading.go)) se aplica ao README de uma funcionalidade, um arquivo cujo título é `# Feature:`. Uma linha que parece um cabeçalho de critério de aceitação deve ser exatamente `### AC: <id>` com um espaço depois dos dois pontos e um id em kebab-case. Também se aceita um cabeçalho da forma `### AC: <id> (verifies ...)`. `--fix` só repara o espaçamento. Um id com maiúsculas ou sublinhados é informado e deixado para uma pessoa. A regra não exige a linha `**Requirements:**`, não pontua palavras como “graceful” ou “fast”, e não avisa quando a prosa contém Given, When ou Then. Como escrever o próprio critério está em [como escrever critérios de aceitação](https://specscore.md/pt-br/articles/acceptance-criteria/).

### Referências do plano a esses identificadores

Num plano que nomeia uma funcionalidade de origem, [plan_rules.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go) lê os cabeçalhos `### AC:` do README dessa funcionalidade. A regra `P-002` informa um valor `**Verifies:**` de uma tarefa que não resolve para `<feature-slug>#ac:<ac-slug>` de um desses cabeçalhos, uma linha `**Verifies:**` vazia, uma linha de origem ausente ou não reconhecida, ou uma funcionalidade de origem que não resolve para um README de funcionalidade. A regra `P-001` informa um cabeçalho que nenhuma tarefa cobre e que não está listado sob `## Deferred AC Coverage`. Ficam isentos os planos com origem numa ideia (`**Source:** idea:<slug>`) e os planos com `**Source:** none`, e também um plano em status de disposição terminal. O texto de uma linha do catálogo para `P-002` diz “valid dependency references”; o checker desse arquivo é a verificação de referências a AC que acaba de ser descrita.

### O que um lint que passa não é

O mesmo comando não decide se um requisito resolve o problema enunciado, se um nome faz sentido, ou se duas funcionalidades se contradizem no significado. A página de validadores lista isso fora do linter da CLI. Também não verifica as palavras-chave dos passos de um cenário. `specscore rehearse` executa os arquivos de cenário. O fluxo deste repositório executa `specscore spec lint` e não chama o rehearse. O catálogo nomeia mais famílias — ideias, decisões, entidades, propriedades, lições, issues e o resto das regras de planos — e cada regra se aplica aos arquivos que lhe correspondem. O catálogo é a lista. Esta página não repete as 183 descrições.

## Executar specscore spec lint na CI

O comando procura para cima, a partir do diretório de trabalho, um `specscore.yaml`. Sem esse arquivo sai com 3 e nomeia `specscore init`. Um job de CI precisa portanto do arquivo de configuração no checkout. [scripts/install.sh](https://github.com/specscore/specscore-cli/blob/v0.55.1/scripts/install.sh) lê `SPECSCORE_VERSION` e, se a variável não está definida, usa `latest`. Fixe uma tag se quiser as mesmas regras em cada execução.

A verificação deste repositório é [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml). Instala a CLI com `SPECSCORE_VERSION` em `v0.39.1` e depois executa `specscore spec lint` sem flags extras, em pull requests e em pushes para main. O GitHub Actions marca o passo como falho quando o processo sai com código diferente de zero. O trecho abaixo conserva esses passos de instalação e de lint. O arquivo também define `permissions: contents: read`, um grupo de concorrência e um comentário sobre por que o pin não é `latest`.

### Passos de instalação e lint de 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
```

### Relatório de falha (specscore 0.55.0, a mesma forma de linha em 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)
```

### Relatório limpo

```text
0 violations found
```

Cada achado é `file:line [severity] rule: message`. O resumo é `N violations found` mais uma contagem entre parênteses, como `(3 errors)`. O código de saída é o estado do processo, não uma linha do relatório. As três linhas acima foram capturadas com specscore 0.55.0 numa funcionalidade da qual se removeu a seção Open Questions e cujo índice omitia um diretório filho vazio. São o mesmo relatório que a página da CLI mostra. `--format` aceita `text` (o padrão), `json` ou `yaml`. `--rules` e `--ignore` selecionam regras e não podem ser combinados. `--fix` reescreve os achados que têm um corretor, inclusive o cabeçalho Outstanding Questions. O job dogfood não passa `--fix`.

## Ferramentas que não lintam este formato na CI

Uma verificação de qualidade de requisitos, nesta CLI, é a verificação estrutural acima. Não é uma nota da prosa. Outras ferramentas de desenvolvimento guiado por especificação publicam verificações diferentes. Os parágrafos abaixo usam só o que dizem as páginas desses projetos. O [guia de ferramentas](https://specscore.md/pt-br/spec-driven-development/tools/) registra as mesmas páginas como lidas em 30 de outubro de 2026, salvo a página inicial da documentação do Spec Kit, que imprime 28 de setembro de 2026, e a página de especificações de funcionalidade do Kiro, que imprime 4 de agosto de 2026.

[GitHub Spec Kit](https://github.github.io/spec-kit/) é um fluxo de agente que escreve artefatos Markdown. A [referência de SDD agêntico](https://github.github.io/spec-kit/reference/agentic-sdd.html) descreve `/speckit.analyze` como um relatório de inconsistências entre a especificação, o plano e as tarefas, sem editar os arquivos. Executa-se no agente. A página inicial da documentação também nomeia extensões da comunidade, inclusive uma chamada CI Guard, que acrescentam portões de conformidade. Isso não é um comando que linta um README de funcionalidade do SpecScore.

[OpenSpec](https://github.com/Fission-AI/OpenSpec) publica sim uma verificação estrutural. `openspec validate`, documentado na [referência da CLI](https://openspec.dev/docs/cli), verifica a estrutura de mudança e de especificação do OpenSpec, sai com código diferente de zero quando a validação falha, e a referência inclui um trecho de shell que um job de CI pode executar. Essa verificação é a forma do OpenSpec, não os cabeçalhos `### AC:` nem um índice do SpecScore.

A [página de especificações de funcionalidade do Kiro](https://kiro.dev/docs/specs/feature-specs/) descreve Analyze Requirements como uma verificação dentro do Kiro, antes do design, que procura inconsistências, ambiguidade, restrições em conflito e lacunas. Não é o comando de `dogfood.yml`. Os padrões de frase que o Kiro escreve estão na [sintaxe de requisitos EARS](https://specscore.md/pt-br/articles/ears-requirements/).

O README do [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) descreve os artefatos do método e os fluxos de agentes. Não documenta um comando que linta um esquema fixo de especificação na CI. O README do [Task Master](https://github.com/eyaltoledano/claude-task-master) descreve converter um PRD em tarefas com `task-master parse-prd`. Não descreve um linter para esse PRD. Um PRD ainda pode ser a entrada de uma funcionalidade SpecScore, e `specscore spec lint` é o que então verifica o arquivo da funcionalidade.

## Perguntas frequentes

### O que é um linter de especificações?

Um linter de especificações lê arquivos de especificação e informa violações estruturais. `specscore spec lint` é esse comando para uma árvore SpecScore. Sai com 0 quando não encontra nada na severidade escolhida, e com 1 quando encontra violações.

### O linter julga a qualidade dos requisitos na redação?

Não. `ac-heading-format` verifica o cabeçalho `### AC:`. Não pontua palavras como “graceful” ou “fast”, e não avisa quando um critério contém Given, When ou Then. A redação é uma tarefa de escrita. A página de validadores separa esse lint determinístico da revisão manual com IA.

### Como linto especificações na CI?

Instale a CLI com `SPECSCORE_VERSION` fixada numa tag de release e execute `specscore spec lint`. O checkout precisa de um `specscore.yaml`. [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml) é um exemplo que funciona no GitHub Actions. Fixa v0.39.1.

### O que uma execução que falha imprime?

Uma linha por achado, `file:line [severity] rule: message`, e depois um resumo como `3 violations found (3 errors)`. O processo sai com 1. Uma árvore limpa imprime `0 violations found` e sai com 0.

### Outras ferramentas validam especificações em CI/CD?

O `openspec validate` do OpenSpec pode fazer um job de CI falhar, e verifica a estrutura de mudança própria do OpenSpec. O `/speckit.analyze` do Spec Kit executa-se na sessão do agente. O Analyze Requirements do Kiro executa-se dentro do Kiro. Os README do BMAD Method e do Task Master não documentam um linter de formato para a CI. O fluxo dogfood do SpecScore executa `specscore spec lint` sobre a árvore SpecScore.

## Fontes

Comportamento da CLI verificado em 4 de novembro de 2026 contra as tags v0.55.1 e v0.39.1 do specscore-cli. As páginas dos concorrentes são as ligadas abaixo; o guia de ferramentas as registra como lidas em 30 de outubro de 2026, salvo onde a página imprime a própria data.

- [specscore/specscore-cli](https://github.com/specscore/specscore-cli)
- [specscore-cli — licença Apache-2.0](https://github.com/specscore/specscore-cli/blob/main/LICENSE)
- [specscore/specscore](https://github.com/specscore/specscore)
- [specscore-cli v0.55.1 — catálogo de regras de lint (183 regras)](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 — regras de plano P-001 e P-002](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go)
- [O que o SpecScore valida](https://specscore.md/pt-br/validators/)
- [Como escrever critérios de aceitação que um agente de IA possa verificar](https://specscore.md/pt-br/articles/acceptance-criteria/)
- [Sintaxe de requisitos EARS explicada, com exemplos](https://specscore.md/pt-br/articles/ears-requirements/)
- [Documentação do GitHub Spec Kit (data da página 28 de setembro de 2026)](https://github.github.io/spec-kit/)
- [GitHub Spec Kit — referência de SDD agêntico (/speckit.analyze)](https://github.github.io/spec-kit/reference/agentic-sdd.html)
- [Referência da CLI do OpenSpec — openspec validate](https://openspec.dev/docs/cli)
- [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec)
- [Kiro — especificações de funcionalidade (atualizado em 4 de agosto de 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)
- [Ferramentas de desenvolvimento guiado por especificação](https://specscore.md/pt-br/spec-driven-development/tools/)

## Relacionados

- [Desenvolvimento baseado em especificações com Claude Code e Cursor](https://specscore.md/pt-br/articles/claude-code-specs/)
- [Modelo de PRD em Markdown para programar com IA](https://specscore.md/pt-br/articles/feature-spec-template/)
- [Como escrever critérios de aceitação que um agente de IA possa verificar](https://specscore.md/pt-br/articles/acceptance-criteria/)
- [Sintaxe de requisitos EARS explicada, com exemplos](https://specscore.md/pt-br/articles/ears-requirements/)
- [O que o SpecScore valida](https://specscore.md/pt-br/validators/)
- [CLI](https://specscore.md/pt-br/cli/)
- [Instalar a CLI](https://specscore.md/pt-br/cli/install/)
- [Desenvolvimento guiado por especificação](https://specscore.md/pt-br/spec-driven-development/)
- [Ferramentas de desenvolvimento guiado por especificação](https://specscore.md/pt-br/spec-driven-development/tools/)
- [Especificação de funcionalidade](https://specscore.md/feature-specification)
- [Especificação de critérios de aceitação](https://specscore.md/acceptance-criteria-specification)
