Articoli

Fare il lint delle specifiche in CI con un linter di specifiche

Un linter di specifiche è un programma che controlla una specifica alla ricerca di errori di struttura ed esce con un codice di errore quando li trova. L’integrazione continua (CI, continuous integration) è un controllo automatico su ogni modifica proposta. L’integrazione continua e la consegna continua (CI/CD, continuous integration and continuous delivery) è la pipeline che esegue quel controllo e mantiene rilasciabile una modifica che passa. Lo sviluppo guidato dalle specifiche (SDD, spec-driven development) è la pratica di scrivere la specifica prima del codice e di trattare la specifica come fonte di verità. Un documento dei requisiti di prodotto (PRD, product requirements document) è la prosa che enuncia il problema e l’ambito. In SpecScore, un requisito (REQ) è una regola con nome dentro una funzionalità, e un criterio di accettazione (AC, acceptance criterion) è una condizione astratta facoltativa che punta a una o più di quelle regole. Il controllo è un comando dell’interfaccia a riga di comando (CLI, command-line interface), specscore spec lint, della CLI in specscore/specscore-cli (Apache-2.0). Easy Approach to Requirements Syntax (EARS) è un modello di frase per un requisito. Questo linter controlla i titoli, le sezioni obbligatorie e i riferimenti. Non valuta l’inglese.

Ultimo aggiornamento: 4 novembre 2026

Che cosa significa fare il lint di una specifica

Fare il lint di una specifica è lo stesso tipo di controllo che fare il lint del codice. Un programma deterministico legge i file e segnala violazioni di regole. Non decide se il prodotto è una buona idea, e non riscrive il requisito in una prosa migliore. La pagina dei validatori separa quel controllo strutturale da una revisione manuale con IA. specscore spec lint è il controllo strutturale.

La descrizione del comando, in internal/cli/spec.go al tag v0.55.1 della CLI e al tag v0.39.1 che il workflow di questo repository installa, dice che valida l’albero delle specifiche rispetto a violazioni di convenzioni strutturali. Un’esecuzione pulita stampa 0 violations found ed esce con 0. Un’esecuzione che trova violazioni stampa una riga per rilievo ed esce con 1. Quel codice di uscita è ciò che fa fallire un job di CI. Gli argomenti non validi escono con 2. Un specscore.yaml mancante esce con 3, e il messaggio dice di eseguire specscore init.

Che cosa controlla il linter di specifiche

Le regole sono della CLI, non di un servizio cloud separato. Il catalogo generato docs/lint-rules.md al tag v0.55.1 elenca 183 regole. Il workflow di questo sito installa v0.39.1, una versione precedente, quindi una regola che esiste solo in un tag successivo non è ciò che quel job esegue. Le regole nominate in questa sezione sono in entrambi i tag. Il --severity predefinito è error. Un avviso viene stampato solo quando passi --severity warning o info, e il comando predefinito non fallisce per un avviso. Il catalogo segna dogfood-version-bump come avviso, quindi il comando predefinito non fallisce quando il pin del workflow è indietro rispetto al binario.

File e sezioni obbligatori

La regola readme-exists (readme_exists.go) richiede un README.md in ogni directory della specifica. La regola oq-section (oq_section.go) richiede che il README di una funzionalità contenga una sezione ## Open Questions. Un titolo ereditato ## Outstanding Questions è un rilievo a parte, e --fix riscrive quel titolo sul posto. Il messaggio nell’esempio sotto, «Open Questions section not found», è il rilievo di un README di funzionalità a cui è stata tolta la sezione.

Righe dell’indice e directory figlie

La regola index-entries (index_entries.go) confronta un indice di funzionalità con le directory figlie sul disco. Una figlia che non è elencata è una violazione, e una riga il cui link punta a una figlia che non c’è è una violazione. --fix può cancellare la riga fantasma e inserire quella mancante. È l’integrità di directory e indice. Non è una scansione di ogni URL nella prosa.

Forma del titolo del criterio di accettazione

