Passa al contenuto principale

ADR 001: Analizza il Sorgente, Non la Build

Stato: Attivo (Decisione Genesi) Decisore: Architecture Lead Data: 2026-01-01 (principio fondante, pre-v0.1.0)


Contesto

Quando Zenzic è stato concepito, l'approccio dominante alla validazione della documentazione era l'analisi basata sull'output: strumenti come linkchecker e htmlproofer recuperano o analizzano l'HTML generato dal motore di build, poi attraversano la struttura della pagina renderizzata per verificare i target dei link, i percorsi delle immagini e gli ID delle ancore.

Questo approccio ha un difetto strutturale fondamentale: il validatore è a valle della build. La validazione può essere eseguita solo dopo che la build ha avuto successo. Se la build fallisce — a causa di un errore di sintassi, un plugin mancante o un'incompatibilità di versione del motore — non avviene alcuna validazione. La pipeline produce silenzio dove dovrebbe produrre una diagnostica.

In ambienti CI emergono tre problemi composti:

  1. Accoppiamento alla build. Un validatore di documentazione che richiede una

    build riuscita non può essere il primo gate della pipeline. Deve essere posizionato dopo mkdocs build o npm run build, aggiungendo 2–10 minuti di overhead prima che venga controllato un singolo link.

  2. Fragilità al motore. I motori di build cambiano il modo in cui generano ID

    delle ancore, slug degli URL e percorsi degli asset tra versioni minori. Un validatore calibrato sull'output di MkDocs 1.5 può perdere silenziosamente link rotti con MkDocs 1.6 perché lo schema di generazione degli ID è cambiato. Il validatore sta effettivamente testando l'output del motore piuttosto che l'intento dell'autore.

  3. Lock-in al motore. Un validatore che comprende l'HTML di un motore non può

    validare l'HTML di un altro senza adattamento specifico. Questo crea un ecosistema di validazione che si frammenta lungo le linee dei motori invece di convergere su standard universali di qualità documentale.

La "Crisi MkDocs" — un periodo nello sviluppo iniziale di Zenzic in cui la documentazione di riferimento perse tutta la validità dei link a causa di un aggiornamento di MkDocs che cambiò la generazione degli slug — cristallizzò il costo della validazione basata sull'output. L'errore non era nel sorgente Markdown; era nel disallineamento tra il sorgente e la nuova convenzione URL del motore. Un validatore basato sull'output lo avrebbe rilevato solo dopo che il sito rotto era stato pubblicato.


Decisione

Zenzic analizza esclusivamente file sorgente Markdown grezzi e file di configurazione statici. Non ispeziona, recupera o dipende mai dall'output HTML di build.

Il veicolo implementativo di questa decisione è la Virtual Site Map (VSM) — una proiezione completa in memoria del sito finale, costruita dai soli file sorgente, utilizzando conoscenza specifica del motore codificata negli adapter (vedi ADR 005, ADR 007).

La VSM permette a Zenzic di rispondere a domande che prima richiedevano un sito live:

  • "Esiste questa ancora #installation nella pagina target?" — risposta

    analizzando la struttura dei titoli Markdown, non l'HTML renderizzato.

  • "Il percorso /docs/reference/finding-codes è una route valida?" — risposta

    dal grafo di route della VSM, che modella i fallback i18n e gli slug con versione senza eseguire la build.

  • "L'asset referenziato in docusaurus.config.ts esiste su disco?" — risposta

    analizzando staticamente il file di configurazione TypeScript, non avviando un processo Node.js.


Motivazione

1. Prevenzione degli Errori Pre-Build

Un link rotto scoperto prima della build è un avvertimento per lo sviluppatore. Un link rotto scoperto dopo una build di 10 minuti è un fallimento CI che blocca la coda delle PR. La posizione di Zenzic nella pipeline è sempre prima della build — è il gate che certifica la solidità strutturale del sorgente prima che venga consumata qualsiasi risorsa di build.

2. Agnosticismo al Motore per Progetto

Analizzando i file sorgente piuttosto che l'output di build, Zenzic è intrinsecamente agnostico al motore. Lo stesso comando check links valida un progetto MkDocs, un sito Docusaurus e un wiki Zensical — perché tutti e tre condividono lo stesso formato Markdown grezzo. Le convenzioni URL specifiche del motore sono codificate nel layer adapter (non nel validatore), rendendo il motore core permanentemente portabile.

3. Analisi Deterministica

I file sorgente sono statici. Un dato insieme di file Markdown produce gli stessi risultati di analisi indipendentemente da quale macchina esegue Zenzic, quale versione di Python è installata o quale fuso orario ha il runner CI. I validatori basati sull'output introducono non-determinismo attraverso la deriva della versione del motore, le pagine recuperate dalla rete e il caching CDN. L'analisi basata sul sorgente di Zenzic è una funzione pura dello stato del repository — input identico, output identico, sempre.

4. La Capacità delle Ghost Route

La VSM modella route che non esistono come file fisici su disco: route di fallback i18n, slug di documentazione con versione e pagine index generate dal motore. Un validatore basato sull'output può testare solo le route che la build produce. La VSM di Zenzic modella l'intento dell'architettura documentale, rilevando errori strutturali in route che l'autore ha pianificato ma non ha ancora pubblicato.


Invarianti (Non Negoziabili)

  • La logica di validazione di Zenzic (core/validator.py, core/scanner.py)

    non deve mai avviare una richiesta HTTP, caricare un browser o analizzare HTML. Tutta l'analisi opera su byte letti dal filesystem.

  • La VSM (models/vsm.py) è la fonte canonica di verità per le route. Nessun

    validatore può calcolare una route invocando il motore di build — nemmeno come subprocess.

  • Gli adapter possono leggere file di configurazione statici (.ts, .yml,

    .toml) usando parsing testuale puro-Python. Non devono eseguire quei file (vedi ADR 002).


Conseguenze

  • Le prestazioni di analisi di Zenzic sono dipendenti dal contenuto.

    Misurato sul progetto reale zenzic-doc (59 pagine MDX con JSX, frontmatter e tabelle): ~420 ms di analisi pura su processo Python già avviato. Progetti Markdown semplici con frontmatter minimo e senza JSX completano 200 file in ~100 ms. Il tempo totale a muro con un'invocazione uvx a freddo aggiunge ~2–8 s di avvio dell'interprete Python al tempo di analisi. Esegui python scripts/benchmark.py --repo <percorso> per misurare il tuo progetto.

  • Zenzic può essere posizionato come primo step in qualsiasi pipeline CI,

    prima di npm install, prima di pip install, prima che il motore di build sia anche solo disponibile.

  • Le peculiarità specifiche del motore (generazione delle ancore di Docusaurus,

    contratti nav di MkDocs, convenzioni slug di Zensical) sono isolate nel layer adapter. Il motore core è permanentemente neutro al motore.

  • La VSM fornisce una struttura dati testabile e ispezionabile per l'architettura

    documentale — abilitando future capacità come il diff strutturale, le metriche di copertura e il rilevamento delle Ghost Route senza modificare il core di analisi.