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:
-
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 buildonpm run build, aggiungendo 2–10 minuti di overhead prima che venga controllato un singolo link. -
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.
-
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
#installationnella pagina target?" — rispostaanalizzando la struttura dei titoli Markdown, non l'HTML renderizzato.
-
"Il percorso
/docs/reference/finding-codesè una route valida?" — rispostadal 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.tsesiste su disco?" — rispostaanalizzando 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. Nessunvalidatore 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'invocazioneuvxa freddo aggiunge ~2–8 s di avvio dell'interprete Python al tempo di analisi. Eseguipython 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 dipip 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.