mjolnir-qa 1.0.8 → 2.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/CHANGELOG.md +208 -0
- package/README.ar.md +434 -478
- package/README.bn.md +434 -491
- package/README.br.md +434 -520
- package/README.bs.md +431 -500
- package/README.da.md +433 -509
- package/README.de.md +432 -522
- package/README.es.md +428 -517
- package/README.fr.md +426 -520
- package/README.gr.md +433 -517
- package/README.he.md +433 -475
- package/README.it.md +436 -525
- package/README.ja.md +436 -506
- package/README.ko.md +434 -494
- package/README.md +416 -426
- package/README.no.md +435 -509
- package/README.pl.md +433 -511
- package/README.ru.md +434 -515
- package/README.th.md +434 -484
- package/README.tr.md +427 -504
- package/README.uk.md +433 -505
- package/README.vi.md +436 -494
- package/README.zh.md +433 -462
- package/README.zht.md +433 -462
- package/dist/cli.d.mts +590 -111
- package/dist/cli.mjs +9937 -8951
- package/dist/mcp/stdio.mjs +1904 -816
- package/dist/rolldown-runtime-8H4AJuhK.mjs +14 -0
- package/package.json +7 -4
package/README.da.md
CHANGED
|
@@ -1,398 +1,431 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/readme/
|
|
3
|
+
<img src="assets/readme/hero.svg" alt="Mjölnir. Tests fortæller dig, hvad der bestod. Mjölnir fortæller dig, hvad du kan stole på." width="100%" />
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<br />
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
tilliden brister.
|
|
7
|
+
Mjölnir finder tests, der ikke kan fejle, og pipelines, der ikke kan blive røde,<br />
|
|
8
|
+
og vurderer derefter, hvor langt resultatet er til at stole på, med beviset for hvert point.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
13
|
-
[](LICENSE)
|
|
14
|
-
[](https://nodejs.org)
|
|
15
|
-
|
|
16
|
-
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | [Español](README.es.md) | [Français](README.fr.md) | [Italiano](README.it.md) | Dansk | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
10
|
+
<br />
|
|
17
11
|
|
|
18
|
-
|
|
12
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
13
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
14
|
+
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
15
|
+
[](https://codecov.io/gh/Sergey-Bar/Mjolnir)
|
|
16
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
|
|
17
|
+
[](LICENSE)
|
|
18
|
+
[](https://nodejs.org)
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npx mjolnir-qa@latest
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
[Se det i aktion](#se-det-i-aktion) · [Kom hurtigt i gang](#kom-hurtigt-i-gang) · [Hvad det finder](#hvad-mjölnir-finder) · [Score](#worthiness-scoren) · [Evidens](#evidensmodellen) · [Kørselsanalyse](#kørselsanalyse) · [CI](#ci-integritet) · [Agenter](#ai-agenter) · [Sikkerhed](#tillid-og-sikkerhed) · [Grænser](#hvad-mjölnir-ikke-kan-fortælle-dig) · [Dokumentation](#dokumentation)
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>Læs på et andet sprog — 22 oversættelser</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](README.it.md) | Dansk | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
25
30
|
|
|
26
|
-
[
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
[Dokumentation](#-dokumentation)
|
|
31
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
|
|
32
|
+
|
|
33
|
+
<!-- Source hash: 3541b09e8d04 -->
|
|
34
|
+
|
|
35
|
+
</details>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
<br />
|
|
40
|
+
|
|
41
|
+
## Et grønt flueben er en påstand, ikke et bevis
|
|
42
|
+
|
|
43
|
+
Et grønt flueben betyder, at pipelinen ikke fejlede. Det betyder ikke, at testene kørte, eller at de kunne have fejlet. Hver eneste af disse går grønt igennem:
|
|
44
|
+
|
|
45
|
+
- en committet `.only`, der kørte 3 tests i stedet for 900
|
|
46
|
+
- `continue-on-error: true` på det job, der skulle have blokeret
|
|
47
|
+
- `|| true` efter testkommandoen
|
|
48
|
+
- en test, der ikke tjekker noget, eller som har en tom krop
|
|
49
|
+
- en retry-wrapper, der gør en reel fejl til et heldigt bestået
|
|
50
|
+
- en rapport, som workflowet uploader, men aldrig har genereret
|
|
51
|
+
- et fast sleep, der holder sammen på en race condition
|
|
52
|
+
|
|
53
|
+
Ingen af dem gør pipelinen rød, og hver af dem ser tilsigtet ud i review. Det er derfor, de overlever. Her læser Mjölnir et rigtigt eksempel:
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="assets/readme/scan.svg" alt="Demo-repositoriets CI-workflow, læst linje for linje. Mjölnir markerer hvert fund på den rapporterede linje, med dets regel, hvad der er galt, dets evidensniveau og dets målte falsk-positiv-rate." width="800" />
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<sub>Hvert fund, som demo-scannet rapporterede for dette workflow, på den rapporterede linje. Genereret af `npm run docs:readme-brand` ud fra [`demo-report.json`](assets/readme/demo-report.json) og låst mod afvigelser i CI.</sub>
|
|
60
|
+
|
|
61
|
+
**Streng tilstand.** De mest aggressive registreringer — `.only`, `continue-on-error`, tomme tests, misbrug af genkørsler — lever i karantænelaget. De kører kun med `--strict` og er begrænset til `info`-alvorlighed: de flagger, de blokerer aldrig. Standardscanningen (`npx mjolnir-qa@latest` uden `--strict`) dækker kun kerne- og udvidede regler. Tilføj `--strict` når du også vil have rådgivningslaget.
|
|
62
|
+
|
|
63
|
+
Mjölnir læser testsuiten, CI-workflowene og, hvis du har en, rapporten fra en rigtig kørsel. Det kører ikke dine tests, installerer ikke dine afhængigheder og udfører ikke den kode, det scanner. Og når det ikke har evidens, siger det det i stedet for at opfinde tillid:
|
|
64
|
+
|
|
65
|
+
| Situation | Hvad Mjölnir rapporterer |
|
|
66
|
+
| -------------------------------------------- | ----------------------------------------------------------- |
|
|
67
|
+
| Ingen testdeklarationer fundet | Score `null`, vist som **UNKNOWN**. Aldrig et opdigtet 100. |
|
|
68
|
+
| Ingen baseline eller sammenlignelig revision | **UNKNOWN**, med årsagen angivet. Aldrig et antaget 0. |
|
|
69
|
+
| Scan afbrudt (tidsbudget, ulæselige filer) | **PARTIAL**, exit `2`. Aldrig præsenteret som rent. |
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="assets/readme/how-it-works.svg" alt="Sådan virker Mjölnir. Det læser testsuiten og CI-pipelinen statisk, og rapporten fra en rigtig kørsel, når der er en. Det vægter hvert fund efter dets evidensniveau og tillidsniveau, hvor kun en rigtig kørsel kan nå L3 til L5, og leverer fund, en worthiness-score og en CI-gate med fastfrosne exitkoder. I agent-loopet skriver AI rettelsen, og Mjölnir scanner igen for at bevise den." width="880" />
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<sub>Komponeret til denne side og vist i 1:1. Genereret af `npm run docs:readme-brand` og låst mod afvigelser i CI; score, antal og regel-ID kommer fra [`script.demo.json`](assets/video/script.demo.json), [`demo-report.json`](assets/readme/demo-report.json) og regelregistret, aldrig tastet ind i hånden. Samme billede som plakat: [`architecture.svg`](assets/readme/architecture.svg).</sub>
|
|
76
|
+
|
|
77
|
+
<br />
|
|
78
|
+
|
|
79
|
+
## Se det i aktion
|
|
80
|
+
|
|
81
|
+
Et rigtigt scan af [`examples/demo-repo`](examples/demo-repo), en lille Playwright-suite med et CI-workflow. Her er, hvor dens point forsvandt hen:
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="Mjölnirs opgørelse af fradrag: WORTHINESS 75/100 NEEDS WORK, scoren pr. kategori, fradragsboksen pr. alvorlighed og en FIX THIS FIRST-liste" width="520" />
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
<sub>Genereret af `npm run docs:hero` ud fra et rigtigt scan og låst mod afvigelser i CI. Den fulde `--verbose`-rapport fra samme scan er [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>Se det</strong> — et scan, rettelsen det udskriver, og det nye scan, der beviser den</summary>
|
|
36
91
|
|
|
37
|
-
|
|
92
|
+
<br />
|
|
38
93
|
|
|
39
94
|
<p align="center">
|
|
40
|
-
<
|
|
95
|
+
<a href="assets/video/mjolnir-demo.mp4">
|
|
96
|
+
<img src="assets/video/mjolnir-demo-poster.png" alt="Et billede fra demo-optagelsen: npx mjolnir-qa@latest scanner demo-repositoriet i et terminalvindue" width="900" />
|
|
97
|
+
</a>
|
|
41
98
|
</p>
|
|
42
99
|
|
|
43
|
-
<sub>
|
|
44
|
-
renderet af den rigtige reporter — intet klippet væk. Regenereres med
|
|
45
|
-
`npm run docs:demo`;
|
|
46
|
-
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
-
får CI til at fejle, hvis artefaktet afviger fra, hvad værktøjet
|
|
48
|
-
printer.</sub>
|
|
100
|
+
<sub>Renderet billede for billede ud fra et rigtigt scan af `npm run docs:video`; aldrig optaget fra skærmen. Vælg billedet for at åbne [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
|
|
49
101
|
|
|
50
|
-
|
|
102
|
+
</details>
|
|
51
103
|
|
|
52
|
-
|
|
53
|
-
CI-workflowet og en Python-testfil — fire sprog/formater, ét
|
|
54
|
-
gennemløb.
|
|
55
|
-
2. Den fandt beviser, der svækker tilliden til suiten — en
|
|
56
|
-
`continue-on-error`, der maskerer et job, en `|| true`, der synker
|
|
57
|
-
en exit-kode, hårde sleeps, en skrøbelig selector, hårdkodede
|
|
58
|
-
staging-URL'er, en `networkidle`-venten.
|
|
59
|
-
3. Den gjorde hver af dem til et konkret fund med regel-ID, placering
|
|
60
|
-
og fix — og til én score, du kan gate en PR på.
|
|
104
|
+
### Ét fund helt tæt på
|
|
61
105
|
|
|
62
|
-
|
|
106
|
+
Hvert fund besvarer fire spørgsmål: hvor det er, hvor sikker Mjölnir er, hvor ofte reglen tager fejl, og hvordan det rettes.
|
|
63
107
|
|
|
64
|
-
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="Det første fund fra demo-scannet, præcis som terminalen udskriver det, med dets fire dele markeret: hvor, hvor sikkert, hvor ofte reglen tager fejl, og rettelsen." width="100%" />
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
`mjolnir explain QA-CI-001` udskriver en regels samlede tillidsprofil, inklusive dens målte falsk-positiv-rate og det niveau, raten har givet den:
|
|
65
113
|
|
|
66
114
|
```text
|
|
67
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
68
116
|
|
|
69
117
|
Severity: error
|
|
70
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
71
120
|
Evidence: E2
|
|
72
|
-
|
|
121
|
+
QA impact: False-green risk (FALSE-GREEN)
|
|
122
|
+
Measured FP: 11% (19 hand-classified corpus verdicts)
|
|
123
|
+
FP risk: low (author estimate)
|
|
124
|
+
Languages: yaml
|
|
125
|
+
Frameworks: github-actions, azure-pipelines
|
|
73
126
|
|
|
74
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
75
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
76
129
|
|
|
77
130
|
WHY IT MATTERS
|
|
78
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
79
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
80
133
|
|
|
81
134
|
HOW TO FIX
|
|
82
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
83
|
-
```
|
|
84
136
|
|
|
85
|
-
|
|
86
|
-
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
138
|
+
|
|
139
|
+
WHAT WOULD CHANGE THE VERDICT
|
|
140
|
+
- a run report next to the scan target (mjolnir.report.json or test-results/)
|
|
141
|
+
corroborating this file lifts its findings to L3–L5
|
|
142
|
+
- a documented suppression (mjolnir.config.json) lowers the finding count
|
|
143
|
+
without claiming correctness
|
|
144
|
+
- quarantine findings run only under --strict and are advisory (E0) — they can
|
|
145
|
+
never gate CI
|
|
146
|
+
|
|
147
|
+
NEXT ACTION
|
|
148
|
+
Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
|
|
149
|
+
occurrence of this rule is listed in the scan output.
|
|
150
|
+
|
|
151
|
+
HOW TO VERIFY THE FIX
|
|
152
|
+
Re-run `mjolnir` on the changed file(s) — this finding should no longer
|
|
153
|
+
appear. `mjolnir --scope changed` scopes the check to just what you touched.
|
|
154
|
+
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
156
|
+
```
|
|
87
157
|
|
|
88
|
-
|
|
158
|
+
Det er værdienheden: ét sted, hvor CI rapporterer et bestået, den ikke har gjort sig fortjent til.
|
|
89
159
|
|
|
90
|
-
|
|
160
|
+
<br />
|
|
91
161
|
|
|
92
|
-
|
|
162
|
+
## Kom hurtigt i gang
|
|
93
163
|
|
|
94
164
|
```bash
|
|
95
165
|
npx mjolnir-qa@latest
|
|
96
166
|
```
|
|
97
167
|
|
|
98
|
-
|
|
99
|
-
|
|
168
|
+
Det scanner den aktuelle mappe og udskriver Trust Report: hvad det fandt, hvor langt du kan stole på det, hvorfor, og hvad du skal gøre nu. Det afslutter med `0`, når intet på eller over gaten blev fundet.
|
|
169
|
+
|
|
170
|
+
I CI skal du kun scanne det, grenen har tilføjet, så en ældre testsuite ikke drukner din første pull request:
|
|
100
171
|
|
|
101
172
|
```bash
|
|
102
173
|
npx mjolnir-qa@latest --scope changed
|
|
103
174
|
```
|
|
104
175
|
|
|
105
|
-
|
|
106
|
-
og du er færdig. Alt andet er valgfrit.
|
|
107
|
-
|
|
108
|
-
| Kommando | Hvad den gør |
|
|
109
|
-
| ----------------------------------- | -------------------------------------------------- |
|
|
110
|
-
| `mjolnir` | Scanning af hele repoet + værdighedsscore |
|
|
111
|
-
| `mjolnir --scope changed` | Kun det, din branch introducerede — CI-formen |
|
|
112
|
-
| `mjolnir ci install` | Genererer den vejledende PR-workflow |
|
|
113
|
-
| `mjolnir explain QA-CI-001` | Hvad / hvorfor / fix + målt FP-rate for én regel |
|
|
114
|
-
| `mjolnir rules --unmeasured` | Reglerne, der kører på antagelse, ikke måling |
|
|
115
|
-
| `mjolnir --json` / `--format sarif` | Maskinlæsbart / GitHub Code Scanning |
|
|
116
|
-
| `mjolnir --strict` | Kør også quarantine-tier-regler (højere FP-risiko) |
|
|
117
|
-
|
|
118
|
-
<details>
|
|
119
|
-
<summary><strong>Når noget er flaky</strong></summary>
|
|
176
|
+
`mjolnir ci install` skriver det som et GitHub Actions-workflow med [action'en](https://github.com/Sergey-Bar/Mjolnir#readme) fastlåst til major-tagget `v1` (eller rent `npx` med `--no-action`). Det forbliver rådgivende, indtil du beslutter, at det skal blokere.
|
|
120
177
|
|
|
121
178
|
| Kommando | Hvad den gør |
|
|
122
179
|
| ----------------------------------- | --------------------------------------------------------- |
|
|
123
|
-
| `mjolnir
|
|
124
|
-
| `mjolnir
|
|
125
|
-
| `mjolnir
|
|
126
|
-
| `mjolnir
|
|
127
|
-
|
|
128
|
-
|
|
180
|
+
| `mjolnir` | Trust Report: dom, sikkerhed, næste handling |
|
|
181
|
+
| `mjolnir --scope changed` | Kun det, din gren har tilføjet (CI-formen) |
|
|
182
|
+
| `mjolnir ci install` | Generér det rådgivende PR-workflow (action-baseret) |
|
|
183
|
+
| `mjolnir explain QA-CI-001` | Hvad, hvorfor og rettelse, plus den målte FP-rate |
|
|
184
|
+
| `mjolnir why src/a.spec.ts:42` | Hvorfor netop denne linje blev markeret. Blokerer aldrig. |
|
|
185
|
+
| `mjolnir forensics ./test-results/` | Kørselsevidens fra en rigtig kørsel |
|
|
186
|
+
| `mjolnir trust-report` | Selvstændigt Trust-artefakt (md + json) |
|
|
187
|
+
| `mjolnir handoff` | Udbedringsplan til en kodeagent |
|
|
188
|
+
| `mjolnir --json` / `--format sarif` | Maskinlæsbart output, GitHub Code Scanning |
|
|
189
|
+
| `mjolnir --format codequality` | GitLab Code Quality-rapport (MR-widget-artefakt) |
|
|
190
|
+
| `mjolnir --strict` | Kør også regler på quarantine-niveau (højere FP-risiko) |
|
|
129
191
|
|
|
130
192
|
<details>
|
|
131
|
-
<summary><strong>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
|
136
|
-
|
|
|
137
|
-
| `mjolnir
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
142
|
-
| `mjolnir
|
|
143
|
-
| `mjolnir
|
|
144
|
-
| `mjolnir
|
|
145
|
-
| `mjolnir
|
|
193
|
+
<summary><strong>Alle andre kommandoer</strong> — triage af ustabile tests, rapportering, governance</summary>
|
|
194
|
+
|
|
195
|
+
<br />
|
|
196
|
+
|
|
197
|
+
| Kommando | Hvad den gør |
|
|
198
|
+
| ----------------------------------- | ------------------------------------------------------------------------- |
|
|
199
|
+
| `mjolnir --classic` | Scorebanneret fra før Trust Report |
|
|
200
|
+
| `mjolnir explain verdict` | Hvorfor dommen for det gemte scan er, som den er |
|
|
201
|
+
| `mjolnir triage ./test-results/` | Guidet triage. Hver række ender med en næste handling. |
|
|
202
|
+
| `mjolnir pw-report ./test-results/` | Opsummering af Playwright-kørsel: retries, ustabile tests, de langsomste |
|
|
203
|
+
| `mjolnir doctor:playwright` | Dybdescan kun for Playwright plus Selector Health Score |
|
|
204
|
+
| `mjolnir fix --dry-run` / `fix` | Sikre autorettelser, hver scannet igen for at bevise, at den virkede |
|
|
205
|
+
| `mjolnir baseline` / `diff` | Gem et øjebliksbillede af fund, og rapportér derefter kun nye eller værre |
|
|
206
|
+
| `mjolnir impact --since <ref>` | Hvad et commit tilføjede og løste |
|
|
207
|
+
| `mjolnir summary` | CI-annoteringer og en step-opsummering ud fra en rapport |
|
|
208
|
+
| `mjolnir pr-comment` | En afgrænset PR-kommentar, som Markdown |
|
|
209
|
+
| `mjolnir debt` | Register over testgæld med en omkostningsmodel |
|
|
210
|
+
| `mjolnir handover` | Introduktionskort over suiten til en ny QA-ingeniør |
|
|
211
|
+
| `mjolnir init` | Find frameworks, udskriv en tjekliste til opsætning |
|
|
212
|
+
| `mjolnir suppressions` | List undertrykte fund, til governance |
|
|
213
|
+
| `mjolnir rules --unmeasured` | De regler, der kører på antagelser, ikke målinger |
|
|
214
|
+
| `mjolnir rules --md` | Fuldt regelkatalog (JSON eller Markdown) |
|
|
215
|
+
| `mjolnir doctor` | Selvrevision af Mjölnirs egen regelbase |
|
|
216
|
+
| `mjolnir create-rule <ID>` | Opret skelettet til en ny regel og dens fixtures |
|
|
217
|
+
| `mjolnir stats` | Lokale tællere over alle rettelser, der nogensinde er set |
|
|
218
|
+
| `mjolnir badge` | shields.io-endpoint-JSON og snippet |
|
|
219
|
+
| `mjolnir --cache` | Inkrementelle genscanninger via en lokal cache over domme |
|
|
220
|
+
| `mjolnir --format mermaid` | Diagram over testarkitekturen til en PR-kommentar |
|
|
221
|
+
|
|
222
|
+
`mjolnir help <command>` udskriver brug, eksempler og næste skridt for hver af dem.
|
|
146
223
|
|
|
147
224
|
</details>
|
|
148
225
|
|
|
149
|
-
|
|
150
|
-
`npm i -g mjolnir-qa`. Kræver Node.js ≥ 22.18. Virker på Windows, macOS
|
|
151
|
-
og Linux.
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## 👥 Hvem er det til?
|
|
226
|
+
Kræver **Node.js ≥ 22.18** på Windows, macOS eller Linux. Foretrækker du en global installation? `npm i -g mjolnir-qa`. Minimumskravet kommer fra build-værktøjskæden (tsdown sigter mod den, og release-pipelinen røgtester mod den); kørselsafhængighederne kræver ikke mere end det.
|
|
156
227
|
|
|
157
|
-
|
|
158
|
-
for beviser for, at suiten faktisk fortjener den grønne check, den
|
|
159
|
-
producerer.
|
|
160
|
-
- **Platform-/DevEx-teams**, der har ansvaret for CI-integritet og
|
|
161
|
-
release gates — folkene, for hvem en `continue-on-error` aldrig må
|
|
162
|
-
male en rød pipeline grøn i stilhed.
|
|
163
|
-
- **OSS-maintainere**, der vil have en billig, altid aktiveret
|
|
164
|
-
verifikationsgate, der kører lokalt og i CI uden netværkskald.
|
|
228
|
+
<br />
|
|
165
229
|
|
|
166
|
-
|
|
230
|
+
## Hvad Mjölnir finder
|
|
167
231
|
|
|
168
|
-
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="Virker med din stack: de sprog, testframeworks og CI-systemer, som reglerne dækker, fra regelregistret." width="100%" />
|
|
234
|
+
</p>
|
|
169
235
|
|
|
170
|
-
|
|
171
|
-
| --- | ------------------------------------------------------------------------------------------------------------------- |
|
|
172
|
-
| ⚖️ | **Værdighedsscore** — ét tal, transparent fradragstabel, ingen black box |
|
|
173
|
-
| 🎭 | **Selector Health Score** — bedømmer dine Playwright-locators, ikke kun din pass rate |
|
|
174
|
-
| 🔬 | **Runtime-forundersøgelse** — læser ægte Playwright/JUnit-kørselsdata og fanger `TRUE-FLAKE`, ikke kun statiske gæt |
|
|
175
|
-
| 🚨 | **CI-integritetsregler** — fanger `continue-on-error`, `\|\| true` og andre falsk-grønne tricks |
|
|
176
|
-
| 🐍 | **Alle fire Playwright-bindings** — TypeScript, Python, Java, C#/.NET — plus pytest, JUnit/TestNG og CI-workflows |
|
|
177
|
-
| 🔒 | **Local-first** — nul netværkskald under scanning, nul telemetri, kører på sekunder |
|
|
236
|
+
**79 regler** i fire familier — testhygiejne, testkvalitet, Playwright og CI-integritet — på tværs af TypeScript og JavaScript, Python, Java, C# og GitHub Actions-YAML. De dækker Playwright i alle fire bindings, plus pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest og Mocha, med startdækning for Cypress og Selenium. Ni af dem, så du kan se formen:
|
|
178
237
|
|
|
179
|
-
|
|
238
|
+
| ID | Regel | Alvorlighed | Niveau |
|
|
239
|
+
| ------------ | ----------------------------------------------------------------- | ----------- | ---------- |
|
|
240
|
+
| QA-CI-001 | `continue-on-error` skjuler en fejlende verifikations-gate | error | quarantine |
|
|
241
|
+
| QA-CI-009 | Testens exitkode videregives ikke (`\|` uden pipefail, `;`-kæder) | error | extended |
|
|
242
|
+
| QA-TEST-001 | Fokuseret test committet (`.only`, `fit`) | error | quarantine |
|
|
243
|
+
| QA-TEST-003 | Test uden assertions | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | Promise-assertion uden await | error | quarantine |
|
|
245
|
+
| QA-PW-002 | Locator-assertion uden await | error | core |
|
|
246
|
+
| QA-PW-004 | Skrøbelige CSS/XPath-selektorer | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | Sprunget test over (`skip`, ikke-streng `xfail`) | warning | core |
|
|
248
|
+
| QA-CS-103 | Testmetode uden assertions | error | core |
|
|
180
249
|
|
|
181
|
-
|
|
182
|
-
En regel, der udløses på sin egen negative fixture, kan ikke skibes —
|
|
183
|
-
det er false-positive-firewallen.
|
|
250
|
+
Det fulde katalog genereres ud fra registret, aldrig vedligeholdt i hånden: `mjolnir rules --md`, [`docs/rules/`](docs/rules/) eller [guiden til, hvad det tjekker](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
|
|
184
251
|
|
|
185
252
|
<details>
|
|
186
|
-
<summary><strong>
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
|
193
|
-
|
|
|
194
|
-
| QA-TEST-
|
|
195
|
-
| QA-TEST-
|
|
196
|
-
| QA-TEST-
|
|
253
|
+
<summary><strong>Alle regler nævnt i denne README</strong>, i én tabel</summary>
|
|
254
|
+
|
|
255
|
+
<br />
|
|
256
|
+
|
|
257
|
+
> `quarantine`-regler kører kun under `--strict` og blokerer aldrig (de er begrænset til info). Den viste alvorlighed er forfatterens.
|
|
258
|
+
|
|
259
|
+
| ID | Familie | Regel | Alvorlighed | Niveau |
|
|
260
|
+
| ------------ | ---------- | --------------------------------------------------------------------- | ----------- | ---------- |
|
|
261
|
+
| QA-TEST-001 | Hygiejne | Fokuseret test committet (`.only`, `fit`) | error | quarantine |
|
|
262
|
+
| QA-TEST-002 | Hygiejne | Sprunget test over. Eskalerer til `error` uden en sporet begrundelse. | warning | quarantine |
|
|
263
|
+
| QA-TEST-003 | Hygiejne | Test uden assertions | error | quarantine |
|
|
264
|
+
| QA-TEST-004 | Hygiejne | Fast sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
|
|
265
|
+
| QA-TEST-006 | Hygiejne | Misbrug af retries, der skjuler ustabilitet | warning | quarantine |
|
|
266
|
+
| QA-TEST-010 | Hygiejne | Tom testkrop | error | quarantine |
|
|
267
|
+
| QA-TQUAL-002 | Kvalitet | Tautologisk assertion | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | Kvalitet | Promise-assertion uden await | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | Kvalitet | Udkommenterede tests | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | Locator-assertion uden await | error | core |
|
|
271
|
+
| QA-PW-003 | Playwright | `page.pause()` / `test.only()` committet | error | core |
|
|
272
|
+
| QA-PW-004 | Playwright | Skrøbelige CSS/XPath-selektorer | warning | quarantine |
|
|
273
|
+
| QA-PW-123 | Playwright | Hardkodede miljø-URL'er | warning | quarantine |
|
|
274
|
+
| QA-PW-140 | Playwright | Skærmbillede uden `maxDiffPixelRatio` | warning | core |
|
|
275
|
+
| QA-CI-001 | CI | `continue-on-error` skjuler en fejlende gate | error | quarantine |
|
|
276
|
+
| QA-CI-002 | CI | `\|\| true` sluger exitkoder | error | extended |
|
|
277
|
+
| QA-CI-005 | CI | Rapport brugt, men aldrig genereret | error | quarantine |
|
|
278
|
+
| QA-CI-007 | CI | Retry-wrappers omkring tests | warning | extended |
|
|
279
|
+
| QA-CI-008 | CI | Step, der altid lykkes, skjuler fejl | error | quarantine |
|
|
280
|
+
| QA-CI-009 | CI | Exitkode videregives ikke (`\|` uden pipefail, `;`-kæder) | error | extended |
|
|
281
|
+
| QA-CI-010 | CI | Tests sprunget over, hvor de skal blokere | error | quarantine |
|
|
282
|
+
| QA-PY-002 | Python | Sprunget test over (`skip`, ikke-streng `xfail`) | warning | core |
|
|
283
|
+
| QA-PY-003 | Python | Testfunktion uden assertions | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | `time.sleep()` i tests | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | Tautologisk assertion | error | quarantine |
|
|
286
|
+
| QA-JV-101 | Java | Deaktiveret test (`@Disabled`) | warning | core |
|
|
287
|
+
| QA-JV-102 | Java | Fast sleep (`Thread.sleep()`) | warning | extended |
|
|
288
|
+
| QA-JV-103 | Java | Testmetode uden assertions | error | extended |
|
|
289
|
+
| QA-JV-105 | Java | Fast sleep med Playwright `waitForTimeout()` | warning | core |
|
|
290
|
+
| QA-JV-106 | Java | Skrøbelig selektor i stedet for rollebaseret locator | warning | quarantine |
|
|
291
|
+
| QA-CS-101 | C# | Sprunget test over (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
|
|
292
|
+
| QA-CS-102 | C# | Fast sleep (`Thread.Sleep` / `Task.Delay`) | warning | core |
|
|
293
|
+
| QA-CS-103 | C# | Testmetode uden assertions | error | core |
|
|
294
|
+
| QA-CS-105 | C# | Fast sleep med `WaitForTimeoutAsync()` | warning | extended |
|
|
295
|
+
| QA-CS-106 | C# | Skrøbelig selektor i stedet for rollebaseret locator | warning | quarantine |
|
|
296
|
+
|
|
297
|
+
Python har desuden QA-PY-001…012 (pytest-hygiejne) og QA-PY-101…108 (Playwright til Python). Cypress og Selenium har startsæt på tre regler hver.
|
|
197
298
|
|
|
198
299
|
</details>
|
|
199
300
|
|
|
200
|
-
|
|
201
|
-
<summary><strong>Testkvalitet</strong></summary>
|
|
301
|
+
Hver regel leveres med en must-fire- **og** en must-not-fire-fixture, og en regel, der udløses på sin egen negative fixture, kan ikke leveres. Det er firewallen mod falske positiver; `mjolnir doctor` håndhæver den i dette repositories egen CI.
|
|
202
302
|
|
|
203
|
-
|
|
204
|
-
| ------------ | ------------------------------- | -------- |
|
|
205
|
-
| QA-TQUAL-002 | Tautologisk assertion | error |
|
|
206
|
-
| QA-TQUAL-009 | Assertion på promise uden await | error |
|
|
207
|
-
| QA-TQUAL-011 | Udkommenterede tests | warning |
|
|
303
|
+
### Selector Health Score
|
|
208
304
|
|
|
209
|
-
|
|
305
|
+
`mjolnir doctor:playwright` bedømmer hver locator efter, hvordan den finder et element: som en bruger ville (rolle, label, tekst), via en eksplicit kontrakt (`data-testid`) eller ved et strukturelt tilfælde (CSS-kæder, XPath). Hver fil får en score fra 0 til 100:
|
|
210
306
|
|
|
211
|
-
|
|
212
|
-
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
213
309
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
| QA-PW-003 | `page.pause()` / `test.only()` committet | error |
|
|
218
|
-
| QA-PW-004 | Skrøbelige CSS/XPath-selectors | warning |
|
|
219
|
-
| QA-PW-123 | Hårdkodede miljø-URL'er | warning |
|
|
310
|
+
e2e/login.spec.ts
|
|
311
|
+
[█████████████░░░░░░░] 65 / 100
|
|
312
|
+
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
220
313
|
|
|
221
|
-
|
|
314
|
+
e2e/checkout.spec.ts
|
|
315
|
+
[█████████████████░░░] 86 / 100
|
|
316
|
+
role/text: 3 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
317
|
+
```
|
|
222
318
|
|
|
223
|
-
|
|
224
|
-
<summary><strong>CI-integritet</strong></summary>
|
|
225
|
-
|
|
226
|
-
| ID | Regel | Severity |
|
|
227
|
-
| --------- | ----------------------------------------------------------------- | -------- |
|
|
228
|
-
| QA-CI-001 | `continue-on-error` maskerer fejl | error |
|
|
229
|
-
| QA-CI-002 | `\|\| true` synker exit-koder | error |
|
|
230
|
-
| QA-CI-005 | Rapport forbruges, men genereres aldrig | error |
|
|
231
|
-
| QA-CI-007 | Retry-wrappers omkring tests | warning |
|
|
232
|
-
| QA-CI-008 | Altid-succesfuldt step maskerer fejl | error |
|
|
233
|
-
| QA-CI-009 | Testens exit-kode propageres ikke (`\|` uden pipefail, `;`-kæder) | error |
|
|
234
|
-
| QA-CI-010 | Tests sprunget over, hvor de skal blokere (skip-on-PR-guards) | error |
|
|
319
|
+
Det måler **robusthed, ikke korrekthed**. `.btn.btn-primary > div:nth-child(2)` består i dag og bliver ved med at bestå, indtil nogen rører ved markuppen. En lav score påstår aldrig, at testen er i stykker, kun at den afhænger af markup, som ingen har lovet at bevare.
|
|
235
320
|
|
|
236
|
-
|
|
321
|
+
<br />
|
|
237
322
|
|
|
238
|
-
|
|
239
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
323
|
+
## Worthiness-scoren
|
|
240
324
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
| QA-PY-003 | Testfunktion uden assertions | error |
|
|
245
|
-
| QA-PY-005 | `time.sleep()` i tests | warning |
|
|
246
|
-
| QA-PY-012 | Tautologisk assertion | error |
|
|
325
|
+
<p align="center">
|
|
326
|
+
<img src="assets/readme/score-gauge.svg" alt="Worthiness-skalaen fra 0 til 100, med en markør, der gennemløber hver score: UNWORTHY under 50, NEEDS WORK fra 50 til 79, WORTHY fra 80 til 99, FORGED ved 100" width="720" />
|
|
327
|
+
</p>
|
|
247
328
|
|
|
248
|
-
|
|
329
|
+
<sub>Hver score fra 0 til 100, placeret af den rigtige `deriveScoreState`. Genereret af `npm run docs:gauge` og låst mod afvigelser i CI.</sub>
|
|
249
330
|
|
|
250
|
-
|
|
331
|
+
| Score | Dom |
|
|
332
|
+
| --------- | ------------------------------------------- |
|
|
333
|
+
| `0 – 49` | **UNWORTHY** |
|
|
334
|
+
| `50 – 79` | **NEEDS WORK** |
|
|
335
|
+
| `80 – 99` | **WORTHY** |
|
|
336
|
+
| `100` | **FORGED** |
|
|
337
|
+
| `null` | **UNKNOWN**: ingen testdeklarationer fundet |
|
|
251
338
|
|
|
252
|
-
|
|
253
|
-
<summary><strong>Java / JUnit · TestNG ☕</strong></summary>
|
|
339
|
+
**Sådan beregnes den.** Alvorligheden fastsætter et grundfradrag (`error −8`, `warning −3`, `info −1`), og evidensniveauet nedskriver det: E2 tæller fuldt, E1 halvt (rundet ned), E0 slet ikke. Summen normaliseres efter suitens eksponering, altså fradrag pr. testdeklaration i stedet for pr. fil. Terminalen udskriver de samme nedskrevne tal, som scoren brugte; der er ingen skjult anden model. Detaljer: [docs/SCORING.md](docs/SCORING.md) og [scoringsguiden](https://sergey-bar.github.io/Mjolnir/guide/scoring).
|
|
254
340
|
|
|
255
|
-
|
|
256
|
-
| --------- | -------------------------------------------- | -------- |
|
|
257
|
-
| QA-JV-101 | Deaktiveret test (`@Disabled`) | warning |
|
|
258
|
-
| QA-JV-102 | Hårdt sleep (`Thread.sleep()`) | warning |
|
|
259
|
-
| QA-JV-103 | Testmetode uden assertions | error |
|
|
260
|
-
| QA-JV-105 | Playwright hårdt sleep `waitForTimeout()` | warning |
|
|
261
|
-
| QA-JV-106 | Skrøbelig selector i stedet for role-locator | warning |
|
|
341
|
+
**Hvad 100 ikke betyder.** Det betyder ikke, at softwaren er korrekt, at suiten er tilstrækkelig, eller at produktet er fejlfrit. Det betyder én ting: **ingen af Mjölnirs evaluerede regler gav et fradrag under dette scan og denne evidensmodel.**
|
|
262
342
|
|
|
263
|
-
|
|
343
|
+
<br />
|
|
264
344
|
|
|
265
|
-
|
|
266
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
345
|
+
## Evidensmodellen
|
|
267
346
|
|
|
268
|
-
|
|
269
|
-
| --------- | -------------------------------------------- | -------- |
|
|
270
|
-
| QA-CS-101 | Sprunget test (`[Ignore]`, `[Fact(Skip=)]`) | warning |
|
|
271
|
-
| QA-CS-102 | Hårdt sleep (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
272
|
-
| QA-CS-103 | Testmetode uden assertions | error |
|
|
273
|
-
| QA-CS-105 | Hårdt sleep `WaitForTimeoutAsync()` | warning |
|
|
274
|
-
| QA-CS-106 | Skrøbelig selector i stedet for role-locator | warning |
|
|
347
|
+
Hvert fund har to etiketter: hvor sikker Mjölnir er, og hvor langt fundet er blevet tjekket. Det er forskellen på et værktøj, der rapporterer mønstre, og et værktøj, du kan lade en release afhænge af.
|
|
275
348
|
|
|
276
|
-
|
|
349
|
+
**Hvor sikkert — evidensniveauet.**
|
|
350
|
+
|
|
351
|
+
| Niveau | Navn | Betyder | Fradrag |
|
|
352
|
+
| ------ | -------------------- | -------------------------------------------------------- | ------- |
|
|
353
|
+
| **E2** | Deterministisk bevis | Defekten findes i koden, som den er skrevet | Fuldt |
|
|
354
|
+
| **E1** | Mønsterevidens | Et mønster, der er stærkt knyttet til defekten, matchede | Halvt |
|
|
355
|
+
| **E0** | Observation | Værd at vide. Ikke en påstand om, at noget er galt. | Nul |
|
|
277
356
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
>
|
|
282
|
-
> ```bash
|
|
283
|
-
> mjolnir rules --md
|
|
284
|
-
> ```
|
|
285
|
-
>
|
|
286
|
-
> Sider pr. regel ligger under [`docs/rules/`](docs/rules/).
|
|
287
|
-
|
|
288
|
-
### Hvor meget er målt
|
|
289
|
-
|
|
290
|
-
**78 af 99 regler bærer en false-positive-rate målt mod rigtig OSS-kode**
|
|
291
|
-
(≥ 10 håndklassificerede fund hver; se
|
|
292
|
-
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). De andre 21 skiber på forfatterens
|
|
293
|
-
estimat. Hver scan-fodnote fortæller, hvor mange af de _udløste_ regler,
|
|
294
|
-
der er målt; `mjolnir rules --unmeasured` lister de uregistrerede; hver
|
|
295
|
-
regels `mjolnir explain`-side angiver dens status. Vi offentliggør
|
|
296
|
-
karantæne for det. At få det tal til at vokse er projektets fortsatte
|
|
297
|
-
arbejde.
|
|
298
|
-
|
|
299
|
-
### Regel-tiers og sproglig modenhed
|
|
300
|
-
|
|
301
|
-
Hver regel er `core`, `extended` eller `quarantine`, tildelt ud fra sin
|
|
302
|
-
**målte** false-positive-rate:
|
|
303
|
-
|
|
304
|
-
| Tier | Betydning | Standardscan | `--strict` |
|
|
305
|
-
| ------------ | ----------------------------------------- | :----------: | :--------: |
|
|
306
|
-
| `core` | ≤ 10 % målt FP | ✅ | ✅ |
|
|
307
|
-
| `extended` | ≤ 30 % målt FP | ✅ | ✅ |
|
|
308
|
-
| `quarantine` | over 30 %, eller endnu ikke målt (n < 10) | ❌ | ✅ |
|
|
309
|
-
|
|
310
|
-
| Sprog | Adapter | Dækning i dag |
|
|
311
|
-
| --------------- | ------------ | ------------------------------------------------ |
|
|
312
|
-
| TypeScript / JS | Compiler-AST | bredeste, mest målte — mest `core`/`extended` |
|
|
313
|
-
| Python / pytest | Regex-lag | bredt, corpus-auditeret — mest `core`/`extended` |
|
|
314
|
-
| Java | Regex-lag | nyere — mest `extended`/`quarantine` |
|
|
315
|
-
| C# / .NET | Regex-lag | nyere — mest `extended`/`quarantine` |
|
|
316
|
-
|
|
317
|
-
TypeScript og Python har den bredeste målte dækning. Java og C# er
|
|
318
|
-
skibet, dokumenteret og holdes uden for overskriftstallet, indtil en
|
|
319
|
-
rigtig forbrugersuite (ikke et binding-biblioteks egne tests) er blevet
|
|
320
|
-
auditeret.
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## Sådan fungerer scoren
|
|
357
|
+
Sikkerhed i en detektion er ikke styrken af beviset. En regel kan være sikker på, at den fandt det, den ledte efter, og stadig kigge på en heuristik. E1-fund er der for at blive læst og vurderet, aldrig anvendt i blinde, og den grænse står på fundet i terminalen, i JSON'en og i overdragelsen til agenten.
|
|
358
|
+
|
|
359
|
+
**Hvor langt det er tjekket — tillidsniveauet.** De fleste fund kommer fra at læse din kode. Giv Mjölnir rapporten fra en rigtig testkørsel, så kan det bekræfte, at koden faktisk kørte.
|
|
325
360
|
|
|
326
361
|
<p align="center">
|
|
327
|
-
<img src="assets/readme/
|
|
362
|
+
<img src="assets/readme/trust-ladder.svg" alt="Tillidsstigen fra L0 til L5. L0 til L2 kommer fra at læse koden; L3 til L5 kræver en rigtig kørselsrapport, markeret med et brud i stigen." width="100%" />
|
|
328
363
|
</p>
|
|
329
364
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
365
|
+
| Niveau | Med almindelige ord | Hvad det kræver |
|
|
366
|
+
| ------ | ------------------- | ---------------------------------------------------- |
|
|
367
|
+
| **L0** | Noteret | At læse koden |
|
|
368
|
+
| **L1** | Ligner problemet | At læse koden: et mønster matchede |
|
|
369
|
+
| **L2** | Bevist i koden | At læse koden: defekten er strukturel |
|
|
370
|
+
| **L3** | Filen kørte | En kørselsrapport viser, at fundets fil blev udført |
|
|
371
|
+
| **L4** | Testen kørte | En kørselsrapport viser, at fundets test blev udført |
|
|
372
|
+
| **L5** | Kørslen er enig | Kørslens eget resultat bekræfter defektklassen |
|
|
334
373
|
|
|
335
|
-
|
|
336
|
-
normaliseret efter suitens eksponering (fradrag pr. testdeklaration).
|
|
337
|
-
Bevisvægtede fradrag betyder, at svage signaler koster mindre.
|
|
338
|
-
Terminalen viser de samme diskonterede tal, som scoren bruger — ingen
|
|
339
|
-
black box. Fuld metode: [docs/SCORING.md](docs/SCORING.md).
|
|
374
|
+
Et statisk scan stopper ved L2. Kun en rigtig kørselsrapport (Playwright JSON, Jest eller Vitest JSON, JUnit XML) kan løfte et fund til L3 eller højere, så et fund, der aldrig er set køre, aldrig kan påstå, at det gjorde. Definitioner: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
|
|
340
375
|
|
|
341
|
-
|
|
376
|
+
### Hvor meget af dette er målt
|
|
342
377
|
|
|
343
|
-
|
|
344
|
-
| ------- | ---------------- |
|
|
345
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
346
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
347
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**74 af 79 regler har en falsk-positiv-rate målt mod rigtig OSS-kode** (mindst 10 håndklassificerede fund hver; se [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). De øvrige 5 bygger på forfatterens skøn og siger det, regel for regel, i `mjolnir explain`. `mjolnir rules --unmeasured` lister dem, og hver scanfod angiver, hvor mange af de regler, der faktisk _blev udløst_, der er målt.
|
|
348
379
|
|
|
349
|
-
|
|
350
|
-
scoren:
|
|
380
|
+
Raterne forbliver offentlige, også når de er dårlige. QA-TEST-001 (en committet `.only`) klarer sig dårligt i revisionen på rigtige repositorier og sidder derfor i quarantine. Det aktuelle tal for hver regel, inklusive QA-PW-141, står i revisionen.
|
|
351
381
|
|
|
352
|
-
|
|
353
|
-
| ------ | --------------------- | -------------- | -------------------------------------------------- |
|
|
354
|
-
| E2 | Deterministisk defekt | Fuldt fradrag | Committet `.only` — strukturelt beviseligt |
|
|
355
|
-
| E1 | Heuristisk mønster | Halvt fradrag | Regex-fundet `sleep()` — stærkt signal, ikke bevis |
|
|
356
|
-
| E0 | Iagttagelse | Nul (kun info) | Rapporteret, men gater aldrig CI eller trækker fra |
|
|
382
|
+
### Tillidsniveauer
|
|
357
383
|
|
|
358
|
-
|
|
359
|
-
system: E2-fund er strukturelt bevis; E1-fund er korrekt positionerede
|
|
360
|
-
advarsler, ikke formelle beviser.
|
|
384
|
+
Niveauerne følger den målte falsk-positiv-rate, ikke holdninger:
|
|
361
385
|
|
|
362
|
-
|
|
363
|
-
|
|
386
|
+
| Niveau | Målt FP | Adfærd |
|
|
387
|
+
| -------------- | ------------------------------ | --------------------------------------------------- |
|
|
388
|
+
| **core** | ≤ 10% | Standardrapport, blokerer |
|
|
389
|
+
| **extended** | ≤ 30% | Standardrapport, lavere sikkerhed |
|
|
390
|
+
| **quarantine** | > 30% eller eksplicit erklæret | Kun `--strict`, begrænset til info, blokerer aldrig |
|
|
391
|
+
| _ikke målt_ | n < 10 | Kan ikke forfremmes til core, før den er målt |
|
|
364
392
|
|
|
365
|
-
|
|
393
|
+
FP-bånd kan kun degradere et niveau — de forfremmer aldrig en regel ud af `quarantine`, hvis den var eksplicit erklæret der. En eksplicit karantænesat regel forbliver i quarantine uanset dens målte FP-rate.
|
|
366
394
|
|
|
367
|
-
|
|
395
|
+
Forfremmelse, degradering og modenhed pr. sprog: [reglernes livscyklus](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
368
396
|
|
|
369
|
-
|
|
397
|
+
### Hvorfor det ikke er en linter
|
|
370
398
|
|
|
371
|
-
|
|
372
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
Linters fortæller dig, om koden følger regler. Mjölnir fortæller dig, om din verifikation er til at stole på.
|
|
373
400
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
401
|
+
| | Linters (ESLint, SonarQube) | Coverage-værktøjer | AI-kodereview | **Mjölnir** |
|
|
402
|
+
| ------------------------------------------------------------- | :-------------------------: | :----------------: | :-----------: | :--------------: |
|
|
403
|
+
| Scorer **verifikationssystemet**, ikke produktkoden | Nej | Nej | Nej | Ja |
|
|
404
|
+
| CI-workflowintegritet (`continue-on-error`, `\|\| true`) | Nej | Nej | kun diffen | Ja |
|
|
405
|
+
| Bedømmer robustheden af Playwright-locators (Selector Health) | Nej | Nej | Nej | Ja |
|
|
406
|
+
| Læser rigtige kørselsdata til `TRUE-FLAKE`-domme | Nej | Nej | Nej | Ja |
|
|
407
|
+
| Offentliggør en målt falsk-positiv-rate pr. regel | Nej | Nej | Nej | Ja |
|
|
408
|
+
| Markerer tests uden assertions | Ja\* | Nej | sommetider | Ja |
|
|
409
|
+
| Fanger faste sleeps (`waitForTimeout`, `time.sleep`) | Ja\* | Nej | sommetider | Ja |
|
|
410
|
+
| Deterministisk (samme input, samme output) | Ja | Ja | Nej | Ja |
|
|
411
|
+
| Pris pr. scan | gratis | gratis | tokens | **nul** (lokalt) |
|
|
377
412
|
|
|
378
|
-
|
|
379
|
-
scoren — de brækker ved enhver DOM-refaktor uden at fortælle dig,
|
|
380
|
-
hvilken adfærd der er regresseret.
|
|
413
|
+
<sub>\*Dækket af `eslint-plugin-jest` og `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) og af SonarQubes egne assertion-regler. Kolonnerne beskriver standardadfærden for verifikation af testsuiter; plugins, betalte planer og egne regler ændrer nogle svar. Dette er en positioneringsoversigt, ikke en benchmark.</sub>
|
|
381
414
|
|
|
382
|
-
|
|
415
|
+
Brug også AI-review. Det fanger nuancer, hensigt og designfejl, som intet mønster kan finde. Mjölnir fanger det, AI-review overser, fordi det ser tilsigtet ud: en committet `.only`, en slugt exitkode, en `continue-on-error` på et testjob. Det kræver scanning, ikke ræsonnement.
|
|
383
416
|
|
|
384
|
-
|
|
417
|
+
<br />
|
|
385
418
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
runner
|
|
419
|
+
## Kørselsanalyse
|
|
420
|
+
|
|
421
|
+
Statisk analyse ræsonnerer om kode, der aldrig har kørt. Kørselsanalysen læser, hvad der faktisk skete: Playwright JSON, Jest JSON, Vitest JSON og JUnit XML fra enhver runner.
|
|
389
422
|
|
|
390
423
|
```bash
|
|
391
424
|
mjolnir forensics ./test-results/
|
|
392
425
|
```
|
|
393
426
|
|
|
394
427
|
```text
|
|
395
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
396
429
|
|
|
397
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
398
431
|
|
|
@@ -402,293 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
402
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
403
436
|
```
|
|
404
437
|
|
|
405
|
-
|
|
406
|
-
er en heldig test. Den markeres `TRUE-FLAKE` uanset den endelige grønne
|
|
407
|
-
check.
|
|
438
|
+
`TRUE-FLAKE` betyder ikke, at testen blev prøvet igen. Det betyder, at testen **fejlede mindst ét forsøg og derefter endte grønt**: et heldigt bestået, markeret uanset hvad det endelige flueben siger. `mjolnir triage` gør den historik til et karantæneforslag, og `mjolnir pw-report` opsummerer en kørsel. Det er de samme kørselsrapporter, der løfter fund til tillidsniveau L3 og derover.
|
|
408
439
|
|
|
409
|
-
|
|
440
|
+
<br />
|
|
410
441
|
|
|
411
|
-
##
|
|
442
|
+
## CI-integritet
|
|
412
443
|
|
|
413
|
-
|
|
414
|
-
om din verifikation kan stoles på.
|
|
444
|
+
En test kan bestå, mens pipelinen omkring den ikke kan fejle. Mjölnir læser også workflowene: `continue-on-error`, `|| true`, exitkoder, der aldrig videregives, steps, der altid lykkes, rapporter, der bruges, men aldrig genereres, og gates, der springes over ved netop de hændelser, der burde blokere. Hvert fund angiver job, step og linje og har sit eget evidensniveau.
|
|
415
445
|
|
|
416
|
-
|
|
417
|
-
| --------------------------------------------------------- | :----------------: | :----------------: | :------------: | :---------: |
|
|
418
|
-
| CI-workflow-integritet (`continue-on-error`, `\|\| true`) | ❌ | ❌ | sjældent | ✅ |
|
|
419
|
-
| På tværs af sprog (TS, Python, Java, C#) fra ét værktøj | ❌ | ❌ | ❌ | ✅ |
|
|
420
|
-
| Bedømmer Playwright-locators robusthed (Selector Health) | ❌ | ❌ | sjældent | ✅ |
|
|
421
|
-
| Markerer tests uden rigtige assertions | ✅ (plugin)\* | ❌ | nogle gange | ✅ |
|
|
422
|
-
| Fanger hårde sleeps (`waitForTimeout`, `time.sleep`) | ✅ (plugin)\* | ❌ | nogle gange | ✅ |
|
|
423
|
-
| Kører på sekunder, nul netværkskald under scanning | ✅ | ✅ | — | ✅ |
|
|
446
|
+
Generér PR-workflowet, rådgivende som standard:
|
|
424
447
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
428
451
|
|
|
429
|
-
|
|
452
|
+
Eller tilføj Marketplace-action'en til et workflow, du allerede har:
|
|
430
453
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
436
460
|
|
|
437
|
-
|
|
438
|
-
flakiness-rapport med domme-etiketter.
|
|
461
|
+
Fastlås `@v1` for at følge major-linjen, eller et præcist tag (`@v0.5.32`) for en reproducerbar gate. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) dækker Marketplace, Smithery og MCP-registrene.
|
|
439
462
|
|
|
440
|
-
|
|
463
|
+
Upload SARIF for at få fund ind i GitHub Code Scanning (kræver `security-events: write` på workflow- eller job-niveau):
|
|
441
464
|
|
|
442
|
-
|
|
465
|
+
```yaml
|
|
466
|
+
- run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
|
|
467
|
+
continue-on-error: true
|
|
468
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
469
|
+
if: ${{ !cancelled() }}
|
|
470
|
+
with:
|
|
471
|
+
sarif_file: mjolnir.sarif
|
|
472
|
+
```
|
|
443
473
|
|
|
444
|
-
|
|
445
|
-
testændring i en diff; det beviser ikke, at verifikationssystemet som
|
|
446
|
-
helhed er troværdigt — og det ser kun den diff, du viser det.
|
|
474
|
+
På GitLab skriver `--format codequality` den Code Quality-rapport, som MR-widgetten og diff-annoteringerne læser ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Opsætning af editor og pipeline: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
447
475
|
|
|
448
|
-
|
|
449
|
-
| ------------------------------------------- | :-----------------------------------------: | :--------------------------------: |
|
|
450
|
-
| Omkostning pr. scan | Tokens (skalerer med diff-størrelse) | **Nul** (lokal, installeret) |
|
|
451
|
-
| Ser hele suiten + alle CI-konfigs | Kun den PR-diff, du viser | **Alt, hver gang** |
|
|
452
|
-
| Deterministisk (samme input → samme output) | ❌ (ikke-deterministisk) | **✅** |
|
|
453
|
-
| Fanger mønstre, der har sovet i måneder | Kun hvis det er i konteksten | **✅** (scanner alle filer) |
|
|
454
|
-
| Husker fund mellem kørsler | ❌ (ingen hukommelse på tværs af sessioner) | **✅** (baseline + diff) |
|
|
455
|
-
| Kører uden menneskelig udløser | Kræver en PR eller prompt | **✅** (CI-hook, kører i sekunder) |
|
|
476
|
+
### Tilskrivning i det ændrede scope
|
|
456
477
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
en `continue-on-error` på et testjob. Det er ikke bugs, der kræver
|
|
461
|
-
resonnement; det er fakta, der kræver scanning.
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
462
481
|
|
|
463
|
-
|
|
482
|
+
Fund tilskrives de linjer, din gren har tilføjet, målt mod **merge-base**. Scopet er det samme filsæt, som et fuldt scan finder (TS/JS-specs og adapterkonfigurationer, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), plus ucommittede og usporede ændringer, så det virker, før du committer. Basen findes i rækkefølgen `main → master → origin/main → origin/master → origin/HEAD`; tilsidesæt den med `--base <ref>`.
|
|
464
483
|
|
|
465
|
-
|
|
484
|
+
Når merge-base ikke kan findes (en shallow clone, et detached HEAD, et mål uden for git), falder fundene tilbage til tilskrivning til hele filen, **og rapporten siger det.** En tavs fallback ville være præcis den slags defekt, dette værktøj findes for at fange.
|
|
466
485
|
|
|
467
|
-
|
|
468
|
-
blokerende:
|
|
486
|
+
<br />
|
|
469
487
|
|
|
470
|
-
|
|
471
|
-
mjolnir ci install
|
|
472
|
-
```
|
|
488
|
+
## AI-agenter
|
|
473
489
|
|
|
474
|
-
|
|
490
|
+
Fund er kun noget værd, hvis noget handler på dem.
|
|
475
491
|
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
- uses: github/codeql-action/upload-sarif@v3
|
|
479
|
-
with:
|
|
480
|
-
sarif_file: mjolnir.sarif
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
481
494
|
```
|
|
482
495
|
|
|
483
|
-
|
|
484
|
-
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
485
|
-
|
|
486
|
-
### Changed-scope-dækning
|
|
487
|
-
|
|
488
|
-
`--scope changed` tilskriver fund de linjer, din branch tilføjede i
|
|
489
|
-
forhold til merge-base med `main`. Den dækker testfiler (`*.spec.*`,
|
|
490
|
-
`*.test.*`) plus GitHub-workflowfiler og Playwright-konfigurationer i
|
|
491
|
-
diffen. Når merge-base ikke kan resolve — shallow clone, detached HEAD,
|
|
492
|
-
ikke-git-mål, anden default-branch — degraderer den ærligt: fund
|
|
493
|
-
falder tilbage til hel-fil-attribuering, og rapporten siger det.
|
|
494
|
-
Overskriv base-ref'en med `--base <ref>`.
|
|
496
|
+
**AI skriver rettelsen. Mjölnir verificerer den.** Beviset kommer fra det nye scan, aldrig fra agentens egen melding om succes.
|
|
495
497
|
|
|
496
|
-
|
|
498
|
+
| Kommando | Hvad agenten får |
|
|
499
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
500
|
+
| `mjolnir mcp` | En [MCP](https://modelcontextprotocol.io)-server over stdio. `scan`, `explain` og `diff` bliver til kaldbare værktøjer. |
|
|
501
|
+
| `mjolnir handoff` | En gemt `--json`-rapport bliver til en deterministisk Markdown-plan: hvad der blev fundet, evidensgrænsen for hvert fund, hvad der **ikke** må ændres, og hvordan det verificeres. |
|
|
502
|
+
| `mjolnir install` | Skriver ind i de agentflader, dit repo allerede har (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`), så agenten scanner igen, før den påstår, at den er færdig. |
|
|
497
503
|
|
|
498
|
-
|
|
504
|
+
Tilføj det til en klient med sin egen CLI:
|
|
499
505
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
506
|
+
```bash
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
508
|
+
```
|
|
503
509
|
|
|
504
|
-
|
|
505
|
-
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
506
|
-
| `exclude` | `string[]` | Ekstra ignore-globs (gitignore-undersæt), oven på de indbyggede defaults |
|
|
507
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | Hvilke severities der afslutter med ikke-nul (default `error`; `advisory` blokerer aldrig) |
|
|
508
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | Omrangordner en regels fund for dit repo |
|
|
509
|
-
| `ignore` | `IgnoreEntry[]` | Undertrykker fund — **`reason` er påkrævet**; indgange udløber efter 90 dage (en eksplicit `expires`-dato, eller config-filens last-modified-tid for indgange uden) |
|
|
510
|
-
| `plugins` | `string[]` | Regelpakker fra tredjepart (se [Tillidsmodellen](#tillidsmodellen)) |
|
|
510
|
+
Eller til enhver klient, der tager en `mcpServers`-blok:
|
|
511
511
|
|
|
512
512
|
```json
|
|
513
513
|
{
|
|
514
|
-
"
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
"ignore": [
|
|
518
|
-
{
|
|
519
|
-
"ruleId": "QA-TEST-004",
|
|
520
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
521
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
522
|
-
"expires": "2026-12-31"
|
|
523
|
-
}
|
|
524
|
-
]
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
525
517
|
}
|
|
526
518
|
```
|
|
527
519
|
|
|
528
|
-
|
|
529
|
-
sti-udelukkelser, samme dialekt som `exclude`. Brug den til
|
|
530
|
-
maskinspecifikt støj; brug `exclude`, når listen hører til i
|
|
531
|
-
versionsstyring sammen med resten af konfigurationen.
|
|
532
|
-
- **CLI-overrides** — `--strict` (inkluder karantæneregler),
|
|
533
|
-
`--width <cols>` og `--ascii` / `--no-ascii` (terminalrendering),
|
|
534
|
-
`--tone blunt` (knugere beskeder), `--max-duration <sec>` (begrænset
|
|
535
|
-
delvis scanning).
|
|
536
|
-
- Regelundertrykkelse og deprecation-levetid:
|
|
537
|
-
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
538
|
-
|
|
539
|
-
`ignore`-indgange driver også den selvstændige kommando
|
|
540
|
-
`mjolnir suppressions`, som lister, hvad der i øjeblikket er
|
|
541
|
-
undertrykket, og hvornår hver indgang udløber.
|
|
542
|
-
|
|
543
|
-
---
|
|
544
|
-
|
|
545
|
-
## 📐 Exit-koder & kontrakter
|
|
546
|
-
|
|
547
|
-
Frosne — trygge at bygge CI-logik på:
|
|
548
|
-
|
|
549
|
-
| Exit-kode | Betydning |
|
|
550
|
-
| --------- | -------------------------------------------------------------------- |
|
|
551
|
-
| `0` | Rent — ingen fund på eller over gaten |
|
|
552
|
-
| `1` | Fund på eller over gaten |
|
|
553
|
-
| `2` | Delvis scanning (tidsbudget ramt, ulæselige filer) — blokerer aldrig |
|
|
554
|
-
| `10` | Brugsfejl (ugyldigt flag, manglende mål) |
|
|
555
|
-
| `20` | Intern fejl |
|
|
556
|
-
|
|
557
|
-
JSON/SARIF-rapporten er `schemaVersion: 1`. Regel-ID'er
|
|
558
|
-
(`QA-<FAMILY>-NNN`) er uforanderlige, når de først er skibet, og
|
|
559
|
-
genbruges aldrig.
|
|
560
|
-
|
|
561
|
-
---
|
|
562
|
-
|
|
563
|
-
## Tillidsmodellen
|
|
564
|
-
|
|
565
|
-
- **Local-first** — nul netværkskald under scanning. Ever. Nul
|
|
566
|
-
telemetri.
|
|
567
|
-
- **Ingen falsk bevis** — vi siger hellere „ukendt" end „verificeret".
|
|
568
|
-
Et tomt repo får `score: null`, aldrig en falsk 100.
|
|
569
|
-
- **Delvis ærlighed** — hvis analysen blev afkortet, siger outputtet
|
|
570
|
-
det. Aldrig „complete", når det ikke er.
|
|
571
|
-
- **FP-firewall** — detektion kører på et kommentar-/string-frit view
|
|
572
|
-
af koden (TypeScript-regler bruger compiler-AST): et mønster inde i
|
|
573
|
-
en prosakommentar eller en doc-eksempelstreng er dokumentation, ikke
|
|
574
|
-
et fund.
|
|
575
|
-
- **Målt, ikke påstået** — kun regler med en false-positive-rate fra
|
|
576
|
-
rigtig OSS-kode skiber i overskriftstierne (se
|
|
577
|
-
[Hvor meget er målt](#hvor-meget-er-målt)); scan-fodnoten og
|
|
578
|
-
`mjolnir rules --unmeasured` fortæller dig, hvilke der er hvad.
|
|
579
|
-
- **Plugin-tillid og kørselsport** — plugins er npm-pakker deklareret under
|
|
580
|
-
`"plugins"`; JS-moduler bor i `mjolnir-rules/*.mjs`.
|
|
581
|
-
Der er **ingen sandbox**: plugin-kode kører med fulde
|
|
582
|
-
Node-privilegier, samme tillidsmodel som ESLint- eller
|
|
583
|
-
Vitest-plugins. Derfor er kodekørsel **opt-in ved hver scan**: giv
|
|
584
|
-
`--enable-plugins` (eller sæt `MJOLNIR_ENABLE_PLUGINS=1`), ellers
|
|
585
|
-
indlæses kilderne IKKE — en højlydt stderr-meddelelse lister
|
|
586
|
-
præcis, hvad der blev sprunget over. At skanne utroværdig kode
|
|
587
|
-
udfører den aldrig. JSON-regelmanifester (`mjolnir-rules/*.json`)
|
|
588
|
-
berøres ikke: de deklarerer regex-mønstre og udfører ingen kode af
|
|
589
|
-
konstruktion. Core regel-ID-præfikser er reserverede og afvises
|
|
590
|
-
fra plugins og eksterne regler mod spoofing.
|
|
591
|
-
- **Workspace-lokale eksterne regler** (mappebaserede, nul netværk) —
|
|
592
|
-
en `mjolnir-rules/`-mappe ved siden af scan-målet loader brugerdefinerede
|
|
593
|
-
regler: JSON-filer deklarerer regex-mønstre (ingen kode eksekveres),
|
|
594
|
-
`.mjs`/`.js`-moduler eksporterer `rules` (fuld Node-tillid, som
|
|
595
|
-
plugins). Eksterne regler bærer samme trust-metadata som core; de kan
|
|
596
|
-
aldrig skibe i core-tieren (core kræver en målt FP-rate fra
|
|
597
|
-
corpus-sidecaren — en deklareret `tier: "core"` klemmes til
|
|
598
|
-
`extended`), adlyder tier-grænser og tjekkes for drift:
|
|
599
|
-
`mjolnir rules --md --external` renderer kataloget fra de loadede
|
|
600
|
-
filer (proveniens `external`), og matrixgeneratoren accepterer
|
|
601
|
-
`--external <root>`.
|
|
602
|
-
|
|
603
|
-
---
|
|
604
|
-
|
|
605
|
-
## 🏗️ Arkitektur
|
|
520
|
+
**Rækværket betyder mere end bekvemmeligheden.** Hvert fund i en overdragelse bærer sin grænse. **E2** siger _deterministisk: tjek placeringen, og anvend rettelsen_. **E1** siger _KRÆVER BEKRÆFTELSE: observationen alene beviser ikke defekten_. En agent, der retter E1 i blinde, undertrykker en regel eller redigerer en regel for at hæve scoren, gør præcis det, dette værktøj findes for at fange, så overdragelsen siger det i prompten, lige ved siden af fundet.
|
|
606
521
|
|
|
607
|
-
<
|
|
608
|
-
<summary>Udvid træet</summary>
|
|
522
|
+
<br />
|
|
609
523
|
|
|
610
|
-
|
|
611
|
-
mjolnir/
|
|
612
|
-
├── src/
|
|
613
|
-
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
614
|
-
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
615
|
-
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
616
|
-
│ ├── playwright/ # Selector Health Score engine
|
|
617
|
-
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
618
|
-
│ ├── scope/ # git merge-base changed-scope engine
|
|
619
|
-
│ ├── scorer/ # transparent deduction table + prioritization
|
|
620
|
-
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
621
|
-
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
622
|
-
│ ├── config/ # mjolnir.config.json + suppressions
|
|
623
|
-
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
624
|
-
│ └── commands/ # every subcommand
|
|
625
|
-
└── tests/
|
|
626
|
-
├── fixtures/ # must-fire / must-not-fire per rule
|
|
627
|
-
└── golden/ # frozen score regression locks
|
|
628
|
-
```
|
|
524
|
+
## Tillid og sikkerhed
|
|
629
525
|
|
|
630
|
-
|
|
526
|
+
**Local-first, nul telemetri.** Der findes ingen netværkskapabel API (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) nogen steder i `src/`, og [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) får buildet til at fejle, hvis der dukker en op. Den forbyder også `eval` og `new Function`. At scanne kode, du ikke stoler på, udfører den aldrig: statisk analyse læser kildetekst, og kørselsanalysen parser rapportfiler, der allerede ligger på disken.
|
|
527
|
+
|
|
528
|
+
To forbehold: `npx` henter selv pakken, før noget kører, og garantien dækker `src/`, ikke tredjeparts-plugins.
|
|
529
|
+
|
|
530
|
+
**Plugins kører ikke i en sandbox.** JS-plugins (`mjolnir-rules/*.mjs` eller npm-pakker angivet under `"plugins"`) kører med fulde Node-rettigheder, samme tillidsmodel som ESLint- eller Vitest-plugins. At indlæse dem er et tilvalg **pr. scan**: uden `--enable-plugins` (eller `MJOLNIR_ENABLE_PLUGINS=1`) indlæses deres kilder aldrig, og en besked på stderr lister, hvad der blev sprunget over. JSON-regelmanifester udfører ingen kode, og præfikserne for core-regel-ID'er er reserverede, så et plugin ikke kan udgive sig for at være en af dem. Rapportér sårbarheder via [SECURITY.md](SECURITY.md).
|
|
531
|
+
|
|
532
|
+
**Det kører på sig selv.** En verification trust engine har ingen troværdighed, medmindre den selv kan verificeres. Hver CI-kørsel scanner dette repository med det build, samme kørsel producerede. Gaten fejler ved ethvert fund med alvorligheden error, og også ved et **delvist** scan eller en **regel, der gik ned**, fordi et afkortet selvscan, der ikke rapporterer noget, er præcis den falske grønne farve, dette projekt findes for at fange. `mjolnir doctor` reviderer regelbasen igen i samme kørsel (fixture-firewall, ærlige niveauer, loftet for core-niveauet), og et INCONCLUSIVE-tjek fejler præcis som et fejlende tjek. Begge rapporter uploades som build-artefakter.
|
|
533
|
+
|
|
534
|
+
### Exitkoder og maskinkontrakten
|
|
631
535
|
|
|
632
|
-
|
|
633
|
-
ingen I/O, ingen globals. Nyt økosystem = én adapter + dens regler.
|
|
634
|
-
- **TypeScript/Playwright bruger compiler-AST** (ts-morph). Python,
|
|
635
|
-
Java og C# kører på et delt regex-lag med maskerede kommentare/strenge.
|
|
636
|
-
- Et tree-sitter WASM AST-lag til Java og C# findes og er næste
|
|
637
|
-
præcisionsskridt — det er endnu ikke koblet på den synkrone
|
|
638
|
-
scan-pipeline.
|
|
536
|
+
Fastfrosne, så du kan bygge CI-logik på dem:
|
|
639
537
|
|
|
640
|
-
|
|
538
|
+
| Exitkode | Betydning |
|
|
539
|
+
| -------- | -------------------------------------------------------------------- |
|
|
540
|
+
| `0` | Rent: ingen fund på eller over gaten |
|
|
541
|
+
| `1` | Fund på eller over gaten |
|
|
542
|
+
| `2` | Delvist scan (tidsbudget opbrugt, ulæselige filer). Blokerer aldrig. |
|
|
543
|
+
| `10` | Brugsfejl (forkert flag, manglende mål) |
|
|
544
|
+
| `20` | Intern fejl |
|
|
641
545
|
|
|
642
|
-
|
|
546
|
+
`2` er bevidst forskellig fra `0`: et scan, der ikke blev færdigt, har ikke fundet ingenting. Det er bare ikke færdigt med at lede.
|
|
643
547
|
|
|
644
|
-
|
|
645
|
-
| ------------------------------------------------------ | ------------------------------------------- |
|
|
646
|
-
| [docs/SCORING.md](docs/SCORING.md) | Score-normalisering + bevisvægtning |
|
|
647
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Målte false-positive-rater + metode |
|
|
648
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Regeltilstande, undertrykkelse, deprecation |
|
|
649
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF-output + editor/CI-opsætning |
|
|
650
|
-
| [docs/rules/](docs/rules/) | Genereret katalog pr. regel |
|
|
651
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev-opsætning + bidrag workflow |
|
|
652
|
-
| [CHANGELOG.md](CHANGELOG.md) | Releasehistorik |
|
|
653
|
-
| [SECURITY.md](SECURITY.md) | Sårbarhedsrapportering |
|
|
548
|
+
Alt, hvad en maskine forbruger (MCP-værktøjsresultater, `--json`, SARIF 2.1), kommer fra ét kanonisk resultat under et versioneret, **kun additivt** skema (`schemaVersion: 1`, `contractVersion: 1`), så ingen forbruger behøver at genskabe betydningen ud fra renderet tekst. Se [maskinkontrakten](docs/machine-contract.md). Regel-ID'er (`QA-<FAMILY>-NNN`) kan ikke ændres, når de er udgivet, og genbruges aldrig.
|
|
654
549
|
|
|
655
|
-
|
|
550
|
+
<br />
|
|
656
551
|
|
|
657
|
-
##
|
|
552
|
+
## Hvad Mjölnir ikke kan fortælle dig
|
|
658
553
|
|
|
659
|
-
**
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
554
|
+
- **Det kører ikke dine tests.** Et rent scan er ikke en bestået suite.
|
|
555
|
+
- **Det kan ikke fortælle dig, at en assertion er _forkert_.** `expect(total).toBe(41)` ser sund ud. Mjölnir finder tests, der _ikke kan fejle_, og pipelines, der _ikke kan blive røde_, ikke tests, der tjekker det forkerte.
|
|
556
|
+
- **Det beviser ikke forretningsmæssig korrekthed.** Intet her siger, at dit produkt gør, hvad kravet bad om.
|
|
557
|
+
- **100 er ikke bevis for en god suite.** Om din suite dækker din reelle risiko, er et andet spørgsmål, og det besvarer dette værktøj ikke.
|
|
558
|
+
- **5 af 79 regler bygger på et skøn**, ikke en målt rate. Hver af dem siger det på sit eget fund.
|
|
559
|
+
- **E1 er ikke E2.** Heuristiske fund er værd at læse, ikke værd at anvende i blinde.
|
|
560
|
+
- **Et tomt repo får `null`, aldrig 100.**
|
|
561
|
+
- **En fil ved navn `*.spec.ts` uden testdeklarationer tæller ikke som dækning.** Et repo, hvis eneste spec-filer indeholder imports eller typer (nul `it`/`test`-kald), får `null`, ikke 100.
|
|
663
562
|
|
|
664
|
-
|
|
563
|
+
<br />
|
|
665
564
|
|
|
666
|
-
##
|
|
565
|
+
## Dokumentation
|
|
667
566
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
567
|
+
Det fulde dokumentationssite ligger på <https://sergey-bar.github.io/Mjolnir/>.
|
|
568
|
+
|
|
569
|
+
| Dokument | Hvad det indeholder |
|
|
570
|
+
| ------------------------------------------------------ | --------------------------------------------------- |
|
|
571
|
+
| [docs/SCORING.md](docs/SCORING.md) | Normalisering af scoren og vægtning af evidens |
|
|
572
|
+
| [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Kanonisk ordforråd: ét ord pr. begreb |
|
|
573
|
+
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Målte falsk-positiv-rater og metoden |
|
|
574
|
+
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Regeltilstande, niveauer, undertrykkelse, udfasning |
|
|
575
|
+
| [docs/VERSIONING.md](docs/VERSIONING.md) | Semver-politik, fastfrosne flader, udfasningscyklus |
|
|
576
|
+
| [docs/machine-contract.md](docs/machine-contract.md) | Det kanoniske maskinlæsbare resultat |
|
|
577
|
+
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF-output og opsætning af editor eller CI |
|
|
578
|
+
| [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: Code Quality-rapport, MR-opskrift, gate |
|
|
579
|
+
| [docs/rules/](docs/rules/) | Genereret katalog pr. regel |
|
|
580
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Udviklingsmiljø og bidragsproces |
|
|
581
|
+
| [SUPPORT.md](SUPPORT.md) | Hvor du kan spørge, rapportere og få hjælp |
|
|
582
|
+
| [SECURITY.md](SECURITY.md) | Rapportering af sårbarheder |
|
|
583
|
+
| [CHANGELOG.md](CHANGELOG.md) | Udgivelseshistorik |
|
|
584
|
+
|
|
585
|
+
### Status
|
|
586
|
+
|
|
587
|
+
**Version 1.** JSON-skemaet og exitkoderne er fastfrosne kontrakter. TypeScript og Python har den bredeste målte dækning. Java og C# er nyere; læs dem gennem [modenhedstabellen](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). Hvad der kommer næste gang, uden opdigtede datoer: [den offentlige roadmap](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
|
|
588
|
+
|
|
589
|
+
### Bidrag
|
|
590
|
+
|
|
591
|
+
Nye regler er det nemmeste første bidrag. Én kommando opretter skelettet til reglen med dens must-fire- **og** must-not-fire-fixtures. Den genererede regel fejler bevidst sine egne fixtures, indtil der er skrevet rigtig detektion, fordi en stub, der bliver leveret, er en regel, ingen har målt:
|
|
672
592
|
|
|
673
593
|
```bash
|
|
674
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
675
595
|
```
|
|
676
596
|
|
|
677
|
-
|
|
678
|
-
fixture-firewall-lovene er i [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
597
|
+
Udviklingsmiljøet, kommandoerne til de faste gates samt anti-creep- og fixture-firewall-lovene står i [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
679
598
|
|
|
680
|
-
|
|
599
|
+
<br />
|
|
681
600
|
|
|
682
601
|
<div align="center">
|
|
683
602
|
|
|
684
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="Kør det på dit repo." width="100%" />
|
|
685
604
|
|
|
686
605
|
```bash
|
|
687
606
|
npx mjolnir-qa@latest
|
|
688
607
|
```
|
|
689
608
|
|
|
690
|
-
|
|
609
|
+
[Læs guiden](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Dokumentationssite](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
|
|
610
|
+
|
|
611
|
+
<br />
|
|
612
|
+
|
|
613
|
+
Spørg ikke, om testene bestod.<br />
|
|
614
|
+
Spørg, om evidensen beviser, at de fortjener tillid.
|
|
691
615
|
|
|
692
|
-
Bygget af [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
|
|
616
|
+
<sub>Bygget af [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · MIT-licens</sub>
|
|
693
617
|
|
|
694
618
|
</div>
|