mjolnir-qa 1.0.9 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.it.md CHANGED
@@ -1,401 +1,431 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/readme/logo.png" alt="Mjölnir — Verification Trust Engine" width="800" />
3
+ <img src="assets/readme/hero.svg" alt="Mjölnir. I test ti dicono cosa è passato. Mjölnir ti dice di cosa puoi fidarti." width="100%" />
4
4
 
5
- ### I tuoi test ti mentono. Noi lo dimostriamo.
5
+ <br />
6
6
 
7
- **Verification Trust Engine per la QA.** Mjölnir audita le suite di test
8
- e le pipeline CI, riporta un punteggio di idoneità e mostra esattamente
9
- dove la fiducia si rompe.
7
+ Mjölnir trova i test che non possono fallire e le pipeline che non possono diventare rosse,<br />
8
+ poi valuta fino a che punto ci si può fidare del risultato, con la prova per ogni punto.
10
9
 
11
- [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=C19A34&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
12
- [![ci](https://img.shields.io/github/actions/workflow/status/Sergey-Bar/Mjolnir/ci.yml?branch=main&style=flat-square&label=ci&labelColor=0A1119)](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
13
- [![license](https://img.shields.io/badge/license-MIT-C19A34.svg?style=flat-square&labelColor=0A1119)](LICENSE)
14
- [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-37ABBD.svg?style=flat-square&labelColor=0A1119)](https://nodejs.org)
15
-
16
- [English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | [Español](README.es.md) | [Français](README.fr.md) | Italiano | [Dansk](README.da.md) | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
10
+ <br />
17
11
 
18
- > 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-08.
12
+ [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
13
+ [![downloads](https://img.shields.io/npm/dm/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
14
+ [![ci](https://img.shields.io/github/actions/workflow/status/Sergey-Bar/Mjolnir/ci.yml?branch=main&style=flat-square&label=ci&labelColor=0A1119)](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
15
+ [![coverage](https://img.shields.io/codecov/c/github/Sergey-Bar/Mjolnir?style=flat-square&color=1F6F7C&labelColor=0A1119&label=coverage)](https://codecov.io/gh/Sergey-Bar/Mjolnir)
16
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Sergey-Bar/Mjolnir/badge)](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
17
+ [![license](https://img.shields.io/badge/license-MIT-1F6F7C.svg?style=flat-square&labelColor=0A1119)](LICENSE)
18
+ [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-1F6F7C.svg?style=flat-square&labelColor=0A1119)](https://nodejs.org)
19
19
 
20
20
  ```bash
21
21
  npx mjolnir-qa@latest
22
22
  ```
23
23
 
24
- **I tuoi test sono degni di fiducia?**
24
+ [Guardalo all'opera](#guardalo-allopera) · [Avvio rapido](#avvio-rapido) · [Cosa trova](#cosa-trova-mjölnir) · [Punteggio](#il-punteggio-di-affidabilità) · [Evidenze](#il-modello-di-evidenza) · [Analisi forense](#analisi-forense-del-runtime) · [CI](#integrità-della-ci) · [Agenti](#agenti-ia) · [Sicurezza](#fiducia-e-sicurezza) · [Limiti](#cosa-mjölnir-non-può-dirti) · [Documentazione](#documentazione)
25
+
26
+ <details>
27
+ <summary>Leggi in un'altra lingua — 22 traduzioni</summary>
28
+
29
+ [English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | [Español](README.es.md) | [Français](README.fr.md) | Italiano | [Dansk](README.da.md) | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
25
30
 
26
- [Guardalo in azione](#-guardalo-in-azione) ·
27
- [Avvio rapido](#-avvio-rapido) ·
28
- [Cosa controlla](#-cosa-controlla-mjölnir) ·
29
- [Punteggio](#come-funziona-il-punteggio) ·
30
- [CI](#-integrazione-ci) · [Configurazione](#configurazione) ·
31
- [Documentazione](#-documentazione)
31
+ > 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
32
+
33
+ <!-- Source hash: 3541b09e8d04 -->
34
+
35
+ </details>
32
36
 
33
37
  </div>
34
38
 
35
- ---
39
+ <br />
40
+
41
+ ## Una spunta verde è un'affermazione, non una prova
42
+
43
+ Una spunta verde significa che la pipeline non è fallita. Non significa che i test siano stati eseguiti, né che avrebbero potuto fallire. Ognuno di questi casi passa in verde:
44
+
45
+ - un `.only` committato che ha eseguito 3 test invece di 900
46
+ - `continue-on-error: true` sul job che doveva fare da gate
47
+ - `|| true` dopo il comando dei test
48
+ - un test che non verifica nulla, o con il corpo vuoto
49
+ - un wrapper di retry che trasforma un vero fallimento in un passaggio fortunato
50
+ - un report che il workflow carica ma che non è mai stato generato
51
+ - uno sleep fisso che tiene insieme una race condition
52
+
53
+ Nessuno di questi fa diventare rossa la pipeline, e ognuno sembra intenzionale in review. Per questo sopravvivono. Ecco Mjölnir che ne legge uno reale:
54
+
55
+ <p align="center">
56
+ <img src="assets/readme/scan.svg" alt="Il workflow CI del repository demo, letto riga per riga. Mjölnir segnala ogni rilievo alla riga riportata, con la sua regola, cosa non va, il suo livello di evidenza e il suo tasso di falsi positivi misurato." width="800" />
57
+ </p>
58
+
59
+ <sub>Ogni rilievo che la scansione demo ha riportato per questo workflow, alla riga riportata. Generato da `npm run docs:readme-brand` a partire da [`demo-report.json`](assets/readme/demo-report.json) e bloccato contro le derive in CI.</sub>
60
+
61
+ **Modalità rigorosa.** I rilevamenti più aggressivi — `.only`, `continue-on-error`, test vuoti, abuso di retry — vivono nel livello di quarantena. Funzionano solo con `--strict` e sono limitati alla gravità `info`: segnalano, non bloccano mai. La scansione predefinita (`npx mjolnir-qa@latest` senza `--strict`) copre solo regole core ed extended. Aggiungi `--strict` quando vuoi anche il livello consultivo.
62
+
63
+ Mjölnir legge la suite, i workflow CI e, se ce l'hai, il report di un'esecuzione reale. Non esegue i tuoi test, non installa le tue dipendenze e non esegue il codice che scansiona. E quando non ha evidenze, lo dice invece di inventarsi fiducia:
64
+
65
+ | Situazione | Cosa riporta Mjölnir |
66
+ | -------------------------------------------------------- | ------------------------------------------------------------------ |
67
+ | Nessuna dichiarazione di test trovata | Punteggio `null`, mostrato come **UNKNOWN**. Mai un 100 inventato. |
68
+ | Nessuna baseline o revisione confrontabile | **UNKNOWN**, con il motivo indicato. Mai uno 0 presunto. |
69
+ | Scansione interrotta (budget di tempo, file illeggibili) | **PARTIAL**, uscita `2`. Mai presentata come pulita. |
70
+
71
+ <p align="center">
72
+ <img src="assets/readme/how-it-works.svg" alt="Come funziona Mjölnir. Legge staticamente la suite di test e la pipeline CI, e il report di un'esecuzione reale quando c'è. Pesa ogni rilievo in base al livello di evidenza e al livello di fiducia, dove solo un'esecuzione reale può raggiungere da L3 a L5, e produce rilievi, un punteggio di affidabilità e un gate CI con codici di uscita congelati. Nel ciclo dell'agente, l'IA scrive la correzione e Mjölnir riesegue la scansione per dimostrarla." width="880" />
73
+ </p>
74
+
75
+ <sub>Composto per questa pagina e mostrato 1:1. Generato da `npm run docs:readme-brand` e bloccato contro le derive in CI; punteggio, conteggi e ID della regola provengono da [`script.demo.json`](assets/video/script.demo.json), [`demo-report.json`](assets/readme/demo-report.json) e dal registro delle regole, mai digitati a mano. La stessa immagine come poster: [`architecture.svg`](assets/readme/architecture.svg).</sub>
76
+
77
+ <br />
78
+
79
+ ## Guardalo all'opera
80
+
81
+ Una scansione reale di [`examples/demo-repo`](examples/demo-repo), una piccola suite Playwright con un workflow CI. Ecco dove sono finiti i suoi punti:
82
+
83
+ <p align="center">
84
+ <img src="assets/readme/terminal-hero.svg" alt="Il dettaglio delle detrazioni di Mjölnir: WORTHINESS 80/100 WORTHY, il punteggio per categoria, il riquadro delle detrazioni per gravità e una lista FIX THIS FIRST" width="520" />
85
+ </p>
86
+
87
+ <sub>Generato da `npm run docs:hero` a partire da una scansione reale e bloccato contro le derive in CI. Il report `--verbose` completo della stessa scansione è [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
88
+
89
+ <details>
90
+ <summary><strong>Guardalo</strong> — una scansione, la correzione che stampa e la nuova scansione che la dimostra</summary>
36
91
 
37
- ## 🎬 Guardalo in azione
92
+ <br />
38
93
 
39
94
  <p align="center">
40
- <img src="assets/readme/demo.svg" alt="Il report --verbose completo di Mjölnir su un repo demo: WORTHINESS 75/100 NEEDS WORK, un dettaglio delle diagnosti per categoria, una lista FIX THIS FIRST e ogni riscontro con ID di regola e numero di riga attraverso CI, Playwright, igiene dei test e regole Python" width="900" />
95
+ <a href="assets/video/mjolnir-demo.mp4">
96
+ <img src="assets/video/mjolnir-demo-poster.png" alt="Un fotogramma della registrazione demo: npx mjolnir-qa@latest che scansiona il repository demo in una finestra di terminale" width="900" />
97
+ </a>
41
98
  </p>
42
99
 
43
- <sub>L'output completo di `npx mjolnir-qa ./examples/demo-repo --verbose`,
44
- renderizzato dal reporter vero — nulla di tagliato. Rigenerato con
45
- `npm run docs:demo`;
46
- [`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
47
- fa fallire la CI se deriva da ciò che lo strumento stampa.</sub>
100
+ <sub>Renderizzato fotogramma per fotogramma da una scansione reale con `npm run docs:video`; mai registrato dallo schermo. Seleziona il fotogramma per aprire [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
48
101
 
49
- **Cosa è appena successo:**
102
+ </details>
50
103
 
51
- 1. Mjölnir ha individuato le spec Playwright, la sua configurazione, il
52
- workflow CI e un file di test Python — quattro linguaggi/formati, un
53
- solo passaggio.
54
- 2. Ha trovato evidenze che indeboliscono la fiducia nella suite — un
55
- `continue-on-error` che maschera un job, un `|| true` che ingoia un
56
- exit code, sleep hardcoded, un selettore fragile, URL di staging
57
- hardcoded, un'attesa `networkidle`.
58
- 3. Di ciascuna ha fatto un riscontro concreto con ID di regola,
59
- posizione e fix — e un unico punteggio su cui fare gate di una PR.
104
+ ### Un rilievo, da vicino
60
105
 
61
- ### Un riscontro da vicino
106
+ Ogni rilievo risponde a quattro domande: dove si trova, quanto è sicuro Mjölnir, quanto spesso la regola sbaglia e come correggerlo.
62
107
 
63
- Esegui `mjolnir explain QA-CI-001` sul primo riscontro qui sopra e
64
- ottieni:
108
+ <p align="center">
109
+ <img src="assets/readme/finding-anatomy.svg" alt="Il primo rilievo della scansione demo, esattamente come lo stampa il terminale, con le sue quattro parti evidenziate: dove, quanto è sicuro, quanto spesso la regola sbaglia, e la correzione." width="100%" />
110
+ </p>
111
+
112
+ `mjolnir explain QA-CI-001` stampa l'intero fascicolo di fiducia di una regola, compreso il suo tasso di falsi positivi misurato e il livello che quel tasso le ha fatto guadagnare:
65
113
 
66
114
  ```text
67
- ▚ QA-CI-001 — continue-on-error masks a failing verification gate
115
+ ▍ QA-CI-001 — continue-on-error masks a failing verification gate
68
116
 
69
117
  Severity: error
70
118
  Confidence: high
119
+ Tier: quarantine
71
120
  Evidence: E2
72
- Measured FP: not yet measured — this rule ships on assumption (see docs/FP-AUDIT.md)
121
+ QA impact: False-green risk (FALSE-GREEN)
122
+ Measured FP: 11% (19 hand-classified corpus verdicts)
123
+ FP risk: low (author estimate)
124
+ Languages: yaml
125
+ Frameworks: github-actions, azure-pipelines
73
126
 
74
127
  WHAT WAS FOUND (real detector output, not a mockup)
75
128
  Job `security-scan` runs a verification gate under `continue-on-error: true`.
76
129
 
77
130
  WHY IT MATTERS
78
- This job can fail every day and CI will still show green. The checkmark
79
- on this workflow cannot be trusted.
131
+ This job can fail every day and CI will still show green. The checkmark on
132
+ this workflow cannot be trusted.
80
133
 
81
134
  HOW TO FIX
82
135
  Remove continue-on-error, or scope it to individual non-blocking steps only.
83
- ```
84
136
 
85
- Questa è l'unità di valore: non una svista di stile, ma un punto in cui
86
- la tua CI ti dice che qualcosa è passato quando non è passato.
137
+ Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
87
138
 
88
- ---
139
+ WHAT WOULD CHANGE THE VERDICT
140
+ - a run report next to the scan target (mjolnir.report.json or test-results/)
141
+ corroborating this file lifts its findings to L3–L5
142
+ - a documented suppression (mjolnir.config.json) lowers the finding count
143
+ without claiming correctness
144
+ - quarantine findings run only under --strict and are advisory (E0) — they can
145
+ never gate CI
89
146
 
90
- ## ⚡ Avvio rapido
147
+ NEXT ACTION
148
+ Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
149
+ occurrence of this rule is listed in the scan output.
91
150
 
92
- Eseguilo su un repo per un report completo e un punteggio di idoneità:
151
+ HOW TO VERIFY THE FIX
152
+ Re-run `mjolnir` on the changed file(s) — this finding should no longer
153
+ appear. `mjolnir --scope changed` scopes the check to just what you touched.
93
154
 
94
- ```bash
95
- npx mjolnir-qa@latest
155
+ Docs: mjolnir rules --md (full catalog, this rule included)
96
156
  ```
97
157
 
98
- **In CI il prodotto è un solo comando.** Scansiona solo ciò che il
99
- branch ha toccato ed esce con un codice diverso da zero su problemi
100
- nuovi:
158
+ Questa è l'unità di valore: un punto in cui la CI riporta un successo che non si è guadagnata.
159
+
160
+ <br />
161
+
162
+ ## Avvio rapido
101
163
 
102
164
  ```bash
103
- npx mjolnir-qa@latest --scope changed
165
+ npx mjolnir-qa@latest
104
166
  ```
105
167
 
106
- Metti quello in un check di PR — `mjolnir ci install` scrive il
107
- workflow — e hai finito. Tutto il resto è opzionale.
108
-
109
- | Comando | Cosa fa |
110
- | ----------------------------------- | ---------------------------------------------------------------- |
111
- | `mjolnir` | Scansione completa del repo + punteggio di idoneità |
112
- | `mjolnir --scope changed` | Solo ciò che il tuo branch ha introdotto — la forma CI |
113
- | `mjolnir ci install` | Genera il workflow di PR consultivo |
114
- | `mjolnir explain QA-CI-001` | Cosa / perché / fix + tasso di FP misurato di una regola |
115
- | `mjolnir rules --unmeasured` | Le regole che girano per assunzione, non per misurazione |
116
- | `mjolnir --json` / `--format sarif` | Leggibile da macchina / GitHub Code Scanning |
117
- | `mjolnir --strict` | Esegue anche le regole del tier quarantena (rischio FP più alto) |
168
+ Scansiona la directory corrente e stampa il Trust Report: cosa ha trovato, fino a che punto puoi fidarti, perché e cosa fare dopo. Esce con `0` quando non è stato trovato nulla al livello del gate o sopra.
118
169
 
119
- <details>
120
- <summary><strong>Quando qualcosa è instabile</strong></summary>
170
+ In CI, scansiona solo ciò che il branch ha introdotto, così una suite legacy non sommerge la tua prima pull request:
121
171
 
122
- | Comando | Cosa fa |
123
- | ----------------------------------- | ---------------------------------------------------------- |
124
- | `mjolnir forensics ./test-results/` | Dati di run reali → verdetti `TRUE-FLAKE`, `FLAKY.md` |
125
- | `mjolnir triage ./test-results/` | Proposta di quarantena dalla cronologia di esecuzione |
126
- | `mjolnir pw-report ./test-results/` | Riepilogo di run Playwright — retry / flake / più lenti |
127
- | `mjolnir doctor:playwright` | Scansione profonda solo Playwright + Selector Health Score |
172
+ ```bash
173
+ npx mjolnir-qa@latest --scope changed
174
+ ```
128
175
 
129
- </details>
176
+ `mjolnir ci install` lo scrive come workflow GitHub Actions, usando l'[action](https://github.com/Sergey-Bar/Mjolnir#readme) fissata al tag maggiore `v1` (o un semplice `npx` con `--no-action`). Resta consultivo finché non decidi che deve bloccare.
177
+
178
+ | Comando | Cosa fa |
179
+ | ----------------------------------- | ---------------------------------------------------------------------- |
180
+ | `mjolnir` | Trust Report: verdetto, confidenza, prossima azione |
181
+ | `mjolnir --scope changed` | Solo ciò che il tuo branch ha introdotto (la forma per la CI) |
182
+ | `mjolnir ci install` | Genera il workflow consultivo per le PR (basato sull'action) |
183
+ | `mjolnir explain QA-CI-001` | Cosa, perché e correzione, più il tasso di FP misurato |
184
+ | `mjolnir why src/a.spec.ts:42` | Perché proprio questa riga è stata segnalata. Non blocca mai. |
185
+ | `mjolnir forensics ./test-results/` | Evidenze di runtime da un'esecuzione reale |
186
+ | `mjolnir trust-report` | Trust Artifact autonomo (md + json) |
187
+ | `mjolnir handoff` | Piano di correzione per un agente di coding |
188
+ | `mjolnir --json` / `--format sarif` | Output leggibile dalle macchine, GitHub Code Scanning |
189
+ | `mjolnir --format codequality` | Report GitLab Code Quality (artefatto del widget della MR) |
190
+ | `mjolnir --strict` | Esegue anche le regole del livello quarantine (rischio di FP più alto) |
130
191
 
131
192
  <details>
132
- <summary><strong>Occasionale / report</strong></summary>
133
-
134
- | Comando | Cosa fa |
135
- | ------------------------------- | ---------------------------------------------------------- |
136
- | `mjolnir fix --dry-run` / `fix` | Auto-fix sicuri con prova |
137
- | `mjolnir baseline` / `diff` | Snapshot dei riscontri, poi riporta solo nuovi/peggiorati |
138
- | `mjolnir impact --since <ref>` | Cosa è cambiato da un commit precedente |
139
- | `mjolnir debt` | Registro del debito di test con un modello di costo |
140
- | `mjolnir handover` | Mappa di onboarding della suite per un nuovo QA |
141
- | `mjolnir stats` | Contatori locali storici dei fix visti |
142
- | `mjolnir badge` | JSON endpoint di shields.io + snippet |
143
- | `mjolnir rules --md` | Catalogo completo delle regole (JSON o Markdown) |
144
- | `mjolnir doctor` | Auto-audit della stessa base di regole di Mjölnir |
145
- | `mjolnir create-rule <ID>` | Imposta lo scheletro di una nuova regola + fixture |
146
- | `mjolnir --format mermaid` | Diagramma dell'architettura dei test per un commento di PR |
193
+ <summary><strong>Tutti gli altri comandi</strong> — triage dei test instabili, report, governance</summary>
194
+
195
+ <br />
196
+
197
+ | Comando | Cosa fa |
198
+ | ----------------------------------- | --------------------------------------------------------------------------------------- |
199
+ | `mjolnir --classic` | Il banner del punteggio di prima del Trust Report |
200
+ | `mjolnir explain verdict` | Perché il verdetto della scansione salvata è quello che è |
201
+ | `mjolnir triage ./test-results/` | Triage guidato. Ogni riga termina con una prossima azione. |
202
+ | `mjolnir pw-report ./test-results/` | Riepilogo dell'esecuzione Playwright: retry, test instabili, i più lenti |
203
+ | `mjolnir doctor:playwright` | Scansione approfondita solo Playwright più Selector Health Score |
204
+ | `mjolnir fix --dry-run` / `fix` | Correzioni automatiche sicure, ognuna riscansionata per dimostrare che è andata a segno |
205
+ | `mjolnir baseline` / `diff` | Fotografa i rilievi, poi riporta solo quelli nuovi o peggiorati |
206
+ | `mjolnir impact --since <ref>` | Cosa ha introdotto e risolto un commit |
207
+ | `mjolnir summary` | Annotazioni CI e un riepilogo dello step da un report |
208
+ | `mjolnir pr-comment` | Un commento di PR mirato, in Markdown |
209
+ | `mjolnir debt` | Registro del debito di test con un modello di costo |
210
+ | `mjolnir handover` | Mappa di onboarding della suite per un nuovo ingegnere QA |
211
+ | `mjolnir init` | Rileva i framework, stampa una checklist di configurazione |
212
+ | `mjolnir suppressions` | Elenca i rilievi soppressi, per la governance |
213
+ | `mjolnir rules --unmeasured` | Le regole che girano su un'ipotesi, non su una misura |
214
+ | `mjolnir rules --md` | Catalogo completo delle regole (JSON o Markdown) |
215
+ | `mjolnir doctor` | Autoverifica della base di regole di Mjölnir |
216
+ | `mjolnir create-rule <ID>` | Crea lo scheletro di una nuova regola e delle sue fixture |
217
+ | `mjolnir stats` | Contatori locali complessivi delle correzioni viste |
218
+ | `mjolnir badge` | JSON dell'endpoint shields.io e snippet |
219
+ | `mjolnir --cache` | Riscansioni incrementali tramite una cache locale dei verdetti |
220
+ | `mjolnir --format mermaid` | Diagramma dell'architettura dei test per un commento di PR |
221
+
222
+ `mjolnir help <command>` stampa uso, esempi e il passo successivo per ognuno di essi.
147
223
 
148
224
  </details>
149
225
 
150
- Installalo globalmente invece che con `npx` se preferisci:
151
- `npm i -g mjolnir-qa`. Richiede Node.js ≥ 22.18. Funziona su Windows,
152
- macOS e Linux.
153
-
154
- ---
226
+ Richiede **Node.js ≥ 22.18** su Windows, macOS o Linux. Preferisci un'installazione globale? `npm i -g mjolnir-qa`. Il requisito minimo viene dalla toolchain di build (tsdown lo ha come target e la pipeline di rilascio esegue smoke test su di esso); le dipendenze di runtime non chiedono di più.
155
227
 
156
- ## 👥 Per chi è?
228
+ <br />
157
229
 
158
- - **QA / SDET** che possiedono una suite e2e o di integrazione e
159
- hanno bisogno di evidenze che la suite meriti davvero la spunta
160
- verde che produce.
161
- - **Team Piattaforma / DevEx** responsabili dell'integrità CI e dei
162
- release gate — le persone per cui un `continue-on-error` non deve mai
163
- trasformare in silenzio una pipeline rossa in verde.
164
- - **Maintainer OSS** che vogliono un gate di verifica economico,
165
- sempre attivo, che gira in locale e in CI senza chiamate di rete.
230
+ ## Cosa trova Mjölnir
166
231
 
167
- ---
168
-
169
- ## 🔨 Cosa controlla Mjölnir
232
+ <p align="center">
233
+ <img src="assets/readme/stack.svg" alt="Funziona con il tuo stack: i linguaggi, i framework di test e i sistemi CI coperti dalle sue regole, dal registro delle regole." width="100%" />
234
+ </p>
170
235
 
171
- | | |
172
- | --- | -------------------------------------------------------------------------------------------------------------------------- |
173
- | ⚖️ | **Punteggio di idoneità** — un numero, tabella di deduzioni trasparente, nessuna black box |
174
- | 🎭 | **Selector Health Score** — valuta i tuoi locator Playwright, non solo il pass rate |
175
- | 🔬 | **Forensica di runtime** — legge dati di run reali Playwright/JUnit per agganciare `TRUE-FLAKE`, non solo ipotesi statiche |
176
- | 🚨 | **Regole di integrità CI** — becca `continue-on-error`, `\|\| true` e altri trucchi da falso verde |
177
- | 🐍 | **Tutti e quattro i binding Playwright** — TypeScript, Python, Java, C#/.NET — più pytest, JUnit/TestNG e workflow CI |
178
- | 🔒 | **Local-first** — zero chiamate di rete durante la scansione, zero telemetria, gira in secondi |
236
+ **79 regole** in quattro famiglie — igiene dei test, qualità dei test, Playwright e integrità della CI — per TypeScript e JavaScript, Python, Java, C# e YAML di GitHub Actions. Coprono Playwright in tutti e quattro i binding, oltre a pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest e Mocha, con una copertura iniziale per Cypress e Selenium. Nove di esse, per mostrarne la forma:
179
237
 
180
- ### Le regole
238
+ | ID | Regola | Gravità | Livello |
239
+ | ------------ | ------------------------------------------------------------------------- | ------- | ---------- |
240
+ | QA-CI-001 | `continue-on-error` maschera un gate di verifica che fallisce | error | quarantine |
241
+ | QA-CI-009 | Codice di uscita dei test non propagato (`\|` senza pipefail, catene `;`) | error | extended |
242
+ | QA-TEST-001 | Test focalizzato committato (`.only`, `fit`) | error | quarantine |
243
+ | QA-TEST-003 | Test senza asserzioni | error | quarantine |
244
+ | QA-TQUAL-009 | Asserzione su promise senza await | error | quarantine |
245
+ | QA-PW-002 | Asserzione su locator senza await | error | core |
246
+ | QA-PW-004 | Selettori CSS/XPath fragili | warning | quarantine |
247
+ | QA-PY-002 | Test saltato (`skip`, `xfail` non rigoroso) | warning | core |
248
+ | QA-CS-103 | Metodo di test senza asserzioni | error | core |
181
249
 
182
- Ogni regola arriva con fixture must-fire **e** must-not-fire. Una
183
- regola che scatta sulla propria fixture negativa non può essere
184
- pubblicata — quello è il firewall dei falsi positivi.
250
+ Il catalogo completo è generato dal registro, mai mantenuto a mano: `mjolnir rules --md`, [`docs/rules/`](docs/rules/), oppure la [guida a cosa controlla](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
185
251
 
186
252
  <details>
187
- <summary><strong>Igiene dei test</strong></summary>
188
-
189
- | ID | Regola | Severity |
190
- | ----------- | -------------------------------------------------------- | -------- |
191
- | QA-TEST-001 | Test focalizzato committato (`.only`, `fit`) | error |
192
- | QA-TEST-002 | Test saltato senza giustificazione | error |
193
- | QA-TEST-002 | Test saltato con giustificazione tracciata | warning |
194
- | QA-TEST-003 | Test senza asserzioni | error |
195
- | QA-TEST-004 | Sleep hardcoded (`waitForTimeout`, `sleep()`, `delay()`) | warning |
196
- | QA-TEST-006 | Abuso di retry che nasconde l'instabilità | warning |
197
- | QA-TEST-010 | Corpo del test vuoto | error |
253
+ <summary><strong>Ogni regola citata in questo README</strong>, in un'unica tabella</summary>
254
+
255
+ <br />
256
+
257
+ > Le regole `quarantine` girano solo con `--strict` e non bloccano mai (sono limitate a info). La gravità mostrata è quella definita dall'autore.
258
+
259
+ | ID | Famiglia | Regola | Gravità | Livello |
260
+ | ------------ | ---------- | ---------------------------------------------------------------- | ------- | ---------- |
261
+ | QA-TEST-001 | Igiene | Test focalizzato committato (`.only`, `fit`) | error | quarantine |
262
+ | QA-TEST-002 | Igiene | Test saltato. Sale a `error` senza un motivo tracciato. | warning | quarantine |
263
+ | QA-TEST-003 | Igiene | Test senza asserzioni | error | quarantine |
264
+ | QA-TEST-004 | Igiene | Sleep fisso (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
265
+ | QA-TEST-006 | Igiene | Abuso dei retry che nasconde l'instabilità | warning | quarantine |
266
+ | QA-TEST-010 | Igiene | Corpo del test vuoto | error | quarantine |
267
+ | QA-TQUAL-002 | Qualità | Asserzione tautologica | error | quarantine |
268
+ | QA-TQUAL-009 | Qualità | Asserzione su promise senza await | error | quarantine |
269
+ | QA-TQUAL-011 | Qualità | Test commentati | warning | extended |
270
+ | QA-PW-002 | Playwright | Asserzione su locator senza await | error | core |
271
+ | QA-PW-003 | Playwright | `page.pause()` / `test.only()` committato | error | core |
272
+ | QA-PW-004 | Playwright | Selettori CSS/XPath fragili | warning | quarantine |
273
+ | QA-PW-123 | Playwright | URL di ambiente scritti nel codice | warning | quarantine |
274
+ | QA-PW-140 | Playwright | Screenshot senza `maxDiffPixelRatio` | warning | core |
275
+ | QA-CI-001 | CI | `continue-on-error` maschera un gate che fallisce | error | quarantine |
276
+ | QA-CI-002 | CI | `\|\| true` ingoia i codici di uscita | error | extended |
277
+ | QA-CI-005 | CI | Report consumato ma mai generato | error | quarantine |
278
+ | QA-CI-007 | CI | Wrapper di retry attorno ai test | warning | extended |
279
+ | QA-CI-008 | CI | Step sempre riuscito che maschera i fallimenti | error | quarantine |
280
+ | QA-CI-009 | CI | Codice di uscita non propagato (`\|` senza pipefail, catene `;`) | error | extended |
281
+ | QA-CI-010 | CI | Test saltati dove devono bloccare | error | quarantine |
282
+ | QA-PY-002 | Python | Test saltato (`skip`, `xfail` non rigoroso) | warning | core |
283
+ | QA-PY-003 | Python | Funzione di test senza asserzioni | error | quarantine |
284
+ | QA-PY-005 | Python | `time.sleep()` nei test | warning | extended |
285
+ | QA-PY-012 | Python | Asserzione tautologica | error | quarantine |
286
+ | QA-JV-101 | Java | Test disabilitato (`@Disabled`) | warning | core |
287
+ | QA-JV-102 | Java | Sleep fisso (`Thread.sleep()`) | warning | extended |
288
+ | QA-JV-103 | Java | Metodo di test senza asserzioni | error | extended |
289
+ | QA-JV-105 | Java | Sleep fisso con `waitForTimeout()` di Playwright | warning | core |
290
+ | QA-JV-106 | Java | Selettore fragile invece di un locator per ruolo | warning | quarantine |
291
+ | QA-CS-101 | C# | Test saltato (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
292
+ | QA-CS-102 | C# | Sleep fisso (`Thread.Sleep` / `Task.Delay`) | warning | core |
293
+ | QA-CS-103 | C# | Metodo di test senza asserzioni | error | core |
294
+ | QA-CS-105 | C# | Sleep fisso con `WaitForTimeoutAsync()` | warning | extended |
295
+ | QA-CS-106 | C# | Selettore fragile invece di un locator per ruolo | warning | quarantine |
296
+
297
+ Python include anche QA-PY-001…012 (igiene pytest) e QA-PY-101…108 (Playwright per Python). Cypress e Selenium hanno set iniziali di tre regole ciascuno.
198
298
 
199
299
  </details>
200
300
 
201
- <details>
202
- <summary><strong>Qualità dei test</strong></summary>
301
+ Ogni regola viene rilasciata con una fixture must-fire **e** una must-not-fire, e una regola che scatta sulla propria fixture negativa non può essere rilasciata. È il firewall contro i falsi positivi; `mjolnir doctor` lo impone nella CI di questo repository.
203
302
 
204
- | ID | Regla | Severity |
205
- | ------------ | --------------------------------- | -------- |
206
- | QA-TQUAL-002 | Asserzione tautologica | error |
207
- | QA-TQUAL-009 | Asserzione di promise senza await | error |
208
- | QA-TQUAL-011 | Test commentati | warning |
303
+ ### Selector Health Score
209
304
 
210
- </details>
305
+ `mjolnir doctor:playwright` valuta ogni locator in base a come trova un elemento: come farebbe un utente (ruolo, etichetta, testo), tramite un contratto esplicito (`data-testid`) o per un caso strutturale (catene CSS, XPath). Ogni file riceve un punteggio da 0 a 100:
211
306
 
212
- <details>
213
- <summary><strong>Playwright 🎭</strong></summary>
307
+ ```text
308
+ ▍ SELECTOR HEALTH
214
309
 
215
- | ID | Regla | Severity |
216
- | --------- | ----------------------------------------- | -------- |
217
- | QA-PW-002 | Asserzione di locator senza await | error |
218
- | QA-PW-003 | `page.pause()` / `test.only()` committati | error |
219
- | QA-PW-004 | Selettori CSS/XPath fragili | warning |
220
- | QA-PW-123 | URL di ambiente hardcoded | warning |
310
+ e2e/login.spec.ts
311
+ [█████████████░░░░░░░] 65 / 100
312
+ role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
221
313
 
222
- </details>
314
+ e2e/checkout.spec.ts
315
+ [██████████████████░░] 88 / 100
316
+ role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
317
+ ```
223
318
 
224
- <details>
225
- <summary><strong>Integrità CI</strong></summary>
226
-
227
- | ID | Regla | Severity |
228
- | --------- | ------------------------------------------------------------------ | -------- |
229
- | QA-CI-001 | `continue-on-error` maschera i fallimenti | error |
230
- | QA-CI-002 | `\|\| true` ingoia gli exit code | error |
231
- | QA-CI-005 | Report consumato ma mai generato | error |
232
- | QA-CI-007 | Wrapper di retry attorno ai test | warning |
233
- | QA-CI-008 | Step sempre riuscito maschera i fallimenti | error |
234
- | QA-CI-009 | Exit code del test non propagato (`\|` senza pipefail, catene `;`) | error |
235
- | QA-CI-010 | Test saltati dove devono bloccare (guardie skip-on-PR) | error |
319
+ Questo misura la **resilienza, non la correttezza**. `.btn.btn-primary > div:nth-child(2)` passa oggi e continua a passare finché qualcuno non tocca il markup. Un punteggio basso non afferma mai che il test è rotto, solo che dipende da un markup che nessuno ha promesso di mantenere.
236
320
 
237
- </details>
321
+ <br />
238
322
 
239
- <details>
240
- <summary><strong>Python / pytest 🐍</strong></summary>
323
+ ## Il punteggio di affidabilità
241
324
 
242
- | ID | Regla | Severity |
243
- | --------- | ----------------------------------------- | -------- |
244
- | QA-PY-002 | Test saltato (`skip`, `xfail` non strict) | warning |
245
- | QA-PY-003 | Funzione di test senza asserzioni | error |
246
- | QA-PY-005 | `time.sleep()` nei test | warning |
247
- | QA-PY-012 | Asserzione tautologica | error |
325
+ <p align="center">
326
+ <img src="assets/readme/score-gauge.svg" alt="La scala di affidabilità da 0 a 100, con un indicatore che percorre ogni punteggio: UNWORTHY sotto 50, NEEDS WORK da 50 a 79, WORTHY da 80 a 99, FORGED a 100" width="720" />
327
+ </p>
248
328
 
249
- 20 regole Python in totale (QA-PY-001…012 igiene pytest + QA-PY-101…108 Playwright-Python).
329
+ <sub>Ogni punteggio da 0 a 100, posizionato dal vero `deriveScoreState`. Generato da `npm run docs:gauge` e bloccato contro le derive in CI.</sub>
250
330
 
251
- </details>
331
+ | Punteggio | Verdetto |
332
+ | --------- | -------------------------------------------------- |
333
+ | `0 – 49` | **UNWORTHY** |
334
+ | `50 – 79` | **NEEDS WORK** |
335
+ | `80 – 99` | **WORTHY** |
336
+ | `100` | **FORGED** |
337
+ | `null` | **UNKNOWN**: nessuna dichiarazione di test trovata |
252
338
 
253
- <details>
254
- <summary><strong>Java / JUnit · TestNG ☕</strong></summary>
339
+ **Come viene calcolato.** La gravità fissa una detrazione di base (`error −8`, `warning −3`, `info −1`) e il livello di evidenza la sconta: E2 conta per intero, E1 a metà (arrotondato per difetto), E0 per niente. Il totale è normalizzato sull'esposizione della suite, cioè detrazioni per dichiarazione di test anziché per file. Il terminale stampa gli stessi numeri scontati usati dal punteggio; non esiste un secondo modello nascosto. Dettagli: [docs/SCORING.md](docs/SCORING.md) e la [guida al punteggio](https://sergey-bar.github.io/Mjolnir/guide/scoring).
255
340
 
256
- | ID | Regla | Severity |
257
- | --------- | --------------------------------------------- | -------- |
258
- | QA-JV-101 | Test disabilitato (`@Disabled`) | warning |
259
- | QA-JV-102 | Sleep hardcoded (`Thread.sleep()`) | warning |
260
- | QA-JV-103 | Metodo di test senza asserzioni | error |
261
- | QA-JV-105 | Sleep hardcoded Playwright `waitForTimeout()` | warning |
262
- | QA-JV-106 | Selettore fragile invece di un role locator | warning |
341
+ **Cosa non significa 100.** Non significa che il software sia corretto, che la suite sia adeguata o che il prodotto sia privo di difetti. Significa una cosa sola: **nessuna delle regole valutate da Mjölnir ha prodotto una detrazione con questa scansione e questo modello di evidenza.**
263
342
 
264
- </details>
343
+ <br />
265
344
 
266
- <details>
267
- <summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
345
+ ## Il modello di evidenza
268
346
 
269
- | ID | Regla | Severity |
270
- | --------- | ----------------------------------------------- | -------- |
271
- | QA-CS-101 | Test saltato (`[Ignore]`, `[Fact(Skip=)]`) | warning |
272
- | QA-CS-102 | Sleep hardcoded (`Thread.Sleep` / `Task.Delay`) | warning |
273
- | QA-CS-103 | Metodo di test senza asserzioni | error |
274
- | QA-CS-105 | Sleep hardcoded `WaitForTimeoutAsync()` | warning |
275
- | QA-CS-106 | Selettore fragile invece di un role locator | warning |
347
+ Ogni rilievo porta due etichette: quanto è sicuro Mjölnir e fino a che punto il rilievo è stato verificato. È la differenza tra uno strumento che segnala pattern e uno strumento su cui puoi basare il via libera a un rilascio.
276
348
 
277
- </details>
349
+ **Quanto è sicuro — il livello di evidenza.**
278
350
 
279
- > Il catalogo live completo — ogni regola con tier, confidence, rischio
280
- > di falso positivo e disponibilità di autofix — è generato dal
281
- > registro:
282
- >
283
- > ```bash
284
- > mjolnir rules --md
285
- > ```
286
- >
287
- > Le pagine per regola vivono in [`docs/rules/`](docs/rules/).
288
-
289
- ### Quanto è misurato
290
-
291
- **78 regole su 99 portano un tasso di falsi positivi misurato su vero
292
- codice OSS** (≥ 10 riscontri classificati a mano ciascuna; vedi
293
- [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Le altre 21 escono sulla stima
294
- dell'autore. Ogni footer di scansione dice quante delle regole
295
- _scattate_ sono misurate; `mjolnir rules --unmeasured` elenca quelle
296
- che non lo sono; la pagina `mjolnir explain` di ogni regola dichiara il
297
- audita al 95 % ed è in quarantena per questo. Far crescere quel numero è il
298
- lavoro continuo del progetto.
299
-
300
- ### Tier delle regole e maturità per linguaggio
301
-
302
- Ogni regola è `core`, `extended` o `quarantine`, assegnato in base al
303
- suo tasso di falsi positivi **misurato**:
304
-
305
- | Tier | Significato | Scansione predefinita | `--strict` |
306
- | ------------ | --------------------------------------------- | :-------------------: | :--------: |
307
- | `core` | ≤ 10 % di FP misurato | ✅ | ✅ |
308
- | `extended` | ≤ 30 % di FP misurato | ✅ | ✅ |
309
- | `quarantine` | sopra il 30 %, o non ancora misurato (n < 10) | ❌ | ✅ |
310
-
311
- | Linguaggio | Adattatore | Copertura oggi |
312
- | --------------- | ------------------- | --------------------------------------------------------- |
313
- | TypeScript / JS | AST del compilatore | la più ampia e misurata — soprattutto `core`/`extended` |
314
- | Python / pytest | Livello regex | ampia, auditata su corpus — soprattutto `core`/`extended` |
315
- | Java | Livello regex | più recente — soprattutto `extended`/`quarantine` |
316
- | C# / .NET | Livello regex | più recente — soprattutto `extended`/`quarantine` |
317
-
318
- TypeScript e Python hanno la copertura misurata più ampia. Java e C#
319
- sono pubblicati, documentati, e restano fuori dal numero di testa fino
320
- a quando una vera suite consumatrice (non i test della stessa
321
- libreria di binding) non sarà stata auditata.
322
-
323
- ---
324
-
325
- ## Come funziona il punteggio
351
+ | Livello | Nome | Significa | Detrazione |
352
+ | ------- | -------------------- | -------------------------------------------------------- | ---------- |
353
+ | **E2** | Prova deterministica | Il difetto è presente nel codice così come è scritto | Piena |
354
+ | **E1** | Evidenza da pattern | Ha corrisposto un pattern strettamente legato al difetto | Metà |
355
+ | **E0** | Osservazione | Utile da sapere. Non afferma che qualcosa sia sbagliato. | Zero |
356
+
357
+ La confidenza in un rilevamento non è la forza della prova. Una regola può essere certa di aver trovato ciò che cercava e star comunque guardando un'euristica. I rilievi E1 servono per essere letti e valutati, mai applicati alla cieca, e questo limite è impresso sul rilievo nel terminale, nel JSON e nel passaggio all'agente.
358
+
359
+ **Fino a che punto è verificato — il livello di fiducia.** La maggior parte dei rilievi nasce dalla lettura del tuo codice. Dai a Mjölnir il report di un'esecuzione reale dei test e potrà confermare che il codice è stato davvero eseguito.
326
360
 
327
361
  <p align="center">
328
- <img src="assets/readme/terminal-hero.svg" alt="Output terminale di Mjölnir — WORTHINESS 75/100 NEEDS WORK, un dettaglio delle diagnosti per categoria e una lista FIX THIS FIRST" width="820" />
362
+ <img src="assets/readme/trust-ladder.svg" alt="La scala di fiducia da L0 a L5. Da L0 a L2 derivano dalla lettura del codice; da L3 a L5 richiedono il report di un'esecuzione reale, segnato da un'interruzione nella scala." width="100%" />
329
363
  </p>
330
364
 
331
- <sub>Rigenerato con `npm run docs:hero`;
332
- [`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
333
- fa fallire la CI se deriva da ciò che il reporter stampa davvero.</sub>
365
+ | Livello | In parole semplici | Cosa serve |
366
+ | ------- | ------------------------ | ----------------------------------------------------------------------- |
367
+ | **L0** | Annotato | Leggere il codice |
368
+ | **L1** | Sembra il problema | Leggere il codice: un pattern ha corrisposto |
369
+ | **L2** | Dimostrato nel codice | Leggere il codice: il difetto è strutturale |
370
+ | **L3** | Il file è stato eseguito | Un report di esecuzione mostra che il file del rilievo è stato eseguito |
371
+ | **L4** | Il test è stato eseguito | Un report di esecuzione mostra che il test del rilievo è stato eseguito |
372
+ | **L5** | L'esecuzione concorda | Il risultato stesso dell'esecuzione conferma la classe di difetto |
334
373
 
335
- Il punteggio è trasparente: **error −8, warning −3, info −1**, poi
336
- normalizzato per l'esposizione della suite (deduzioni per dichiarazione
337
- di test). Le deduzioni ponderate per evidenza significano che i segnali
338
- deboli costano meno. Il terminale mostra gli stessi numeri scontati che
339
- usa il punteggio — niente black box. Metodo completo:
340
- [docs/SCORING.md](docs/SCORING.md).
374
+ Una scansione statica si ferma a L2. Solo il report di un'esecuzione reale (Playwright JSON, Jest o Vitest JSON, JUnit XML) può portare un rilievo a L3 o oltre, così un rilievo che non è mai stato visto in esecuzione non può mai affermare di esserlo stato. Definizioni: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
341
375
 
342
- **Verdetti**
376
+ ### Quanto di tutto questo è misurato
343
377
 
344
- | Score | Verdetto |
345
- | ------- | ---------------- |
346
- | ≥ 80 | ✓ **WORTHY** |
347
- | 50 – 79 | ⚠ **NEEDS WORK** |
348
- | < 50 | ✖ **UNWORTHY** |
378
+ **74 regole su 79 hanno un tasso di falsi positivi misurato su codice OSS reale** (almeno 10 rilievi classificati a mano ciascuna; vedi [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Le altre 5 si basano sulla stima dell'autore e lo dicono, regola per regola, in `mjolnir explain`. `mjolnir rules --unmeasured` le elenca, e il piè di pagina di ogni scansione riporta quante delle regole effettivamente _scattate_ sono misurate.
349
379
 
350
- **Livelli di evidenza** — ogni riscontro ne porta uno; fissano il peso
351
- del riscontro nel punteggio:
380
+ I tassi restano pubblici anche quando sono cattivi. QA-TEST-001 (un `.only` committato) va male nell'audit sui repository reali e per questo sta in quarantine. Il dato aggiornato di ogni regola, QA-PW-141 compresa, è nell'audit.
352
381
 
353
- | Livello | Significato | Impatto sul punteggio | Esempio |
354
- | ------- | ---------------------- | --------------------- | ------------------------------------------------------ |
355
- | E2 | Difetto deterministico | Deduzione piena | `.only` committato — dimostrabile strutturalmente |
356
- | E1 | Pattern euristico | Mezza deduzione | `sleep()` trovato via regex — segnale forte, non prova |
357
- | E0 | Osservazione | Zero (solo info) | Riportato ma non fa mai gate alla CI né deduce |
382
+ ### Livelli di fiducia delle regole
358
383
 
359
- La maggior parte delle regole è **E1**. Lo slogan «we prove it» si
360
- riferisce a questo sistema: i riscontri E2 sono prova strutturale; i
361
- riscontri E1 sono avvertimenti correttamente posizionati, non prove
362
- formali.
384
+ I livelli seguono il tasso di falsi positivi misurato, non un'opinione:
363
385
 
364
- Un repo vuoto ottiene `null`, mai un falso 100 — vedi
365
- [Modello di fiducia](#modello-di-fiducia).
386
+ | Livello | FP misurato | Comportamento |
387
+ | -------------- | --------------------------------- | ---------------------------------------------------- |
388
+ | **core** | ≤ 10% | Report predefinito, blocca |
389
+ | **extended** | ≤ 30% | Report predefinito, confidenza più bassa |
390
+ | **quarantine** | > 30% o esplicitamente dichiarato | Solo con `--strict`, limitato a info, non blocca mai |
391
+ | _non misurata_ | n < 10 | Non può essere promossa a core finché non è misurata |
366
392
 
367
- ---
393
+ Le fasce di FP possono solo retrocedere un livello — non promuovono mai una regola fuori da `quarantine` se è stata esplicitamente dichiarata lì. Una regla esplicitamente messa in quarantine rimane in quarantine indipendentemente dal suo tasso di FP misurato.
368
394
 
369
- ## 🎭 Selector Health Score
395
+ Promozione, retrocessione e maturità per linguaggio: [ciclo di vita delle regole](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
370
396
 
371
- La metrica di testa per le suite Playwright — quanto sono resilienti
372
- i tuoi locator:
397
+ ### Perché non è un linter
373
398
 
374
- ```text
375
- ▚ SELECTOR HEALTH — e2e/checkout.spec.ts
399
+ I linter ti dicono se il codice segue delle regole. Mjölnir ti dice se della tua verifica ci si può fidare.
376
400
 
377
- [█████████████████░░░] 83 / 100
378
- role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
379
- ```
401
+ | | Linter (ESLint, SonarQube) | Strumenti di copertura | Code review con IA | **Mjölnir** |
402
+ | ------------------------------------------------------------- | :------------------------: | :--------------------: | :----------------: | :---------------: |
403
+ | Valuta il **sistema di verifica**, non il codice del prodotto | No | No | No | Sì |
404
+ | Integrità dei workflow CI (`continue-on-error`, `\|\| true`) | No | No | solo il diff | Sì |
405
+ | Valuta la resilienza dei locator Playwright (Selector Health) | No | No | No | Sì |
406
+ | Legge dati di esecuzione reali per i verdetti `TRUE-FLAKE` | No | No | No | Sì |
407
+ | Pubblica un tasso di falsi positivi misurato per regola | No | No | No | Sì |
408
+ | Segnala i test senza asserzioni | Sì\* | No | a volte | Sì |
409
+ | Rileva gli sleep fissi (`waitForTimeout`, `time.sleep`) | Sì\* | No | a volte | Sì |
410
+ | Deterministico (stesso input, stesso output) | Sì | Sì | No | Sì |
411
+ | Costo per scansione | gratuito | gratuito | token | **zero** (locale) |
412
+
413
+ <sub>\*Coperto da `eslint-plugin-jest` e `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) e dalle regole sulle asserzioni di SonarQube. Le colonne descrivono il comportamento predefinito per la verifica delle suite di test; plugin, piani a pagamento e regole personalizzate cambiano alcune risposte. È un riepilogo di posizionamento, non un benchmark.</sub>
380
414
 
381
- I locator basati sui ruoli prendono il punteggio pieno. Le catene di
382
- classi CSS e XPath affossano il punteggio — si rompono a ogni refactor
383
- del DOM senza dirti quale comportamento è regredito.
415
+ Usa anche la review con IA. Coglie sfumature, intenzioni e difetti di progettazione che nessun pattern può trovare. Mjölnir coglie ciò che la review con IA trascura perché sembra intenzionale: un `.only` committato, un codice di uscita ingoiato, un `continue-on-error` su un job di test. Per questi serve una scansione, non un ragionamento.
384
416
 
385
- ---
417
+ <br />
386
418
 
387
- ## 🔬 Evidenza di runtime
419
+ ## Analisi forense del runtime
388
420
 
389
- La rilevazione statica di instabilità è tirare a indovinare. Mjölnir
390
- legge **veri dati di esecuzione** — report JSON Playwright e XML JUnit
391
- da qualsiasi runner:
421
+ L'analisi statica ragiona su codice che non è mai stato eseguito. L'analisi forense legge ciò che è successo davvero: Playwright JSON, Jest JSON, Vitest JSON e JUnit XML da qualsiasi runner.
392
422
 
393
423
  ```bash
394
424
  mjolnir forensics ./test-results/
395
425
  ```
396
426
 
397
427
  ```text
398
- ▚ FLAKINESS LEADERBOARD
428
+ ▍ FLAKINESS LEADERBOARD
399
429
 
400
430
  3 tests · 1 failed · 1 flaky · 1 retried
401
431
 
@@ -405,303 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
405
435
  ████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
406
436
  ```
407
437
 
408
- Un test che passa solo dal tentativo ≥ 2 non è un test che passa — è un
409
- test fortunato. Viene marcato `TRUE-FLAKE` a prescindere dalla spunta
410
- verde finale.
438
+ `TRUE-FLAKE` non significa che il test è stato ritentato. Significa che il test **ha fallito almeno un tentativo e poi è finito in verde**: un passaggio fortunato, segnalato qualunque cosa dica la spunta finale. `mjolnir triage` trasforma quello storico in una proposta di quarantena, e `mjolnir pw-report` riassume un'esecuzione. Sono proprio questi report di esecuzione a portare i rilievi ai livelli di fiducia L3 e superiori.
439
+
440
+ <br />
441
+
442
+ ## Integrità della CI
411
443
 
412
- ---
444
+ Un test può passare mentre la pipeline intorno a lui non può fallire. Mjölnir legge anche i workflow: `continue-on-error`, `|| true`, codici di uscita che non vengono mai propagati, step sempre riusciti, report consumati ma mai generati e gate saltati proprio negli eventi che dovrebbero bloccare. Ogni rilievo indica il job, lo step e la riga, e porta il proprio livello di evidenza.
413
445
 
414
- ## ⚡ Mjölnir non è un linter in più
446
+ Genera il workflow per le PR, consultivo per impostazione predefinita:
447
+
448
+ ```bash
449
+ mjolnir ci install
450
+ ```
415
451
 
416
- I linter ti dicono se il codice segue le regole. Mjölnir ti dice se la
417
- tua verifica può essere ritenuta affidabile.
452
+ Oppure aggiungi l'action del Marketplace a un workflow che hai già:
418
453
 
419
- | | ESLint / SonarQube | Strumenti di coverage | Review manuale | **Mjölnir** |
420
- | ------------------------------------------------------------- | :----------------: | :-------------------: | :------------: | :---------: |
421
- | Integrità dei workflow CI (`continue-on-error`, `\|\| true`) | ❌ | ❌ | raramente | ✅ |
422
- | Cross-linguaggio (TS, Python, Java, C#) da un solo strumento | ❌ | ❌ | ❌ | ✅ |
423
- | Valuta la resilienza dei locator Playwright (Selector Health) | ❌ | ❌ | raramente | ✅ |
424
- | Segnala test senza vere asserzioni | ✅ (plugin)\* | ❌ | a volte | ✅ |
425
- | Becca gli sleep hardcoded (`waitForTimeout`, `time.sleep`) | ✅ (plugin)\* | ❌ | a volte | ✅ |
426
- | Gira in secondi, zero chiamate di rete durante la scansione | ✅ | ✅ | — | ✅ |
454
+ ```yaml
455
+ - uses: Sergey-Bar/Mjolnir@v1
456
+ with:
457
+ scope: changed
458
+ fail-on: error
459
+ ```
460
+
461
+ Fissa `@v1` per seguire la linea maggiore, oppure un tag esatto (`@v0.5.32`) per un gate riproducibile. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) copre il Marketplace, Smithery e i registri MCP.
462
+
463
+ Per portare i rilievi in GitHub Code Scanning, carica il SARIF (richiede `security-events: write` a livello di workflow o job):
464
+
465
+ ```yaml
466
+ - run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
467
+ continue-on-error: true
468
+ - uses: github/codeql-action/upload-sarif@v3
469
+ if: ${{ !cancelled() }}
470
+ with:
471
+ sarif_file: mjolnir.sarif
472
+ ```
427
473
 
428
- \*`eslint-plugin-jest` (`expect-expect`) e `eslint-plugin-playwright`
429
- (`expect-expect`, `no-wait-for-timeout`) coprono questo per i rispettivi
430
- framework.
474
+ Su GitLab, `--format codequality` scrive il report Code Quality che leggono il widget della MR e le annotazioni del diff ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Configurazione dell'editor e della pipeline: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
431
475
 
432
- **L'analisi di runtime** è una categoria a sé rispetto al linting
433
- statico:
476
+ ### Attribuzione sull'ambito modificato
434
477
 
435
- | | Playwright retry reporter | Allure / ReportPortal | **Mjölnir forensics** |
436
- | -------------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
437
- | Legge dati di run reali per verdetti `TRUE-FLAKE` | parziale\* | parziale (tag) | ✅ |
438
- | Report di triage dell'instabilità dalla cronologia | ❌ | ✅ | ✅ |
439
- | Si integra con il punteggio di idoneità statico | ❌ | ❌ | ✅ |
478
+ ```bash
479
+ npx mjolnir-qa@latest --scope changed
480
+ ```
440
481
 
441
- \*Playwright traccia i retry internamente ma non produce un report di
442
- instabilità autonomo con etichette di verdetto.
482
+ I rilievi vengono attribuiti alle righe aggiunte dal tuo branch, misurate rispetto alla **merge-base**. L'ambito è lo stesso insieme di file che scopre una scansione completa (spec TS/JS e configurazioni degli adapter, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), più le modifiche non committate e non tracciate, quindi funziona anche prima del commit. La base viene risolta come `main → master → origin/main → origin/master → origin/HEAD`; puoi sovrascriverla con `--base <ref>`.
443
483
 
444
- ---
484
+ Quando la merge-base non può essere risolta (un clone superficiale, un HEAD staccato, un target fuori da git), i rilievi ripiegano sull'attribuzione all'intero file **e il report lo dice.** Un ripiego silenzioso sarebbe proprio il tipo di difetto che questo strumento esiste per scovare.
445
485
 
446
- ## 🤖 Perché non usare semplicemente la code review con IA?
486
+ <br />
447
487
 
448
- Problema diverso, livello diverso. Una review IA può beccare una
449
- modifica sospetta a un test in un diff; non dimostra che il sistema di
450
- verifica nel suo insieme sia affidabile — e vede solo il diff che gli
451
- mostri.
488
+ ## Agenti IA
452
489
 
453
- | | Code review IA (Copilot, ecc.) | **Mjölnir** |
454
- | --------------------------------------------- | :--------------------------------------: | :-------------------------------------: |
455
- | Costo per scansione | Token (scala con la dimensione del diff) | **Zero** (locale, installato) |
456
- | Vede tutta la suite + tutte le config CI | Solo il diff di PR che mostri | **Tutto, ogni volta** |
457
- | Deterministico (stesso input → stesso output) | ❌ (non deterministico) | **✅** |
458
- | Becca pattern dormienti da mesi | Solo se è nel contesto | **✅** (scansiona tutti i file) |
459
- | Ricorda i riscontri tra le esecuzioni | ❌ (nessuna memoria tra sessioni) | **✅** (baseline + diff) |
460
- | Gira senza innesco umano | Serve una PR o un prompt | **✅** (hook CI, gira in pochi secondi) |
490
+ I rilievi valgono qualcosa solo se qualcosa agisce su di essi.
461
491
 
462
- **Usali entrambi.** L'IA becca la sfumatura, l'intento e i difetti di
463
- design che nessuna regex trova. Mjölnir becca i pattern strutturali che
464
- l'IA trascura perché sembrano "intenzionali" — un `.only` committato,
465
- un exit code ingoiato, un `continue-on-error` su un job di test. Non
466
- sono bug che richiedono ragionamento; sono fatti che richiedono
467
- scansione.
492
+ ```text
493
+ SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
494
+ ```
468
495
 
469
- ---
496
+ **L'IA scrive la correzione. Mjölnir la verifica.** La prova viene dalla nuova scansione, mai dal resoconto di successo dell'agente stesso.
470
497
 
471
- ## 🤖 Integrazione CI
498
+ | Comando | Cosa riceve l'agente |
499
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
500
+ | `mjolnir mcp` | Un server [MCP](https://modelcontextprotocol.io) su stdio. `scan`, `explain` e `diff` diventano strumenti invocabili. |
501
+ | `mjolnir handoff` | Un report `--json` salvato diventa un piano Markdown deterministico: cosa è stato rilevato, il limite di evidenza per ogni rilievo, cosa **non** deve cambiare, come verificare. |
502
+ | `mjolnir install` | Scrive nelle superfici per agenti che il tuo repo ha già (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`) così l'agente riesegue la scansione prima di dichiarare di aver finito. |
472
503
 
473
- Un comando genera un workflow di PR — consultivo per impostazione
474
- predefinita, mai bloccante:
504
+ Aggiungilo a un client che ha una propria CLI:
475
505
 
476
506
  ```bash
477
- mjolnir ci install
507
+ claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
478
508
  ```
479
509
 
480
- Oppure collegalo nativamente a GitHub Code Scanning via SARIF:
510
+ Oppure a qualsiasi client che accetti un blocco `mcpServers`:
481
511
 
482
- ```yaml
483
- - run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
484
- - uses: github/codeql-action/upload-sarif@v3
485
- with:
486
- sarif_file: mjolnir.sarif
512
+ ```json
513
+ {
514
+ "mcpServers": {
515
+ "mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
516
+ }
517
+ }
487
518
  ```
488
519
 
489
- Setup per editor e pipeline per SARIF:
490
- [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
520
+ **Il guardrail conta più della comodità.** Ogni rilievo in un passaggio porta il suo limite. **E2** dice _deterministico: controlla la posizione e applica la correzione_. **E1** dice _RICHIEDE CONFERMA: l'osservazione da sola non dimostra il difetto_. Un agente che corregge un E1 alla cieca, sopprime una regola o modifica una regola per alzare il punteggio sta facendo esattamente ciò che questo strumento esiste per scovare, quindi il passaggio lo dice nel prompt, accanto al rilievo.
491
521
 
492
- ### Copertura del perimetro modificato
522
+ <br />
493
523
 
494
- `--scope changed` attribuisce i riscontri alle righe aggiunte nel tuo
495
- branch rispetto al merge-base con `main`. Copre i file di test
496
- (`*.spec.*`, `*.test.*`) più i file di workflow GitHub e le
497
- configurazioni Playwright nel diff. Quando il merge-base non si può
498
- risolvere — clone shallow, HEAD detached, target non git, branch
499
- predefinito diverso — degrada onestamente: i riscontri tornano a
500
- un'attribuzione per intero file e il report lo dice. Sovrascrivi la ref
501
- di base con `--base <ref>`.
524
+ ## Fiducia e sicurezza
502
525
 
503
- ---
526
+ **Local-first, zero telemetria.** Nessuna API con accesso alla rete (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) esiste da nessuna parte in `src/`, e [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) fa fallire la build se ne compare una. Vieta anche `eval` e `new Function`. Scansionare codice non attendibile non lo esegue mai: l'analisi statica legge il testo sorgente e l'analisi forense interpreta file di report che esistono già su disco.
504
527
 
505
- ## Configurazione
528
+ Due avvertenze: `npx` stesso scarica il pacchetto prima che qualsiasi cosa venga eseguita, e la garanzia copre `src/`, non i plugin di terze parti.
506
529
 
507
- Mjölnir è zero-config. Un `mjolnir.config.json` opzionale (o
508
- `.mjolnir.json`) alla radice del repo regola severità, gating e
509
- perimetro — non cambia mai la semantica di rilevamento.
530
+ **I plugin non sono in sandbox.** I plugin JS (`mjolnir-rules/*.mjs`, o i pacchetti npm elencati sotto `"plugins"`) girano con tutti i privilegi di Node, lo stesso modello di fiducia dei plugin di ESLint o Vitest. Caricarli è una scelta esplicita **per scansione**: senza `--enable-plugins` (o `MJOLNIR_ENABLE_PLUGINS=1`) i loro sorgenti non vengono mai caricati, e un avviso su stderr elenca cosa è stato saltato. I manifesti di regole JSON non eseguono codice, e i prefissi degli ID delle regole core sono riservati, così nessun plugin può spacciarsi per una di esse. Segnala le vulnerabilità tramite [SECURITY.md](SECURITY.md).
510
531
 
511
- | Key | Tipo | Effetto |
512
- | ------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
513
- | `exclude` | `string[]` | Glob di ignore aggiuntivi (sottoinsieme gitignore), sopra i default integrati |
514
- | `gate` | `"advisory" \| "error" \| "warning"` | Quali severità escono con codice diverso da zero (predefinito `error`; `advisory` non blocca mai) |
515
- | `severityOverrides` | `{ "<RULE-ID>": severity }` | Riordina i riscontri di una regola per il tuo repo |
516
- | `ignore` | `IgnoreEntry[]` | Sopprime riscontri — **`reason` è obbligatorio**; le voci scadono dopo 90 giorni (una data `expires` esplicita, o la data di modifica del file di config per le voci senza) |
517
- | `plugins` | `string[]` | Pacchetti di regole di terze parti (vedi [Modello di fiducia](#modello-di-fiducia)) |
532
+ **Gira su se stesso.** Un motore di fiducia della verifica non ha credibilità se non è esso stesso verificabile. Ogni esecuzione della CI scansiona questo repository con la build prodotta da quella stessa esecuzione. Il gate fallisce su qualsiasi rilievo di gravità error, e anche su una scansione **parziale** o su una **regola andata in crash**, perché un'autoscansione troncata che non riporta nulla è proprio il falso verde che questo progetto esiste per scovare. `mjolnir doctor` ri-verifica la base di regole nella stessa esecuzione (firewall delle fixture, onestà dei livelli, tetto del livello core), e un controllo INCONCLUSIVE fallisce esattamente come uno fallito. Entrambi i report vengono caricati come artefatti della build.
518
533
 
519
- ```json
520
- {
521
- "gate": "error",
522
- "exclude": ["legacy/**"],
523
- "severityOverrides": { "QA-PW-141": "warning" },
524
- "ignore": [
525
- {
526
- "ruleId": "QA-TEST-004",
527
- "files": ["e2e/legacy-login.spec.ts"],
528
- "reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
529
- "expires": "2026-12-31"
530
- }
531
- ]
532
- }
533
- ```
534
+ ### Codici di uscita e contratto macchina
534
535
 
535
- - **`.mjolnirignore`** — un file semplice in stile gitignore per le
536
- esclusioni di percorsi, stesso dialetto di `exclude`. Usalo per il
537
- rumore specifico della macchina; usa `exclude` quando la lista
538
- appartiene al version control, accanto al resto della configurazione.
539
- - **Override CLI** — `--strict` (includere le regole in quarantena),
540
- `--width <cols>` e `--ascii` / `--no-ascii` (rendering terminale),
541
- `--tone blunt` (messaggi più secchi), `--max-duration <sec>` (scansione
542
- parziale limitata).
543
- - Soppressione delle regole e ciclo di vita delle deprecazioni:
544
- [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
545
-
546
- Le voci `ignore` alimentano anche il comando autonomo
547
- `mjolnir suppressions`, che elenca ciò che è attualmente soppresso e
548
- quando scade ogni voce.
549
-
550
- ---
551
-
552
- ## 📐 Exit code & contratti
553
-
554
- Congelati — sicuri su cui costruire logica CI:
555
-
556
- | Exit code | Significato |
557
- | --------- | -------------------------------------------------------------------------------- |
558
- | `0` | Pulito — nessun riscontro a o sopra il gate |
559
- | `1` | Riscontri a o sopra il gate |
560
- | `2` | Scansione parziale (budget di tempo esaurito, file illeggibili) — non blocca mai |
561
- | `10` | Errore d'uso (flag errato, target mancante) |
562
- | `20` | Errore interno |
563
-
564
- Il report JSON/SARIF è `schemaVersion: 1`. Gli ID di regola
565
- (`QA-<FAMILY>-NNN`) sono immutabili una volta pubblicati e mai
566
- riusati.
567
-
568
- ---
569
-
570
- ## Modello di fiducia
571
-
572
- - **Local-first** — zero chiamate di rete durante la scansione. Mai.
573
- Zero telemetria.
574
- - **Nessuna prova falsa** — preferiamo dire "sconosciuto" che
575
- "verificato". Un repo vuoto riceve `score: null`, mai un falso 100.
576
- - **Onestà parziale** — se l'analisi è stata troncata, l'output lo dice.
577
- Mai "complete" quando non lo è.
578
- - **Firewall FP** — il rilevamento gira su una vista del codice senza
579
- commenti/stringhe (le regole TypeScript usano l'AST del compilatore):
580
- un pattern dentro un commento di prosa o una stringa di esempio di
581
- documentazione è documentazione, non un riscontro.
582
- - **Misurato, non affermato** — solo le regole con un tasso di falsi
583
- positivi da vero codice OSS escono nei tier di testa (vedi
584
- [Quanto è misurato](#quanto-è-misurato)); il footer della scansione e
585
- `mjolnir rules --unmeasured` ti dicono quale è quale.
586
- - **Fiducia nei plugin e cancelletto di esecuzione** — i plugin sono
587
- pacchetti npm dichiarati sotto
588
- `"plugins"`; i moduli JS vivono in `mjolnir-rules/*.mjs`.
589
- **Non c'è sandbox**: il codice del plugin gira con tutti
590
- i privilegi Node, lo stesso modello di fiducia dei plugin ESLint o
591
- Vitest. Per questo, l'esecuzione di codice è **opt-in a ogni
592
- scansione**: passa `--enable-plugins` (o imposta
593
- `MJOLNIR_ENABLE_PLUGINS=1`), altrimenti le sorgenti NON vengono
594
- caricate — un avviso chiassoso su stderr elenca esattamente cosa è
595
- stato saltato. Scansionare codice non affidabile non lo esegue mai.
596
- I manifest di regole JSON (`mjolnir-rules/*.json`) non sono toccati:
597
- dichiarano pattern regex e per progetto non eseguono codice.
598
- I prefissi di ID delle regole core sono riservati e rifiutati
599
- da plugin e regole esterne per evitare spoofing.
600
- - **Regole esterne locali al workspace** (basate su cartella, zero
601
- rete) — una directory `mjolnir-rules/` accanto al target della
602
- scansione carica regole personalizzate: i file JSON dichiarano
603
- pattern regex (nessun codice eseguito), i moduli `.mjs`/`.js`
604
- esportano `rules` (fiducia Node piena, come i plugin). Le regole
605
- esterne portano gli stessi metadati di fiducia del core; non possono
606
- mai uscire nel tier core (core richiede un tasso di FP misurato dal
607
- sidecar corpus — un `tier: "core"` dichiarato viene limitato a
608
- `extended`), obbediscono ai tetti di tier e sono controllate contro
609
- la deriva: `mjolnir rules --md --external` renderizza il catalogo dai
610
- file caricati (provenienza `external`), e il generatore di matrice
611
- accetta `--external <root>`.
612
-
613
- ---
614
-
615
- ## 🏗️ Architettura
536
+ Congelati, così puoi costruirci sopra la logica della CI:
616
537
 
617
- <details>
618
- <summary>Espandi l'albero</summary>
538
+ | Codice di uscita | Significato |
539
+ | ---------------- | -------------------------------------------------------------------------------- |
540
+ | `0` | Pulito: nessun rilievo al livello del gate o sopra |
541
+ | `1` | Rilievi al livello del gate o sopra |
542
+ | `2` | Scansione parziale (budget di tempo esaurito, file illeggibili). Non blocca mai. |
543
+ | `10` | Errore d'uso (flag errato, target mancante) |
544
+ | `20` | Errore interno |
619
545
 
620
- ```
621
- mjolnir/
622
- ├── src/
623
- │ ├── engine/ # LanguageAdapter interface + rule runner
624
- │ ├── adapters/ # typescript · python · java · csharp · github-actions
625
- │ ├── rules/ # rules across 8 families + the measured-FP table
626
- │ ├── playwright/ # Selector Health Score engine
627
- │ ├── discovery/ # workspace, frameworks, ignore resolution
628
- │ ├── scope/ # git merge-base changed-scope engine
629
- │ ├── scorer/ # transparent deduction table + prioritization
630
- │ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
631
- │ ├── forensics/ # run-data ingestion · flake verdicts · triage
632
- │ ├── config/ # mjolnir.config.json + suppressions
633
- │ ├── plugins/ # third-party rule loading (no sandbox)
634
- │ └── commands/ # every subcommand
635
- └── tests/
636
- ├── fixtures/ # must-fire / must-not-fire per rule
637
- └── golden/ # frozen score regression locks
638
- ```
546
+ `2` è volutamente diverso da `0`: una scansione che non è finita non ha trovato «niente». Semplicemente non ha finito di cercare.
639
547
 
640
- </details>
548
+ Tutto ciò che una macchina consuma (risultati degli strumenti MCP, `--json`, SARIF 2.1) proviene da un unico risultato canonico sotto uno schema versionato e **solo additivo** (`schemaVersion: 1`, `contractVersion: 1`), così nessun consumatore deve ricostruire il significato dal testo renderizzato. Vedi [il contratto macchina](docs/machine-contract.md). Gli ID delle regole (`QA-<FAMILY>-NNN`) sono immutabili una volta rilasciati e non vengono mai riutilizzati.
641
549
 
642
- - **Le regole sono funzioni pure** —
643
- `(SourceFileContext) → Finding[]`, niente I/O, niente globali.
644
- Aggiungere un ecosistema = un adattatore + le sue regole.
645
- - **TypeScript/Playwright usa l'AST del compilatore** (ts-morph).
646
- Python, Java e C# girano su un livello regex condiviso con
647
- commenti/stringhe mascherati.
648
- - Un livello AST tree-sitter WASM per Java e C# esiste ed è il
649
- prossimo passo di precisione — non è ancora cablato nella pipeline
650
- di scansione sincrona.
550
+ <br />
651
551
 
652
- ---
552
+ ## Cosa Mjölnir non può dirti
653
553
 
654
- ## 📚 Documentazione
554
+ - **Non esegue i tuoi test.** Una scansione pulita non è una suite che passa.
555
+ - **Non può dirti che un'asserzione è _sbagliata_.** `expect(total).toBe(41)` sembra sana. Mjölnir trova i test che _non possono fallire_ e le pipeline che _non possono diventare rosse_, non i test che verificano la cosa sbagliata.
556
+ - **Non dimostra la correttezza di business.** Niente qui dice che il tuo prodotto fa ciò che il requisito chiedeva.
557
+ - **Un 100 non è la prova di una buona suite.** Se la tua suite copre il tuo rischio reale è un'altra domanda, e questo strumento non vi risponde.
558
+ - **5 regole su 79 si basano su una stima**, non su un tasso misurato. Ognuna lo dice sul proprio rilievo.
559
+ - **E1 non è E2.** I rilievi euristici meritano di essere letti, non di essere applicati alla cieca.
560
+ - **Un repo vuoto ottiene `null`, mai 100.**
561
+ - **Un file chiamato `*.spec.ts` senza dichiarazioni di test non conta come copertura.** Un repo i cui unici file spec contengono import o tipi (zero chiamate `it`/`test`) ottiene `null`, non 100.
655
562
 
656
- | Documento | Cosa contiene |
657
- | ------------------------------------------------------ | ---------------------------------------------------------- |
658
- | [docs/SCORING.md](docs/SCORING.md) | Normalizzazione del punteggio + ponderazione dell'evidenza |
659
- | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Tassi di falsi positivi misurati + metodo |
660
- | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Stati delle regole, soppressione, deprecazione |
661
- | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Output SARIF + setup editor/CI |
662
- | [docs/rules/](docs/rules/) | Catalogo generato per regola |
663
- | [CONTRIBUTING.md](CONTRIBUTING.md) | Setup dev + workflow di contribuzione |
664
- | [CHANGELOG.md](CHANGELOG.md) | Cronologia delle release |
665
- | [SECURITY.md](SECURITY.md) | Segnalazione vulnerabilità |
563
+ <br />
666
564
 
667
- ---
565
+ ## Documentazione
668
566
 
669
- ## 📈 Stato
567
+ Il sito completo della documentazione è su <https://sergey-bar.github.io/Mjolnir/>.
670
568
 
671
- **v0.5.x · beta aperta.** Lo schema JSON e gli exit code sono contratti
672
- congelati. TypeScript e Python hanno la copertura misurata più ampia;
673
- Java e C# sono più recenti — leggili attraverso la
674
- [tabella dei tier](#tier-delle-regole-e-maturità-per-linguaggio).
569
+ | Documento | Cosa contiene |
570
+ | ------------------------------------------------------ | ----------------------------------------------------------- |
571
+ | [docs/SCORING.md](docs/SCORING.md) | Normalizzazione del punteggio e ponderazione delle evidenze |
572
+ | [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Vocabolario canonico: una parola per concetto |
573
+ | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Tassi di falsi positivi misurati e il metodo |
574
+ | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Stati delle regole, livelli, soppressione, deprecazione |
575
+ | [docs/VERSIONING.md](docs/VERSIONING.md) | Politica semver, superfici congelate, ciclo di deprecazione |
576
+ | [docs/machine-contract.md](docs/machine-contract.md) | Il risultato canonico leggibile dalle macchine |
577
+ | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Output SARIF e configurazione dell'editor o della CI |
578
+ | [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: report Code Quality, ricetta per le MR, gate |
579
+ | [docs/rules/](docs/rules/) | Catalogo generato per regola |
580
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | Ambiente di sviluppo e flusso di contribuzione |
581
+ | [SUPPORT.md](SUPPORT.md) | Dove chiedere, segnalare e ottenere aiuto |
582
+ | [SECURITY.md](SECURITY.md) | Segnalazione delle vulnerabilità |
583
+ | [CHANGELOG.md](CHANGELOG.md) | Storico dei rilasci |
675
584
 
676
- ---
585
+ ### Stato
677
586
 
678
- ## 🤝 Contribuire
587
+ **Versione 1.** Lo schema JSON e i codici di uscita sono contratti congelati. TypeScript e Python hanno la copertura misurata più ampia. Java e C# sono più recenti; leggili attraverso la [tabella di maturità](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). Cosa viene dopo, senza date inventate: [la roadmap pubblica](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
679
588
 
680
- Le nuove regole sono il primo contributo più semplice — un comando
681
- imposta lo scheletro della regola più le sue fixture must-fire **e**
682
- must-not-fire (la regola generata fallisce apposta le fixture finché
683
- non implementi il rilevamento vero — uno stub non può uscire):
589
+ ### Contribuire
590
+
591
+ Le nuove regole sono il primo contributo più semplice. Un comando crea lo scheletro della regola con le sue fixture must-fire **e** must-not-fire. La regola generata fallisce di proposito le proprie fixture finché non viene scritto un vero rilevamento, perché uno stub rilasciato è una regola che nessuno ha misurato:
684
592
 
685
593
  ```bash
686
594
  mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
687
595
  ```
688
596
 
689
- Setup dev completo, i comandi della barriera permanente e le leggi
690
- anti-creep / firewall delle fixture sono in
691
- [CONTRIBUTING.md](CONTRIBUTING.md).
597
+ L'ambiente di sviluppo, i comandi dei gate permanenti e le leggi anti-creep e del firewall delle fixture si trovano in [CONTRIBUTING.md](CONTRIBUTING.md).
692
598
 
693
- ---
599
+ <br />
694
600
 
695
601
  <div align="center">
696
602
 
697
- **Smetti di pubblicare test di cui non ti puoi fidare.**
603
+ <img src="assets/readme/closing.svg" alt="Provalo sul tuo repo." width="100%" />
698
604
 
699
605
  ```bash
700
606
  npx mjolnir-qa@latest
701
607
  ```
702
608
 
703
- **Star ⭐ · Watch 👀 · Contribute 🤝**
609
+ [Leggi la guida](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Sito della documentazione](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
610
+
611
+ <br />
612
+
613
+ Non chiederti se i test sono passati.<br />
614
+ Chiediti se le evidenze dimostrano che meritano fiducia.
704
615
 
705
- Costruito da [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
616
+ <sub>Creato da [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Licenza MIT</sub>
706
617
 
707
618
  </div>