Metriche di Salute — Perché il 100/100 è l’Unico Numero che Conta
"Un Safe Harbor deve saper dire esattamente quanto è solido il suo molo."
Per i tuoi utenti, un link rotto è un cliente perso. Per il tuo team, una credenziale esposta è una crisi a mezzanotte. Per il tuo brand, un punteggio di 97 significa tre cose che non hai ancora risolto.
Il Punteggio di Qualità di Zenzic non è una metrica di vanità. È un valore deterministico da 0 a 100 calcolato dal conteggio concreto dei problemi rilevati da ogni controllo. Zero problemi significa 100/100 — una prova formale, non una stima. Nessun credito parziale, nessun arrotondamento favorevole, nessuna sorpresa.
Scopri dove sei adesso:
uvx zenzic score [PATH]— nessuna installazione, nessuna configurazione richiesta.
Cosa Misura il Punteggio
Il Punteggio di Qualità è un composito pesato di quattro categorie di controllo.
Ogni categoria corrisponde direttamente a un sotto-comando zenzic check e ai
codici di finding Zxxx che emette.
| Categoria | Comando | Codici Finding | Peso |
|---|---|---|---|
| Integrità Strutturale | zenzic check links [PATH] | Z101, Z102, Z103, Z104, Z105, Z107 | 40 % |
| Eccellenza dei Contenuti | zenzic check all [PATH] | Z501, Z502, Z503, Z505 | 30 % |
| Navigazione & SEO | zenzic check orphans [PATH] | Z402 | 20 % |
| Brand & Asset | zenzic check assets [PATH] | Z903, Z904, Z905 | 10 % |
Se viene rilevato un finding di sicurezza — Z201 (Shield), Z202 o Z203 (Blood Sentinel) — il Punteggio di Qualità crolla a 0/100 incondizionatamente. Una sorgente documentale che perde attivamente una credenziale non può ricevere un Punteggio di Qualità.
La Tabella di Penalità Quartz
Ogni codice di finding porta una deduzione fissa in punti all'interno della sua categoria. Le deduzioni si accumulano; una volta che il contributo di una categoria raggiunge zero, ulteriori violazioni in quella categoria non hanno ulteriori effetti sul punteggio totale — questo è il Category Cap (Tetto di Categoria).
| Codice | Descrizione | Penalità (pts) | Categoria |
|---|---|---|---|
| Z2xx | Violazione di Sicurezza | Override → 0/100 | — |
| Z503 | Errore Sintassi Snippet | 10.0 | Content |
| Z101 | Link Interrotto | 8.0 | Structural |
| Z104 | File Non Trovato | 8.0 | Structural |
| Z102 | Ancora Mancante | 5.0 | Structural |
| Z402 | Pagina Orfana | 4.0 | Navigation |
| Z905 | Brand Obsoleto | 3.0 | Brand |
| Z903 | Asset Non Utilizzato | 3.0 | Brand |
| Z501 | Placeholder (TODO / FIXME) | 2.0 | Content |
| Z904 | Errore Nav Contract | 2.0 | Brand |
| Z105 | Percorso Assoluto | 2.0 | Structural |
| Z502 | Contenuto Breve | 1.0 | Content |
| Z505 | Blocco di Codice Non Etichettato | 1.0 | Content |
| Z107 | Ancora Circolare | 1.0 | Structural |
| Z106 | Link Circolare | 1.0 | Structural |
Invariante del Category Cap
Le deduzioni di categoria sono limitate dal peso della categoria:
- Tetto Structural: 40 pts (40% × 100)
- Tetto Content: 30 pts (30% × 100)
- Tetto Navigation: 20 pts (20% × 100)
- Tetto Brand: 10 pts (10% × 100)
Esempio: 100 × Z505 (1,0 pt ciascuno) genera 100 pts di deduzione potenziale contro la categoria Content — ma il tetto limita la perdita effettiva a 30 pts. Le altre tre categorie rimangono inalterate: 70/100 totale.
Separazione Score vs. Gate
Lo Score e la soglia fail_under sono indipendenti:
- Score (la Metrica): Misurazione oggettiva della qualità, limitata dai Category Cap.
fail_under(il Gate): La tua policy di enforcement inzenzic.toml.
Uno score di 70/100 con fail_under = 80 esce comunque con codice 1. Il Category Cap
impedisce che un tipo di violazione rumoroso mascheri la salute strutturale —
non indebolisce il tuo gate.
Il punteggio finale 0–100 è la somma dei contributi di categoria pesati:
Esecuzione del Punteggio
# Calcola e mostra il punteggio (nessun file scritto)
zenzic score [PATH]
# Calcola, mostra e persiste in .zenzic-score.json
zenzic score [PATH] --save
# Calcola e fallisce se il punteggio scende sotto N
zenzic score [PATH] --fail-under 80
# Confronta il punteggio attuale con il baseline salvato (gate di regressione CI)
zenzic diff [PATH]
Lo snapshot è scritto in .zenzic-score.json nella root del repository. È un file
JSON leggibile dalle macchine — committalo nel repository affinché zenzic diff
abbia un baseline con cui confrontarsi.
Pattern CI consigliato
# Sui push al branch main: salva il nuovo baseline
- run: zenzic score --save --fail-under 80
# Sulle pull request: fallisce se il punteggio è sceso
- run: zenzic diff --threshold 0
zenzic diff esce con 1 se il punteggio attuale è inferiore al baseline salvato
(aggiustato da --threshold). Non fallisce se il punteggio è stabile o migliorante.
Regressione di Qualità — Z504
Quando zenzic diff rileva una diminuzione del punteggio, emette
Z504 QUALITY_REGRESSION come finding. Questo è l'unico codice di finding
che fa da ponte tra il layer di scoring e il layer di finding — significa:
"qualcosa che hai cambiato ha peggiorato il punteggio."
Z504 non viene pesato nel punteggio stesso (sarebbe circolare). È il segnale che comunica quale commit ha introdotto una regressione.
Connessione ai Tre Pilastri
Il Punteggio di Qualità è la prova operativa dei Tre Pilastri di Zenzic:
1. Analizza la Sorgente, Non il Build. Il punteggio è calcolato dall'analisi del sorgente Markdown grezzo — mai dall'output HTML o da un server web in esecuzione. Il peso del 40% per la categoria strutturale premia una sorgente che è internamente coerente prima che qualsiasi passo di build venga eseguito.
2. Zero Sottoprocessi.
compute_score() in core/scorer.py è una funzione Python pura — nessuna chiamata
shell, nessun subprocess.run, nessuna richiesta di rete. Riceve una mappa
findings_counts: dict[str, int] e restituisce uno ScoreReport. Questo garantisce
risultati identici su ogni OS e versione Python nella matrice CI
(ubuntu / windows / macos × Python 3.10–3.14).
3. Funzioni Pure Prima di Tutto.
compute_score() non ha effetti collaterali. save_snapshot() è l'unica funzione
di I/O e viene chiamata esplicitamente solo quando l'utente passa --save. La suite
di test verifica i calcoli del punteggio con test basati su proprietà (Hypothesis)
per garantire gli invarianti matematici.
Integrità del Nav Contract — Valutata come Brand & Asset
L’audit del CEO ha segnalato una correzione terminologica: quello che gli utenti chiamano a volte “Nav Isolation” è formalmente Integrità del Nav Contract (Z904).
Z904 si attiva quando un file dichiarato nella configurazione di navigazione del motore
(es. una voce nav: di mkdocs.yml o una voce esplicita di sidebars.ts in
Docusaurus) non esiste su disco. Ogni violazione Z904 contribuisce alla categoria Brand & Asset (10%) usando
la stessa penaltà per codice degli altri finding valutati (Z904: 2,0 pts per violazione).
Safe Harbor Guarantee
Quando zenzic score restituisce 100/100, è una garanzia formale che:
- Ogni link interno si risolve (zero Z101/Z102/Z103/Z104/Z105)
- Ogni riferimento ad ancora si risolve (zero Z107)
- Ogni pagina è raggiungibile da almeno un punto di accesso di navigazione (zero Z402)
- Ogni snippet di codice è sintatticamente valido (zero Z503)
- Non esistono contenuti placeholder (zero Z501)
- Non esistono blocchi di codice non etichettati (zero Z505)
- Non esistono asset inutilizzati (zero Z903)
- Non esistono violazioni del nav contract (zero Z904)
- Non esistono riferimenti di brand obsoleti (zero Z905)
- Lo Shield non ha trovato credenziali in nessun file (zero Z201 — implicito, fa crollare il punteggio a 0)
Questo è il Sentinel Seal: lo stato in cui la documentazione è strutturalmente completa, pulita nel contenuto e verificata per la sicurezza.
Porta il Sigillo nel tuo README: una volta raggiunto il 100/100, esegui
zenzic score --savee aggiungi il badge dinamico del punteggio al tuo progetto. Mostra ai contributor lo standard che stanno per rispettare. Vedi Badge Ufficiali per le URL copy-paste.