# Come revisionare codice generato dall'IA: i test verdi non bastano

> Canonical: https://vxi.me/it/posts/vibe-coding-ai-code-review-evidence-gates/
> Locale: it-it
> Published: 2026-10-25
> Updated: 2026-10-25
> Markdown: https://vxi.me/it/posts/vibe-coding-ai-code-review-evidence-gates.md

<figure class="ai-review-evidence-hero not-prose" lang="it-it">
<picture><source media="(prefers-reduced-motion: reduce) and (max-width: 640px)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-evidence-gates.mobile.still.it-it.svg" type="image/svg+xml"><source media="(prefers-reduced-motion: reduce)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-evidence-gates.still.it-it.svg" type="image/svg+xml"><source media="(max-width: 640px)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-evidence-gates.mobile.it-it.svg" type="image/svg+xml"><img src="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-evidence-gates.it-it.svg" alt="Tre versioni di codice hanno superato 8/8, 10/10 e 12/12 test principali. La review indipendente ha trovato quattro classi di difetti e respinto quattro probe separati. Solo offline." width="1200" height="700" loading="eager" fetchpriority="high" decoding="async" style="display:block;width:100%;height:auto"></picture>
<figcaption style="font-size:0.8rem;line-height:1.5;opacity:.78;margin-top:.35rem">Tre versioni distinte e i risultati della revisione indipendente. I test verdi non autorizzano la produzione.</figcaption>
</figure>

Vibe Coding accelera la produzione di codice, ma non riduce automaticamente il lavoro di review. Un LLM può creare rapidamente un diff ordinato. Una spiegazione convincente o una suite verde non dimostrano da sole che l'implementazione sia sicura per la produzione.

Il caso riguarda un validatore pre-build per gli SVG di terminale animati di questo programma del blog. Controlla regole XML/CSS limitate, percorsi e SHA-256 del manifest e immagini demo visibili negli articoli in otto lingue. Un SVG canonical fisso è il caso positivo. I quattro difetti sono stati trovati in test isolati prima del merge; le prove valgono solo per il validatore offline.

La suite iniziale ha superato **8/8**, ma una review indipendente ha trovato due accettazioni non sicure. Dopo la prima correzione sono passati **10/10** test, poi sono emersi altri due difetti. La versione finale fissata ha superato **12/12 test principali**; quattro probe d'attacco aggiuntivi sono stati eseguiti separatamente e respinti. Tre file JavaScript hanno superato anche node --check.

Il metodo ha cinque passaggi: fissare ambito e invarianti; creare controesempi minimi; registrare RED solo se esiste un'esecuzione realmente fallita; verificare indipendentemente casi positivi e negativi sul commit esatto; decidere in base al rischio. I test logici non sostituiscono build, controlli di piattaforma e verifica runtime. Per modifiche rischiose, una scheda può registrare ambito, commit Base/Head, invarianti, caso positivo, controesempio, comando e ambiente reali, limiti non verificati e conclusione. Il validatore è un componente pre-build del blog, non un CLI generico distribuito separatamente. Non è stato misurato alcun risparmio di tempo di review.

Il repository pubblico contiene solo controesempi sintetici sanificati e test didattici eseguibili; non include il validatore di produzione di questo programma del blog, le correzioni reali né l'architettura interna. La sequenza 8/8 → 10/10 → 12/12 proviene dalla revisione offline originale; i test pubblici riproducono i quattro schemi di difetto, non l'implementazione di produzione.

<a class="gh-repo-pill" href="https://github.com/vxime/ai-code-review-counterexamples/tree/74d9f12331ef4d015bf882a6e09d66e59434368b" target="_blank" rel="noopener noreferrer"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" width="18" height="18"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645.12.54 2.873.12 3.176.765.84 1.23 1.91.81 3.22.61 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606.21 2.896.015 3.286C20.565 22.092 24 17.592 24 12.297"/></svg><span>Esempi sintetici sanificati e test riproducibili</span></a>

## Perché 8/8 test hanno accettato input errati?

Una suite verde mostra solo che gli input correnti soddisfano le asserzioni correnti. Non dimostra che ogni input non valido venga respinto.

Il primo controesempio metteva un'immagine consentita e un riferimento non autorizzato a un altro articolo sulla stessa riga. La vecchia logica trovava un'immagine consentita e lasciava passare tutta la riga. La review indipendente ha creato un SVG reale sotto un altro slug e aggiunto il riferimento Markdown accanto all'immagine valida negli otto articoli localizzati. Il file è stato creato per escludere un falso fallimento per destinazione mancante. La vecchia implementazione restituiva ancora successo con posts_checked=8.

~~~html
<img src="/assets/terminal-demo.svg" alt="Terminal demo" width="356" height="137" /> ![foreign](../foreign/terminal-demo.svg)
~~~

Il secondo controesempio è una race del filesystem: il percorso controllato può non essere il file aperto alla fine. Il test ha sostituito una directory genitore al confine di apertura; fuori dal checkout c'era un SVG canonical con SHA-256 corretto. Dopo la sostituzione con un symlink, la vecchia implementazione ha letto e accettato il file esterno. È stata aggirata la provenienza, non il controllo hash.

