# Lintear especificaciones en CI con un linter de especificaciones

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

Última actualización: 4 de noviembre de 2026

Un linter de especificaciones es un programa que revisa una especificación en busca de errores de estructura y termina con un código de fallo cuando los encuentra. La [integración continua](https://specscore.md/es/validators/) (CI, continuous integration) es una comprobación automática en cada cambio propuesto. La integración continua y la entrega continua (CI/CD, continuous integration and continuous delivery) es el pipeline que ejecuta esa comprobación y mantiene publicable un cambio que pasa. El [desarrollo basado en especificaciones](https://specscore.md/es/spec-driven-development/) (SDD, spec-driven development) es la práctica de escribir la especificación antes del código y tratarla como la fuente de verdad. Un documento de requisitos de producto (PRD, product requirements document) es la prosa que enuncia el problema y el alcance. En [SpecScore](https://specscore.md/), un requisito (REQ) es una regla con nombre dentro de una funcionalidad, y un criterio de aceptación (AC, acceptance criterion) es una condición abstracta y opcional que apunta a una o más de esas reglas. La comprobación es un comando de la [interfaz de línea de comandos](https://specscore.md/es/cli/) (CLI, command-line interface), `specscore spec lint`, de la CLI en [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/es/articles/ears-requirements/) (EARS) es un patrón de frase para un requisito. Este linter comprueba encabezados, secciones obligatorias y referencias. No califica el inglés.

## Qué significa lintear una especificación

Lintear una especificación es el mismo tipo de comprobación que lintear código. Un programa determinista lee los archivos e informa de violaciones de reglas. No decide si el producto es una buena idea, y no reescribe el requisito con mejor prosa. La [página de validadores](https://specscore.md/es/validators/) separa esa comprobación estructural de una revisión manual con IA. `specscore spec lint` es la comprobación estructural.

La descripción del comando, en [internal/cli/spec.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/internal/cli/spec.go) en la etiqueta v0.55.1 de la CLI y en la etiqueta v0.39.1 que instala el workflow de este repositorio, dice que valida el árbol de especificaciones frente a violaciones de convenciones estructurales. Una ejecución limpia imprime `0 violations found` y sale con 0. Una ejecución con violaciones imprime una línea por hallazgo y sale con 1. Ese código de salida es lo que hace fallar un job de CI. Los argumentos inválidos salen con 2. Si falta `specscore.yaml`, sale con 3 y el mensaje indica ejecutar `specscore init`.

## Qué comprueba el linter de especificaciones

Las reglas son de la CLI, no de un servicio en la nube. El catálogo generado [docs/lint-rules.md](https://github.com/specscore/specscore-cli/blob/v0.55.1/docs/lint-rules.md) en la etiqueta v0.55.1 lista 183 reglas. El workflow de este sitio instala v0.39.1, una versión anterior, así que una regla que solo existe en una etiqueta posterior no es lo que ejecuta ese job. Las reglas nombradas en esta sección están en ambas etiquetas. El `--severity` predeterminado es `error`. Un aviso solo se imprime si pasas `--severity warning` o `info`, y el comando predeterminado no falla por un aviso. El catálogo marca `dogfood-version-bump` como aviso, así que el comando predeterminado no falla cuando el pin del workflow va por detrás del binario.

### Archivos y secciones obligatorios

La regla `readme-exists` ([readme_exists.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/readme_exists.go)) exige un `README.md` en cada directorio de la especificación. La regla `oq-section` ([oq_section.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/oq_section.go)) exige que el README de una funcionalidad contenga una sección `## Open Questions`. Un encabezado heredado `## Outstanding Questions` es un hallazgo aparte, y `--fix` reescribe ese encabezado en el sitio. El mensaje del ejemplo, “Open Questions section not found”, es el hallazgo de un README al que se le quitó la sección.

### Filas del índice y directorios hijos

La regla `index-entries` ([index_entries.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/index_entries.go)) compara un índice de funcionalidades con los directorios hijos en disco. Un hijo que no está en la lista es una violación, y una fila cuyo enlace apunta a un hijo que no existe también. `--fix` puede borrar la fila fantasma e insertar la que falta. Es integridad de directorios e índice. No es un rastreo de cada URL de la prosa.

### Forma del encabezado de criterios de aceptación

La regla `ac-heading-format` ([ac_heading.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/ac_heading.go)) se aplica al README de una funcionalidad, un archivo cuyo título es `# Feature:`. Una línea que parece un encabezado de criterio de aceptación debe ser exactamente `### AC: <id>` con un espacio después de los dos puntos y un id en kebab-case. También se acepta `### AC: <id> (verifies ...)`. `--fix` solo repara el espaciado. Un id con mayúsculas o guiones bajos se informa y se deja a una persona. La regla no exige la línea `**Requirements:**`, no puntúa palabras como “graceful” o “fast”, y no avisa cuando la prosa contiene Given, When o Then. Cómo escribir el criterio está en [cómo escribir criterios de aceptación](https://specscore.md/es/articles/acceptance-criteria/).

### Referencias del plan a esos identificadores

En un plan que nombra una funcionalidad de origen, [plan_rules.go](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go) lee los encabezados `### AC:` del README de esa funcionalidad. La regla `P-002` informa un valor `**Verifies:**` de una tarea que no resuelve a `<feature-slug>#ac:<ac-slug>` para uno de esos encabezados, una línea `**Verifies:**` vacía, una línea de origen ausente o no reconocida, o una funcionalidad de origen que no resuelve a un README. La regla `P-001` informa un encabezado que ninguna tarea cubre y que no está bajo `## Deferred AC Coverage`. Quedan exentos los planes con origen en una idea (`**Source:** idea:<slug>`), los planes con `**Source:** none` y un plan en un estado de disposición terminal. El texto de una línea del catálogo para `P-002` dice “valid dependency references”; el checker de ese archivo es la comprobación de referencias a AC que acaba de describirse.

### Lo que un lint que pasa no es

El mismo comando no decide si un requisito resuelve el problema enunciado, si un nombre tiene sentido, o si dos funcionalidades se contradicen en el significado. La página de validadores lista eso fuera del linter de la CLI. Tampoco comprueba las palabras clave de los pasos de un escenario. `specscore rehearse` ejecuta los archivos de escenario. El workflow de este repositorio ejecuta `specscore spec lint` y no llama a rehearse. El catálogo nombra más familias — ideas, decisiones, entidades, propiedades, lecciones, issues y el resto de reglas de planes — y cada regla se aplica a los archivos que le corresponden. El catálogo es la lista. Esta página no repite las 183 descripciones.

## Ejecutar specscore spec lint en CI

El comando busca hacia arriba desde el directorio de trabajo un `specscore.yaml`. Sin ese archivo sale con 3 y nombra `specscore init`. Un job de CI necesita por tanto el archivo de configuración en el checkout. [scripts/install.sh](https://github.com/specscore/specscore-cli/blob/v0.55.1/scripts/install.sh) lee `SPECSCORE_VERSION` y, si la variable no está definida, usa `latest`. Fija una etiqueta si quieres las mismas reglas en cada ejecución.

La comprobación de este repositorio es [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml). Instala la CLI con `SPECSCORE_VERSION` en `v0.39.1` y luego ejecuta `specscore spec lint` sin flags extra, en las pull requests y en los push a main. GitHub Actions marca el paso como fallido cuando el proceso sale distinto de cero. El extracto conserva esos pasos de instalación y de lint. El archivo también fija `permissions: contents: read`, un grupo de concurrencia y un comentario sobre por qué el pin no es `latest`.

### Pasos de instalación y 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
```

### Informe de fallo (specscore 0.55.0, la misma forma de línea en 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)
```

### Informe limpio

```text
0 violations found
```

Cada hallazgo es `file:line [severity] rule: message`. El resumen es `N violations found` más un recuento entre paréntesis, como `(3 errors)`. El código de salida es el estado del proceso, no una línea del informe. Las tres líneas de arriba se capturaron con specscore 0.55.0 en una funcionalidad a la que se le quitó Open Questions y cuyo índice omitía un directorio hijo vacío. Son el mismo informe que muestra la página de la CLI. `--format` acepta `text` (el predeterminado), `json` o `yaml`. `--rules` y `--ignore` seleccionan reglas y no pueden combinarse. `--fix` reescribe los hallazgos que tienen un arreglador, incluido el encabezado Outstanding Questions. El job dogfood no pasa `--fix`.

## Herramientas que no lintean este formato en CI

Una comprobación de calidad de requisitos, en esta CLI, es la comprobación estructural de arriba. No es una nota de la prosa. Otras herramientas de desarrollo basado en especificaciones publican comprobaciones distintas. Los párrafos de abajo usan solo lo que dicen las páginas de esos proyectos. La [ronda de herramientas](https://specscore.md/es/spec-driven-development/tools/) registra las mismas páginas como leídas el 30 de octubre de 2026, salvo la portada de documentación de Spec Kit, que imprime el 28 de septiembre de 2026, y la página de especificaciones de funcionalidad de Kiro, que imprime el 4 de agosto de 2026.

[GitHub Spec Kit](https://github.github.io/spec-kit/) es un workflow de agente que escribe artefactos Markdown. La [referencia de SDD agéntico](https://github.github.io/spec-kit/reference/agentic-sdd.html) describe `/speckit.analyze` como un informe de inconsistencias entre la especificación, el plan y las tareas, sin editar los archivos. Se ejecuta en el agente. La portada de la documentación también nombra extensiones de la comunidad, incluida una llamada CI Guard, que añaden puertas de cumplimiento. Eso no es un comando que lintee un README de funcionalidad de SpecScore.

[OpenSpec](https://github.com/Fission-AI/OpenSpec) sí publica una comprobación estructural. `openspec validate`, documentado en la [referencia de la CLI](https://openspec.dev/docs/cli), comprueba la estructura de cambio y de especificación de OpenSpec, sale distinto de cero cuando la validación falla, y la referencia incluye un fragmento de shell que un job de CI puede ejecutar. Esa comprobación es la forma de OpenSpec, no los encabezados `### AC:` ni un índice de SpecScore.

La [página de especificaciones de funcionalidad de Kiro](https://kiro.dev/docs/specs/feature-specs/) describe Analyze Requirements como una comprobación dentro de Kiro, antes del diseño, que busca inconsistencias, ambigüedad, restricciones en conflicto y huecos. No es el comando de `dogfood.yml`. Los patrones de frase que escribe Kiro están en [la sintaxis de requisitos EARS](https://specscore.md/es/articles/ears-requirements/).

El README de [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) describe los artefactos del método y los workflows de agentes. No documenta un comando que lintee un esquema fijo de especificación en CI. El README de [Task Master](https://github.com/eyaltoledano/claude-task-master) describe convertir un PRD en tareas con `task-master parse-prd`. No describe un linter para ese PRD. Un PRD puede seguir siendo la entrada de una funcionalidad SpecScore, y `specscore spec lint` es lo que entonces comprueba el archivo de la funcionalidad.

## Preguntas frecuentes

### ¿Qué es un linter de especificaciones?

Un linter de especificaciones lee archivos de especificación e informa de violaciones estructurales. `specscore spec lint` es ese comando para un árbol SpecScore. Sale con 0 cuando no encuentra nada en la severidad elegida, y con 1 cuando encuentra violaciones.

### ¿El linter juzga la calidad de los requisitos en la redacción?

No. `ac-heading-format` comprueba el encabezado `### AC:`. No puntúa palabras como “graceful” o “fast”, y no avisa cuando un criterio contiene Given, When o Then. La redacción es una tarea de escritura. La página de validadores separa ese lint determinista de la revisión manual con IA.

### ¿Cómo linteo especificaciones en CI?

Instala la CLI con `SPECSCORE_VERSION` fijada a una etiqueta de release y ejecuta `specscore spec lint`. El checkout necesita un `specscore.yaml`. [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml) es un ejemplo que funciona en GitHub Actions. Fija v0.39.1.

### ¿Qué imprime una ejecución que falla?

Una línea por hallazgo, `file:line [severity] rule: message`, y luego un resumen como `3 violations found (3 errors)`. El proceso sale con 1. Un árbol limpio imprime `0 violations found` y sale con 0.

### ¿Otras herramientas validan especificaciones en CI/CD?

El `openspec validate` de OpenSpec puede hacer fallar un job de CI, y comprueba la estructura de cambio propia de OpenSpec. El `/speckit.analyze` de Spec Kit se ejecuta en la sesión del agente. Analyze Requirements de Kiro se ejecuta dentro de Kiro. Los README de BMAD Method y de Task Master no documentan un linter de formato para CI. El workflow dogfood de SpecScore ejecuta `specscore spec lint` sobre el árbol SpecScore.

## Fuentes

Comportamiento de la CLI comprobado el 4 de noviembre de 2026 contra las etiquetas v0.55.1 y v0.39.1 de specscore-cli. Las páginas de terceros son las enlazadas abajo; la ronda de herramientas las registra como leídas el 30 de octubre de 2026, salvo donde la página imprime su propia fecha.

- [specscore/specscore-cli](https://github.com/specscore/specscore-cli)
- [specscore-cli — licencia 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 reglas de lint (183 reglas)](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 — reglas de plan P-001 y P-002](https://github.com/specscore/specscore-cli/blob/v0.55.1/pkg/lint/plan_rules.go)
- [Qué valida SpecScore](https://specscore.md/es/validators/)
- [Cómo escribir criterios de aceptación que un agente de IA pueda verificar](https://specscore.md/es/articles/acceptance-criteria/)
- [Sintaxis de requisitos EARS explicada, con ejemplos](https://specscore.md/es/articles/ears-requirements/)
- [Documentación de GitHub Spec Kit (fecha de página 28 de septiembre de 2026)](https://github.github.io/spec-kit/)
- [GitHub Spec Kit — referencia de SDD agéntico (/speckit.analyze)](https://github.github.io/spec-kit/reference/agentic-sdd.html)
- [Referencia de la CLI de OpenSpec — openspec validate](https://openspec.dev/docs/cli)
- [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec)
- [Kiro — especificaciones de funcionalidad (actualizado el 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)
- [Herramientas de desarrollo basado en especificaciones](https://specscore.md/es/spec-driven-development/tools/)

## Relacionado

- [Desarrollo basado en especificaciones con Claude Code y Cursor](https://specscore.md/es/articles/claude-code-specs/)
- [Plantilla de PRD en Markdown para programar con IA](https://specscore.md/es/articles/feature-spec-template/)
- [Cómo escribir criterios de aceptación que un agente de IA pueda verificar](https://specscore.md/es/articles/acceptance-criteria/)
- [Sintaxis de requisitos EARS explicada, con ejemplos](https://specscore.md/es/articles/ears-requirements/)
- [Qué valida SpecScore](https://specscore.md/es/validators/)
- [CLI](https://specscore.md/es/cli/)
- [Instalar la CLI](https://specscore.md/es/cli/install/)
- [Desarrollo basado en especificaciones](https://specscore.md/es/spec-driven-development/)
- [Herramientas de desarrollo basado en especificaciones](https://specscore.md/es/spec-driven-development/tools/)
- [Especificación de funcionalidad](https://specscore.md/feature-specification)
- [Especificación de criterios de aceptación](https://specscore.md/acceptance-criteria-specification)
