Algoritmo di Scoring
"Zenzic non scala i voti. Sicurezza e Governance non sono opzionali."
Il Documentation Quality Score (DQS) di Zenzic è un intero deterministico da 0 a 100 calcolato dai risultati di tutti i check attivi. Dato lo stesso stato del repository, l'algoritmo produce sempre lo stesso punteggio. Non ci sono euristiche di ponderazione, nessuna interpolazione e nessun arrotondamento fino al cast finale dell'intero.
Architettura Generale
La pipeline di scoring ha cinque stadi sequenziali:
1. Security Gate → Finding Z2xx? score = 0, early return.
2. Tabella Penalità → deduzioni per codice, cap per tier.
3. Governance Esc. → amplificazione esponenziale se Z6xx > 10.
4. Gravity Cap → brand score = 0 ⟹ totale ≤ 70.
5. Suppression Debt → sottrai ω_debt dal totale con cap.
Ogni stadio è descritto di seguito con la formula completa.
Stadio 1 — Security Override
Prima di qualsiasi calcolo del punteggio, il motore controlla la presenza di finding Z2xx:
dove .
Si tratta di un early return incondizionale — nessun flag, nessuna opzione di configurazione e nessuna soppressione può bypassarlo. I quattro codici in rappresentano condizioni di fallimento binarie:
| Codice | Nome | Condizione |
|---|---|---|
| Z201 | CREDENTIAL | Pattern di credenziale rilevato nel documento |
| Z202 | PATH_TRAVERSAL | Tentativo di escape di sistema in un link |
| Z203 | PATTERN_MATCH | Corrispondenza di pattern vietato personalizzato |
| Z204 | FORBIDDEN_TERM | Privacy Gate — esposizione di termine riservato |
Quando si attiva il Security Override, ScoreReport restituisce security_override=True e security_findings=N (conteggio totale Z2xx). Il flag --strict e la configurazione fail-on-error sono irrilevanti — il gate opera prima di entrambi.
:::danger I Codici di Sicurezza Non Sono Sopprimibili
Nessun inline <!-- zenzic:ignore -->, nessun per_file_ignores e nessun excluded_dirs può sopprimere un finding Z2xx. Il finding si attiva comunque. Il punteggio è comunque 0.
:::
Stadio 2 — Tabella Penalità e Cap per Tier
Se non sono presenti finding Z2xx, il motore calcola un punteggio per tier.
Matrice dei Pesi Zenzic (5-Tier)
| Tier | Categoria | Codici | Peso | Cap |
|---|---|---|---|---|
| Security Gate | — | Z2xx | — | score = 0 |
| Structural | structural | Z1xx | 30% | 30 pts |
| Navigation | navigation | Z3xx, Z4xx | 25% | 25 pts |
| Content | content | Z5xx | 20% | 20 pts |
| Governance | brand | Z404, Z405, Z406, Z6xx | 25% | 25 pts |
Formula per Categoria
Per ogni tier :
L'invariante del Category Cap garantisce che un singolo tier non possa trascinare il punteggio sotto il suo pavimento. Ad esempio, 1 000 occorrenze di Z505 (1 pt ciascuna) esauriscono il bucket content a −20 pts. Gli 80 pts rimanenti dagli altri tier non vengono toccati.
Punteggio Base
Tabella di Riferimento delle Penalità
| Codice | Nome | Penalità / occorrenza | Tier |
|---|---|---|---|
| Z101 | LINK_BROKEN | 8.0 pts | Structural |
| Z102 | ANCHOR_MISSING | 5.0 pts | Structural |
| Z103 | ORPHAN_LINK | 2.0 pts | Structural |
| Z104 | FILE_NOT_FOUND | 8.0 pts | Structural |
| Z105 | ABSOLUTE_PATH | 2.0 pts | Structural |
| Z107 | CIRCULAR_ANCHOR | 1.0 pts | Structural |
| Z106 | CIRCULAR_LINK | 0.0 pts | Informativo (nessun impatto sul DQS) |
| Z108 | EMPTY_LINK_TEXT | 1.0 pts | Structural |
| Z111 | VIRTUAL_ROUTE_BROKEN | 8.0 pts | Structural |
| Z113 | AUTHOR_KEY_COLLISION | 2.0 pts | Structural |
| Z301 | DANGLING_REF | 4.0 pts | Navigation |
| Z302 | DEAD_DEF | 1.0 pts | Navigation |
| Z303 | DUPLICATE_DEF | 3.0 pts | Navigation |
| Z402 | ORPHAN_PAGE | 4.0 pts | Navigation |
| Z401 | MISSING_DIRECTORY_INDEX | 2.0 pts | Navigation |
| Z501 | PLACEHOLDER | 2.0 pts | Content |
| Z502 | SHORT_CONTENT | 1.0 pts | Content |
| Z503 | SNIPPET_ERROR | 10.0 pts | Content |
| Z505 | UNTAGGED_CODE_BLOCK | 1.0 pts | Content |
| Z403 | MISSING_ALT | 1.0 pts | Content |
| Z405 | UNUSED_ASSET | 3.0 pts | Governance |
| Z404 | CONFIG_ASSET_MISSING | 3.0 pts | Governance |
| Z406 | NAV_CONTRACT | 2.0 pts | Governance |
| Z601 | BRAND_OBSOLESCENCE | 2.0 pts | Governance |
::: note Z106 — Telemetria del Knowledge Graph, non un difetto
Z106 è escluso dalla tabella delle penalità per scelta progettuale. Elevarlo a finding con punteggio sottrarrebbe punti al Quality Score, spingendo gli ingegneri a rimuovere link utili per soddisfare il linter — un incentivo perverso che degrada la qualità reale della documentazione. I link circolari in un Knowledge Graph sono dati strutturali, non difetti. Z106 viene emesso come telemetria topologica; ispezionalo con --show-info.
:::
:::note Z602 non è incluso nel punteggio Z602 (I18N_PARITY) è un gate di Governance che si attiva come finding autonomo. Non contribuisce a nessun bucket DQS e quindi non ha un valore di penalità nella tabella sopra. :::
Stadio 3 — Governance Escalation
Le violazioni Z6xx rappresentano decadimento del brand e della governance — il tipo che si accumula silenziosamente. Oltre 10 occorrenze, il motore applica un amplificatore esponenziale alle deduzioni del bucket Governance:
dove .
La deduzione è limitata al massimo del tier Governance (25 pts) per evitare overflow. L'effetto pratico: un repository con 20 violazioni Z601 (10 in eccesso → moltiplicatore ) subisce quattro volte il normale impatto sulla governance.
Stadio 4 — Gravity Cap
Se il bucket Governance viene completamente azzerato dalle deduzioni:
Motivazione (ADR-031): un insieme di documentazione con violazioni di governance incontrollate — decadimento del brand, asset stantii, contratti di navigazione rotti — non può essere considerato un prodotto di alta qualità, indipendentemente dal grafo dei link. Il Gravity Cap impone questo vincolo strutturalmente.
Stadio 5 — Suppression Debt
Ogni soppressione attiva è un'assunzione consapevole di responsabilità. Il modello flat-cost deduce esattamente 1 punto per soppressione, indipendentemente da quante soppressioni siano presenti. Non esiste una franchigia gratuita.
suppression_cap (default: 30) è una soglia di hard-fail, non un limite di franchigia. Quando suppression_count > suppression_cap, zenzic score termina con codice 1 immediatamente, prima della valutazione della soglia di punteggio. La formula della penaltà è indipendente dal cap:
dove:
- = soppressioni attive totali (inline
zenzic:ignore+ vociper_file_ignores)
Il punteggio finale è:
Riferimento Costo Soppressioni
| Numero soppressioni | Costo per soppressione | Note |
|---|---|---|
| 1 pt ciascuna | Postura gestita — ogni soppressione ha un costo | |
| 1 pt ciascuna | Hard-fail: zenzic score termina con codice 1 |
:::info Condizione al Contorno — Invariante di Configurazione Poiché ogni soppressione deduce 1 punto, il punteggio massimo raggiungibile per un repository è:
dove è il conteggio totale delle soppressioni attive. Configurare fail_under > 100 - suppression_cap crea una contraddizione matematica: il gate di punteggio si attiva per il debito da soppressioni prima che venga raggiunto il cap di governance. Regola di configurazione sicura:
:::
fail_under e suppression_cap operano come vincoli ortogonali valutati indipendentemente dalla pipeline CI. Un'esecuzione della pipeline fallisce se una delle due condizioni viene soddisfatta:
- Score gate:
score < fail_under→zenzic scoretermina con codice 1 - Governance cap:
|F_s| > suppression_cap→zenzic scoretermina con codice 1
Questa architettura dual-gate consente un bounding asimmetrico del debito tecnico. Una politica ibrida come fail_under = 90, suppression_cap = 30 impone: "La qualità complessiva non deve mai scendere sotto 90/100, e indipendentemente dal punteggio, non più di 30 difetti soppressi sono mai tollerati."
:::tip Il Suppression Debt nella CLI
Esegui zenzic score per vedere la postura corrente delle soppressioni:
Suppression Audit: 8/30 (inline: 5, per-file: 3)
Esegui zenzic check all --audit per vedere i finding senza applicare soppressioni.
:::
Interpretazione dei Risultati
1) Finding Informativi
I finding informativi sono diagnostica non bloccante usata per visibilita e osservabilita.
- Non riducono il DQS.
- Non attivano mai il Security Override.
- In SARIF vengono emessi al livello
note.
Esempi tipici includono Z106 (CIRCULAR_LINK) e superfici informative come Z114 o Z906.
2) Audit delle Soppressioni
Il Suppression Audit e telemetria di governance, non un semplice contatore di failure.
- Riporta il totale delle soppressioni attive (direttive inline + voci
per_file_ignores). - Esplicita il perimetro di debito tecnico autorizzato.
- L'impatto sul punteggio si applica a ogni soppressione attiva (flat-cost: 1 pt ciascuna).
3) Semantica Label: [MANAGED DEBT] e [EXTENDED DEBT]
[MANAGED DEBT]: sono presenti soppressioni attive e il progetto resta nel profilo cap sovrano (suppression_cap <= 30).[EXTENDED DEBT]: sono presenti soppressioni attive con profilo cap esteso (suppression_cap > 30).
Queste label descrivono la postura di governance. Sono complementari alla matematica del punteggio e aiutano i revisori a tracciare la crescita delle soppressioni nel tempo.
:::warning Breaking Change
Le soppressioni non sono allowance-based. Ogni soppressione deduce 1 punto (modello flat-cost), mentre suppression_cap resta una soglia di hard-fail indipendente. I progetti con soppressioni attive vedranno sempre il punteggio massimo raggiungibile ridotto del numero di soppressioni.
:::
Formula Completa
Assemblando tutti e cinque gli stadi:
dove è il conteggio totale delle soppressioni attive e:
Esempio Pratico
Scenario: Un repository ha 2 link rotti (Z101), 3 pagine orfane (Z402), 5 blocchi di codice senza tag (Z505) e 15 violazioni Z601 brand, con 8 soppressioni attive (cap = 30).
Stadio 1 — Security Gate: Nessun finding Z2xx → continua.
Stadio 2 — Tabella Penalità:
| Tier | Cap | Deduzione | cat_pts |
|---|---|---|---|
| Structural | 30 | 2 × 8.0 = 16.0 | 14.0 |
| Navigation | 25 | 3 × 4.0 = 12.0 | 13.0 |
| Content | 20 | 5 × 1.0 = 5.0 | 15.0 |
| Governance | 25 | 15 × 2.0 = 30.0 → cap a 25 | 0.0 |
Stadio 3 — Governance Escalation: 15 violazioni Z601 → → moltiplicatore → deduzione . Bucket brand = 0.
Stadio 4 — Gravity Cap: → .
Stadio 5 — Suppression Debt: soppressioni → flat-cost: .
Lettura dell'Output CLI
Eseguendo zenzic score viene visualizzato un Ledger Quality Breakdown che
esplicita ogni passo aritmetico: dalle penalità raw per tier al cap applicato,
all'aggiustamento del Gravity Cap, al debito da soppressioni e al punteggio finale.
✨ Quality Score: 65/100
╭─ Quality Breakdown ──────────────────────────────────────╮
│ Category Issues Weight Raw Pts Applied Pts │
├──────────────────────────────────────────────────────────┤
│ ✓ structural 0 30% 0 0 │
│ ✓ navigation 0 25% 0 0 │
│ ✗ content 2 20% -4 -4 │
│ ✗ brand 15 25% -30 -25 (CAPPED) │
├──────────────────────────────────────────────────────────┤
│ Σ Subtotal 71 │
╰──────────────────────────────────────────────────────────╯
! Technical Debt (6 suppressions) -6 pts
= Final Quality Score 65 / 100
Guida alle colonne:
| Colonna | Significato |
|---|---|
| Raw Pts | Deduzione post-escalation prima del cap di categoria, mostrata come valore negativo (o 0). |
| Applied Pts | Deduzione effettivamente applicata, limitata al massimo del tier. |
| (CAPPED) | La deduzione raw ha superato il cap del tier ed è stata troncata. |
| Σ Subtotal | Somma di tutti i cat_pts residui prima del Gravity Cap e del Suppression Debt. |
Quando scatta il Gravity Cap (bucket Brand = 0), compare una riga extra tra Σ Subtotal e Technical Debt:
│ Σ Subtotal 75 │
╰──────────────────────────────────────────────────────────╯
! Gravity Cap Enforcement (Brand = 0) -5 pts
! Technical Debt (0 suppressions) 0 pts
= Final Quality Score 70 / 100
L'aritmetica è sempre esplicita: Σ Subtotal − Gravity Cap − Suppression Debt = Final Score.
Vedi Anche
- Suppression Policy — Tre livelli di soppressione, formula del debito e l'override
--audit - Finding Codes — Enciclopedia completa dei codici Zxxx con passi di rimedio
- Gestione del Technical Debt — Workflow di remediation passo dopo passo
- Configura il Privacy Gate — Architettura Z204 FORBIDDEN_TERM