Il percorso Linux finale apre la radice fidata del checkout e risolve i componenti rispetto a descrittori di directory genitore già aperti. I componenti intermedi devono essere directory e usano O_NOFOLLOW; anche il file finale rifiuta symlink. Vengono controllati tipo, numero di link e dimensione, confrontati device, inode e dimensione prima/dopo la lettura e infine verificato il digest. Usa Linux /proc/self/fd e fallisce in modo chiuso se procfs non è disponibile. Il perimetro presume checkout fidato e procfs disponibile, non aggressori arbitrari con lo stesso UID o privilegi host. Vedi [Linux openat2(2)](https://man7.org/linux/man-pages/man2/openat2.2.html).

## Secondo round: l'hash è corretto, ma il contenuto può essere invisibile

Dopo il primo fix, 10/10 test sono passati. Il terzo controesempio riguarda reduced motion: i frame SVG partono trasparenti e l'animazione li rivela. Se la regola riduce il movimento fermando solo l'animazione senza mostrare il frame finale, il risultato resta vuoto.

~~~css
.f { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  #f0 { animation: none; opacity: 1; }
  #f3 { animation: none; } /* il frame finale resta trasparente */
}
~~~

Il test ha ricalcolato SHA-256, dimensione, nome content-addressed e manifest canonical per mantenere validi i controlli circostanti. Ha verificato il contratto “il risultato finale deve essere visibile”. Vedi [MDN su prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/%40media/prefers-reduced-motion).

Il quarto controesempio viene da Markdown. La vecchia regex contava immagini anche nei commenti HTML. Commentando l'unica immagine, il tag restava nel sorgente ma non appariva nella pagina. Secondo le [regole HTML block di CommonMark 0.31.2](https://spec.commonmark.org/0.31.2/#html-blocks), un tag commentato non è un'immagine visibile.

~~~html
<!-- <img src="/assets/demo.svg" alt="Terminal demo" /> -->
~~~

<figure class="ai-review-counterexample not-prose" lang="it-it">
<picture><source media="(prefers-reduced-motion: reduce) and (max-width: 640px)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-counterexample.mobile.still.it-it.svg" type="image/svg+xml"><source media="(prefers-reduced-motion: reduce)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-counterexample.still.it-it.svg" type="image/svg+xml"><source media="(max-width: 640px)" srcset="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-counterexample.mobile.it-it.svg" type="image/svg+xml"><img src="/images/posts/vibe-coding-ai-code-review-evidence-gates/ai-review-counterexample.it-it.svg" alt="Dopo 10/10 test superati, una review indipendente ha trovato un'immagine commentata conteggiata come visibile. La versione finale ha superato 12/12 test e respinto quattro probe." width="1200" height="700" loading="lazy" decoding="async" style="display:block;width:100%;height:auto"></picture>
<figcaption style="font-size:0.8rem;line-height:1.5;opacity:.78;margin-top:.35rem">I test verdi possono ignorare controesempi: un tag commentato non è un'immagine visibile.</figcaption>
</figure>

## Collegare i risultati ai commit esatti

| Versione | Suite principale | Review indipendente successiva |
| --- | --- | --- |
| Versione iniziale | 8/8 superati | Accettazioni errate SEC-01 e SEC-02 |
| Versione dopo la prima correzione | 10/10 superati | Accettazioni errate SEC-03 e SEC-04 |
| Versione finale verificata offline | 12/12 test principali superati | Quattro probe separati respinti |

La suite finale include regressioni per SEC-01–04. I quattro probe aggiuntivi non fanno parte del 12/12 e non vanno sommati come 16/16. Tre file JavaScript hanno superato node --check, che verifica la sintassi, non il comportamento.

Gli ultimi due test di regressione sono stati committati prima del fix del sorgente, ma la suite completa non è stata eseguita sul commit con i soli test. Non esiste quindi un'esecuzione completa 10/12 RED registrata. È verificabile che la review indipendente ha riprodotto le accettazioni errate nel vecchio validatore e che la versione finale ha superato suite e probe separati.

Solo dopo aver stabilizzato le prove sul comportamento controllo la complessità: quale invariante protegge ogni helper, ramo o configurazione, se la logica è duplicata e se esistono chiamanti reali. Meno codice non significa sempre più semplicità; rimuovere una protezione del percorso può reintrodurre una race.


<!-- vxi-evidence-panel: ai-code-review-counterexamples -->

Articoli correlati: [Mutation Testing](/posts/ai-generated-tests-mutation-testing/), [il limite fail-open della review pre-push di OpenQodex](/posts/openqodex-prepush-review-fail-open/) e [gli ancoraggi dei commenti di Diffle](/posts/diffle-git-diff-comment-anchoring/).

## Cosa manca tra test superati e approvazione alla produzione?

La verifica finale ha riguardato il validatore offline su Node.js v22.16.0, Linux x64: 12/12 test principali superati, quattro probe d'attacco aggiuntivi respinti, casi positivi di SVG canonical, manifest e otto lingue superati; tre file JavaScript hanno superato node --check.

Questo sostiene una conclusione limitata: le quattro accettazioni errate note sono state corrette in quell'ambiente e con quelle regole. Non dimostra che tutto il blog sia pronto per la produzione. La resistenza nativa di macOS a scrittori filesystem concorrenti malevoli non è verificata; build completa e controllo runtime della pagina finale erano fuori dal test offline.

Una vera linea di rilascio va suddivisa per rischio: test unitari per il comportamento coperto, controlli statici per pattern specifici, build e integrazione per la composizione, test di piattaforma e runtime per i confini del deployment. Se una frontiera critica resta non verificata, un successo locale non è piena prontezza alla produzione.

Contratti e controesempi aiutano a trovare il comportamento sospetto; test della versione esatta e prove indipendenti decidono dove approfondire. Non elimina il giudizio umano, ma trasforma “sembra a posto” in una decisione di review con prove, ambito e verificabilità.

## Verification context

- Level: first-party
- Verified: 2026-10-25T00:00:00.000Z
- Environment: Node.js v22.16.0 / Linux x64
- Evidence mode: mixed
- Public repository: https://github.com/vxime/ai-code-review-counterexamples
- Evidence commit: 74d9f12331ef4d015bf882a6e09d66e59434368b
- Evidence receipt: https://vxi.me/evidence/vibe-coding-ai-code-review-evidence-gates.json
