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/CHANGELOG.md +204 -0
- package/README.ar.md +434 -478
- package/README.bn.md +434 -491
- package/README.br.md +434 -520
- package/README.bs.md +431 -500
- package/README.da.md +433 -509
- package/README.de.md +432 -522
- package/README.es.md +428 -517
- package/README.fr.md +426 -520
- package/README.gr.md +433 -517
- package/README.he.md +433 -475
- package/README.it.md +436 -525
- package/README.ja.md +436 -506
- package/README.ko.md +434 -494
- package/README.md +453 -438
- package/README.no.md +435 -509
- package/README.pl.md +433 -511
- package/README.ru.md +434 -515
- package/README.th.md +434 -484
- package/README.tr.md +427 -504
- package/README.uk.md +433 -505
- package/README.vi.md +436 -494
- package/README.zh.md +433 -462
- package/README.zht.md +433 -462
- package/dist/cli.d.mts +716 -110
- package/dist/cli.mjs +9815 -22027
- package/dist/mcp/stdio.mjs +2164 -886
- package/dist/rolldown-runtime-8H4AJuhK.mjs +14 -0
- package/dist/scan-pipeline-C0ka-RmX.mjs +2 -0
- package/dist/scan-pipeline-D3Yk2cef.mjs +15309 -0
- package/package.json +14 -8
package/README.it.md
CHANGED
|
@@ -1,401 +1,431 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/readme/
|
|
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
|
-
|
|
5
|
+
<br />
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
12
|
-
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
13
|
-
[](LICENSE)
|
|
14
|
-
[](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
|
-
|
|
12
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
13
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
14
|
+
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
15
|
+
[](https://codecov.io/gh/Sergey-Bar/Mjolnir)
|
|
16
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
|
|
17
|
+
[](LICENSE)
|
|
18
|
+
[](https://nodejs.org)
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npx mjolnir-qa@latest
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
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
|
-
[
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
92
|
+
<br />
|
|
38
93
|
|
|
39
94
|
<p align="center">
|
|
40
|
-
<
|
|
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>
|
|
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
|
-
|
|
102
|
+
</details>
|
|
50
103
|
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
95
|
-
npx mjolnir-qa@latest
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
96
156
|
```
|
|
97
157
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
165
|
+
npx mjolnir-qa@latest
|
|
104
166
|
```
|
|
105
167
|
|
|
106
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
142
|
-
| `mjolnir
|
|
143
|
-
| `mjolnir
|
|
144
|
-
| `mjolnir
|
|
145
|
-
| `mjolnir
|
|
146
|
-
| `mjolnir
|
|
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
|
-
|
|
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
|
-
|
|
228
|
+
<br />
|
|
157
229
|
|
|
158
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
|
194
|
-
|
|
|
195
|
-
| QA-TEST-
|
|
196
|
-
| QA-TEST-
|
|
197
|
-
| QA-TEST-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
214
309
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
321
|
+
<br />
|
|
238
322
|
|
|
239
|
-
|
|
240
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
323
|
+
## Il punteggio di affidabilità
|
|
241
324
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
343
|
+
<br />
|
|
265
344
|
|
|
266
|
-
|
|
267
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
345
|
+
## Il modello di evidenza
|
|
268
346
|
|
|
269
|
-
|
|
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
|
-
|
|
349
|
+
**Quanto è sicuro — il livello di evidenza.**
|
|
278
350
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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/
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
|
|
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
|
-
|
|
376
|
+
### Quanto di tutto questo è misurato
|
|
343
377
|
|
|
344
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
365
|
-
|
|
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
|
-
|
|
395
|
+
Promozione, retrocessione e maturità per linguaggio: [ciclo di vita delle regole](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
370
396
|
|
|
371
|
-
|
|
372
|
-
i tuoi locator:
|
|
397
|
+
### Perché non è un linter
|
|
373
398
|
|
|
374
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
419
|
+
## Analisi forense del runtime
|
|
388
420
|
|
|
389
|
-
|
|
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
|
-
|
|
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
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
446
|
+
Genera il workflow per le PR, consultivo per impostazione predefinita:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
415
451
|
|
|
416
|
-
|
|
417
|
-
tua verifica può essere ritenuta affidabile.
|
|
452
|
+
Oppure aggiungi l'action del Marketplace a un workflow che hai già:
|
|
418
453
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
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
|
-
|
|
433
|
-
statico:
|
|
476
|
+
### Attribuzione sull'ambito modificato
|
|
434
477
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
-
|
|
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
|
-
|
|
486
|
+
<br />
|
|
447
487
|
|
|
448
|
-
|
|
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
|
-
|
|
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
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
-
|
|
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
|
-
|
|
474
|
-
predefinita, mai bloccante:
|
|
504
|
+
Aggiungilo a un client che ha una propria CLI:
|
|
475
505
|
|
|
476
506
|
```bash
|
|
477
|
-
mjolnir
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
478
508
|
```
|
|
479
509
|
|
|
480
|
-
Oppure
|
|
510
|
+
Oppure a qualsiasi client che accetti un blocco `mcpServers`:
|
|
481
511
|
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
512
|
+
```json
|
|
513
|
+
{
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
517
|
+
}
|
|
487
518
|
```
|
|
488
519
|
|
|
489
|
-
|
|
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
|
-
|
|
522
|
+
<br />
|
|
493
523
|
|
|
494
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
618
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
567
|
+
Il sito completo della documentazione è su <https://sergey-bar.github.io/Mjolnir/>.
|
|
670
568
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
[
|
|
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
|
-
|
|
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
|
-
|
|
681
|
-
|
|
682
|
-
must-not-fire
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
616
|
+
<sub>Creato da [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Licenza MIT</sub>
|
|
706
617
|
|
|
707
618
|
</div>
|