La regola ac-heading-format (ac_heading.go) si applica al README di una funzionalità, un file il cui titolo è # Feature:. Una riga che sembra un titolo di criterio di accettazione deve essere esattamente ### AC: <id> con uno spazio dopo i due punti e un id in kebab-case. È accettato anche un titolo della forma ### AC: <id> (verifies ...). --fix corregge solo la spaziatura. Un id con lettere maiuscole o trattini bassi viene segnalato e lasciato a una persona. La regola non richiede la riga **Requirements:**, non assegna un punteggio a parole come «graceful» o «fast», e non avvisa quando la prosa contiene Given, When o Then. Come scrivere il criterio stesso è in come scrivere criteri di accettazione.

Riferimenti del piano a quegli identificatori

In un piano che nomina una funzionalità di origine, plan_rules.go legge i titoli ### AC: nel README di quella funzionalità. La regola P-002 segnala un valore **Verifies:** di un’attività che non si risolve in <feature-slug>#ac:<ac-slug> per uno di quei titoli, una riga **Verifies:** vuota, una riga di origine assente o non riconosciuta, o una funzionalità di origine che non si risolve in un README di funzionalità. La regola P-001 segnala un titolo che nessuna attività copre e che non è elencato sotto ## Deferred AC Coverage. I piani la cui origine è un’idea (**Source:** idea:<slug>) e i piani con **Source:** none sono esenti, e lo è anche un piano in uno stato di disposizione terminale. Il testo di catalogo su una riga per P-002 dice «valid dependency references»; il controllo in quel file è il controllo dei riferimenti AC appena descritto.

Che cosa non è un lint superato

Lo stesso comando non decide se un requisito risolve il problema enunciato, se un nome ha senso, o se due funzionalità si contraddicono nel significato. La pagina dei validatori le elenca come esterne al linter della CLI. Non controlla nemmeno le parole chiave dei passi di uno scenario. specscore rehearse esegue i file di scenario. Il workflow di questo repository esegue specscore spec lint e non chiama rehearse. Il catalogo nomina altre famiglie — idee, decisioni, entità, proprietà, lezioni, issue e il resto delle regole di piano — e ogni regola si applica ai file che le appartengono. Il catalogo è la lista. Questa pagina non ripete tutte le 183 descrizioni.

Eseguire specscore spec lint in CI

Il comando cerca verso l’alto, a partire dalla directory di lavoro, un specscore.yaml. Senza quel file esce con 3 e nomina specscore init. Un job di CI ha quindi bisogno del file di configurazione nel checkout. scripts/install.sh legge SPECSCORE_VERSION e, se la variabile non è impostata, usa latest. Fissa un tag se vuoi le stesse regole a ogni esecuzione.

Il controllo di questo repository è dogfood.yml. Installa la CLI con SPECSCORE_VERSION impostata su v0.39.1 e poi esegue specscore spec lint senza flag aggiuntivi, sulle pull request e sui push verso main. GitHub Actions fa fallire il passo quando quel processo esce con un codice diverso da zero. L’estratto sotto conserva quei passi di installazione e di lint. Il file imposta anche permissions: contents: read, un gruppo di concorrenza e un commento sul perché il pin non è latest.

Passi di installazione e di lint da 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
Rapporto di fallimento (specscore 0.55.0, stessa forma di riga in 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)
Rapporto pulito
0 violations found

Ogni rilievo è file:line [severity] rule: message. Il riepilogo è N violations found più un conteggio tra parentesi, come (3 errors). Il codice di uscita è lo stato del processo, non una riga del rapporto. Le tre righe sopra sono state catturate da specscore 0.55.0 su una funzionalità a cui era stata tolta la sezione Open Questions e il cui indice ometteva una directory figlia vuota. Sono lo stesso rapporto che mostra la pagina della CLI. --format accetta text (il predefinito), json o yaml. --rules e --ignore selezionano regole e non si possono combinare. --fix riscrive i rilievi che hanno un correttore, compreso il titolo Outstanding Questions. Il job dogfood non passa --fix.

