mjolnir-qa 4.0.0 → 6.0.0

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 DELETED
@@ -1,647 +0,0 @@
1
- <div align="center">
2
-
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
-
5
- <br />
6
-
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.
9
-
10
- <br />
11
-
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
-
20
- ```bash
21
- npx mjolnir-qa@3.0.0
22
- ```
23
-
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)
30
-
31
- > 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-26.
32
-
33
- <!-- Source hash: `de04dfb1677b` -->
34
-
35
- </details>
36
-
37
- </div>
38
-
39
- <br />
40
-
41
- ## Release status (English canonical)
42
-
43
- The published line is `3.0.0`; this working tree is the `4.0.0-rc.1`
44
- candidate. `3.0.0` must not be republished or retagged. The M26–M50 program is
45
- tracked in
46
- [`docs/ROADMAP.yaml`](docs/ROADMAP.yaml); provisional capability contracts
47
- are not automatically enabled or certified. Repository-owned checks pass, but
48
- Trust certification remains `NOT_CERTIFIED` until the protected holdout,
49
- real-world, platform/consumer, remote-workflow, support-matrix, and corpus
50
- evidence gates pass. Run `npm run m26:readiness` before treating any candidate
51
- as releasable. This document does not publish a tag or authorize a release.
52
-
53
- > Machine-assisted canonical text. Translate this block before treating it as localized copy.
54
-
55
- ## Una spunta verde è un'affermazione, non una prova
56
-
57
- 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:
58
-
59
- - un `.only` committato che ha eseguito 3 test invece di 900
60
- - `continue-on-error: true` sul job che doveva fare da gate
61
- - `|| true` dopo il comando dei test
62
- - un test che non verifica nulla, o con il corpo vuoto
63
- - un wrapper di retry che trasforma un vero fallimento in un passaggio fortunato
64
- - un report che il workflow carica ma che non è mai stato generato
65
- - uno sleep fisso che tiene insieme una race condition
66
-
67
- 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:
68
-
69
- <p align="center">
70
- <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" />
71
- </p>
72
-
73
- <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>
74
-
75
- **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@3.0.0` senza `--strict`) copre solo regole core ed extended. Aggiungi `--strict` quando vuoi anche il livello consultivo.
76
-
77
- 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:
78
-
79
- | Situazione | Cosa riporta Mjölnir |
80
- | -------------------------------------------------------- | ------------------------------------------------------------------ |
81
- | Nessuna dichiarazione di test trovata | Punteggio `null`, mostrato come **UNKNOWN**. Mai un 100 inventato. |
82
- | Nessuna baseline o revisione confrontabile | **UNKNOWN**, con il motivo indicato. Mai uno 0 presunto. |
83
- | Scansione interrotta (budget di tempo, file illeggibili) | **PARTIAL**, uscita `2`. Mai presentata come pulita. |
84
-
85
- <p align="center">
86
- <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" />
87
- </p>
88
-
89
- <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>
90
-
91
- <br />
92
-
93
- ## Guardalo all'opera
94
-
95
- 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:
96
-
97
- <p align="center">
98
- <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" />
99
- </p>
100
-
101
- <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>
102
-
103
- <details>
104
- <summary><strong>Guardalo</strong> — una scansione, la correzione che stampa e la nuova scansione che la dimostra</summary>
105
-
106
- <br />
107
-
108
- <p align="center">
109
- <a href="assets/video/mjolnir-demo.mp4">
110
- <img src="assets/video/mjolnir-demo-poster.png" alt="Un fotogramma della registrazione demo: npx mjolnir-qa@3.0.0 che scansiona il repository demo in una finestra di terminale" width="900" />
111
- </a>
112
- </p>
113
-
114
- <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>
115
-
116
- </details>
117
-
118
- ### Un rilievo, da vicino
119
-
120
- Ogni rilievo risponde a quattro domande: dove si trova, quanto è sicuro Mjölnir, quanto spesso la regola sbaglia e come correggerlo.
121
-
122
- <p align="center">
123
- <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%" />
124
- </p>
125
-
126
- `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:
127
-
128
- ```text
129
- ▍ QA-CI-001 — continue-on-error masks a failing verification gate
130
-
131
- Severity: error
132
- Confidence: high
133
- Tier: quarantine
134
- Evidence: E2
135
- QA impact: False-green risk (FALSE-GREEN)
136
- Measured FP: 11% (19 hand-classified corpus verdicts)
137
- FP risk: low (author estimate)
138
- Languages: yaml
139
- Frameworks: github-actions, azure-pipelines
140
-
141
- WHAT WAS FOUND (real detector output, not a mockup)
142
- Job `security-scan` runs a verification gate under `continue-on-error: true`.
143
-
144
- WHY IT MATTERS
145
- This job can fail every day and CI will still show green. The checkmark on
146
- this workflow cannot be trusted.
147
-
148
- HOW TO FIX
149
- Remove continue-on-error, or scope it to individual non-blocking steps only.
150
-
151
- Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
152
-
153
- WHAT WOULD CHANGE THE VERDICT
154
- - a run report next to the scan target (mjolnir.report.json or test-results/)
155
- corroborating this file lifts its findings to L3–L5
156
- - a documented suppression (mjolnir.config.json) lowers the finding count
157
- without claiming correctness
158
- - quarantine findings run only under --strict and are advisory (E0) — they can
159
- never gate CI
160
-
161
- NEXT ACTION
162
- Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
163
- occurrence of this rule is listed in the scan output.
164
-
165
- HOW TO VERIFY THE FIX
166
- Re-run `mjolnir` on the changed file(s) — this finding should no longer
167
- appear. `mjolnir --scope changed` scopes the check to just what you touched.
168
-
169
- Docs: mjolnir rules --md (full catalog, this rule included)
170
- ```
171
-
172
- Questa è l'unità di valore: un punto in cui la CI riporta un successo che non si è guadagnata.
173
-
174
- <br />
175
-
176
- ## Avvio rapido
177
-
178
- ```bash
179
- npx mjolnir-qa@3.0.0
180
- ```
181
-
182
- 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.
183
-
184
- In CI, scansiona solo ciò che il branch ha introdotto, così una suite legacy non sommerge la tua prima pull request:
185
-
186
- ```bash
187
- npx mjolnir-qa@3.0.0 --scope changed
188
- ```
189
-
190
- `mjolnir ci install` lo scrive come workflow GitHub Actions, usando l'[action](https://github.com/Sergey-Bar/Mjolnir#readme) fissata al tag maggiore `v3` (o un semplice `npx` con `--no-action`). Resta consultivo finché non decidi che deve bloccare.
191
-
192
- | Comando | Cosa fa |
193
- | --------------------------------------------- | ---------------------------------------------------------------------- |
194
- | `mjolnir` | Trust Report: verdetto, confidenza, prossima azione |
195
- | `mjolnir --scope changed` | Solo ciò che il tuo branch ha introdotto (la forma per la CI) |
196
- | `mjolnir ci install` | Genera il workflow consultivo per le PR (basato sull'action) |
197
- | `mjolnir business-case` | ROI estimate: projected savings per finding |
198
- | `mjolnir release-report` | Release readiness: GO, CONDITIONAL GO, or NO-GO |
199
- | `mjolnir release-trust` | 12-dimension release assurance verdict |
200
- | `mjolnir report` | Generate a Playwright-compatible report |
201
- | `mjolnir trend` | Record, show, or diff local quality snapshots |
202
- | `mjolnir policy` | Initialize, validate, or check policy gates |
203
- | `mjolnir quarantine` | Review deterministic proposals (prototype) |
204
- | `mjolnir analyze --cross-file` | Bounded cross-file analysis |
205
- | `mjolnir ci-adapter github .` | Generate CI templates for supported providers |
206
- | `mjolnir dashboard` | Generate a self-contained quality dashboard |
207
- | `mjolnir exec-report` | Executive KPIs and recommendations (advisory) |
208
- | `mjolnir enterprise` | Self-hosted templates (prototype) |
209
- | `mjolnir maturity` | Assess maturity or display maturity levels |
210
- | `mjolnir mutation tests/mutation-report.json` | Analyze mutation reports; never promotes trust |
211
- | `mjolnir mcp` | Read-only MCP tools over stdio |
212
- | `mjolnir explain QA-CI-001` | Cosa, perché e correzione, più il tasso di FP misurato |
213
- | `mjolnir why src/a.spec.ts:42` | Perché proprio questa riga è stata segnalata. Non blocca mai. |
214
- | `mjolnir forensics ./test-results/` | Evidenze di runtime da un'esecuzione reale |
215
- | `mjolnir trust-report` | Trust Artifact autonomo (md + json) |
216
- | `mjolnir handoff` | Piano di correzione per un agente di coding |
217
- | `mjolnir --json` / `--format sarif` | Output leggibile dalle macchine, GitHub Code Scanning |
218
- | `mjolnir --format codequality` | Report GitLab Code Quality (artefatto del widget della MR) |
219
- | `mjolnir --strict` | Esegue anche le regole del livello quarantine (rischio di FP più alto) |
220
-
221
- <details>
222
- <summary><strong>Tutti gli altri comandi</strong> — triage dei test instabili, report, governance</summary>
223
-
224
- <br />
225
-
226
- | Comando | Cosa fa |
227
- | ----------------------------------- | --------------------------------------------------------------------------------------- |
228
- | `mjolnir --classic` | Il banner del punteggio di prima del Trust Report |
229
- | `mjolnir explain verdict` | Perché il verdetto della scansione salvata è quello che è |
230
- | `mjolnir triage ./test-results/` | Triage guidato. Ogni riga termina con una prossima azione. |
231
- | `mjolnir pw-report ./test-results/` | Riepilogo dell'esecuzione Playwright: retry, test instabili, i più lenti |
232
- | `mjolnir doctor:playwright` | Scansione approfondita solo Playwright più Selector Health Score |
233
- | `mjolnir fix --dry-run` / `fix` | Correzioni automatiche sicure, ognuna riscansionata per dimostrare che è andata a segno |
234
- | `mjolnir baseline` / `diff` | Fotografa i rilievi, poi riporta solo quelli nuovi o peggiorati |
235
- | `mjolnir impact --since <ref>` | Cosa ha introdotto e risolto un commit |
236
- | `mjolnir summary` | Annotazioni CI e un riepilogo dello step da un report |
237
- | `mjolnir pr-comment` | Un commento di PR mirato, in Markdown |
238
- | `mjolnir debt` | Registro del debito di test con un modello di costo |
239
- | `mjolnir handover` | Mappa di onboarding della suite per un nuovo ingegnere QA |
240
- | `mjolnir init` | Rileva i framework, stampa una checklist di configurazione |
241
- | `mjolnir suppressions` | Elenca i rilievi soppressi, per la governance |
242
- | `mjolnir rules --unmeasured` | Le regole che girano su un'ipotesi, non su una misura |
243
- | `mjolnir rules --md` | Catalogo completo delle regole (JSON o Markdown) |
244
- | `mjolnir doctor` | Autoverifica della base di regole di Mjölnir |
245
- | `mjolnir create-rule <ID>` | Crea lo scheletro di una nuova regola e delle sue fixture |
246
- | `mjolnir stats` | Contatori locali complessivi delle correzioni viste |
247
- | `mjolnir badge` | JSON dell'endpoint shields.io e snippet |
248
- | `mjolnir --cache` | Riscansioni incrementali tramite una cache locale dei verdetti |
249
- | `mjolnir --format mermaid` | Diagramma dell'architettura dei test per un commento di PR |
250
-
251
- `mjolnir help <command>` stampa uso, esempi e il passo successivo per ognuno di essi.
252
-
253
- </details>
254
-
255
- 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ù.
256
-
257
- <br />
258
-
259
- ## Cosa trova Mjölnir
260
-
261
- <p align="center">
262
- <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%" />
263
- </p>
264
-
265
- **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:
266
-
267
- | ID | Regola | Gravità | Livello |
268
- | ------------ | ------------------------------------------------------------------------- | ------- | ---------- |
269
- | QA-CI-001 | `continue-on-error` maschera un gate di verifica che fallisce | error | quarantine |
270
- | QA-CI-009 | Codice di uscita dei test non propagato (`\|` senza pipefail, catene `;`) | error | extended |
271
- | QA-TEST-001 | Test focalizzato committato (`.only`, `fit`) | error | quarantine |
272
- | QA-TEST-003 | Test senza asserzioni | error | quarantine |
273
- | QA-TQUAL-009 | Asserzione su promise senza await | error | quarantine |
274
- | QA-PW-002 | Asserzione su locator senza await | error | core |
275
- | QA-PW-004 | Selettori CSS/XPath fragili | warning | quarantine |
276
- | QA-PY-002 | Test saltato (`skip`, `xfail` non rigoroso) | warning | core |
277
- | QA-CS-103 | Metodo di test senza asserzioni | error | core |
278
-
279
- 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).
280
-
281
- <details>
282
- <summary><strong>Ogni regola citata in questo README</strong>, in un'unica tabella</summary>
283
-
284
- <br />
285
-
286
- > Le regole `quarantine` girano solo con `--strict` e non bloccano mai (sono limitate a info). La gravità mostrata è quella definita dall'autore.
287
-
288
- | ID | Famiglia | Regola | Gravità | Livello |
289
- | ------------ | ---------- | ---------------------------------------------------------------- | ------- | ---------- |
290
- | QA-TEST-001 | Igiene | Test focalizzato committato (`.only`, `fit`) | error | quarantine |
291
- | QA-TEST-002 | Igiene | Test saltato. Sale a `error` senza un motivo tracciato. | warning | quarantine |
292
- | QA-TEST-003 | Igiene | Test senza asserzioni | error | quarantine |
293
- | QA-TEST-004 | Igiene | Sleep fisso (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
294
- | QA-TEST-006 | Igiene | Abuso dei retry che nasconde l'instabilità | warning | quarantine |
295
- | QA-TEST-010 | Igiene | Corpo del test vuoto | error | quarantine |
296
- | QA-TQUAL-002 | Qualità | Asserzione tautologica | error | quarantine |
297
- | QA-TQUAL-009 | Qualità | Asserzione su promise senza await | error | quarantine |
298
- | QA-TQUAL-011 | Qualità | Test commentati | warning | extended |
299
- | QA-PW-002 | Playwright | Asserzione su locator senza await | error | core |
300
- | QA-PW-003 | Playwright | `page.pause()` / `test.only()` committato | error | core |
301
- | QA-PW-004 | Playwright | Selettori CSS/XPath fragili | warning | quarantine |
302
- | QA-PW-123 | Playwright | URL di ambiente scritti nel codice | warning | quarantine |
303
- | QA-PW-140 | Playwright | Screenshot senza `maxDiffPixelRatio` | warning | core |
304
- | QA-CI-001 | CI | `continue-on-error` maschera un gate che fallisce | error | quarantine |
305
- | QA-CI-002 | CI | `\|\| true` ingoia i codici di uscita | error | extended |
306
- | QA-CI-005 | CI | Report consumato ma mai generato | error | quarantine |
307
- | QA-CI-007 | CI | Wrapper di retry attorno ai test | warning | extended |
308
- | QA-CI-008 | CI | Step sempre riuscito che maschera i fallimenti | error | quarantine |
309
- | QA-CI-009 | CI | Codice di uscita non propagato (`\|` senza pipefail, catene `;`) | error | extended |
310
- | QA-CI-010 | CI | Test saltati dove devono bloccare | error | quarantine |
311
- | QA-PY-002 | Python | Test saltato (`skip`, `xfail` non rigoroso) | warning | core |
312
- | QA-PY-003 | Python | Funzione di test senza asserzioni | error | quarantine |
313
- | QA-PY-005 | Python | `time.sleep()` nei test | warning | extended |
314
- | QA-PY-012 | Python | Asserzione tautologica | error | quarantine |
315
- | QA-JV-101 | Java | Test disabilitato (`@Disabled`) | warning | core |
316
- | QA-JV-102 | Java | Sleep fisso (`Thread.sleep()`) | warning | extended |
317
- | QA-JV-103 | Java | Metodo di test senza asserzioni | error | extended |
318
- | QA-JV-105 | Java | Sleep fisso con `waitForTimeout()` di Playwright | warning | core |
319
- | QA-JV-106 | Java | Selettore fragile invece di un locator per ruolo | warning | quarantine |
320
- | QA-CS-101 | C# | Test saltato (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
321
- | QA-CS-102 | C# | Sleep fisso (`Thread.Sleep` / `Task.Delay`) | warning | core |
322
- | QA-CS-103 | C# | Metodo di test senza asserzioni | error | core |
323
- | QA-CS-105 | C# | Sleep fisso con `WaitForTimeoutAsync()` | warning | extended |
324
- | QA-CS-106 | C# | Selettore fragile invece di un locator per ruolo | warning | quarantine |
325
-
326
- 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.
327
-
328
- </details>
329
-
330
- 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.
331
-
332
- ### Selector Health Score
333
-
334
- `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:
335
-
336
- ```text
337
- ▍ SELECTOR HEALTH
338
-
339
- e2e/login.spec.ts
340
- [█████████████░░░░░░░] 65 / 100
341
- role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
342
-
343
- e2e/checkout.spec.ts
344
- [██████████████████░░] 88 / 100
345
- role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
346
- ```
347
-
348
- 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.
349
-
350
- <br />
351
-
352
- ## Il punteggio di affidabilità
353
-
354
- <p align="center">
355
- <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" />
356
- </p>
357
-
358
- <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>
359
-
360
- | Punteggio | Verdetto |
361
- | --------- | -------------------------------------------------- |
362
- | `0 – 49` | **UNWORTHY** |
363
- | `50 – 79` | **NEEDS WORK** |
364
- | `80 – 99` | **WORTHY** |
365
- | `100` | **FORGED** |
366
- | `null` | **UNKNOWN**: nessuna dichiarazione di test trovata |
367
-
368
- **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).
369
-
370
- **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.**
371
-
372
- <br />
373
-
374
- ## Il modello di evidenza
375
-
376
- 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.
377
-
378
- **Quanto è sicuro — il livello di evidenza.**
379
-
380
- | Livello | Nome | Significa | Detrazione |
381
- | ------- | -------------------- | -------------------------------------------------------- | ---------- |
382
- | **E2** | Prova deterministica | Il difetto è presente nel codice così come è scritto | Piena |
383
- | **E1** | Evidenza da pattern | Ha corrisposto un pattern strettamente legato al difetto | Metà |
384
- | **E0** | Osservazione | Utile da sapere. Non afferma che qualcosa sia sbagliato. | Zero |
385
-
386
- 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.
387
-
388
- **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.
389
-
390
- <p align="center">
391
- <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%" />
392
- </p>
393
-
394
- | Livello | In parole semplici | Cosa serve |
395
- | ------- | ------------------------ | ----------------------------------------------------------------------- |
396
- | **L0** | Annotato | Leggere il codice |
397
- | **L1** | Sembra il problema | Leggere il codice: un pattern ha corrisposto |
398
- | **L2** | Dimostrato nel codice | Leggere il codice: il difetto è strutturale |
399
- | **L3** | Il file è stato eseguito | Un report di esecuzione mostra che il file del rilievo è stato eseguito |
400
- | **L4** | Il test è stato eseguito | Un report di esecuzione mostra che il test del rilievo è stato eseguito |
401
- | **L5** | L'esecuzione concorda | Il risultato stesso dell'esecuzione conferma la classe di difetto |
402
-
403
- 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).
404
-
405
- ### Quanto di tutto questo è misurato
406
-
407
- **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.
408
-
409
- 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.
410
-
411
- ### Livelli di fiducia delle regole
412
-
413
- I livelli seguono il tasso di falsi positivi misurato, non un'opinione:
414
-
415
- | Livello | FP misurato | Comportamento |
416
- | -------------- | --------------------------------- | ---------------------------------------------------- |
417
- | **core** | ≤ 10% | Report predefinito, blocca |
418
- | **extended** | ≤ 30% | Report predefinito, confidenza più bassa |
419
- | **quarantine** | > 30% o esplicitamente dichiarato | Solo con `--strict`, limitato a info, non blocca mai |
420
- | _non misurata_ | n < 10 | Non può essere promossa a core finché non è misurata |
421
-
422
- 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.
423
-
424
- Promozione, retrocessione e maturità per linguaggio: [ciclo di vita delle regole](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
425
-
426
- ### Perché non è un linter
427
-
428
- I linter ti dicono se il codice segue delle regole. Mjölnir ti dice se della tua verifica ci si può fidare.
429
-
430
- | | Linter (ESLint, SonarQube) | Strumenti di copertura | Code review con IA | **Mjölnir** |
431
- | ------------------------------------------------------------- | :------------------------: | :--------------------: | :----------------: | :---------------: |
432
- | Valuta il **sistema di verifica**, non il codice del prodotto | No | No | No | Sì |
433
- | Integrità dei workflow CI (`continue-on-error`, `\|\| true`) | No | No | solo il diff | Sì |
434
- | Valuta la resilienza dei locator Playwright (Selector Health) | No | No | No | Sì |
435
- | Legge dati di esecuzione reali per i verdetti `TRUE-FLAKE` | No | No | No | Sì |
436
- | Pubblica un tasso di falsi positivi misurato per regola | No | No | No | Sì |
437
- | Segnala i test senza asserzioni | Sì\* | No | a volte | Sì |
438
- | Rileva gli sleep fissi (`waitForTimeout`, `time.sleep`) | Sì\* | No | a volte | Sì |
439
- | Deterministico (stesso input, stesso output) | Sì | Sì | No | Sì |
440
- | Costo per scansione | gratuito | gratuito | token | **zero** (locale) |
441
-
442
- <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>
443
-
444
- 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.
445
-
446
- <br />
447
-
448
- ## Analisi forense del runtime
449
-
450
- 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.
451
-
452
- ```bash
453
- mjolnir forensics ./test-results/
454
- ```
455
-
456
- ```text
457
- ▍ FLAKINESS LEADERBOARD
458
-
459
- 3 tests · 1 failed · 1 flaky · 1 retried
460
-
461
- TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
462
- ████████████████████ 6.0s · 2 attempts
463
- FAILING declines an expired card (e2e/checkout.spec.ts)
464
- ████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
465
- ```
466
-
467
- `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.
468
-
469
- <br />
470
-
471
- ## Integrità della CI
472
-
473
- 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.
474
-
475
- Genera il workflow per le PR, consultivo per impostazione predefinita:
476
-
477
- ```bash
478
- mjolnir ci install
479
- ```
480
-
481
- Oppure aggiungi l'action del Marketplace a un workflow che hai già:
482
-
483
- ```yaml
484
- - uses: Sergey-Bar/Mjolnir@v3
485
- with:
486
- scope: changed
487
- fail-on: error
488
- ```
489
-
490
- Fissa `@v3` 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.
491
-
492
- Per portare i rilievi in GitHub Code Scanning, carica il SARIF (richiede `security-events: write` a livello di workflow o job):
493
-
494
- ```yaml
495
- - run: npx mjolnir-qa@3.0.0 --format sarif > mjolnir.sarif
496
- continue-on-error: true
497
- - uses: github/codeql-action/upload-sarif@v3
498
- if: ${{ !cancelled() }}
499
- with:
500
- sarif_file: mjolnir.sarif
501
- ```
502
-
503
- 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).
504
-
505
- ### Attribuzione sull'ambito modificato
506
-
507
- ```bash
508
- npx mjolnir-qa@3.0.0 --scope changed
509
- ```
510
-
511
- 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>`.
512
-
513
- 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.
514
-
515
- <br />
516
-
517
- ## Agenti IA
518
-
519
- I rilievi valgono qualcosa solo se qualcosa agisce su di essi.
520
-
521
- ```text
522
- SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
523
- ```
524
-
525
- **L'IA scrive la correzione. Mjölnir la verifica.** La prova viene dalla nuova scansione, mai dal resoconto di successo dell'agente stesso.
526
-
527
- | Comando | Cosa riceve l'agente |
528
- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529
- | `mjolnir mcp` | Un server [MCP](https://modelcontextprotocol.io) su stdio. `scan`, `explain` e `diff` diventano strumenti invocabili. |
530
- | `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. |
531
- | `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. |
532
-
533
- Aggiungilo a un client che ha una propria CLI:
534
-
535
- ```bash
536
- claude mcp add mjolnir -- npx -y mjolnir-qa@3.0.0 mcp
537
- ```
538
-
539
- Oppure a qualsiasi client che accetti un blocco `mcpServers`:
540
-
541
- ```json
542
- {
543
- "mcpServers": {
544
- "mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@3.0.0", "mcp"] }
545
- }
546
- }
547
- ```
548
-
549
- **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.
550
-
551
- <br />
552
-
553
- ## Fiducia e sicurezza
554
-
555
- **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.
556
-
557
- Due avvertenze: `npx` stesso scarica il pacchetto prima che qualsiasi cosa venga eseguita, e la garanzia copre `src/`, non i plugin di terze parti.
558
-
559
- **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).
560
-
561
- **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.
562
-
563
- ### Codici di uscita e contratto macchina
564
-
565
- Congelati, così puoi costruirci sopra la logica della CI:
566
-
567
- | Codice di uscita | Significato |
568
- | ---------------- | -------------------------------------------------------------------------------- |
569
- | `0` | Pulito: nessun rilievo al livello del gate o sopra |
570
- | `1` | Rilievi al livello del gate o sopra |
571
- | `2` | Scansione parziale (budget di tempo esaurito, file illeggibili). Non blocca mai. |
572
- | `10` | Errore d'uso (flag errato, target mancante) |
573
- | `20` | Errore interno |
574
-
575
- `2` è volutamente diverso da `0`: una scansione che non è finita non ha trovato «niente». Semplicemente non ha finito di cercare.
576
-
577
- 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.
578
-
579
- <br />
580
-
581
- ## Cosa Mjölnir non può dirti
582
-
583
- - **Non esegue i tuoi test.** Una scansione pulita non è una suite che passa.
584
- - **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.
585
- - **Non dimostra la correttezza di business.** Niente qui dice che il tuo prodotto fa ciò che il requisito chiedeva.
586
- - **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.
587
- - **5 regole su 79 si basano su una stima**, non su un tasso misurato. Ognuna lo dice sul proprio rilievo.
588
- - **E1 non è E2.** I rilievi euristici meritano di essere letti, non di essere applicati alla cieca.
589
- - **Un repo vuoto ottiene `null`, mai 100.**
590
- - **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.
591
-
592
- <br />
593
-
594
- ## Documentazione
595
-
596
- Il sito completo della documentazione è su <https://sergey-bar.github.io/Mjolnir/>.
597
-
598
- | Documento | Cosa contiene |
599
- | ------------------------------------------------------ | ----------------------------------------------------------- |
600
- | [docs/SCORING.md](docs/SCORING.md) | Normalizzazione del punteggio e ponderazione delle evidenze |
601
- | [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Vocabolario canonico: una parola per concetto |
602
- | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Tassi di falsi positivi misurati e il metodo |
603
- | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Stati delle regole, livelli, soppressione, deprecazione |
604
- | [docs/VERSIONING.md](docs/VERSIONING.md) | Politica semver, superfici congelate, ciclo di deprecazione |
605
- | [docs/machine-contract.md](docs/machine-contract.md) | Il risultato canonico leggibile dalle macchine |
606
- | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Output SARIF e configurazione dell'editor o della CI |
607
- | [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: report Code Quality, ricetta per le MR, gate |
608
- | [docs/rules/](docs/rules/) | Catalogo generato per regola |
609
- | [CONTRIBUTING.md](CONTRIBUTING.md) | Ambiente di sviluppo e flusso di contribuzione |
610
- | [SUPPORT.md](SUPPORT.md) | Dove chiedere, segnalare e ottenere aiuto |
611
- | [SECURITY.md](SECURITY.md) | Segnalazione delle vulnerabilità |
612
- | [CHANGELOG.md](CHANGELOG.md) | Storico dei rilasci |
613
-
614
- ### Stato
615
-
616
- **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).
617
-
618
- ### Contribuire
619
-
620
- 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:
621
-
622
- ```bash
623
- mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
624
- ```
625
-
626
- 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).
627
-
628
- <br />
629
-
630
- <div align="center">
631
-
632
- <img src="assets/readme/closing.svg" alt="Provalo sul tuo repo." width="100%" />
633
-
634
- ```bash
635
- npx mjolnir-qa@3.0.0
636
- ```
637
-
638
- [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)
639
-
640
- <br />
641
-
642
- Non chiederti se i test sono passati.<br />
643
- Chiediti se le evidenze dimostrano che meritano fiducia.
644
-
645
- <sub>Creato da [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Licenza MIT</sub>
646
-
647
- </div>