mjolnir-qa 0.4.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1199 -28
- package/README.ar.md +667 -0
- package/README.bn.md +678 -0
- package/README.br.md +706 -0
- package/README.bs.md +690 -0
- package/README.da.md +698 -0
- package/README.de.md +711 -0
- package/README.es.md +709 -0
- package/README.fr.md +714 -0
- package/README.gr.md +705 -0
- package/README.he.md +664 -0
- package/README.it.md +709 -0
- package/README.ja.md +692 -0
- package/README.ko.md +681 -0
- package/README.md +425 -152
- package/README.no.md +696 -0
- package/README.pl.md +699 -0
- package/README.ru.md +701 -0
- package/README.th.md +672 -0
- package/README.tr.md +699 -0
- package/README.uk.md +693 -0
- package/README.vi.md +680 -0
- package/README.zh.md +652 -0
- package/README.zht.md +652 -0
- package/dist/cli.d.mts +469 -22
- package/dist/cli.mjs +9780 -5230
- package/package.json +25 -7
package/README.de.md
ADDED
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/readme/logo.png" alt="Mjölnir — Verification Trust Engine" width="800" />
|
|
4
|
+
|
|
5
|
+
### Deine Tests lügen. Wir beweisen es.
|
|
6
|
+
|
|
7
|
+
**Verification Trust Engine für QA.** Mjölnir prüft Testsuiten und
|
|
8
|
+
CI-Pipelines, meldet einen Würdigkeitswert und zeigt genau, wo Vertrauen
|
|
9
|
+
bricht.
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
12
|
+
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
[](https://nodejs.org)
|
|
15
|
+
|
|
16
|
+
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | Deutsch | [Español](README.es.md) | [Français](README.fr.md) | [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)
|
|
17
|
+
|
|
18
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-04.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx mjolnir-qa@latest
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Sind deine Tests Vertrauen wert?**
|
|
25
|
+
|
|
26
|
+
[So funktioniert es](#-so-funktioniert-es) ·
|
|
27
|
+
[Schnellstart](#-schnellstart) ·
|
|
28
|
+
[Was es prüft](#-was-mjölnir-prüft) ·
|
|
29
|
+
[Scoring](#so-funktioniert-der-score) ·
|
|
30
|
+
[CI](#-ci-integration) · [Konfiguration](#konfiguration) ·
|
|
31
|
+
[Dokumentation](#-dokumentation)
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🎬 So funktioniert es
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<img src="assets/readme/demo.svg" alt="Mjölnirs voller --verbose-Bericht über ein Demo-Repo: WORTHINESS 75/100 NEEDS WORK, eine Diagnose-Aufschlüsselung nach Kategorien, eine FIX-THIS-FIRST-Liste und jeder Befund mit Regel-ID und Zeilennummer über CI, Playwright, Test-Hygiene und Python-Regeln hinweg" width="900" />
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<sub>Die komplette `npx mjolnir-qa ./examples/demo-repo --verbose`-Ausgabe,
|
|
44
|
+
gerendert vom echten Reporter — nichts gekürzt. Neu erzeugt per
|
|
45
|
+
`npm run docs:demo`;
|
|
46
|
+
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
+
lässt CI fehlschlagen, wenn es von dem abweicht, was das Tool ausgibt.</sub>
|
|
48
|
+
|
|
49
|
+
**Was da gerade passiert ist:**
|
|
50
|
+
|
|
51
|
+
1. Mjölnir fand die Playwright-Specs, seine Konfiguration, den
|
|
52
|
+
CI-Workflow und eine Python-Testdatei — vier Sprachen/Formate, ein
|
|
53
|
+
Durchlauf.
|
|
54
|
+
2. Es fand Belege, die das Vertrauen in die Suite schwächen — ein
|
|
55
|
+
`continue-on-error`, das einen Job maskiert, ein `|| true`, das einen
|
|
56
|
+
Exit-Code schluckt, harte Sleeps, einen spröden Selektor,
|
|
57
|
+
hartkodierte Staging-URLs, ein `networkidle`-Warten.
|
|
58
|
+
3. Jeden davon machte es zu einem konkreten Befund mit Regel-ID, Ort
|
|
59
|
+
und Fix — und zu einem einzigen Score, an dem man einen PR gate-en
|
|
60
|
+
kann.
|
|
61
|
+
|
|
62
|
+
### Ein Befund aus der Nähe
|
|
63
|
+
|
|
64
|
+
Führe `mjolnir explain QA-CI-001` für den ersten Befund oben aus, und du
|
|
65
|
+
erhältst:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
▚▞ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
69
|
+
|
|
70
|
+
Severity: error
|
|
71
|
+
Confidence: high
|
|
72
|
+
Evidence: E2
|
|
73
|
+
Measured FP: not yet measured — this rule ships on assumption (see docs/FP-AUDIT.md)
|
|
74
|
+
|
|
75
|
+
WHAT WAS FOUND (real detector output, not a mockup)
|
|
76
|
+
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
77
|
+
|
|
78
|
+
WHY IT MATTERS
|
|
79
|
+
This job can fail every day and CI will still show green. The checkmark
|
|
80
|
+
on this workflow cannot be trusted.
|
|
81
|
+
|
|
82
|
+
HOW TO FIX
|
|
83
|
+
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Das ist die Einheit des Werts: kein Stil-Nit, sondern eine Stelle, an
|
|
87
|
+
der dein CI etwas als bestanden ausweist, das nicht bestanden ist.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## ⚡ Schnellstart
|
|
92
|
+
|
|
93
|
+
Führe es gegen ein Repo aus — für einen vollen Bericht und einen
|
|
94
|
+
Würdigkeitswert:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx mjolnir-qa@latest
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**In CI ist das Produkt ein einziger Befehl.** Er scannt nur, was der
|
|
101
|
+
Branch berührt hat, und beendet sich mit einem Wert ungleich null bei
|
|
102
|
+
neuen Problemen:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx mjolnir-qa@latest --scope changed
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Wirf das in einen PR-Check — `mjolnir ci install` schreibt den Workflow —
|
|
109
|
+
und fertig. Alles andere ist optional.
|
|
110
|
+
|
|
111
|
+
| Befehl | Was er tut |
|
|
112
|
+
| ----------------------------------- | --------------------------------------------------------- |
|
|
113
|
+
| `mjolnir` | Repoweiter Scan + Würdigkeitswert |
|
|
114
|
+
| `mjolnir --scope changed` | Nur, was dein Branch eingeführt hat — die CI-Form |
|
|
115
|
+
| `mjolnir ci install` | Erzeugt den advisorischen PR-Workflow |
|
|
116
|
+
| `mjolnir explain QA-CI-001` | Was / warum / Fix + gemessene FP-Rate für eine Regel |
|
|
117
|
+
| `mjolnir rules --unmeasured` | Die Regeln, die auf Annahme statt Messung laufen |
|
|
118
|
+
| `mjolnir --json` / `--format sarif` | Maschinenlesbar / GitHub Code Scanning |
|
|
119
|
+
| `mjolnir --strict` | Auch Quarantine-Tier-Regeln ausführen (höheres FP-Risiko) |
|
|
120
|
+
|
|
121
|
+
<details>
|
|
122
|
+
<summary><strong>Wenn etwas flaky ist</strong></summary>
|
|
123
|
+
|
|
124
|
+
| Befehl | Was er tut |
|
|
125
|
+
| ----------------------------------- | -------------------------------------------------------------- |
|
|
126
|
+
| `mjolnir forensics ./test-results/` | Echte Laufdaten → `TRUE-FLAKE`-Urteile, `FLAKY.md` |
|
|
127
|
+
| `mjolnir triage ./test-results/` | Quarantine-Vorschlag aus der Ausführungshistorie |
|
|
128
|
+
| `mjolnir pw-report ./test-results/` | Playwright-Laufübersicht — Retries / Flakes / langsamste Tests |
|
|
129
|
+
| `mjolnir doctor:playwright` | Playwright-only Tiefenscan + Selector Health Score |
|
|
130
|
+
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary><strong>Gelegentlich / Berichte</strong></summary>
|
|
135
|
+
|
|
136
|
+
| Befehl | Was er tut |
|
|
137
|
+
| ------------------------------- | ------------------------------------------------------ |
|
|
138
|
+
| `mjolnir fix --dry-run` / `fix` | Sichere Auto-Fixes mit Nachweis |
|
|
139
|
+
| `mjolnir baseline` / `diff` | Befunde speichern, dann nur neue/verschlimmerte melden |
|
|
140
|
+
| `mjolnir impact --since <ref>` | Was sich seit einem früheren Commit geändert hat |
|
|
141
|
+
| `mjolnir debt` | Test-Debt-Register mit Kostenmodell |
|
|
142
|
+
| `mjolnir handover` | Onboarding-Karte der Suite für neue QA-Leute |
|
|
143
|
+
| `mjolnir stats` | Lokale All-Time-Zähler der gesehenen Fixes |
|
|
144
|
+
| `mjolnir badge` | shields.io-Endpoint-JSON + Snippet |
|
|
145
|
+
| `mjolnir rules --md` | Voller Regelkatalog (JSON oder Markdown) |
|
|
146
|
+
| `mjolnir doctor` | Selbstaudit von Mjölnirs eigener Regelbasis |
|
|
147
|
+
| `mjolnir create-rule <ID>` | Neuen Regel-Scaffold + Fixtures anlegen |
|
|
148
|
+
| `mjolnir --format mermaid` | Test-Architekturdiagramm für einen PR-Kommentar |
|
|
149
|
+
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
Installiere es global statt per `npx`, wenn du lieber: `npm i -g
|
|
153
|
+
mjolnir-qa`. Erfordert Node.js ≥ 22.18. Läuft auf Windows, macOS und
|
|
154
|
+
Linux.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 👥 Für wen ist das?
|
|
159
|
+
|
|
160
|
+
- **QA / SDET**, die eine e2e- oder Integration-Suite besitzen und
|
|
161
|
+
Belege brauchen, dass die Suite den grünen Haken wirklich verdient,
|
|
162
|
+
den sie produziert.
|
|
163
|
+
- **Plattform-/DevEx-Teams**, die für CI-Integrität und Release-Gates
|
|
164
|
+
verantwortlich sind — die Leute, denen ein `continue-on-error` nie
|
|
165
|
+
stillschweigend eine rote Pipeline grün färben darf.
|
|
166
|
+
- **OSS-Maintainer**, die ein günstiges, immer aktives
|
|
167
|
+
Verifikations-Gate wollen, das lokal und in CI ohne Netzwerkaufrufe
|
|
168
|
+
läuft.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🔨 Was Mjölnir prüft
|
|
173
|
+
|
|
174
|
+
| | |
|
|
175
|
+
| --- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
176
|
+
| ⚖️ | **Würdigkeitswert** — eine Zahl, transparente Abzugstabelle, keine Blackbox |
|
|
177
|
+
| 🎭 | **Selector Health Score** — benotet deine Playwright-Locators, nicht nur deine Pass-Rate |
|
|
178
|
+
| 🔬 | **Runtime-Forensik** — liest echte Playwright/JUnit-Laufdaten und findet `TRUE-FLAKE`, nicht nur statische Vermutungen |
|
|
179
|
+
| 🚨 | **CI-Integritätsregeln** — findet `continue-on-error`, `\|\| true` und andere False-Green-Tricks |
|
|
180
|
+
| 🐍 | **Alle vier Playwright-Bindings** — TypeScript, Python, Java, C#/.NET — plus pytest, JUnit/TestNG und CI-Workflows |
|
|
181
|
+
| 🔒 | **Local-first** — null Netzwerkaufrufe beim Scannen, null Telemetrie, läuft in Sekunden |
|
|
182
|
+
|
|
183
|
+
### Die Regeln
|
|
184
|
+
|
|
185
|
+
Jede Regel kommt mit Must-Fire- **und** Must-Not-Fire-Fixtures. Eine
|
|
186
|
+
Regel, die auf ihrem eigenen Negativ-Fixture auslöst, kann nicht
|
|
187
|
+
geshippt werden — das ist die False-Positive-Firewall.
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary><strong>Test-Hygiene</strong></summary>
|
|
191
|
+
|
|
192
|
+
| ID | Regel | Severity |
|
|
193
|
+
| ----------- | ----------------------------------------------------- | -------- |
|
|
194
|
+
| QA-TEST-001 | Committeter Focused Test (`.only`, `fit`) | error |
|
|
195
|
+
| QA-TEST-002 | Übersprungener Test ohne Begründung | error |
|
|
196
|
+
| QA-TEST-002 | Übersprungener Test mit erfasster Begründung | warning |
|
|
197
|
+
| QA-TEST-003 | Test ohne Assertionen | error |
|
|
198
|
+
| QA-TEST-004 | Harter Sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning |
|
|
199
|
+
| QA-TEST-006 | Retry-Missbrauch, der Flakiness versteckt | warning |
|
|
200
|
+
| QA-TEST-010 | Leerer Testkörper | error |
|
|
201
|
+
|
|
202
|
+
</details>
|
|
203
|
+
|
|
204
|
+
<details>
|
|
205
|
+
<summary><strong>Test-Qualität</strong></summary>
|
|
206
|
+
|
|
207
|
+
| ID | Regel | Severity |
|
|
208
|
+
| ------------ | ----------------------------------- | -------- |
|
|
209
|
+
| QA-TQUAL-001 | Nur-Mock-Verifikation | info |
|
|
210
|
+
| QA-TQUAL-002 | Tautologische Assertion | error |
|
|
211
|
+
| QA-TQUAL-009 | Nicht abgewartete Promise-Assertion | error |
|
|
212
|
+
| QA-TQUAL-011 | Auskommentierte Tests | warning |
|
|
213
|
+
|
|
214
|
+
</details>
|
|
215
|
+
|
|
216
|
+
<details>
|
|
217
|
+
<summary><strong>Playwright 🎭</strong></summary>
|
|
218
|
+
|
|
219
|
+
| ID | Regel | Severity |
|
|
220
|
+
| --------- | ---------------------------------------- | -------- |
|
|
221
|
+
| QA-PW-002 | Nicht abgewartete Locator-Assertion | error |
|
|
222
|
+
| QA-PW-003 | `page.pause()` / `test.only()` committed | error |
|
|
223
|
+
| QA-PW-004 | Spröde CSS/XPath-Selektoren | warning |
|
|
224
|
+
| QA-PW-005 | Business-Logik in `page.evaluate()` | info |
|
|
225
|
+
| QA-PW-114 | Legacy Element Handles (`page.$`) | info |
|
|
226
|
+
| QA-PW-118 | `networkidle`-Warten (flaky by design) | info |
|
|
227
|
+
| QA-PW-123 | Hartkodierte Umgebungs-URLs | warning |
|
|
228
|
+
|
|
229
|
+
</details>
|
|
230
|
+
|
|
231
|
+
<details>
|
|
232
|
+
<summary><strong>CI-Integrität</strong></summary>
|
|
233
|
+
|
|
234
|
+
| ID | Regel | Severity |
|
|
235
|
+
| --------- | ------------------------------------------------------------------------- | -------- |
|
|
236
|
+
| QA-CI-001 | `continue-on-error` maskiert Fehler | error |
|
|
237
|
+
| QA-CI-002 | `\|\| true` schluckt Exit-Codes | error |
|
|
238
|
+
| QA-CI-005 | Report konsumiert, aber nie erzeugt | error |
|
|
239
|
+
| QA-CI-007 | Retry-Wrapper um Tests | warning |
|
|
240
|
+
| QA-CI-008 | Immer-erfolgreicher Step maskiert Fehler | error |
|
|
241
|
+
| QA-CI-009 | Test-Exit-Code wird nicht weitergereicht (`\|` ohne pipefail, `;`-Ketten) | error |
|
|
242
|
+
| QA-CI-010 | Tests übersprungen, wo sie blockieren müssen (skip-on-PR-Guards) | error |
|
|
243
|
+
|
|
244
|
+
</details>
|
|
245
|
+
|
|
246
|
+
<details>
|
|
247
|
+
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
248
|
+
|
|
249
|
+
| ID | Regel | Severity |
|
|
250
|
+
| --------- | ---------------------------------------------------- | -------- |
|
|
251
|
+
| QA-PY-002 | Übersprungener Test (`skip`, nicht-strictes `xfail`) | warning |
|
|
252
|
+
| QA-PY-003 | Testfunktion ohne Assertionen | error |
|
|
253
|
+
| QA-PY-005 | `time.sleep()` in Tests | warning |
|
|
254
|
+
| QA-PY-006 | Leerer Testkörper (`pass`) | info |
|
|
255
|
+
| QA-PY-010 | Zufalls-/Zeitabhängigkeit ohne Freeze | info |
|
|
256
|
+
| QA-PY-012 | Tautologische Assertion | error |
|
|
257
|
+
|
|
258
|
+
20 Python-Regeln insgesamt (QA-PY-001…012 pytest-Hygiene + QA-PY-101…108 Playwright-Python).
|
|
259
|
+
|
|
260
|
+
</details>
|
|
261
|
+
|
|
262
|
+
<details>
|
|
263
|
+
<summary><strong>Java / JUnit · TestNG ☕</strong></summary>
|
|
264
|
+
|
|
265
|
+
| ID | Regel | Severity |
|
|
266
|
+
| --------- | ------------------------------------------ | -------- |
|
|
267
|
+
| QA-JV-101 | Deaktivierter Test (`@Disabled`) | warning |
|
|
268
|
+
| QA-JV-102 | Harter Sleep (`Thread.sleep()`) | warning |
|
|
269
|
+
| QA-JV-103 | Testmethode ohne Assertionen | error |
|
|
270
|
+
| QA-JV-105 | Playwright `waitForTimeout()`-harter Sleep | warning |
|
|
271
|
+
| QA-JV-106 | Spröder Selektor statt Role-Locator | warning |
|
|
272
|
+
| QA-JV-108 | Hartkodierte Umgebungs-URL im Test | info |
|
|
273
|
+
| QA-JV-111 | Pauschales `page.route("**")`-Mock | info |
|
|
274
|
+
|
|
275
|
+
</details>
|
|
276
|
+
|
|
277
|
+
<details>
|
|
278
|
+
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
279
|
+
|
|
280
|
+
| ID | Regel | Severity |
|
|
281
|
+
| --------- | ------------------------------------------------- | -------- |
|
|
282
|
+
| QA-CS-101 | Übersprungener Test (`[Ignore]`, `[Fact(Skip=)]`) | warning |
|
|
283
|
+
| QA-CS-102 | Harter Sleep (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
284
|
+
| QA-CS-103 | Testmethode ohne Assertionen | error |
|
|
285
|
+
| QA-CS-105 | `WaitForTimeoutAsync()`-harter Sleep | warning |
|
|
286
|
+
| QA-CS-106 | Spröder Selektor statt Role-Locator | warning |
|
|
287
|
+
| QA-CS-108 | Hartkodierte Umgebungs-URL im Test | info |
|
|
288
|
+
| QA-CS-111 | Pauschales `page.RouteAsync("**")`-Mock | info |
|
|
289
|
+
|
|
290
|
+
</details>
|
|
291
|
+
|
|
292
|
+
> Der volle Live-Katalog — jede Regel mit Tier, Confidence,
|
|
293
|
+
> False-Positive-Risiko und Autofix-Verfügbarkeit — wird aus der
|
|
294
|
+
> Registry erzeugt:
|
|
295
|
+
>
|
|
296
|
+
> ```bash
|
|
297
|
+
> mjolnir rules --md
|
|
298
|
+
> ```
|
|
299
|
+
>
|
|
300
|
+
> Pro-Regel-Seiten liegen unter [`docs/rules/`](docs/rules/).
|
|
301
|
+
|
|
302
|
+
### Wie viel davon gemessen ist
|
|
303
|
+
|
|
304
|
+
**74 von 99 Regeln tragen eine False-Positive-Rate, gemessen an echtem
|
|
305
|
+
OSS-Code** (jeweils ≥ 10 handklassifizierte Befunde; siehe
|
|
306
|
+
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Die anderen 19 gehen auf der
|
|
307
|
+
Schätzung des Autors. Jeder Scan-Footer sagt dir, wie viele der
|
|
308
|
+
_ausgelösten_ Regeln gemessen sind; `mjolnir rules --unmeasured` listet
|
|
309
|
+
die nicht gemessenen; die `mjolnir explain`-Seite jeder Regel nennt
|
|
310
|
+
ihren Status. Wir veröffentlichen die Rate, selbst wenn sie hässlich
|
|
311
|
+
ist — QA-CS-103 auditiert bei 95 % und ist deshalb quarantäniert. Diese
|
|
312
|
+
78 zu vergrößern ist die fortlaufende Arbeit des Projekts.
|
|
313
|
+
|
|
314
|
+
### Regel-Tiers und Sprachreife
|
|
315
|
+
|
|
316
|
+
Jede Regel ist `core`, `extended` oder `quarantine`, zugewiesen nach
|
|
317
|
+
ihrer **gemessenen** False-Positive-Rate:
|
|
318
|
+
|
|
319
|
+
| Tier | Bedeutung | Standard-Scan | `--strict` |
|
|
320
|
+
| ------------ | ------------------------------------------ | :-----------: | :--------: |
|
|
321
|
+
| `core` | ≤ 10 % gemessene FP | ✅ | ✅ |
|
|
322
|
+
| `extended` | ≤ 30 % gemessene FP | ✅ | ✅ |
|
|
323
|
+
| `quarantine` | darüber, oder noch nicht gemessen (n < 10) | ❌ | ✅ |
|
|
324
|
+
|
|
325
|
+
| Sprache | Adapter | Abdeckung heute |
|
|
326
|
+
| --------------- | ------------- | ------------------------------------------------------------ |
|
|
327
|
+
| TypeScript / JS | Compiler-AST | am breitesten, am meisten gemessen — meist `core`/`extended` |
|
|
328
|
+
| Python / pytest | Regex-Schicht | breit, corpus-auditiert — meist `core`/`extended` |
|
|
329
|
+
| Java | Regex-Schicht | neuer — meist `extended`/`quarantine` |
|
|
330
|
+
| C# / .NET | Regex-Schicht | neuer — meist `extended`/`quarantine` |
|
|
331
|
+
|
|
332
|
+
TypeScript und Python haben die breiteste gemessene Abdeckung. Java und
|
|
333
|
+
C# sind geshippt, dokumentiert und bleiben aus der Schlagzeilen-Zahl
|
|
334
|
+
heraus, bis eine echte Consumer-Suite (nicht die eigenen Tests einer
|
|
335
|
+
Binding-Library) auditiert wurde.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## So funktioniert der Score
|
|
340
|
+
|
|
341
|
+
<p align="center">
|
|
342
|
+
<img src="assets/readme/terminal-hero.svg" alt="Mjölnir-Terminalausgabe — WORTHINESS 75/100 NEEDS WORK, eine Diagnose-Aufschlüsselung nach Kategorien und eine FIX-THIS-FIRST-Liste" width="820" />
|
|
343
|
+
</p>
|
|
344
|
+
|
|
345
|
+
<sub>Neu erzeugt per `npm run docs:hero`;
|
|
346
|
+
[`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
|
|
347
|
+
lässt CI fehlschlagen, wenn es von dem abweicht, was der Reporter
|
|
348
|
+
wirklich druckt.</sub>
|
|
349
|
+
|
|
350
|
+
Der Score ist transparent: **error −8, warning −3, info −1**, dann
|
|
351
|
+
normalisiert um die Suite-Exposition (Abzüge pro Testdeklaration).
|
|
352
|
+
Evidenzgewichtete Abzüge bedeuten: schwache Signale kosten weniger. Das
|
|
353
|
+
Terminal zeigt dieselben diskontierten Zahlen, die der Score verwendet —
|
|
354
|
+
keine Blackbox. Volle Methode: [docs/SCORING.md](docs/SCORING.md).
|
|
355
|
+
|
|
356
|
+
**Urteile**
|
|
357
|
+
|
|
358
|
+
| Score | Urteil |
|
|
359
|
+
| ------- | ---------------- |
|
|
360
|
+
| ≥ 80 | ✓ **WORTHY** |
|
|
361
|
+
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
362
|
+
| < 50 | ✖ **UNWORTHY** |
|
|
363
|
+
|
|
364
|
+
**Evidenzlevel** — jeder Befund trägt eines; es setzt das Gewicht des
|
|
365
|
+
Befunds im Score:
|
|
366
|
+
|
|
367
|
+
| Level | Bedeutung | Score-Auswirkung | Beispiel |
|
|
368
|
+
| ----- | ------------------------ | ---------------- | --------------------------------------------------------- |
|
|
369
|
+
| E2 | Deterministischer Defekt | Voller Abzug | `.only` committed — strukturell beweisbar |
|
|
370
|
+
| E1 | Heuristisches Muster | Halbierter Abzug | Regex-getroffenes `sleep()` — starkes Signal, kein Beweis |
|
|
371
|
+
| E0 | Beobachtung | Null (nur Info) | Gemeldet, gated aber nie CI und zieht nie ab |
|
|
372
|
+
|
|
373
|
+
Die meisten Regeln sind **E1**. Der Tagline „we prove it“ bezieht sich
|
|
374
|
+
auf dieses System: E2-Befunde sind struktureller Beweis; E1-Befunde
|
|
375
|
+
sind korrekt positionierte Warnungen, keine formalen Beweise.
|
|
376
|
+
|
|
377
|
+
Ein leeres Repo scored `null`, nie eine fake 100 — siehe
|
|
378
|
+
[Vertrauensmodell](#vertrauensmodell).
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 🎭 Selector Health Score
|
|
383
|
+
|
|
384
|
+
Die Headline-Metrik für Playwright-Suiten — wie belastbar deine
|
|
385
|
+
Locators sind:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
▚▞ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
389
|
+
|
|
390
|
+
[█████████████████░░░] 83 / 100
|
|
391
|
+
role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Rollenbasierte Locators bekommen die volle Punktzahl.
|
|
395
|
+
CSS-Klassenketten und XPath ruiniern den Score — sie brechen bei jedem
|
|
396
|
+
DOM-Refactor, ohne dir zu sagen, welches Verhalten regressiert ist.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## 🔬 Runtime-Evidenz
|
|
401
|
+
|
|
402
|
+
Statische Flakiness-Erkennung ist Raten. Mjölnir liest **echte
|
|
403
|
+
Ausführungsdaten** — Playwright-JSON-Reports und JUnit-XML von jedem
|
|
404
|
+
Runner:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
mjolnir forensics ./test-results/
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
```text
|
|
411
|
+
▚▞ FLAKINESS LEADERBOARD
|
|
412
|
+
|
|
413
|
+
3 tests · 1 failed · 1 flaky · 1 retried
|
|
414
|
+
|
|
415
|
+
TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
|
|
416
|
+
████████████████████ 6.0s · 2 attempts
|
|
417
|
+
FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
418
|
+
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Ein Test, der nur ab Versuch ≥ 2 besteht, ist kein bestandener Test —
|
|
422
|
+
es ist ein glücklicher Test. Er wird als `TRUE-FLAKE` markiert, egal
|
|
423
|
+
wie grün der finale Haken ist.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## ⚡ Mjölnir ist kein weiterer Linter
|
|
428
|
+
|
|
429
|
+
Linter sagen dir, ob Code Regeln folgt. Mjölnir sagt dir, ob deine
|
|
430
|
+
Verifikation vertraut werden kann.
|
|
431
|
+
|
|
432
|
+
| | ESLint / SonarQube | Coverage-Tools | Manueller Review | **Mjölnir** |
|
|
433
|
+
| ------------------------------------------------------------------- | :----------------: | :------------: | :--------------: | :---------: |
|
|
434
|
+
| CI-Workflow-Integrität (`continue-on-error`, `\|\| true`) | ❌ | ❌ | selten | ✅ |
|
|
435
|
+
| Cross-Sprache (TS, Python, Java, C#) aus einem Tool | ❌ | ❌ | ❌ | ✅ |
|
|
436
|
+
| Benotet die Belastbarkeit von Playwright-Locators (Selector Health) | ❌ | ❌ | selten | ✅ |
|
|
437
|
+
| Findet Tests ohne echte Assertionen | ✅ (Plugin)\* | ❌ | manchmal | ✅ |
|
|
438
|
+
| Findet harte Sleeps (`waitForTimeout`, `time.sleep`) | ✅ (Plugin)\* | ❌ | manchmal | ✅ |
|
|
439
|
+
| Läuft in Sekunden, null Netzwerkaufrufe beim Scannen | ✅ | ✅ | — | ✅ |
|
|
440
|
+
|
|
441
|
+
\*`eslint-plugin-jest` (`expect-expect`) und `eslint-plugin-playwright`
|
|
442
|
+
(`expect-expect`, `no-wait-for-timeout`) decken das für die jeweiligen
|
|
443
|
+
Frameworks ab.
|
|
444
|
+
|
|
445
|
+
**Runtime-Analyse** ist eine eigene Kategorie neben dem statischen
|
|
446
|
+
Linten:
|
|
447
|
+
|
|
448
|
+
| | Playwright Retry Reporter | Allure / ReportPortal | **Mjölnir Forensics** |
|
|
449
|
+
| ------------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
|
|
450
|
+
| Liest echte Laufdaten für `TRUE-FLAKE`-Urteile | teilweise\* | teilweise (Tag) | ✅ |
|
|
451
|
+
| Flaky-Triage-Bericht aus der Ausführungshistorie | ❌ | ✅ | ✅ |
|
|
452
|
+
| Integriert sich in den statischen Würdigkeitswert | ❌ | ❌ | ✅ |
|
|
453
|
+
|
|
454
|
+
\*Playwright trackt Retries intern, erzeugt aber keinen eigenständigen
|
|
455
|
+
Flakiness-Bericht mit Urteil-Labels.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## 🤖 Warum nicht einfach KI-Code-Review?
|
|
460
|
+
|
|
461
|
+
Anderes Problem, andere Schicht. KI-Review kann eine verdächtige
|
|
462
|
+
Teständerung in einem Diff erkennen; sie beweist nicht, dass das
|
|
463
|
+
Verifikationssystem als Ganzes vertrauenswürdig ist — und sie sieht nur
|
|
464
|
+
das Diff, das du ihr zeigst.
|
|
465
|
+
|
|
466
|
+
| | KI-Code-Review (Copilot & co.) | **Mjölnir** |
|
|
467
|
+
| -------------------------------------------------- | :--------------------------------: | :---------------------------: |
|
|
468
|
+
| Kosten pro Scan | Tokens (skaliert mit Diff-Größe) | **Null** (lokal, installiert) |
|
|
469
|
+
| Sieht die ganze Suite + alle CI-Konfigs | Nur das PR-Diff, das du zeigst | **Alles, jedes Mal** |
|
|
470
|
+
| Deterministisch (gleicher Input → gleicher Output) | ❌ (nicht-deterministisch) | **✅** |
|
|
471
|
+
| Findet monatelang schlafende Muster | Nur, wenn es im Kontext steht | **✅** (scannt alle Dateien) |
|
|
472
|
+
| Erinnert sich an Befunde zwischen Läufen | ❌ (kein Gedächtnis über Sessions) | **✅** (Baseline + Diff) |
|
|
473
|
+
| Läuft ohne menschlichen Auslöser | Braucht einen PR oder Prompt | **✅** (CI-Hook, 3 Sekunden) |
|
|
474
|
+
|
|
475
|
+
**Benutze beides.** KI findet Nuance, Intent und Designfehler, die
|
|
476
|
+
keine Regex findet. Mjölnir findet die strukturellen Muster, die KI
|
|
477
|
+
übersieht, weil sie „absichtlich“ aussehen — ein committetes `.only`,
|
|
478
|
+
ein geschluckter Exit-Code, ein `continue-on-error` auf einem
|
|
479
|
+
Test-Job. Das sind keine Bugs, die Denken brauchen; das sind Fakten,
|
|
480
|
+
die Scannen brauchen.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## 🤖 CI-Integration
|
|
485
|
+
|
|
486
|
+
Ein Befehl erzeugt einen PR-Workflow — standardmäßig advisory, nie
|
|
487
|
+
blockierend:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
mjolnir ci install
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Oder binde es nativ in GitHub Code Scanning über SARIF ein:
|
|
494
|
+
|
|
495
|
+
```yaml
|
|
496
|
+
- run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
|
|
497
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
498
|
+
with:
|
|
499
|
+
sarif_file: mjolnir.sarif
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Editor- und Pipeline-Setup für SARIF:
|
|
503
|
+
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
504
|
+
|
|
505
|
+
### Changed-Scope-Abdeckung
|
|
506
|
+
|
|
507
|
+
`--scope changed` attribuiert Befunde zu Zeilen, die dein Branch
|
|
508
|
+
gegenüber dem Merge-Base mit `main` hinzugefügt hat. Es deckt
|
|
509
|
+
Testdateien (`*.spec.*`, `*.test.*`) plus GitHub-Workflow-Dateien und
|
|
510
|
+
Playwright-Konfigurationen im Diff ab. Wenn sich das Merge-Base nicht
|
|
511
|
+
auflösen lässt — flacher Clone, detached HEAD, Nicht-git-Ziel,
|
|
512
|
+
abweichender Default-Branch — degradiert es ehrlich: Befunde fallen auf
|
|
513
|
+
Full-File-Attribution zurück, und der Bericht sagt es. Überschreibe die
|
|
514
|
+
Base-Ref mit `--base <ref>`.
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## Konfiguration
|
|
519
|
+
|
|
520
|
+
Mjölnir ist Zero-Config. Eine optionale `mjolnir.config.json` (oder
|
|
521
|
+
`.mjolnir.json`) im Repo-Root stimmt Severity, Gating und Scope ab —
|
|
522
|
+
sie ändert nie die Erkennungssemantik.
|
|
523
|
+
|
|
524
|
+
| Key | Typ | Wirkung |
|
|
525
|
+
| ------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
526
|
+
| `exclude` | `string[]` | Zusätzliche Ignore-Globs (gitignore-Teilmenge), über den eingebauten Defaults |
|
|
527
|
+
| `gate` | `"advisory" \| "error" \| "warning"` | Welche Severities mit Wert ungleich null beenden (Default `error`; `advisory` blockiert nie) |
|
|
528
|
+
| `severityOverrides` | `{ "<RULE-ID>": severity }` | Rangiert die Befunde einer Regel für dein Repo um |
|
|
529
|
+
| `ignore` | `IgnoreEntry[]` | Unterdrückt Befunde — **`reason` ist Pflicht**; Einträge laufen nach 90 Tagen ab (ein explizites `expires`-Datum, oder die Last-Modified-Zeit der Config-Datei für Einträge ohne eines) |
|
|
530
|
+
| `plugins` | `string[]` | Drittanbieter-Regelpakete (siehe [Vertrauensmodell](#vertrauensmodell)) |
|
|
531
|
+
|
|
532
|
+
```json
|
|
533
|
+
{
|
|
534
|
+
"gate": "error",
|
|
535
|
+
"exclude": ["legacy/**"],
|
|
536
|
+
"severityOverrides": { "QA-PW-118": "warning" },
|
|
537
|
+
"ignore": [
|
|
538
|
+
{
|
|
539
|
+
"ruleId": "QA-TEST-004",
|
|
540
|
+
"files": ["e2e/legacy-login.spec.ts"],
|
|
541
|
+
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
542
|
+
"expires": "2026-12-31"
|
|
543
|
+
}
|
|
544
|
+
]
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
- **`.mjolnirignore`** — eine schlichte gitignore-artige Datei für
|
|
549
|
+
Pfad-Ausschlüsse, gleicher Dialekt wie `exclude`. Nutze sie für
|
|
550
|
+
maschinenweites Rauschen; nutze `exclude`, wenn die Liste in die
|
|
551
|
+
Versionskontrolle gehört, neben dem Rest der Konfiguration.
|
|
552
|
+
- **CLI-Overrides** — `--strict` (Quarantine-Regeln einschließen),
|
|
553
|
+
`--width <cols>` und `--ascii` / `--no-ascii` (Terminal-Rendering),
|
|
554
|
+
`--tone blunt` (schärfere Meldungen), `--max-duration <sec>`
|
|
555
|
+
(begrenzter Teil-Scan).
|
|
556
|
+
- Regel-Unterdrückung und Deprecation-Lebenszyklus:
|
|
557
|
+
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
558
|
+
|
|
559
|
+
`ignore`-Einträge speisen auch den eigenständigen Befehl
|
|
560
|
+
`mjolnir suppressions`, der auflistet, was aktuell unterdrückt ist und
|
|
561
|
+
wann jeder Eintrag abläuft.
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## 📐 Exit-Codes & Verträge
|
|
566
|
+
|
|
567
|
+
Eingefroren — sicher, um CI-Logik darauf zu bauen:
|
|
568
|
+
|
|
569
|
+
| Exit-Code | Bedeutung |
|
|
570
|
+
| --------- | ------------------------------------------------------------------ |
|
|
571
|
+
| `0` | Sauber — keine Befunde auf oder über dem Gate |
|
|
572
|
+
| `1` | Befunde auf oder über dem Gate |
|
|
573
|
+
| `2` | Teil-Scan (Zeitbudget erreicht, unlesbare Dateien) — blockiert nie |
|
|
574
|
+
| `10` | Verwendungsfehler (bad flag, fehlendes Ziel) |
|
|
575
|
+
| `20` | Interner Fehler |
|
|
576
|
+
|
|
577
|
+
Der JSON/SARIF-Bericht ist `schemaVersion: 1`. Regel-IDs
|
|
578
|
+
(`QA-<FAMILY>-NNN`) sind nach dem Shipment unveränderlich und werden
|
|
579
|
+
nie wiederverwendet.
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## Vertrauensmodell
|
|
584
|
+
|
|
585
|
+
- **Local-first** — null Netzwerkaufrufe während des Scannens. Nie.
|
|
586
|
+
Null Telemetrie.
|
|
587
|
+
- **Kein falscher Beweis** — wir sagen lieber „unbekannt“ als
|
|
588
|
+
„verifiziert“. Ein leeres Repo bekommt `score: null`, nie eine fake 100.
|
|
589
|
+
- **Partielle Ehrlichkeit** — wenn die Analyse vorzeitig abgebrochen
|
|
590
|
+
wurde, sagt die Ausgabe es. Nie „complete“, wenn es nicht stimmt.
|
|
591
|
+
- **FP-Firewall** — Erkennung läuft auf einer comment-/string-freien
|
|
592
|
+
Sicht des Codes (TypeScript-Regeln nutzen den Compiler-AST): ein
|
|
593
|
+
Muster in einem Prosa-Kommentar oder einem Doc-Beispiel-String ist
|
|
594
|
+
Dokumentation, kein Befund.
|
|
595
|
+
- **Gemessen, nicht behauptet** — nur Regeln mit einer
|
|
596
|
+
False-Positive-Rate aus echtem OSS-Code fahren in den
|
|
597
|
+
Headline-Tiers (siehe [Wie viel davon gemessen ist](#wie-viel-davon-gemessen-ist));
|
|
598
|
+
der Scan-Footer und `mjolnir rules --unmeasured` sagen dir, welche
|
|
599
|
+
welche sind.
|
|
600
|
+
- **Plugin-Vertrauen** — Plugins sind npm-Pakete, deklariert unter
|
|
601
|
+
`"plugins"`. Es gibt **keine Sandbox**: Plugin-Code läuft mit vollen
|
|
602
|
+
Node-Privilegien, dasselbe Vertrauensmodell wie ESLint- oder
|
|
603
|
+
Vitest-Plugins. Kern-Regel-ID-Präfixe sind reserviert und werden von
|
|
604
|
+
Plugins abgelehnt, um Spoofing zu verhindern.
|
|
605
|
+
- **Workspace-lokale externe Regeln** (ordnerbasiert, null Netzwerk) —
|
|
606
|
+
ein `mjolnir-rules/`-Verzeichnis neben dem Scan-Ziel lädt eigene
|
|
607
|
+
Regeln: JSON-Dateien deklarieren Regex-Muster (kein Code wird
|
|
608
|
+
ausgeführt), `.mjs`/`.js`-Module exportieren `rules` (Full-Node-Vertrauen,
|
|
609
|
+
wie Plugins). Externe Regeln tragen dieselben Trust-Metadaten wie
|
|
610
|
+
Core; sie können nie im Core-Tier fahren (Core verlangt eine
|
|
611
|
+
gemessene FP-Rate aus dem Corpus-Sidecar — ein deklariertes
|
|
612
|
+
`tier: "core"` wird auf `extended` geklemmt), gehorchen Tier-Caps und
|
|
613
|
+
sind drift-geprüft: `mjolnir rules --md --external` rendert den
|
|
614
|
+
Katalog aus den geladenen Dateien (Provenienz `external`), und der
|
|
615
|
+
Matrix-Generator akzeptiert `--external <root>`.
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## 🏗️ Architektur
|
|
620
|
+
|
|
621
|
+
<details>
|
|
622
|
+
<summary>Baum ausklappen</summary>
|
|
623
|
+
|
|
624
|
+
```
|
|
625
|
+
mjolnir/
|
|
626
|
+
├── src/
|
|
627
|
+
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
628
|
+
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
629
|
+
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
630
|
+
│ ├── playwright/ # Selector Health Score engine
|
|
631
|
+
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
632
|
+
│ ├── scope/ # git merge-base changed-scope engine
|
|
633
|
+
│ ├── scorer/ # transparent deduction table + prioritization
|
|
634
|
+
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
635
|
+
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
636
|
+
│ ├── config/ # mjolnir.config.json + suppressions
|
|
637
|
+
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
638
|
+
│ └── commands/ # every subcommand
|
|
639
|
+
└── tests/
|
|
640
|
+
├── fixtures/ # must-fire / must-not-fire per rule
|
|
641
|
+
└── golden/ # frozen score regression locks
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
</details>
|
|
645
|
+
|
|
646
|
+
- **Regeln sind reine Funktionen** — `(SourceFileContext) → Finding[]`,
|
|
647
|
+
kein I/O, keine Globals. Ein neues Ökosystem = ein Adapter + seine
|
|
648
|
+
Regeln.
|
|
649
|
+
- **TypeScript/Playwright nutzt den Compiler-AST** (ts-morph). Python,
|
|
650
|
+
Java und C# laufen auf einer gemeinsamen comment-/string-maskierten
|
|
651
|
+
Regex-Schicht.
|
|
652
|
+
- Eine Tree-sitter-WASM-AST-Schicht für Java und C# existiert und ist
|
|
653
|
+
der nächste Präzisionsschritt — sie ist noch nicht in die synchrone
|
|
654
|
+
Scan-Pipeline verdrahtet.
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## 📚 Dokumentation
|
|
659
|
+
|
|
660
|
+
| Dokument | Was drinsteht |
|
|
661
|
+
| ------------------------------------------------------ | ----------------------------------------- |
|
|
662
|
+
| [docs/SCORING.md](docs/SCORING.md) | Score-Normalisierung + Evidenzgewichtung |
|
|
663
|
+
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Gemessene False-Positive-Raten + Methode |
|
|
664
|
+
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Regelzustände, Unterdrückung, Deprecation |
|
|
665
|
+
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF-Ausgabe + Editor/CI-Setup |
|
|
666
|
+
| [docs/rules/](docs/rules/) | Generierter Pro-Regel-Katalog |
|
|
667
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev-Setup + Beitrags-Workflow |
|
|
668
|
+
| [CHANGELOG.md](CHANGELOG.md) | Release-Historie |
|
|
669
|
+
| [SECURITY.md](SECURITY.md) | Schwachstellenmeldung |
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
## 📈 Status
|
|
674
|
+
|
|
675
|
+
**v0.5.x · offene Beta.** Das JSON-Schema und die Exit-Codes sind
|
|
676
|
+
eingefrorene Verträge. TypeScript und Python haben die breiteste
|
|
677
|
+
gemessene Abdeckung; Java und C# sind neuer — lies sie durch die
|
|
678
|
+
[Tiers-Tabelle](#regel-tiers-und-sprachreife).
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## 🤝 Mitwirken
|
|
683
|
+
|
|
684
|
+
Neue Regeln sind der einfachste erste Beitrag — ein Befehl scaffolded
|
|
685
|
+
die Regel plus ihre Must-Fire- **und** Must-Not-Fire-Fixtures (die
|
|
686
|
+
generierte Regel schlägt absichtlich in ihren Fixtures fehl, bis du
|
|
687
|
+
echte Detektion implementierst — ein Stub kann nicht geshippt werden):
|
|
688
|
+
|
|
689
|
+
```bash
|
|
690
|
+
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Volles Dev-Setup, die Standing-Gate-Befehle und die
|
|
694
|
+
Anti-Creep-/Fixture-Firewall-Gesetze stehen in
|
|
695
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
<div align="center">
|
|
700
|
+
|
|
701
|
+
**Ship keine Tests, denen du nicht vertraust.**
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
npx mjolnir-qa@latest
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**Star ⭐ · Watch 👀 · Contribute 🤝**
|
|
708
|
+
|
|
709
|
+
Gebaut von [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
|
|
710
|
+
|
|
711
|
+
</div>
|