Strumenti che non fanno il lint di questo formato in CI

Un controllo di qualità dei requisiti, in questa CLI, è il controllo strutturale sopra. Non è un punteggio della prosa. Altri strumenti di sviluppo guidato dalle specifiche pubblicano controlli diversi. I paragrafi sotto usano solo ciò che dicono le pagine di quei progetti. La rassegna degli strumenti registra le stesse pagine come lette il 30 ottobre 2026, tranne la home della documentazione di Spec Kit, che stampa il 28 settembre 2026, e la pagina delle specifiche di funzionalità di Kiro, che stampa il 4 agosto 2026.

GitHub Spec Kit è un workflow di agente che scrive artefatti Markdown. Il riferimento di SDD agentico descrive /speckit.analyze come un rapporto di incoerenze tra la specifica, il piano e le attività, senza modificare i file. Si esegue nell’agente. La home della documentazione nomina anche estensioni della comunità, tra cui una chiamata CI Guard, che aggiungono varchi di conformità. Non è un comando che fa il lint di un README di funzionalità SpecScore.

OpenSpec pubblica un controllo strutturale. openspec validate, documentato nel riferimento della CLI, controlla la struttura di cambiamento e di specifica di OpenSpec, esce con un codice diverso da zero quando la validazione fallisce, e il riferimento include un frammento di shell che un job di CI può eseguire. Quel controllo è la forma di OpenSpec, non i titoli ### AC: né un indice SpecScore.

La pagina delle specifiche di funzionalità di Kiro descrive Analyze Requirements come un controllo dentro Kiro, prima della progettazione, che cerca incoerenze, ambiguità, vincoli in conflitto e lacune. Non è il comando di dogfood.yml. I modelli di frase che Kiro scrive sono nella sintassi dei requisiti EARS.

Il README di BMAD Method descrive gli artefatti del metodo e i workflow degli agenti. Non documenta un comando che fa il lint di uno schema di specifica fisso in CI. Il README di Task Master descrive la trasformazione di un PRD in attività con task-master parse-prd. Non descrive un linter per quel PRD. Un PRD può comunque essere l’ingresso di una funzionalità SpecScore, e specscore spec lint è ciò che poi controlla il file della funzionalità.

Domande frequenti

Che cos’è un linter di specifiche?

Un linter di specifiche legge file di specifica e segnala violazioni strutturali. specscore spec lint è quel comando per un albero SpecScore. Esce con 0 quando non trova nulla alla severità scelta, e con 1 quando trova violazioni.

Il linter di specifiche giudica la qualità dei requisiti nella formulazione?

No. ac-heading-format controlla il titolo ### AC:. Non assegna un punteggio a parole come «graceful» o «fast», e non avvisa quando un criterio contiene Given, When o Then. La formulazione è un lavoro di scrittura. La pagina dei validatori separa quel lint deterministico dalla revisione manuale con IA.

Come faccio il lint delle specifiche in CI?

Installa la CLI con SPECSCORE_VERSION impostata su un tag di release, poi esegui specscore spec lint. Il checkout ha bisogno di un specscore.yaml. dogfood.yml è un esempio funzionante di GitHub Actions. Il file fissa v0.39.1.

Che cosa stampa un’esecuzione che fallisce?

Una riga per rilievo, file:line [severity] rule: message, poi un riepilogo come 3 violations found (3 errors). Il processo esce con 1. Un albero pulito stampa 0 violations found ed esce con 0.

Altri strumenti di sviluppo guidato dalle specifiche validano le specifiche in CI/CD?

L’openspec validate di OpenSpec può far fallire un job di CI, e controlla la struttura di cambiamento propria di OpenSpec. Il /speckit.analyze di Spec Kit viene eseguito nella sessione dell’agente. Analyze Requirements di Kiro viene eseguito dentro Kiro. I README di BMAD Method e di Task Master non documentano un linter di formato per la CI. Il workflow dogfood di SpecScore esegue specscore spec lint sull’albero SpecScore.

Esegui il lint della specifica in CI.

Have an idea how to improve this page?