mjolnir-qa 5.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.fr.md DELETED
@@ -1,647 +0,0 @@
1
- <div align="center">
2
-
3
- <img src="assets/readme/hero.svg" alt="Mjölnir. Les tests vous disent ce qui a réussi. Mjölnir vous dit à quoi vous pouvez vous fier." width="100%" />
4
-
5
- <br />
6
-
7
- Mjölnir trouve les tests qui ne peuvent pas échouer et les pipelines qui ne peuvent pas passer au rouge,<br />
8
- puis évalue jusqu'où le résultat mérite confiance, avec la preuve de chaque point.
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
- [Le voir à l'œuvre](#le-voir-à-lœuvre) · [Démarrage rapide](#démarrage-rapide) · [Ce qu'il trouve](#ce-que-mjölnir-trouve) · [Score](#le-score-de-fiabilité) · [Preuves](#le-modèle-de-preuves) · [Forensique](#forensique-dexécution) · [CI](#intégrité-de-la-ci) · [Agents](#agents-ia) · [Sécurité](#confiance-et-sécurité) · [Limites](#ce-que-mjölnir-ne-peut-pas-vous-dire) · [Docs](#documentation)
25
-
26
- <details>
27
- <summary>Lire dans une autre langue — 22 traductions</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 | [Italiano](README.it.md) | [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
- ## Une coche verte est une affirmation, pas une preuve
56
-
57
- Une coche verte signifie que le pipeline n'a pas échoué. Elle ne signifie pas que les tests ont tourné, ni qu'ils auraient pu échouer. Chacun de ces cas passe au vert :
58
-
59
- - un `.only` commité qui a exécuté 3 tests au lieu de 900
60
- - `continue-on-error: true` sur le job censé servir de barrière
61
- - `|| true` après la commande de test
62
- - un test qui n'affirme rien, ou dont le corps est vide
63
- - un wrapper de relance qui transforme un vrai échec en réussite chanceuse
64
- - un rapport que le workflow téléverse mais n'a jamais généré
65
- - un sleep fixe qui maintient une condition de concurrence
66
-
67
- Aucun ne fait passer le pipeline au rouge, et chacun semble délibéré en revue. C'est pour cela qu'ils survivent. Voici Mjölnir lisant un cas réel :
68
-
69
- <p align="center">
70
- <img src="assets/readme/scan.svg" alt="Le workflow CI du dépôt de démonstration, lu ligne par ligne. Mjölnir signale chaque constat à la ligne rapportée, avec sa règle, ce qui ne va pas, son niveau de preuve et son taux de faux positifs mesuré." width="800" />
71
- </p>
72
-
73
- <sub>Chaque constat que le scan de démonstration a rapporté pour ce workflow, à la ligne rapportée. Généré par `npm run docs:readme-brand` à partir de [`demo-report.json`](assets/readme/demo-report.json) et verrouillé contre toute dérive en CI.</sub>
74
-
75
- **Mode strict.** Les détections les plus agressives — `.only`, `continue-on-error`, tests vides, abus de retry — vivent dans le niveau quarantaine. Elles ne tournent qu'avec `--strict` et sont limitées à la sévérité `info` : elles signalent, ne bloquent jamais. Le scan par défaut (`npx mjolnir-qa@3.0.0` sans `--strict`) ne couvre que les règles core et extended. Ajoutez `--strict` quand vous voulez aussi la couche consultative.
76
-
77
- Mjölnir lit la suite, les workflows CI et, si vous en avez un, le rapport d'une exécution réelle. Il n'exécute pas vos tests, n'installe pas vos dépendances et n'exécute pas le code qu'il analyse. Et quand il n'a pas de preuve, il le dit au lieu d'inventer de la confiance :
78
-
79
- | Situation | Ce que Mjölnir rapporte |
80
- | ------------------------------------------------------ | --------------------------------------------------------------- |
81
- | Aucune déclaration de test trouvée | Score `null`, affiché comme **UNKNOWN**. Jamais un 100 inventé. |
82
- | Aucune baseline ni révision comparable | **UNKNOWN**, avec la raison indiquée. Jamais un 0 supposé. |
83
- | Scan interrompu (budget de temps, fichiers illisibles) | **PARTIAL**, sortie `2`. Jamais présenté comme propre. |
84
-
85
- <p align="center">
86
- <img src="assets/readme/how-it-works.svg" alt="Comment fonctionne Mjölnir. Il lit la suite de tests et le pipeline CI de manière statique, ainsi que le rapport d'une exécution réelle quand il y en a un. Il pondère chaque constat par son niveau de preuve et son niveau de confiance, où seule une exécution réelle peut atteindre L3 à L5, et produit des constats, un score de fiabilité et une barrière CI aux codes de sortie figés. Dans la boucle d'agent, l'IA écrit le correctif et Mjölnir relance le scan pour le prouver." width="880" />
87
- </p>
88
-
89
- <sub>Composé pour cette page et affiché à 1:1. Généré par `npm run docs:readme-brand` et verrouillé contre toute dérive en CI ; le score, les décomptes et l'ID de règle proviennent de [`script.demo.json`](assets/video/script.demo.json), de [`demo-report.json`](assets/readme/demo-report.json) et du registre des règles, jamais saisis à la main. La même image en affiche : [`architecture.svg`](assets/readme/architecture.svg).</sub>
90
-
91
- <br />
92
-
93
- ## Le voir à l'œuvre
94
-
95
- Un vrai scan de [`examples/demo-repo`](examples/demo-repo), une petite suite Playwright avec un workflow CI. Voici où sont partis ses points :
96
-
97
- <p align="center">
98
- <img src="assets/readme/terminal-hero.svg" alt="Le détail des déductions de Mjölnir : WORTHINESS 80/100 WORTHY, le score par catégorie, l'encadré des déductions par sévérité et une liste FIX THIS FIRST" width="520" />
99
- </p>
100
-
101
- <sub>Généré par `npm run docs:hero` à partir d'un vrai scan et verrouillé contre toute dérive en CI. Le rapport `--verbose` complet du même scan est [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
102
-
103
- <details>
104
- <summary><strong>Le regarder</strong> — un scan, le correctif qu'il affiche et le nouveau scan qui le prouve</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="Une image de l'enregistrement de démonstration : npx mjolnir-qa@3.0.0 analysant le dépôt de démonstration dans une fenêtre de terminal" width="900" />
111
- </a>
112
- </p>
113
-
114
- <sub>Rendu image par image à partir d'un vrai scan par `npm run docs:video` ; jamais enregistré à l'écran. Sélectionnez l'image pour ouvrir [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
115
-
116
- </details>
117
-
118
- ### Un constat, de près
119
-
120
- Chaque constat répond à quatre questions : où il se trouve, à quel point Mjölnir est sûr, à quelle fréquence la règle se trompe, et comment le corriger.
121
-
122
- <p align="center">
123
- <img src="assets/readme/finding-anatomy.svg" alt="Le premier constat du scan de démonstration, exactement tel que le terminal l'affiche, avec ses quatre parties repérées : où, à quel point c'est sûr, à quelle fréquence la règle se trompe, et le correctif." width="100%" />
124
- </p>
125
-
126
- `mjolnir explain QA-CI-001` affiche tout le dossier de confiance d'une règle, y compris son taux de faux positifs mesuré et le niveau que ce taux lui a valu :
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
- Voilà l'unité de valeur : un endroit où la CI rapporte une réussite qu'elle n'a pas méritée.
173
-
174
- <br />
175
-
176
- ## Démarrage rapide
177
-
178
- ```bash
179
- npx mjolnir-qa@3.0.0
180
- ```
181
-
182
- Il analyse le répertoire courant et affiche le Trust Report : ce qu'il a trouvé, jusqu'où vous pouvez vous y fier, pourquoi, et quoi faire ensuite. Il sort avec `0` quand rien n'a été trouvé au niveau de la barrière ou au-dessus.
183
-
184
- En CI, n'analysez que ce que la branche a introduit, pour qu'une suite historique ne noie pas votre première pull request :
185
-
186
- ```bash
187
- npx mjolnir-qa@3.0.0 --scope changed
188
- ```
189
-
190
- `mjolnir ci install` l'écrit sous forme de workflow GitHub Actions, en utilisant l'[action](https://github.com/Sergey-Bar/Mjolnir#readme) épinglée sur le tag majeur `v3` (ou un simple `npx` avec `--no-action`). Il reste consultatif jusqu'à ce que vous décidiez qu'il doit bloquer.
191
-
192
- | Commande | Ce qu'elle fait |
193
- | --------------------------------------------- | ----------------------------------------------------------------------- |
194
- | `mjolnir` | Trust Report : verdict, confiance, prochaine action |
195
- | `mjolnir --scope changed` | Uniquement ce que votre branche a introduit (la forme CI) |
196
- | `mjolnir ci install` | Génère le workflow de PR consultatif (basé sur l'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` | Quoi, pourquoi et correctif, plus le taux de FP mesuré |
213
- | `mjolnir why src/a.spec.ts:42` | Pourquoi cette ligne précise a été signalée. Ne bloque jamais. |
214
- | `mjolnir forensics ./test-results/` | Preuves d'exécution tirées d'une exécution réelle |
215
- | `mjolnir trust-report` | Trust Artifact autonome (md + json) |
216
- | `mjolnir handoff` | Plan de remédiation pour un agent de code |
217
- | `mjolnir --json` / `--format sarif` | Sortie lisible par machine, GitHub Code Scanning |
218
- | `mjolnir --format codequality` | Rapport GitLab Code Quality (artefact du widget de MR) |
219
- | `mjolnir --strict` | Exécute aussi les règles du niveau quarantine (risque de FP plus élevé) |
220
-
221
- <details>
222
- <summary><strong>Toutes les autres commandes</strong> — tri des tests instables, rapports, gouvernance</summary>
223
-
224
- <br />
225
-
226
- | Commande | Ce qu'elle fait |
227
- | ----------------------------------- | -------------------------------------------------------------------------------- |
228
- | `mjolnir --classic` | La bannière de score d'avant le Trust Report |
229
- | `mjolnir explain verdict` | Pourquoi le verdict du scan enregistré est ce qu'il est |
230
- | `mjolnir triage ./test-results/` | Tri guidé. Chaque ligne se termine par une prochaine action. |
231
- | `mjolnir pw-report ./test-results/` | Résumé d'exécution Playwright : relances, tests instables, les plus lents |
232
- | `mjolnir doctor:playwright` | Scan approfondi dédié à Playwright plus Selector Health Score |
233
- | `mjolnir fix --dry-run` / `fix` | Correctifs automatiques sûrs, chacun re-scanné pour prouver qu'il s'est appliqué |
234
- | `mjolnir baseline` / `diff` | Photographie les constats, puis ne rapporte que les nouveaux ou les aggravés |
235
- | `mjolnir impact --since <ref>` | Ce qu'un commit a introduit et résolu |
236
- | `mjolnir summary` | Annotations CI et résumé d'étape à partir d'un rapport |
237
- | `mjolnir pr-comment` | Un commentaire de PR ciblé, en Markdown |
238
- | `mjolnir debt` | Registre de la dette de tests avec un modèle de coût |
239
- | `mjolnir handover` | Carte d'intégration de la suite pour un nouvel ingénieur QA |
240
- | `mjolnir init` | Détecte les frameworks, affiche une checklist d'installation |
241
- | `mjolnir suppressions` | Liste les constats supprimés, pour la gouvernance |
242
- | `mjolnir rules --unmeasured` | Les règles qui reposent sur une hypothèse, pas sur une mesure |
243
- | `mjolnir rules --md` | Catalogue complet des règles (JSON ou Markdown) |
244
- | `mjolnir doctor` | Auto-audit de la base de règles de Mjölnir |
245
- | `mjolnir create-rule <ID>` | Crée le squelette d'une nouvelle règle et de ses fixtures |
246
- | `mjolnir stats` | Compteurs locaux cumulés des correctifs observés |
247
- | `mjolnir badge` | JSON d'endpoint shields.io et extrait |
248
- | `mjolnir --cache` | Re-scans incrémentaux via un cache local des verdicts |
249
- | `mjolnir --format mermaid` | Diagramme d'architecture de tests pour un commentaire de PR |
250
-
251
- `mjolnir help <command>` affiche l'usage, des exemples et la prochaine étape pour chacune d'elles.
252
-
253
- </details>
254
-
255
- Nécessite **Node.js ≥ 22.18** sous Windows, macOS ou Linux. Vous préférez une installation globale ? `npm i -g mjolnir-qa`. Ce minimum vient de la chaîne de build (tsdown le cible et le pipeline de publication fait des tests de fumée dessus) ; les dépendances d'exécution n'en demandent pas davantage.
256
-
257
- <br />
258
-
259
- ## Ce que Mjölnir trouve
260
-
261
- <p align="center">
262
- <img src="assets/readme/stack.svg" alt="Fonctionne avec votre stack : les langages, frameworks de test et systèmes CI couverts par ses règles, d'après le registre des règles." width="100%" />
263
- </p>
264
-
265
- **79 règles** en quatre familles — hygiène des tests, qualité des tests, Playwright et intégrité de la CI — pour TypeScript et JavaScript, Python, Java, C# et le YAML de GitHub Actions. Elles couvrent Playwright dans ses quatre bindings, ainsi que pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest et Mocha, avec une couverture de départ pour Cypress et Selenium. Neuf d'entre elles, pour donner une idée :
266
-
267
- | ID | Règle | Sévérité | Niveau |
268
- | ------------ | ---------------------------------------------------------------------- | -------- | ---------- |
269
- | QA-CI-001 | `continue-on-error` masque une barrière de vérification en échec | error | quarantine |
270
- | QA-CI-009 | Code de sortie des tests non propagé (`\|` sans pipefail, chaînes `;`) | error | extended |
271
- | QA-TEST-001 | Test ciblé commité (`.only`, `fit`) | error | quarantine |
272
- | QA-TEST-003 | Test sans assertion | error | quarantine |
273
- | QA-TQUAL-009 | Assertion de promesse sans await | error | quarantine |
274
- | QA-PW-002 | Assertion de locator sans await | error | core |
275
- | QA-PW-004 | Sélecteurs CSS/XPath fragiles | warning | quarantine |
276
- | QA-PY-002 | Test ignoré (`skip`, `xfail` non strict) | warning | core |
277
- | QA-CS-103 | Méthode de test sans assertion | error | core |
278
-
279
- Le catalogue complet est généré depuis le registre, jamais maintenu à la main : `mjolnir rules --md`, [`docs/rules/`](docs/rules/), ou le [guide de ce qu'il vérifie](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
280
-
281
- <details>
282
- <summary><strong>Toutes les règles citées dans ce README</strong>, dans un seul tableau</summary>
283
-
284
- <br />
285
-
286
- > Les règles `quarantine` ne tournent que sous `--strict` et ne bloquent jamais (elles sont plafonnées à info). La sévérité indiquée est celle définie par l'auteur.
287
-
288
- | ID | Famille | Règle | Sévérité | Niveau |
289
- | ------------ | ---------- | ------------------------------------------------------------ | -------- | ---------- |
290
- | QA-TEST-001 | Hygiène | Test ciblé commité (`.only`, `fit`) | error | quarantine |
291
- | QA-TEST-002 | Hygiène | Test ignoré. Passe à `error` sans raison suivie. | warning | quarantine |
292
- | QA-TEST-003 | Hygiène | Test sans assertion | error | quarantine |
293
- | QA-TEST-004 | Hygiène | Sleep fixe (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
294
- | QA-TEST-006 | Hygiène | Abus de relances masquant l'instabilité | warning | quarantine |
295
- | QA-TEST-010 | Hygiène | Corps de test vide | error | quarantine |
296
- | QA-TQUAL-002 | Qualité | Assertion tautologique | error | quarantine |
297
- | QA-TQUAL-009 | Qualité | Assertion de promesse sans await | error | quarantine |
298
- | QA-TQUAL-011 | Qualité | Tests commentés | warning | extended |
299
- | QA-PW-002 | Playwright | Assertion de locator sans await | error | core |
300
- | QA-PW-003 | Playwright | `page.pause()` / `test.only()` commité | error | core |
301
- | QA-PW-004 | Playwright | Sélecteurs CSS/XPath fragiles | warning | quarantine |
302
- | QA-PW-123 | Playwright | URL d'environnement codées en dur | warning | quarantine |
303
- | QA-PW-140 | Playwright | Capture d'écran sans `maxDiffPixelRatio` | warning | core |
304
- | QA-CI-001 | CI | `continue-on-error` masque une barrière en échec | error | quarantine |
305
- | QA-CI-002 | CI | `\|\| true` avale les codes de sortie | error | extended |
306
- | QA-CI-005 | CI | Rapport consommé mais jamais généré | error | quarantine |
307
- | QA-CI-007 | CI | Wrappers de relance autour des tests | warning | extended |
308
- | QA-CI-008 | CI | Étape toujours réussie qui masque les échecs | error | quarantine |
309
- | QA-CI-009 | CI | Code de sortie non propagé (`\|` sans pipefail, chaînes `;`) | error | extended |
310
- | QA-CI-010 | CI | Tests ignorés là où ils doivent bloquer | error | quarantine |
311
- | QA-PY-002 | Python | Test ignoré (`skip`, `xfail` non strict) | warning | core |
312
- | QA-PY-003 | Python | Fonction de test sans assertion | error | quarantine |
313
- | QA-PY-005 | Python | `time.sleep()` dans les tests | warning | extended |
314
- | QA-PY-012 | Python | Assertion tautologique | error | quarantine |
315
- | QA-JV-101 | Java | Test désactivé (`@Disabled`) | warning | core |
316
- | QA-JV-102 | Java | Sleep fixe (`Thread.sleep()`) | warning | extended |
317
- | QA-JV-103 | Java | Méthode de test sans assertion | error | extended |
318
- | QA-JV-105 | Java | Sleep fixe via `waitForTimeout()` de Playwright | warning | core |
319
- | QA-JV-106 | Java | Sélecteur fragile au lieu d'un locator par rôle | warning | quarantine |
320
- | QA-CS-101 | C# | Test ignoré (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
321
- | QA-CS-102 | C# | Sleep fixe (`Thread.Sleep` / `Task.Delay`) | warning | core |
322
- | QA-CS-103 | C# | Méthode de test sans assertion | error | core |
323
- | QA-CS-105 | C# | Sleep fixe via `WaitForTimeoutAsync()` | warning | extended |
324
- | QA-CS-106 | C# | Sélecteur fragile au lieu d'un locator par rôle | warning | quarantine |
325
-
326
- Python fournit aussi QA-PY-001…012 (hygiène pytest) et QA-PY-101…108 (Playwright pour Python). Cypress et Selenium disposent de jeux de départ de trois règles chacun.
327
-
328
- </details>
329
-
330
- Chaque règle est livrée avec une fixture must-fire **et** une fixture must-not-fire, et une règle qui se déclenche sur sa propre fixture négative ne peut pas être livrée. C'est le pare-feu anti-faux-positifs ; `mjolnir doctor` l'applique dans la CI de ce dépôt.
331
-
332
- ### Selector Health Score
333
-
334
- `mjolnir doctor:playwright` note chaque locator selon la façon dont il trouve un élément : comme le ferait un utilisateur (rôle, libellé, texte), par un contrat explicite (`data-testid`), ou par un accident structurel (chaînes CSS, XPath). Chaque fichier reçoit un score de 0 à 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
- Cela mesure la **robustesse, pas l'exactitude**. `.btn.btn-primary > div:nth-child(2)` passe aujourd'hui et continue de passer jusqu'à ce que quelqu'un touche au balisage. Un score bas n'affirme jamais que le test est cassé, seulement qu'il dépend d'un balisage que personne n'a promis de conserver.
349
-
350
- <br />
351
-
352
- ## Le score de fiabilité
353
-
354
- <p align="center">
355
- <img src="assets/readme/score-gauge.svg" alt="L'échelle de fiabilité de 0 à 100, avec un marqueur qui parcourt chaque score : UNWORTHY sous 50, NEEDS WORK de 50 à 79, WORTHY de 80 à 99, FORGED à 100" width="720" />
356
- </p>
357
-
358
- <sub>Chaque score de 0 à 100, placé par le vrai `deriveScoreState`. Généré par `npm run docs:gauge` et verrouillé contre toute dérive en CI.</sub>
359
-
360
- | Score | Verdict |
361
- | --------- | ------------------------------------------------ |
362
- | `0 – 49` | **UNWORTHY** |
363
- | `50 – 79` | **NEEDS WORK** |
364
- | `80 – 99` | **WORTHY** |
365
- | `100` | **FORGED** |
366
- | `null` | **UNKNOWN** : aucune déclaration de test trouvée |
367
-
368
- **Comment il est calculé.** La sévérité fixe une déduction de base (`error −8`, `warning −3`, `info −1`) et le niveau de preuve la réduit : E2 compte en entier, E1 à moitié (arrondi à l'inférieur), E0 pas du tout. Le total est normalisé par l'exposition de la suite, c'est-à-dire en déductions par déclaration de test plutôt que par fichier. Le terminal affiche les mêmes nombres réduits que ceux utilisés par le score ; il n'y a pas de second modèle caché. Détails : [docs/SCORING.md](docs/SCORING.md) et le [guide du score](https://sergey-bar.github.io/Mjolnir/guide/scoring).
369
-
370
- **Ce que 100 ne veut pas dire.** Cela ne veut pas dire que le logiciel est correct, que la suite est suffisante ou que le produit est exempt de défauts. Cela veut dire une seule chose : **aucune des règles évaluées par Mjölnir n'a produit de déduction avec ce scan et ce modèle de preuves.**
371
-
372
- <br />
373
-
374
- ## Le modèle de preuves
375
-
376
- Chaque constat porte deux étiquettes : à quel point Mjölnir est sûr, et jusqu'où le constat a été vérifié. C'est la différence entre un outil qui signale des motifs et un outil sur lequel on peut conditionner une release.
377
-
378
- **À quel point c'est sûr — le niveau de preuve.**
379
-
380
- | Niveau | Nom | Signifie | Déduction |
381
- | ------ | ------------------- | -------------------------------------------------------------- | --------- |
382
- | **E2** | Preuve déterministe | Le défaut est présent dans le code tel qu'il est écrit | Totale |
383
- | **E1** | Preuve par motif | Un motif fortement lié au défaut a correspondu | Moitié |
384
- | **E0** | Observation | Bon à savoir. Pas une affirmation que quelque chose ne va pas. | Nulle |
385
-
386
- La confiance dans une détection n'est pas la force de la preuve. Une règle peut être certaine d'avoir trouvé ce qu'elle cherchait tout en regardant une heuristique. Les constats E1 sont là pour être lus et jugés, jamais appliqués aveuglément, et cette limite est inscrite sur le constat dans le terminal, le JSON et le passage de relais à l'agent.
387
-
388
- **Jusqu'où c'est vérifié — le niveau de confiance.** La plupart des constats viennent de la lecture de votre code. Donnez à Mjölnir le rapport d'une vraie exécution de tests et il pourra confirmer que le code a bien tourné.
389
-
390
- <p align="center">
391
- <img src="assets/readme/trust-ladder.svg" alt="L'échelle de confiance de L0 à L5. L0 à L2 viennent de la lecture du code ; L3 à L5 exigent le rapport d'une exécution réelle, marqué par une rupture dans l'échelle." width="100%" />
392
- </p>
393
-
394
- | Niveau | En clair | Ce qu'il faut |
395
- | ------ | --------------------- | --------------------------------------------------------------------- |
396
- | **L0** | Noté | Lire le code |
397
- | **L1** | Ressemble au problème | Lire le code : un motif a correspondu |
398
- | **L2** | Prouvé dans le code | Lire le code : le défaut est structurel |
399
- | **L3** | Le fichier a tourné | Un rapport d'exécution montre que le fichier du constat a été exécuté |
400
- | **L4** | Le test a tourné | Un rapport d'exécution montre que le test du constat a été exécuté |
401
- | **L5** | L'exécution concorde | Le résultat même de l'exécution confirme la classe de défaut |
402
-
403
- Un scan statique s'arrête à L2. Seul le rapport d'une exécution réelle (Playwright JSON, Jest ou Vitest JSON, JUnit XML) peut élever un constat à L3 ou plus, si bien qu'un constat qu'on n'a jamais vu tourner ne peut jamais prétendre l'avoir fait. Définitions : [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
404
-
405
- ### Quelle part est mesurée
406
-
407
- **74 règles sur 79 ont un taux de faux positifs mesuré sur du vrai code OSS** (au moins 10 constats classés à la main chacune ; voir [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Les 5 autres reposent sur l'estimation de l'auteur et le disent, règle par règle, dans `mjolnir explain`. `mjolnir rules --unmeasured` les liste, et le pied de chaque scan indique combien des règles qui se sont réellement _déclenchées_ sont mesurées.
408
-
409
- Les taux restent publics quand ils sont mauvais. QA-TEST-001 (un `.only` commité) obtient un mauvais audit sur des dépôts réels et se trouve en quarantine pour cette raison. Le chiffre actuel de chaque règle, QA-PW-141 comprise, figure dans l'audit.
410
-
411
- ### Niveaux de confiance des règles
412
-
413
- Les niveaux suivent le taux de faux positifs mesuré, pas une opinion :
414
-
415
- | Niveau | FP mesuré | Comportement |
416
- | -------------- | ------------------------------ | -------------------------------------------------------- |
417
- | **core** | ≤ 10% | Rapport par défaut, bloque |
418
- | **extended** | ≤ 30% | Rapport par défaut, confiance moindre |
419
- | **quarantine** | > 30% ou explicitement déclaré | Uniquement `--strict`, plafonné à info, ne bloque jamais |
420
- | _non mesurée_ | n < 10 | Ne peut être promue en core avant d'être mesurée |
421
-
422
- Les bandes de FP ne peuvent que rétrograder un niveau — elles ne promeuvent jamais une règle hors de `quarantine` si elle y a été explicitement déclarée. Une règle explicitement mise en quarantine y reste quelle que soit son taux de FP mesuré.
423
-
424
- Promotion, rétrogradation et maturité par langage : [cycle de vie des règles](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
425
-
426
- ### Pourquoi ce n'est pas un linter
427
-
428
- Les linters vous disent si le code suit des règles. Mjölnir vous dit si votre vérification mérite confiance.
429
-
430
- | | Linters (ESLint, SonarQube) | Outils de couverture | Revue de code par IA | **Mjölnir** |
431
- | ---------------------------------------------------------------- | :-------------------------: | :------------------: | :------------------: | :--------------: |
432
- | Note le **système de vérification**, pas le code produit | Non | Non | Non | Oui |
433
- | Intégrité des workflows CI (`continue-on-error`, `\|\| true`) | Non | Non | seulement le diff | Oui |
434
- | Note la robustesse des locators Playwright (Selector Health) | Non | Non | Non | Oui |
435
- | Lit de vraies données d'exécution pour les verdicts `TRUE-FLAKE` | Non | Non | Non | Oui |
436
- | Publie un taux de faux positifs mesuré par règle | Non | Non | Non | Oui |
437
- | Signale les tests sans assertion | Oui\* | Non | parfois | Oui |
438
- | Détecte les sleeps fixes (`waitForTimeout`, `time.sleep`) | Oui\* | Non | parfois | Oui |
439
- | Déterministe (même entrée, même sortie) | Oui | Oui | Non | Oui |
440
- | Coût par scan | gratuit | gratuit | tokens | **zéro** (local) |
441
-
442
- <sub>\*Couvert par `eslint-plugin-jest` et `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) ainsi que par les propres règles d'assertion de SonarQube. Les colonnes décrivent le comportement par défaut pour la vérification de suites de tests ; les plugins, les offres payantes et les règles personnalisées changent certaines réponses. C'est un résumé de positionnement, pas un benchmark.</sub>
443
-
444
- Utilisez aussi la revue par IA. Elle saisit les nuances, l'intention et les défauts de conception qu'aucun motif ne peut trouver. Mjölnir détecte ce que la revue par IA laisse passer parce que cela semble intentionnel : un `.only` commité, un code de sortie avalé, un `continue-on-error` sur un job de tests. Cela demande un scan, pas un raisonnement.
445
-
446
- <br />
447
-
448
- ## Forensique d'exécution
449
-
450
- L'analyse statique raisonne sur du code qui n'a jamais tourné. La forensique lit ce qui s'est réellement passé : Playwright JSON, Jest JSON, Vitest JSON et JUnit XML de n'importe quel 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` ne signifie pas que le test a été relancé. Cela signifie que le test **a échoué au moins une tentative puis a terminé au vert** : une réussite chanceuse, signalée quoi que dise la coche finale. `mjolnir triage` transforme cet historique en proposition de quarantaine, et `mjolnir pw-report` résume une exécution. Ce sont ces mêmes rapports d'exécution qui élèvent les constats aux niveaux de confiance L3 et au-delà.
468
-
469
- <br />
470
-
471
- ## Intégrité de la CI
472
-
473
- Un test peut réussir alors que le pipeline qui l'entoure ne peut pas échouer. Mjölnir lit aussi les workflows : `continue-on-error`, `|| true`, les codes de sortie jamais propagés, les étapes toujours réussies, les rapports consommés mais jamais générés, et les barrières ignorées sur les événements qui devraient bloquer. Chaque constat nomme le job, l'étape et la ligne, et porte son propre niveau de preuve.
474
-
475
- Générez le workflow de PR, consultatif par défaut :
476
-
477
- ```bash
478
- mjolnir ci install
479
- ```
480
-
481
- Ou ajoutez l'action du Marketplace à un workflow existant :
482
-
483
- ```yaml
484
- - uses: Sergey-Bar/Mjolnir@v3
485
- with:
486
- scope: changed
487
- fail-on: error
488
- ```
489
-
490
- Épinglez `@v3` pour suivre la ligne majeure, ou un tag exact (`@v0.5.32`) pour une barrière reproductible. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) couvre le Marketplace, Smithery et les registres MCP.
491
-
492
- Pour envoyer les constats dans GitHub Code Scanning, téléversez le SARIF (nécessite `security-events: write` au niveau du workflow ou du 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
- Sur GitLab, `--format codequality` écrit le rapport Code Quality que lisent le widget de MR et les annotations du diff ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Configuration de l'éditeur et du pipeline : [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
504
-
505
- ### Attribution sur le périmètre modifié
506
-
507
- ```bash
508
- npx mjolnir-qa@3.0.0 --scope changed
509
- ```
510
-
511
- Les constats sont attribués aux lignes ajoutées par votre branche, mesurées par rapport à la **merge-base**. Le périmètre est le même ensemble de fichiers qu'un scan complet découvre (specs TS/JS et configurations d'adaptateurs, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), plus les modifications non commitées et non suivies, si bien que cela fonctionne avant le commit. La base est résolue selon `main → master → origin/main → origin/master → origin/HEAD` ; remplacez-la avec `--base <ref>`.
512
-
513
- Quand la merge-base ne peut pas être résolue (un clone superficiel, un HEAD détaché, une cible hors de git), les constats se replient sur une attribution au fichier entier **et le rapport le dit.** Un repli silencieux serait exactement le type de défaut que cet outil existe pour détecter.
514
-
515
- <br />
516
-
517
- ## Agents IA
518
-
519
- Les constats ne valent quelque chose que si quelque chose agit dessus.
520
-
521
- ```text
522
- SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
523
- ```
524
-
525
- **L'IA écrit le correctif. Mjölnir le vérifie.** La preuve vient du nouveau scan, jamais du propre compte rendu de réussite de l'agent.
526
-
527
- | Commande | Ce que reçoit l'agent |
528
- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529
- | `mjolnir mcp` | Un serveur [MCP](https://modelcontextprotocol.io) sur stdio. `scan`, `explain` et `diff` deviennent des outils appelables. |
530
- | `mjolnir handoff` | Un rapport `--json` enregistré devient un plan Markdown déterministe : ce qui a été détecté, la limite de preuve de chaque constat, ce qui ne doit **pas** changer, comment vérifier. |
531
- | `mjolnir install` | Écrit dans les surfaces d'agent que votre dépôt possède déjà (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`) pour que l'agent relance le scan avant d'affirmer qu'il a terminé. |
532
-
533
- Ajoutez-le à un client qui fournit sa propre CLI :
534
-
535
- ```bash
536
- claude mcp add mjolnir -- npx -y mjolnir-qa@3.0.0 mcp
537
- ```
538
-
539
- Ou à tout client qui accepte un bloc `mcpServers` :
540
-
541
- ```json
542
- {
543
- "mcpServers": {
544
- "mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@3.0.0", "mcp"] }
545
- }
546
- }
547
- ```
548
-
549
- **Le garde-fou compte plus que la commodité.** Chaque constat d'un passage de relais porte sa limite. **E2** dit _déterministe : vérifiez l'emplacement et appliquez le correctif_. **E1** dit _CONFIRMATION REQUISE : l'observation seule ne prouve pas le défaut_. Un agent qui corrige un E1 aveuglément, supprime une règle ou modifie une règle pour faire monter le score fait exactement ce que cet outil existe pour détecter ; le passage de relais le dit donc dans le prompt, à côté du constat.
550
-
551
- <br />
552
-
553
- ## Confiance et sécurité
554
-
555
- **Local d'abord, zéro télémétrie.** Aucune API capable d'accéder au réseau (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) n'existe nulle part dans `src/`, et [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) fait échouer le build si l'une d'elles apparaît. Il interdit aussi `eval` et `new Function`. Analyser du code non fiable ne l'exécute jamais : l'analyse statique lit du texte source, et la forensique analyse des fichiers de rapport déjà présents sur le disque.
556
-
557
- Deux réserves : `npx` lui-même télécharge le paquet avant que quoi que ce soit ne tourne, et la garantie couvre `src/`, pas les plugins tiers.
558
-
559
- **Les plugins ne sont pas isolés dans un bac à sable.** Les plugins JS (`mjolnir-rules/*.mjs`, ou les paquets npm listés sous `"plugins"`) tournent avec tous les privilèges de Node, le même modèle de confiance que les plugins ESLint ou Vitest. Les charger est un choix explicite **par scan** : sans `--enable-plugins` (ou `MJOLNIR_ENABLE_PLUGINS=1`), leurs sources ne sont jamais chargées, et un avis sur stderr liste ce qui a été ignoré. Les manifestes de règles JSON n'exécutent aucun code, et les préfixes d'ID des règles core sont réservés pour qu'un plugin ne puisse pas se faire passer pour l'une d'elles. Signalez les vulnérabilités via [SECURITY.md](SECURITY.md).
560
-
561
- **Il s'analyse lui-même.** Un moteur de confiance de vérification n'a aucune légitimité s'il n'est pas lui-même vérifiable. Chaque exécution de la CI analyse ce dépôt avec le build produit par cette même exécution. La barrière échoue sur tout constat de sévérité error, ainsi que sur un scan **partiel** ou une **règle qui plante**, parce qu'un auto-scan tronqué qui ne rapporte rien est exactement le faux vert que ce projet existe pour détecter. `mjolnir doctor` ré-audite la base de règles dans la même exécution (pare-feu des fixtures, honnêteté des niveaux, plafond du niveau core), et une vérification INCONCLUSIVE échoue exactement comme une vérification en échec. Les deux rapports sont téléversés comme artefacts de build.
562
-
563
- ### Codes de sortie et contrat machine
564
-
565
- Figés, pour que vous puissiez bâtir de la logique CI dessus :
566
-
567
- | Code de sortie | Signification |
568
- | -------------- | ------------------------------------------------------------------------------ |
569
- | `0` | Propre : aucun constat au niveau de la barrière ou au-dessus |
570
- | `1` | Constats au niveau de la barrière ou au-dessus |
571
- | `2` | Scan partiel (budget de temps atteint, fichiers illisibles). Ne bloque jamais. |
572
- | `10` | Erreur d'utilisation (option invalide, cible manquante) |
573
- | `20` | Erreur interne |
574
-
575
- `2` est volontairement distinct de `0` : un scan qui n'a pas terminé n'a pas « rien trouvé ». Il n'a pas fini de chercher.
576
-
577
- Tout ce qu'une machine consomme (résultats des outils MCP, `--json`, SARIF 2.1) provient d'un unique résultat canonique sous un schéma versionné et **uniquement additif** (`schemaVersion: 1`, `contractVersion: 1`), si bien qu'aucun consommateur n'a à reconstruire le sens à partir du texte affiché. Voir [le contrat machine](docs/machine-contract.md). Les ID de règle (`QA-<FAMILY>-NNN`) sont immuables une fois publiés et ne sont jamais réutilisés.
578
-
579
- <br />
580
-
581
- ## Ce que Mjölnir ne peut pas vous dire
582
-
583
- - **Il n'exécute pas vos tests.** Un scan propre n'est pas une suite qui passe.
584
- - **Il ne peut pas vous dire qu'une assertion est _fausse_.** `expect(total).toBe(41)` a l'air saine. Mjölnir trouve les tests qui _ne peuvent pas échouer_ et les pipelines qui _ne peuvent pas passer au rouge_, pas les tests qui vérifient la mauvaise chose.
585
- - **Il ne prouve pas l'exactitude métier.** Rien ici ne dit que votre produit fait ce que l'exigence demandait.
586
- - **Un 100 n'est pas la preuve d'une bonne suite.** Savoir si votre suite couvre votre risque réel est une autre question, et cet outil n'y répond pas.
587
- - **5 règles sur 79 reposent sur une estimation**, pas sur un taux mesuré. Chacune le dit sur son propre constat.
588
- - **E1 n'est pas E2.** Les constats heuristiques méritent d'être lus, pas d'être appliqués aveuglément.
589
- - **Un dépôt vide obtient `null`, jamais 100.**
590
- - **Un fichier nommé `*.spec.ts` sans déclaration de test ne compte pas comme couverture.** Un dépôt dont les seuls fichiers spec contiennent des imports ou des types (zéro appel `it`/`test`) obtient `null`, pas 100.
591
-
592
- <br />
593
-
594
- ## Documentation
595
-
596
- Le site de documentation complet se trouve sur <https://sergey-bar.github.io/Mjolnir/>.
597
-
598
- | Document | Contenu |
599
- | ------------------------------------------------------ | ----------------------------------------------------------- |
600
- | [docs/SCORING.md](docs/SCORING.md) | Normalisation du score et pondération des preuves |
601
- | [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Vocabulaire canonique : un mot par concept |
602
- | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Taux de faux positifs mesurés et méthode |
603
- | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | États des règles, niveaux, suppression, dépréciation |
604
- | [docs/VERSIONING.md](docs/VERSIONING.md) | Politique semver, surfaces figées, cycle de dépréciation |
605
- | [docs/machine-contract.md](docs/machine-contract.md) | Le résultat canonique lisible par machine |
606
- | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Sortie SARIF et configuration de l'éditeur ou de la CI |
607
- | [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab : rapport Code Quality, recette de MR, barrière |
608
- | [docs/rules/](docs/rules/) | Catalogue généré par règle |
609
- | [CONTRIBUTING.md](CONTRIBUTING.md) | Environnement de développement et processus de contribution |
610
- | [SUPPORT.md](SUPPORT.md) | Où poser des questions, signaler et obtenir de l'aide |
611
- | [SECURITY.md](SECURITY.md) | Signalement des vulnérabilités |
612
- | [CHANGELOG.md](CHANGELOG.md) | Historique des versions |
613
-
614
- ### Statut
615
-
616
- **Version 3.0.0.** Le schéma JSON et les codes de sortie sont des contrats figés. TypeScript et Python ont la couverture mesurée la plus large. Java et C# sont plus récents ; lisez-les à travers le [tableau de maturité](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). La suite, sans dates inventées : [la feuille de route publique](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
617
-
618
- ### Contribuer
619
-
620
- Les nouvelles règles sont la première contribution la plus facile. Une commande crée le squelette de la règle avec ses fixtures must-fire **et** must-not-fire. La règle générée échoue volontairement sur ses propres fixtures tant qu'une vraie détection n'est pas écrite, parce qu'un stub livré est une règle que personne n'a mesurée :
621
-
622
- ```bash
623
- mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
624
- ```
625
-
626
- L'environnement de développement, les commandes des barrières permanentes et les lois anti-creep et du pare-feu des fixtures se trouvent dans [CONTRIBUTING.md](CONTRIBUTING.md).
627
-
628
- <br />
629
-
630
- <div align="center">
631
-
632
- <img src="assets/readme/closing.svg" alt="Lancez-le sur votre dépôt." width="100%" />
633
-
634
- ```bash
635
- npx mjolnir-qa@3.0.0
636
- ```
637
-
638
- [Lire le guide](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Site de documentation](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
639
-
640
- <br />
641
-
642
- Ne demandez pas si les tests ont réussi.<br />
643
- Demandez si les preuves montrent qu'ils méritent la confiance.
644
-
645
- <sub>Créé par [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Licence MIT</sub>
646
-
647
- </div>