mjolnir-qa 1.0.9 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +204 -0
- package/README.ar.md +434 -478
- package/README.bn.md +434 -491
- package/README.br.md +434 -520
- package/README.bs.md +431 -500
- package/README.da.md +433 -509
- package/README.de.md +432 -522
- package/README.es.md +428 -517
- package/README.fr.md +426 -520
- package/README.gr.md +433 -517
- package/README.he.md +433 -475
- package/README.it.md +436 -525
- package/README.ja.md +436 -506
- package/README.ko.md +434 -494
- package/README.md +453 -438
- package/README.no.md +435 -509
- package/README.pl.md +433 -511
- package/README.ru.md +434 -515
- package/README.th.md +434 -484
- package/README.tr.md +427 -504
- package/README.uk.md +433 -505
- package/README.vi.md +436 -494
- package/README.zh.md +433 -462
- package/README.zht.md +433 -462
- package/dist/cli.d.mts +716 -110
- package/dist/cli.mjs +9815 -22027
- package/dist/mcp/stdio.mjs +2164 -886
- package/dist/rolldown-runtime-8H4AJuhK.mjs +14 -0
- package/dist/scan-pipeline-C0ka-RmX.mjs +2 -0
- package/dist/scan-pipeline-D3Yk2cef.mjs +15309 -0
- package/package.json +14 -8
package/README.bs.md
CHANGED
|
@@ -1,390 +1,431 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/readme/
|
|
3
|
+
<img src="assets/readme/hero.svg" alt="Mjölnir. Testovi vam govore šta je prošlo. Mjölnir vam govori čemu možete vjerovati." width="100%" />
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<br />
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
povjerenje lomi.
|
|
7
|
+
Mjölnir pronalazi testove koji ne mogu pasti i pipelineove koji ne mogu postati crveni,<br />
|
|
8
|
+
a zatim ocjenjuje koliko se rezultatu može vjerovati, uz dokaz za svaki bod.
|
|
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.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
|
|
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
|
+
[Pogledajte kako radi](#pogledajte-kako-radi) · [Brzi početak](#brzi-početak) · [Šta pronalazi](#šta-mjölnir-pronalazi) · [Ocjena](#ocjena-vrijednosti) · [Dokazi](#model-dokaza) · [Analiza pokretanja](#analiza-pokretanja-testova) · [CI](#integritet-ci-ja) · [Agenti](#ai-agenti) · [Sigurnost](#povjerenje-i-sigurnost) · [Ograničenja](#šta-vam-mjölnir-ne-može-reći) · [Dokumentacija](#dokumentacija)
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>Čitajte na drugom jeziku — 22 prijevoda</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.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
|
|
30
|
+
|
|
31
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
|
|
32
|
+
|
|
33
|
+
<!-- Source hash: 3541b09e8d04 -->
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
[Brzi početak](#-brzi-početak) ·
|
|
28
|
-
[Šta provjerava](#-šta-mjölnir-provjerava) ·
|
|
29
|
-
[Bodovanje](#kako-radi-bodovanje) ·
|
|
30
|
-
[CI](#-ci-integracija) · [Konfiguracija](#konfiguracija) ·
|
|
31
|
-
[Dokumentacija](#-dokumentacija)
|
|
35
|
+
</details>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
<br />
|
|
40
|
+
|
|
41
|
+
## Zelena kvačica je tvrdnja, a ne dokaz
|
|
42
|
+
|
|
43
|
+
Zelena kvačica znači da pipeline nije pao. Ne znači da su se testovi izvršili, niti da su mogli pasti. Svaki od ovih slučajeva prolazi zeleno:
|
|
44
|
+
|
|
45
|
+
- commitovani `.only` koji je pokrenuo 3 testa umjesto 900
|
|
46
|
+
- `continue-on-error: true` na jobu koji je trebao blokirati
|
|
47
|
+
- `|| true` nakon naredbe za testove
|
|
48
|
+
- test koji ništa ne provjerava ili ima prazno tijelo
|
|
49
|
+
- retry omotač koji pravi pad pretvara u sretan prolaz
|
|
50
|
+
- izvještaj koji workflow otprema, a nikad ga nije generisao
|
|
51
|
+
- fiksni sleep koji drži na okupu race condition
|
|
52
|
+
|
|
53
|
+
Nijedan od njih ne boji pipeline u crveno, a svaki na reviewu izgleda namjerno. Zato i opstaju. Evo kako Mjölnir čita stvaran primjer:
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="assets/readme/scan.svg" alt="CI workflow demo repozitorija, pročitan red po red. Mjölnir označava svaki nalaz u redu u kojem ga je prijavio, s pravilom, onim što nije u redu, nivoom dokaza i izmjerenom stopom lažno pozitivnih rezultata." width="800" />
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<sub>Svaki nalaz koji je demo skeniranje prijavilo za ovaj workflow, u redu u kojem je prijavljen. Generisano naredbom `npm run docs:readme-brand` iz [`demo-report.json`](assets/readme/demo-report.json) i zaključano protiv odstupanja u CI-ju.</sub>
|
|
60
|
+
|
|
61
|
+
**Strogi režim.** Najagresivnija otkrivanja — `.only`, `continue-on-error`, prazni testovi, zloupotreba ponavljanja — žive u karantinskom nivou. Rade samo pod `--strict` i ograničena su na `info` ozbiljnost: označavaju, ali nikada ne blokiraju. Podrazumijevano skeniranje (`npx mjolnir-qa@latest` bez `--strict`) pokriva samo osnovna i proširena pravila. Dodajte `--strict` kada želite i savjetodavni sloj.
|
|
62
|
+
|
|
63
|
+
Mjölnir čita skup testova, CI workflowe i, ako ga imate, izvještaj stvarnog pokretanja. Ne pokreće vaše testove, ne instalira vaše zavisnosti i ne izvršava kod koji skenira. A kada nema dokaza, to i kaže umjesto da izmišlja pouzdanost:
|
|
64
|
+
|
|
65
|
+
| Situacija | Šta Mjölnir prijavljuje |
|
|
66
|
+
| ------------------------------------------------------------ | ---------------------------------------------------------------- |
|
|
67
|
+
| Nisu pronađene deklaracije testova | Ocjena `null`, prikazana kao **UNKNOWN**. Nikad izmišljenih 100. |
|
|
68
|
+
| Nema baselinea ni uporedive revizije | **UNKNOWN**, uz naveden razlog. Nikad pretpostavljena 0. |
|
|
69
|
+
| Skeniranje prekinuto (vremenski budžet, nečitljive datoteke) | **PARTIAL**, izlaz `2`. Nikad se ne prikazuje kao čisto. |
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="assets/readme/how-it-works.svg" alt="Kako Mjölnir radi. Statički čita skup testova i CI pipeline, kao i izvještaj stvarnog pokretanja kada postoji. Svaki nalaz vaga prema nivou dokaza i nivou povjerenja, pri čemu samo stvarno pokretanje može dosegnuti L3 do L5, i daje nalaze, ocjenu vrijednosti i CI kapiju sa zamrznutim izlaznim kodovima. U petlji agenta, AI piše ispravku, a Mjölnir ponovo skenira da je dokaže." width="880" />
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<sub>Napravljeno za ovu stranicu i prikazano u omjeru 1:1. Generisano naredbom `npm run docs:readme-brand` i zaključano protiv odstupanja u CI-ju; ocjena, brojevi i ID pravila dolaze iz [`script.demo.json`](assets/video/script.demo.json), [`demo-report.json`](assets/readme/demo-report.json) i registra pravila, nikad se ne kucaju ručno. Ista slika kao poster: [`architecture.svg`](assets/readme/architecture.svg).</sub>
|
|
76
|
+
|
|
77
|
+
<br />
|
|
78
|
+
|
|
79
|
+
## Pogledajte kako radi
|
|
36
80
|
|
|
37
|
-
|
|
81
|
+
Stvarno skeniranje [`examples/demo-repo`](examples/demo-repo), malog Playwright skupa testova s CI workflowom. Evo gdje su otišli njegovi bodovi:
|
|
38
82
|
|
|
39
83
|
<p align="center">
|
|
40
|
-
<img src="assets/readme/
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="Mjölnirov pregled odbitaka: WORTHINESS 80/100 WORTHY, ocjena po kategoriji, okvir odbitaka po ozbiljnosti i lista FIX THIS FIRST" width="520" />
|
|
41
85
|
</p>
|
|
42
86
|
|
|
43
|
-
<sub>
|
|
44
|
-
renderiran od pravog reportera — ništa skraćeno. Regenerira se preko
|
|
45
|
-
`npm run docs:demo`;
|
|
46
|
-
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
-
obara CI ako artefakt odskoči od onoga što alat ispisuje.</sub>
|
|
87
|
+
<sub>Generisano naredbom `npm run docs:hero` iz stvarnog skeniranja i zaključano protiv odstupanja u CI-ju. Puni `--verbose` izvještaj istog skeniranja je [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
|
|
48
88
|
|
|
49
|
-
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>Pogledajte</strong> — skeniranje, ispravka koju ispisuje i ponovno skeniranje koje je dokazuje</summary>
|
|
91
|
+
|
|
92
|
+
<br />
|
|
50
93
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
94
|
+
<p align="center">
|
|
95
|
+
<a href="assets/video/mjolnir-demo.mp4">
|
|
96
|
+
<img src="assets/video/mjolnir-demo-poster.png" alt="Kadar demo snimka: npx mjolnir-qa@latest skenira demo repozitorij u prozoru terminala" width="900" />
|
|
97
|
+
</a>
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
<sub>Renderovano kadar po kadar iz stvarnog skeniranja naredbom `npm run docs:video`; nikad snimljeno sa ekrana. Odaberite kadar da otvorite [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
|
|
101
|
+
|
|
102
|
+
</details>
|
|
58
103
|
|
|
59
104
|
### Jedan nalaz izbliza
|
|
60
105
|
|
|
61
|
-
|
|
106
|
+
Svaki nalaz odgovara na četiri pitanja: gdje je, koliko je Mjölnir siguran, koliko često pravilo griješi i kako ga ispraviti.
|
|
107
|
+
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="Prvi nalaz demo skeniranja, tačno onako kako ga terminal ispisuje, s označena četiri dijela: gdje, koliko sigurno, koliko često pravilo griješi, i ispravka." width="100%" />
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
`mjolnir explain QA-CI-001` ispisuje cijeli zapis povjerenja pravila, uključujući izmjerenu stopu lažno pozitivnih rezultata i nivo koji mu je ta stopa donijela:
|
|
62
113
|
|
|
63
114
|
```text
|
|
64
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
65
116
|
|
|
66
117
|
Severity: error
|
|
67
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
68
120
|
Evidence: E2
|
|
69
|
-
|
|
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
|
|
70
126
|
|
|
71
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
72
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
73
129
|
|
|
74
130
|
WHY IT MATTERS
|
|
75
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
76
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
77
133
|
|
|
78
134
|
HOW TO FIX
|
|
79
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
80
|
-
```
|
|
81
136
|
|
|
82
|
-
|
|
83
|
-
poručuje da je nešto prošlo, a nije prošlo.
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
84
138
|
|
|
85
|
-
|
|
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
|
|
86
146
|
|
|
87
|
-
|
|
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.
|
|
88
150
|
|
|
89
|
-
|
|
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
|
+
```
|
|
157
|
+
|
|
158
|
+
To je jedinica vrijednosti: jedno mjesto na kojem CI prijavljuje prolaz koji nije zaslužio.
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## Brzi početak
|
|
90
163
|
|
|
91
164
|
```bash
|
|
92
165
|
npx mjolnir-qa@latest
|
|
93
166
|
```
|
|
94
167
|
|
|
95
|
-
|
|
96
|
-
|
|
168
|
+
Skenira trenutni direktorij i ispisuje Trust Report: šta je pronašao, koliko mu možete vjerovati, zašto i šta dalje uraditi. Završava s `0` kada ništa na nivou kapije ili iznad nije pronađeno.
|
|
169
|
+
|
|
170
|
+
U CI-ju skenirajte samo ono što je grana uvela, kako stari skup testova ne bi potopio vaš prvi pull request:
|
|
97
171
|
|
|
98
172
|
```bash
|
|
99
173
|
npx mjolnir-qa@latest --scope changed
|
|
100
174
|
```
|
|
101
175
|
|
|
102
|
-
|
|
103
|
-
gotovo. Sve ostalo je opciono.
|
|
176
|
+
`mjolnir ci install` to zapisuje kao GitHub Actions workflow, koristeći [action](https://github.com/Sergey-Bar/Mjolnir#readme) prikovan za glavni tag `v1` (ili obični `npx` s `--no-action`). Ostaje savjetodavan dok ne odlučite da treba blokirati.
|
|
104
177
|
|
|
105
|
-
|
|
|
178
|
+
| Naredba | Šta radi |
|
|
106
179
|
| ----------------------------------- | ------------------------------------------------------- |
|
|
107
|
-
| `mjolnir` |
|
|
108
|
-
| `mjolnir --scope changed` | Samo ono što je
|
|
109
|
-
| `mjolnir ci install` | Generiše savjetodavni PR workflow
|
|
110
|
-
| `mjolnir explain QA-CI-001` | Šta
|
|
111
|
-
| `mjolnir
|
|
112
|
-
| `mjolnir
|
|
113
|
-
| `mjolnir
|
|
180
|
+
| `mjolnir` | Trust Report: presuda, pouzdanost, sljedeći korak |
|
|
181
|
+
| `mjolnir --scope changed` | Samo ono što je vaša grana uvela (CI oblik) |
|
|
182
|
+
| `mjolnir ci install` | Generiše savjetodavni PR workflow (zasnovan na actionu) |
|
|
183
|
+
| `mjolnir explain QA-CI-001` | Šta, zašto i ispravka, plus izmjerena FP stopa |
|
|
184
|
+
| `mjolnir why src/a.spec.ts:42` | Zašto je baš ovaj red označen. Nikad ne blokira. |
|
|
185
|
+
| `mjolnir forensics ./test-results/` | Dokazi iz stvarnog pokretanja |
|
|
186
|
+
| `mjolnir trust-report` | Samostalni Trust Artifact (md + json) |
|
|
187
|
+
| `mjolnir handoff` | Plan sanacije za agenta za kodiranje |
|
|
188
|
+
| `mjolnir --json` / `--format sarif` | Mašinski čitljiv izlaz, GitHub Code Scanning |
|
|
189
|
+
| `mjolnir --format codequality` | GitLab Code Quality izvještaj (artefakt MR widgeta) |
|
|
190
|
+
| `mjolnir --strict` | Pokreće i pravila nivoa quarantine (veći FP rizik) |
|
|
114
191
|
|
|
115
192
|
<details>
|
|
116
|
-
<summary><strong>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
| `mjolnir
|
|
123
|
-
| `mjolnir
|
|
193
|
+
<summary><strong>Sve ostale naredbe</strong> — trijaža nestabilnih testova, izvještavanje, upravljanje</summary>
|
|
194
|
+
|
|
195
|
+
<br />
|
|
196
|
+
|
|
197
|
+
| Naredba | Šta radi |
|
|
198
|
+
| ----------------------------------- | ------------------------------------------------------------------------------ |
|
|
199
|
+
| `mjolnir --classic` | Baner ocjene iz vremena prije Trust Reporta |
|
|
200
|
+
| `mjolnir explain verdict` | Zašto je presuda sačuvanog skeniranja takva kakva jeste |
|
|
201
|
+
| `mjolnir triage ./test-results/` | Vođena trijaža. Svaki red završava sljedećim korakom. |
|
|
202
|
+
| `mjolnir pw-report ./test-results/` | Sažetak Playwright pokretanja: ponavljanja, nestabilni testovi, najsporiji |
|
|
203
|
+
| `mjolnir doctor:playwright` | Dubinsko skeniranje samo za Playwright plus Selector Health Score |
|
|
204
|
+
| `mjolnir fix --dry-run` / `fix` | Sigurne automatske ispravke, svaka ponovo skenirana da se dokaže da je uspjela |
|
|
205
|
+
| `mjolnir baseline` / `diff` | Snimak nalaza, a zatim prijava samo novih ili gorih |
|
|
206
|
+
| `mjolnir impact --since <ref>` | Šta je commit uveo i riješio |
|
|
207
|
+
| `mjolnir summary` | CI anotacije i sažetak koraka iz izvještaja |
|
|
208
|
+
| `mjolnir pr-comment` | Ciljani PR komentar, u Markdownu |
|
|
209
|
+
| `mjolnir debt` | Registar testnog duga s modelom troškova |
|
|
210
|
+
| `mjolnir handover` | Mapa skupa testova za novog QA inženjera |
|
|
211
|
+
| `mjolnir init` | Otkriva frameworke, ispisuje listu za podešavanje |
|
|
212
|
+
| `mjolnir suppressions` | Prikazuje utišane nalaze, radi upravljanja |
|
|
213
|
+
| `mjolnir rules --unmeasured` | Pravila koja rade na pretpostavci, a ne na mjerenju |
|
|
214
|
+
| `mjolnir rules --md` | Kompletan katalog pravila (JSON ili Markdown) |
|
|
215
|
+
| `mjolnir doctor` | Samorevizija Mjölnirove vlastite baze pravila |
|
|
216
|
+
| `mjolnir create-rule <ID>` | Pravi kostur novog pravila i njegovih fixturea |
|
|
217
|
+
| `mjolnir stats` | Lokalni brojači svih viđenih ispravki |
|
|
218
|
+
| `mjolnir badge` | JSON za shields.io endpoint i isječak koda |
|
|
219
|
+
| `mjolnir --cache` | Inkrementalna ponovna skeniranja preko lokalnog keša presuda |
|
|
220
|
+
| `mjolnir --format mermaid` | Dijagram arhitekture testova za PR komentar |
|
|
221
|
+
|
|
222
|
+
`mjolnir help <command>` ispisuje upotrebu, primjere i sljedeći korak za svaku od njih.
|
|
124
223
|
|
|
125
224
|
</details>
|
|
126
225
|
|
|
127
|
-
|
|
128
|
-
<summary><strong>Povremeno / izvještaji</strong></summary>
|
|
129
|
-
|
|
130
|
-
| Komanda | Šta radi |
|
|
131
|
-
| ------------------------------- | ------------------------------------------------- |
|
|
132
|
-
| `mjolnir fix --dry-run` / `fix` | Sigurne automatske popravke s dokazom |
|
|
133
|
-
| `mjolnir baseline` / `diff` | Snimak nalaza, pa izvještaj samo novih/pogoršanih |
|
|
134
|
-
| `mjolnir impact --since <ref>` | Šta se promijenilo od ranijeg commita |
|
|
135
|
-
| `mjolnir debt` | Registarr testnog duga s modelom troška |
|
|
136
|
-
| `mjolnir handover` | Karta onboardingu suite-a za novog QA |
|
|
137
|
-
| `mjolnir stats` | Lokalni ukupni brojači viđenih fixova |
|
|
138
|
-
| `mjolnir badge` | shields.io endpoint JSON + snippet |
|
|
139
|
-
| `mjolnir rules --md` | Potpuni katalog pravila (JSON ili Markdown) |
|
|
140
|
-
| `mjolnir doctor` | Samoaudit Mjölnirove vlastite baze pravila |
|
|
141
|
-
| `mjolnir create-rule <ID>` | Scafholduje novo pravilo + fixture |
|
|
142
|
-
| `mjolnir --format mermaid` | Dijagram test arhitekture za PR komentar |
|
|
226
|
+
Zahtijeva **Node.js ≥ 22.18** na Windowsu, macOS-u ili Linuxu. Više volite globalnu instalaciju? `npm i -g mjolnir-qa`. Minimum dolazi iz lanca alata za build (tsdown cilja na njega, a pipeline izdanja radi smoke testove na njemu); zavisnostima za izvršavanje ne treba više od toga.
|
|
143
227
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
Instaliraj globalno umjesto `npx` ako preferiraš: `npm i -g mjolnir-qa`.
|
|
147
|
-
Zahtijeva Node.js ≥ 22.18. Radi na Windows, macOS i Linux.
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## 👥 Za koga je ovo?
|
|
152
|
-
|
|
153
|
-
- **QA / SDET** koji drže e2e ili integracioni suite i trebaju dokaz da
|
|
154
|
-
suite stvarno zaslužuje zeleni check koji proizvodi.
|
|
155
|
-
- **Platform / DevEx timovi** odgovorni za CI integritet i release
|
|
156
|
-
gateove — ljudi kojima je stalo da `continue-on-error` nikad ne
|
|
157
|
-
preboji crveni pipeline u zeleni u tišini.
|
|
158
|
-
- **OSS maintaineri** koji žele jeftin, uvijek uključen verifikacioni
|
|
159
|
-
gate koji radi lokalno i u CI bez mrežnih poziva.
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 🔨 Šta Mjölnir provjerava
|
|
164
|
-
|
|
165
|
-
| | |
|
|
166
|
-
| --- | --------------------------------------------------------------------------------------------------------------------- |
|
|
167
|
-
| ⚖️ | **Ocjenjivački rezultat** — jedan broj, transparentna tabela odbitaka, bez crne kutije |
|
|
168
|
-
| 🎭 | **Selector Health Score** — ocjenjuje tvoje Playwright locatore, ne samo prolaznost |
|
|
169
|
-
| 🔬 | **Runtime forenzika** — čita stvarne Playwright/JUnit podatke runova i hvata `TRUE-FLAKE`, ne samo statičke nagađanja |
|
|
170
|
-
| 🚨 | **Pravila CI integriteta** — hvata `continue-on-error`, `\|\| true` i druge trikove lažno zelenog |
|
|
171
|
-
| 🐍 | **Sva četiri Playwright bindinga** — TypeScript, Python, Java, C#/.NET — plus pytest, JUnit/TestNG i CI workflowi |
|
|
172
|
-
| 🔒 | **Local-first** — nula mrežnih poziva pri skeniranju, nula telemetrije, radi u sekundama |
|
|
228
|
+
<br />
|
|
173
229
|
|
|
174
|
-
|
|
230
|
+
## Šta Mjölnir pronalazi
|
|
175
231
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<details>
|
|
181
|
-
<summary><strong>Test higijena</strong></summary>
|
|
182
|
-
|
|
183
|
-
| ID | Pravilo | Severity |
|
|
184
|
-
| ----------- | ---------------------------------------------------- | -------- |
|
|
185
|
-
| QA-TEST-001 | Commitiran fokusirani test (`.only`, `fit`) | error |
|
|
186
|
-
| QA-TEST-002 | Preskočen test bez opravdanja | error |
|
|
187
|
-
| QA-TEST-002 | Preskočen test s evidentiranim opravdanjem | warning |
|
|
188
|
-
| QA-TEST-003 | Test bez asercija | error |
|
|
189
|
-
| QA-TEST-004 | Tvrdi sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning |
|
|
190
|
-
| QA-TEST-006 | Zloupotreba retrya koja krije flakiness | warning |
|
|
191
|
-
| QA-TEST-010 | Prazno tijelo testa | error |
|
|
192
|
-
|
|
193
|
-
</details>
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="Radi s vašim stackom: jezici, test frameworci i CI sistemi koje pokrivaju njegova pravila, prema registru pravila." width="100%" />
|
|
234
|
+
</p>
|
|
194
235
|
|
|
195
|
-
|
|
196
|
-
<summary><strong>Kvalitet testova</strong></summary>
|
|
236
|
+
**79 pravila** u četiri porodice — higijena testova, kvalitet testova, Playwright i integritet CI-ja — za TypeScript i JavaScript, Python, Javu, C# i GitHub Actions YAML. Pokrivaju Playwright u sva četiri bindinga, plus pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest i Mochu, s početnom pokrivenošću za Cypress i Selenium. Devet od njih, da se vidi oblik:
|
|
197
237
|
|
|
198
|
-
| ID | Pravilo
|
|
199
|
-
| ------------ |
|
|
200
|
-
| QA-
|
|
201
|
-
| QA-
|
|
202
|
-
| QA-
|
|
238
|
+
| ID | Pravilo | Ozbiljnost | Nivo |
|
|
239
|
+
| ------------ | -------------------------------------------------------------------- | ---------- | ---------- |
|
|
240
|
+
| QA-CI-001 | `continue-on-error` maskira kapiju verifikacije koja pada | error | quarantine |
|
|
241
|
+
| QA-CI-009 | Izlazni kod testova se ne prosljeđuje (`\|` bez pipefail, `;` lanci) | error | extended |
|
|
242
|
+
| QA-TEST-001 | Commitovan fokusirani test (`.only`, `fit`) | error | quarantine |
|
|
243
|
+
| QA-TEST-003 | Test bez asercija | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | Asercija na promise bez await | error | quarantine |
|
|
245
|
+
| QA-PW-002 | Asercija na lokatoru bez await | error | core |
|
|
246
|
+
| QA-PW-004 | Krhki CSS/XPath selektori | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | Preskočen test (`skip`, nestriktni `xfail`) | warning | core |
|
|
248
|
+
| QA-CS-103 | Testna metoda bez asercija | error | core |
|
|
203
249
|
|
|
204
|
-
|
|
250
|
+
Kompletan katalog se generiše iz registra, nikad se ne održava ručno: `mjolnir rules --md`, [`docs/rules/`](docs/rules/) ili [vodič o tome šta provjerava](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
|
|
205
251
|
|
|
206
252
|
<details>
|
|
207
|
-
<summary><strong>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
|
214
|
-
|
|
|
253
|
+
<summary><strong>Svako pravilo navedeno u ovom README-u</strong>, u jednoj tabeli</summary>
|
|
254
|
+
|
|
255
|
+
<br />
|
|
256
|
+
|
|
257
|
+
> Pravila `quarantine` se pokreću samo uz `--strict` i nikad ne blokiraju (ograničena su na info). Prikazana ozbiljnost je ona koju je odredio autor.
|
|
258
|
+
|
|
259
|
+
| ID | Porodica | Pravilo | Ozbiljnost | Nivo |
|
|
260
|
+
| ------------ | ---------- | ------------------------------------------------------------ | ---------- | ---------- |
|
|
261
|
+
| QA-TEST-001 | Higijena | Commitovan fokusirani test (`.only`, `fit`) | error | quarantine |
|
|
262
|
+
| QA-TEST-002 | Higijena | Preskočen test. Bez praćenog razloga eskalira na `error`. | warning | quarantine |
|
|
263
|
+
| QA-TEST-003 | Higijena | Test bez asercija | error | quarantine |
|
|
264
|
+
| QA-TEST-004 | Higijena | Fiksni sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
|
|
265
|
+
| QA-TEST-006 | Higijena | Zloupotreba ponavljanja koja skriva nestabilnost | warning | quarantine |
|
|
266
|
+
| QA-TEST-010 | Higijena | Prazno tijelo testa | error | quarantine |
|
|
267
|
+
| QA-TQUAL-002 | Kvalitet | Tautološka asercija | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | Kvalitet | Asercija na promise bez await | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | Kvalitet | Zakomentarisani testovi | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | Asercija na lokatoru bez await | error | core |
|
|
271
|
+
| QA-PW-003 | Playwright | Commitovani `page.pause()` / `test.only()` | error | core |
|
|
272
|
+
| QA-PW-004 | Playwright | Krhki CSS/XPath selektori | warning | quarantine |
|
|
273
|
+
| QA-PW-123 | Playwright | Hardkodirani URL-ovi okruženja | warning | quarantine |
|
|
274
|
+
| QA-PW-140 | Playwright | Snimak ekrana bez `maxDiffPixelRatio` | warning | core |
|
|
275
|
+
| QA-CI-001 | CI | `continue-on-error` maskira kapiju koja pada | error | quarantine |
|
|
276
|
+
| QA-CI-002 | CI | `\|\| true` guta izlazne kodove | error | extended |
|
|
277
|
+
| QA-CI-005 | CI | Izvještaj se koristi, ali se nikad ne generiše | error | quarantine |
|
|
278
|
+
| QA-CI-007 | CI | Retry omotači oko testova | warning | extended |
|
|
279
|
+
| QA-CI-008 | CI | Korak koji uvijek uspijeva maskira padove | error | quarantine |
|
|
280
|
+
| QA-CI-009 | CI | Izlazni kod se ne prosljeđuje (`\|` bez pipefail, `;` lanci) | error | extended |
|
|
281
|
+
| QA-CI-010 | CI | Testovi preskočeni tamo gdje moraju blokirati | error | quarantine |
|
|
282
|
+
| QA-PY-002 | Python | Preskočen test (`skip`, nestriktni `xfail`) | warning | core |
|
|
283
|
+
| QA-PY-003 | Python | Testna funkcija bez asercija | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | `time.sleep()` u testovima | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | Tautološka asercija | error | quarantine |
|
|
286
|
+
| QA-JV-101 | Java | Onemogućen test (`@Disabled`) | warning | core |
|
|
287
|
+
| QA-JV-102 | Java | Fiksni sleep (`Thread.sleep()`) | warning | extended |
|
|
288
|
+
| QA-JV-103 | Java | Testna metoda bez asercija | error | extended |
|
|
289
|
+
| QA-JV-105 | Java | Fiksni sleep preko Playwright `waitForTimeout()` | warning | core |
|
|
290
|
+
| QA-JV-106 | Java | Krhki selektor umjesto lokatora zasnovanog na ulozi | warning | quarantine |
|
|
291
|
+
| QA-CS-101 | C# | Preskočen test (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
|
|
292
|
+
| QA-CS-102 | C# | Fiksni sleep (`Thread.Sleep` / `Task.Delay`) | warning | core |
|
|
293
|
+
| QA-CS-103 | C# | Testna metoda bez asercija | error | core |
|
|
294
|
+
| QA-CS-105 | C# | Fiksni sleep preko `WaitForTimeoutAsync()` | warning | extended |
|
|
295
|
+
| QA-CS-106 | C# | Krhki selektor umjesto lokatora zasnovanog na ulozi | warning | quarantine |
|
|
296
|
+
|
|
297
|
+
Python dolazi i s pravilima QA-PY-001…012 (higijena pytesta) i QA-PY-101…108 (Playwright za Python). Cypress i Selenium imaju početne skupove od po tri pravila.
|
|
215
298
|
|
|
216
299
|
</details>
|
|
217
300
|
|
|
218
|
-
|
|
219
|
-
<summary><strong>CI integritet</strong></summary>
|
|
220
|
-
|
|
221
|
-
| ID | Pravilo | Severity |
|
|
222
|
-
| --------- | --------------------------------------------------------------- | -------- |
|
|
223
|
-
| QA-CI-001 | `continue-on-error` maskira padove | error |
|
|
224
|
-
| QA-CI-002 | `\|\| true` guta exit kodove | error |
|
|
225
|
-
| QA-CI-005 | Izvještaj se troši ali nikad ne generira | error |
|
|
226
|
-
| QA-CI-007 | Retry omotači oko testova | warning |
|
|
227
|
-
| QA-CI-008 | Uvijek uspješan step maskira padove | error |
|
|
228
|
-
| QA-CI-009 | Exit kod testa se ne propagira (`\|` bez pipefail, `;` lanci) | error |
|
|
229
|
-
| QA-CI-010 | Testovi preskaču se gdje moraju blokirati (skip-on-PR guardovi) | error |
|
|
230
|
-
|
|
231
|
-
</details>
|
|
301
|
+
Svako pravilo se isporučuje s must-fire **i** must-not-fire fixtureom, a pravilo koje se okine na vlastitom negativnom fixtureu ne može biti isporučeno. To je zaštitni zid od lažno pozitivnih rezultata; `mjolnir doctor` ga provodi u vlastitom CI-ju ovog repozitorija.
|
|
232
302
|
|
|
233
|
-
|
|
234
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
303
|
+
### Selector Health Score
|
|
235
304
|
|
|
236
|
-
|
|
237
|
-
| --------- | ----------------------------------------- | -------- |
|
|
238
|
-
| QA-PY-002 | Preskočen test (`skip`, nestrogi `xfail`) | warning |
|
|
239
|
-
| QA-PY-003 | Test funkcija bez asercija | error |
|
|
240
|
-
| QA-PY-005 | `time.sleep()` u testovima | warning |
|
|
241
|
-
| QA-PY-012 | Tautološka asercija | error |
|
|
305
|
+
`mjolnir doctor:playwright` ocjenjuje svaki lokator prema tome kako pronalazi element: onako kako bi to uradio korisnik (uloga, oznaka, tekst), preko eksplicitnog ugovora (`data-testid`) ili strukturnom slučajnošću (CSS lanci, XPath). Svaka datoteka dobija ocjenu od 0 do 100:
|
|
242
306
|
|
|
243
|
-
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
244
309
|
|
|
245
|
-
|
|
310
|
+
e2e/login.spec.ts
|
|
311
|
+
[█████████████░░░░░░░] 65 / 100
|
|
312
|
+
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
246
313
|
|
|
247
|
-
|
|
248
|
-
|
|
314
|
+
e2e/checkout.spec.ts
|
|
315
|
+
[██████████████████░░] 88 / 100
|
|
316
|
+
role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
317
|
+
```
|
|
249
318
|
|
|
250
|
-
|
|
251
|
-
| --------- | ----------------------------------------- | -------- |
|
|
252
|
-
| QA-JV-101 | Onemogućen test (`@Disabled`) | warning |
|
|
253
|
-
| QA-JV-102 | Tvrdi sleep (`Thread.sleep()`) | warning |
|
|
254
|
-
| QA-JV-103 | Test metoda bez asercija | error |
|
|
255
|
-
| QA-JV-105 | Tvrdi sleep Playwright `waitForTimeout()` | warning |
|
|
256
|
-
| QA-JV-106 | Krhki selektor umjesto role lokatora | warning |
|
|
319
|
+
Ovo mjeri **otpornost, a ne ispravnost**. `.btn.btn-primary > div:nth-child(2)` prolazi danas i nastavlja prolaziti dok neko ne dirne markup. Niska ocjena nikad ne tvrdi da je test pokvaren, samo da zavisi od markupa koji niko nije obećao sačuvati.
|
|
257
320
|
|
|
258
|
-
|
|
321
|
+
<br />
|
|
259
322
|
|
|
260
|
-
|
|
261
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
323
|
+
## Ocjena vrijednosti
|
|
262
324
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
| QA-CS-102 | Tvrdi sleep (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
267
|
-
| QA-CS-103 | Test metoda bez asercija | error |
|
|
268
|
-
| QA-CS-105 | Tvrdi sleep `WaitForTimeoutAsync()` | warning |
|
|
269
|
-
| QA-CS-106 | Krhki selektor umjesto role lokatora | warning |
|
|
325
|
+
<p align="center">
|
|
326
|
+
<img src="assets/readme/score-gauge.svg" alt="Skala vrijednosti od 0 do 100, s markerom koji prelazi svaku ocjenu: UNWORTHY ispod 50, NEEDS WORK od 50 do 79, WORTHY od 80 do 99, FORGED na 100" width="720" />
|
|
327
|
+
</p>
|
|
270
328
|
|
|
271
|
-
|
|
329
|
+
<sub>Svaka ocjena od 0 do 100, postavljena stvarnim `deriveScoreState`. Generisano naredbom `npm run docs:gauge` i zaključano protiv odstupanja u CI-ju.</sub>
|
|
272
330
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
> Stranice po pravilu žive u [`docs/rules/`](docs/rules/).
|
|
331
|
+
| Ocjena | Presuda |
|
|
332
|
+
| --------- | ----------------------------------------------- |
|
|
333
|
+
| `0 – 49` | **UNWORTHY** |
|
|
334
|
+
| `50 – 79` | **NEEDS WORK** |
|
|
335
|
+
| `80 – 99` | **WORTHY** |
|
|
336
|
+
| `100` | **FORGED** |
|
|
337
|
+
| `null` | **UNKNOWN**: nisu pronađene deklaracije testova |
|
|
281
338
|
|
|
282
|
-
|
|
339
|
+
**Kako se računa.** Ozbiljnost određuje osnovni odbitak (`error −8`, `warning −3`, `info −1`), a nivo dokaza ga umanjuje: E2 se računa u potpunosti, E1 upola (zaokruženo nadolje), E0 nikako. Zbir se normalizuje prema izloženosti skupa testova, odnosno odbici po deklaraciji testa umjesto po datoteci. Terminal ispisuje iste umanjene brojeve koje je ocjena koristila; nema skrivenog drugog modela. Detalji: [docs/SCORING.md](docs/SCORING.md) i [vodič za ocjenjivanje](https://sergey-bar.github.io/Mjolnir/guide/scoring).
|
|
283
340
|
|
|
284
|
-
**
|
|
285
|
-
OSS kodom** (≥ 10 ručno klasificiranih nalaza svako; vidi
|
|
286
|
-
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Ostalih 21 izlazi na autorovoj
|
|
287
|
-
procjeni. Podnožje svakog skana kaže koliko od _okinutih_ pravila je
|
|
288
|
-
izmjereno; `mjolnir rules --unmeasured` izlista neizmjerena; stranica
|
|
289
|
-
`mjolnir explain` svakog pravila navodi njen status. Objavljujemo stopu
|
|
290
|
-
toga. Rast tog broja je neprekidni rad projekta.
|
|
341
|
+
**Šta 100 ne znači.** Ne znači da je softver ispravan, da je skup testova dovoljan ili da je proizvod bez grešaka. Znači jednu stvar: **nijedno od pravila koja je Mjölnir procijenio nije proizvelo odbitak u ovom skeniranju i ovom modelu dokaza.**
|
|
291
342
|
|
|
292
|
-
|
|
343
|
+
<br />
|
|
293
344
|
|
|
294
|
-
|
|
295
|
-
njegovoj **izmjerenij** stopi lažnih pozitiva:
|
|
345
|
+
## Model dokaza
|
|
296
346
|
|
|
297
|
-
|
|
298
|
-
| ------------ | ---------------------------------------- | :---------: | :--------: |
|
|
299
|
-
| `core` | ≤ 10 % izmjerena FP | ✅ | ✅ |
|
|
300
|
-
| `extended` | ≤ 30 % izmjerena FP | ✅ | ✅ |
|
|
301
|
-
| `quarantine` | iznad 30 %, ili još neizmjereno (n < 10) | ❌ | ✅ |
|
|
347
|
+
Svaki nalaz nosi dvije oznake: koliko je Mjölnir siguran i koliko je daleko nalaz provjeren. To je razlika između alata koji prijavljuje obrasce i alata od kojeg možete uslovljavati izdanje.
|
|
302
348
|
|
|
303
|
-
|
|
304
|
-
| --------------- | -------------- | --------------------------------------------------------- |
|
|
305
|
-
| TypeScript / JS | AST kompajlera | najšira, najviše mjerena — pretežno `core`/`extended` |
|
|
306
|
-
| Python / pytest | Regex sloj | široka, auditrana na korpusu — pretežno `core`/`extended` |
|
|
307
|
-
| Java | Regex sloj | novija — pretežno `extended`/`quarantine` |
|
|
308
|
-
| C# / .NET | Regex sloj | novija — pretežno `extended`/`quarantine` |
|
|
349
|
+
**Koliko sigurno — nivo dokaza.**
|
|
309
350
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
351
|
+
| Nivo | Naziv | Znači | Odbitak |
|
|
352
|
+
| ------ | --------------------- | -------------------------------------------------- | ------- |
|
|
353
|
+
| **E2** | Deterministički dokaz | Defekt je prisutan u kodu onakvom kakav je napisan | Pun |
|
|
354
|
+
| **E1** | Dokaz iz obrasca | Poklopio se obrazac usko povezan s defektom | Pola |
|
|
355
|
+
| **E0** | Zapažanje | Vrijedi znati. Nije tvrdnja da nešto nije u redu. | Nula |
|
|
313
356
|
|
|
314
|
-
|
|
357
|
+
Pouzdanost detekcije nije snaga dokaza. Pravilo može biti sigurno da je pronašlo ono što je tražilo, a ipak gledati heuristiku. E1 nalazi su tu da se čitaju i procjenjuju, nikad da se primjenjuju naslijepo, i ta granica je utisnuta na nalaz u terminalu, u JSON-u i u predaji agentu.
|
|
315
358
|
|
|
316
|
-
|
|
359
|
+
**Koliko daleko je provjereno — nivo povjerenja.** Većina nalaza dolazi iz čitanja vašeg koda. Dajte Mjölniru izvještaj stvarnog pokretanja testova i on može potvrditi da se kod zaista izvršio.
|
|
317
360
|
|
|
318
361
|
<p align="center">
|
|
319
|
-
<img src="assets/readme/
|
|
362
|
+
<img src="assets/readme/trust-ladder.svg" alt="Ljestvica povjerenja od L0 do L5. L0 do L2 dolaze iz čitanja koda; L3 do L5 zahtijevaju izvještaj stvarnog pokretanja, što je označeno prekidom na ljestvici." width="100%" />
|
|
320
363
|
</p>
|
|
321
364
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
365
|
+
| Nivo | Jednostavnim riječima | Šta je potrebno |
|
|
366
|
+
| ------ | --------------------- | ------------------------------------------------------------ |
|
|
367
|
+
| **L0** | Zabilježeno | Čitanje koda |
|
|
368
|
+
| **L1** | Liči na problem | Čitanje koda: poklopio se obrazac |
|
|
369
|
+
| **L2** | Dokazano u kodu | Čitanje koda: defekt je strukturni |
|
|
370
|
+
| **L3** | Datoteka se izvršila | Izvještaj pokretanja pokazuje da je datoteka nalaza izvršena |
|
|
371
|
+
| **L4** | Test se izvršio | Izvještaj pokretanja pokazuje da je test nalaza izvršen |
|
|
372
|
+
| **L5** | Pokretanje se slaže | Vlastiti rezultat pokretanja potvrđuje klasu defekta |
|
|
325
373
|
|
|
326
|
-
|
|
327
|
-
normalizirano izloženošću suite-a (odbitci po deklaraciji testa).
|
|
328
|
-
Odbitci ponderirani dokazima znače da slabi signali koštaju manje.
|
|
329
|
-
Terminal pokazuje iste popustljive brojeve koje koristi bodovanje —
|
|
330
|
-
bez crne kutije. Puna metoda: [docs/SCORING.md](docs/SCORING.md).
|
|
374
|
+
Statičko skeniranje staje na L2. Samo izvještaj stvarnog pokretanja (Playwright JSON, Jest ili Vitest JSON, JUnit XML) može podići nalaz na L3 ili više, pa nalaz koji nikad nije viđen u izvršavanju nikad ne može tvrditi da jeste. Definicije: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
|
|
331
375
|
|
|
332
|
-
|
|
376
|
+
### Koliko je od ovoga izmjereno
|
|
333
377
|
|
|
334
|
-
|
|
335
|
-
| ------- | ---------------- |
|
|
336
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
337
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
338
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**74 od 79 pravila imaju stopu lažno pozitivnih rezultata izmjerenu na stvarnom OSS kodu** (najmanje 10 ručno klasifikovanih nalaza za svako; pogledajte [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Ostalih 5 se isporučuje na autorovoj procjeni i to kaže, pravilo po pravilo, u `mjolnir explain`. `mjolnir rules --unmeasured` ih navodi, a podnožje svakog skeniranja prijavljuje koliko je izmjereno od pravila koja su se zaista _okinula_.
|
|
339
379
|
|
|
340
|
-
|
|
341
|
-
bodovanju:
|
|
380
|
+
Stope ostaju javne i kada su loše. QA-TEST-001 (commitovani `.only`) loše prolazi reviziju na stvarnim repozitorijima i zato je u quarantine. Aktuelni broj za svako pravilo, uključujući QA-PW-141, nalazi se u reviziji.
|
|
342
381
|
|
|
343
|
-
|
|
344
|
-
| ---- | ---------------------- | -------------------- | -------------------------------------------------- |
|
|
345
|
-
| E2 | Deterministički defekt | Potpuni odbitak | Commitirani `.only` — strukturno dokazivo |
|
|
346
|
-
| E1 | Heuristički obrazac | Polovina odbitka | Regexom pogođen `sleep()` — jak signal, nije dokaz |
|
|
347
|
-
| E0 | Zapažanje | Nula (samo info) | Prijavljeno ali nikad ne gate-uje CI niti odbija |
|
|
382
|
+
### Nivoi povjerenja pravila
|
|
348
383
|
|
|
349
|
-
|
|
350
|
-
sistem: E2 nalazi su strukturni dokaz; E1 nalazi su ispravno
|
|
351
|
-
pozicionirana upozorenja, ne formalni dokazi.
|
|
384
|
+
Nivoi prate izmjerenu stopu lažno pozitivnih rezultata, a ne mišljenje:
|
|
352
385
|
|
|
353
|
-
|
|
354
|
-
|
|
386
|
+
| Nivo | Izmjereni FP | Ponašanje |
|
|
387
|
+
| -------------- | --------------------------------- | ----------------------------------------------------- |
|
|
388
|
+
| **core** | ≤ 10% | Zadani izvještaj, blokira |
|
|
389
|
+
| **extended** | ≤ 30% | Zadani izvještaj, niža pouzdanost |
|
|
390
|
+
| **quarantine** | > 30% ili eksplicitno deklarisano | Samo `--strict`, ograničeno na info, nikad ne blokira |
|
|
391
|
+
| _neizmjereno_ | n < 10 | Ne može se unaprijediti u core dok se ne izmjeri |
|
|
355
392
|
|
|
356
|
-
|
|
393
|
+
FP opsezi mogu samo degradirati nivo — nikad ne unapređuju pravilo iz `quarantine` ako je tamo eksplicitno deklarisano. Eksplicitno karantinirano pravilo ostaje u quarantine bez obzira na izmjerenu FP stopu.
|
|
357
394
|
|
|
358
|
-
|
|
395
|
+
Unapređenje, degradacija i zrelost po jeziku: [životni ciklus pravila](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
359
396
|
|
|
360
|
-
|
|
361
|
-
lokatori:
|
|
397
|
+
### Zašto ovo nije linter
|
|
362
398
|
|
|
363
|
-
|
|
364
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
Linteri vam govore da li kod poštuje pravila. Mjölnir vam govori može li se vjerovati vašoj verifikaciji.
|
|
365
400
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
401
|
+
| | Linteri (ESLint, SonarQube) | Alati za pokrivenost | AI pregled koda | **Mjölnir** |
|
|
402
|
+
| ---------------------------------------------------------------- | :-------------------------: | :------------------: | :-------------: | :----------------: |
|
|
403
|
+
| Ocjenjuje **sistem verifikacije**, a ne kod proizvoda | Ne | Ne | Ne | Da |
|
|
404
|
+
| Integritet CI workflowa (`continue-on-error`, `\|\| true`) | Ne | Ne | samo diff | Da |
|
|
405
|
+
| Ocjenjuje otpornost Playwright lokatora (Selector Health) | Ne | Ne | Ne | Da |
|
|
406
|
+
| Čita stvarne podatke pokretanja za `TRUE-FLAKE` presude | Ne | Ne | Ne | Da |
|
|
407
|
+
| Objavljuje izmjerenu stopu lažno pozitivnih rezultata po pravilu | Ne | Ne | Ne | Da |
|
|
408
|
+
| Označava testove bez asercija | Da\* | Ne | ponekad | Da |
|
|
409
|
+
| Hvata fiksne sleepove (`waitForTimeout`, `time.sleep`) | Da\* | Ne | ponekad | Da |
|
|
410
|
+
| Deterministički (isti ulaz, isti izlaz) | Da | Da | Ne | Da |
|
|
411
|
+
| Trošak po skeniranju | besplatno | besplatno | tokeni | **nula** (lokalno) |
|
|
412
|
+
|
|
413
|
+
<sub>\*Pokriveno s `eslint-plugin-jest` i `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) te vlastitim pravilima za asercije u SonarQubeu. Kolone opisuju zadano ponašanje za verifikaciju skupova testova; dodaci, plaćeni paketi i prilagođena pravila mijenjaju neke odgovore. Ovo je sažetak pozicioniranja, a ne benchmark.</sub>
|
|
369
414
|
|
|
370
|
-
|
|
371
|
-
XPath tone rezultat — lome se na svakom DOM refactoru ne govoreći ti
|
|
372
|
-
koje ponašanje je regresiralo.
|
|
415
|
+
Koristite i AI pregled. Hvata nijanse, namjeru i greške u dizajnu koje nijedan obrazac ne može pronaći. Mjölnir hvata ono što AI pregled previdi jer izgleda namjerno: commitovani `.only`, progutan izlazni kod, `continue-on-error` na test jobu. Za to treba skeniranje, a ne rasuđivanje.
|
|
373
416
|
|
|
374
|
-
|
|
417
|
+
<br />
|
|
375
418
|
|
|
376
|
-
##
|
|
419
|
+
## Analiza pokretanja testova
|
|
377
420
|
|
|
378
|
-
Statička
|
|
379
|
-
podatke izvršavanja** — Playwright JSON izvještaje i JUnit XML od
|
|
380
|
-
bilo kojeg runnera:
|
|
421
|
+
Statička analiza rasuđuje o kodu koji se nikad nije izvršio. Analiza pokretanja čita šta se zaista dogodilo: Playwright JSON, Jest JSON, Vitest JSON i JUnit XML iz bilo kojeg runnera.
|
|
381
422
|
|
|
382
423
|
```bash
|
|
383
424
|
mjolnir forensics ./test-results/
|
|
384
425
|
```
|
|
385
426
|
|
|
386
427
|
```text
|
|
387
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
388
429
|
|
|
389
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
390
431
|
|
|
@@ -394,294 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
394
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
395
436
|
```
|
|
396
437
|
|
|
397
|
-
|
|
398
|
-
sretan test. Označava se kao `TRUE-FLAKE` bez obzira na konačni zeleni
|
|
399
|
-
check.
|
|
438
|
+
`TRUE-FLAKE` ne znači da je test ponovljen. Znači da je test **pao barem u jednom pokušaju, a zatim završio zeleno**: sretan prolaz, označen bez obzira na to šta kaže konačna kvačica. `mjolnir triage` tu historiju pretvara u prijedlog karantina, a `mjolnir pw-report` sažima pokretanje. Upravo ti izvještaji pokretanja podižu nalaze na nivoe povjerenja L3 i više.
|
|
400
439
|
|
|
401
|
-
|
|
440
|
+
<br />
|
|
402
441
|
|
|
403
|
-
##
|
|
442
|
+
## Integritet CI-ja
|
|
404
443
|
|
|
405
|
-
|
|
406
|
-
verifikaciji vjerovati.
|
|
444
|
+
Test može prolaziti dok pipeline oko njega ne može pasti. Mjölnir čita i workflowe: `continue-on-error`, `|| true`, izlazne kodove koji se nikad ne prosljeđuju, korake koji uvijek uspijevaju, izvještaje koji se koriste, a nikad ne generišu, i kapije preskočene baš na događajima koji bi trebali blokirati. Svaki nalaz navodi job, korak i red, i nosi vlastiti nivo dokaza.
|
|
407
445
|
|
|
408
|
-
|
|
409
|
-
| --------------------------------------------------------- | :----------------: | :------------: | :----------: | :---------: |
|
|
410
|
-
| CI workflow integritet (`continue-on-error`, `\|\| true`) | ❌ | ❌ | rijetko | ✅ |
|
|
411
|
-
| Unakrsno-jezično (TS, Python, Java, C#) iz jednog alata | ❌ | ❌ | ❌ | ✅ |
|
|
412
|
-
| Ocjenjuje otpornost Playwright lokatora (Selector Health) | ❌ | ❌ | rijetko | ✅ |
|
|
413
|
-
| Označava testove bez pravih asercija | ✅ (plugin)\* | ❌ | ponekad | ✅ |
|
|
414
|
-
| Hvata tvrde sleepove (`waitForTimeout`, `time.sleep`) | ✅ (plugin)\* | ❌ | ponekad | ✅ |
|
|
415
|
-
| Radi u sekundama, nula mrežnih poziva pri skeniranju | ✅ | ✅ | — | ✅ |
|
|
446
|
+
Generišite PR workflow, zadano savjetodavan:
|
|
416
447
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
420
451
|
|
|
421
|
-
|
|
452
|
+
Ili dodajte Marketplace action u workflow koji već imate:
|
|
422
453
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
428
460
|
|
|
429
|
-
|
|
430
|
-
flakinessa s oznakama presuda.
|
|
461
|
+
Prikujte `@v1` da pratite glavnu liniju, ili tačan tag (`@v0.5.32`) za ponovljivu kapiju. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) pokriva Marketplace, Smithery i MCP registre.
|
|
431
462
|
|
|
432
|
-
|
|
463
|
+
Da nalaze stavite u GitHub Code Scanning, otpremite SARIF (potrebno `security-events: write` na nivou workflowa ili joba):
|
|
433
464
|
|
|
434
|
-
|
|
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
|
+
```
|
|
435
473
|
|
|
436
|
-
|
|
437
|
-
testa u diffu; ne dokazuje da je verifikacioni sistem kao cjelina
|
|
438
|
-
dostojan povjerenja — i vidi samo diff koji mu pokažeš.
|
|
474
|
+
Na GitLabu, `--format codequality` zapisuje Code Quality izvještaj koji čitaju MR widget i diff anotacije ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Podešavanje editora i pipelinea: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
439
475
|
|
|
440
|
-
|
|
441
|
-
| ---------------------------------------- | :------------------------------: | :-------------------------------------: |
|
|
442
|
-
| Trošak po skanu | Tokeni (raste s veličinom diffa) | **Nula** (lokalno, instalirano) |
|
|
443
|
-
| Vidi cijeli suite + sve CI konfiguracije | Samo PR diff koji pokažeš | **Sve, svaki put** |
|
|
444
|
-
| Deterministički (isti ulaz → isti izlaz) | ❌ (nedeterministički) | **✅** |
|
|
445
|
-
| Hvata obrasce dormantne mjesecima | Samo ako je u kontekstu | **✅** (skenira sve fajlove) |
|
|
446
|
-
| Pamti nalaze između runova | ❌ (nema memorije između sesija) | **✅** (baseline + diff) |
|
|
447
|
-
| Radi bez ljudskog okidača | Treba PR ili prompt | **✅** (CI hook, izvodi se u sekundama) |
|
|
476
|
+
### Pripisivanje u opsegu promjena
|
|
448
477
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
exit kod, `continue-on-error` na test jobu. To nisu bugovi koji trebaju
|
|
453
|
-
razmišljanje; to su činjenice koje trebaju skeniranje.
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
454
481
|
|
|
455
|
-
|
|
482
|
+
Nalazi se pripisuju redovima koje je vaša grana dodala, mjereno u odnosu na **merge-base**. Opseg je isti skup datoteka koji otkriva puno skeniranje (TS/JS specifikacije i konfiguracije adaptera, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), plus necommitovane i nepraćene promjene, pa radi i prije commita. Baza se razrješava redom `main → master → origin/main → origin/master → origin/HEAD`; zamijenite je s `--base <ref>`.
|
|
456
483
|
|
|
457
|
-
|
|
484
|
+
Kada se merge-base ne može razriješiti (plitki klon, odvojeni HEAD, cilj izvan gita), nalazi se vraćaju na pripisivanje cijeloj datoteci **i izvještaj to kaže.** Tihi prelazak na rezervnu opciju bio bi upravo ona vrsta defekta zbog koje ovaj alat postoji.
|
|
458
485
|
|
|
459
|
-
|
|
460
|
-
blokirajući:
|
|
486
|
+
<br />
|
|
461
487
|
|
|
462
|
-
|
|
463
|
-
mjolnir ci install
|
|
464
|
-
```
|
|
488
|
+
## AI agenti
|
|
465
489
|
|
|
466
|
-
|
|
490
|
+
Nalazi vrijede samo ako nešto na osnovu njih djeluje.
|
|
467
491
|
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
- uses: github/codeql-action/upload-sarif@v3
|
|
471
|
-
with:
|
|
472
|
-
sarif_file: mjolnir.sarif
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
473
494
|
```
|
|
474
495
|
|
|
475
|
-
|
|
476
|
-
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
496
|
+
**AI piše ispravku. Mjölnir je verifikuje.** Dokaz dolazi iz ponovnog skeniranja, nikad iz agentovog vlastitog izvještaja o uspjehu.
|
|
477
497
|
|
|
478
|
-
|
|
498
|
+
| Naredba | Šta agent dobija |
|
|
499
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
500
|
+
| `mjolnir mcp` | [MCP](https://modelcontextprotocol.io) server preko stdio. `scan`, `explain` i `diff` postaju alati koji se mogu pozvati. |
|
|
501
|
+
| `mjolnir handoff` | Sačuvani `--json` izvještaj postaje deterministički Markdown plan: šta je otkriveno, granica dokaza za svaki nalaz, šta se **ne** smije promijeniti i kako verifikovati. |
|
|
502
|
+
| `mjolnir install` | Upisuje u agentske površine koje vaš repozitorij već ima (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`) kako bi agent ponovo skenirao prije nego što tvrdi da je gotov. |
|
|
479
503
|
|
|
480
|
-
|
|
481
|
-
merge-base s `main`. Pokriva test fajlove (`*.spec.*`, `*.test.*`) plus
|
|
482
|
-
GitHub workflow fajlove i Playwright konfiguracije u diffu. Kad se
|
|
483
|
-
merge-base ne može razriješiti — shallow clone, detached HEAD, non-git
|
|
484
|
-
cilj, drugi zadani branch — pošteno degradira: nalazi se vraćaju na
|
|
485
|
-
atribuciju po cijelom fajlu i izvještaj to kaže. Prepiši baznu ref s
|
|
486
|
-
`--base <ref>`.
|
|
504
|
+
Dodajte ga klijentu koji ima vlastiti CLI:
|
|
487
505
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
Mjölnir je zero-config. Opcioni `mjolnir.config.json` (ili
|
|
493
|
-
`.mjolnir.json`) u korijenu repoa podešava severity, gating i opseg —
|
|
494
|
-
nikad ne mijenja semantiku detekcije.
|
|
506
|
+
```bash
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
508
|
+
```
|
|
495
509
|
|
|
496
|
-
|
|
497
|
-
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
498
|
-
| `exclude` | `string[]` | Dodatni ignore globovi (gitignore podskup), preko ugrađenih defaulta |
|
|
499
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | Koji severity izlaze s ne-nula kodom (default `error`; `advisory` nikad ne blokira) |
|
|
500
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | Prerangiraje nalaze pravila za tvoj repo |
|
|
501
|
-
| `ignore` | `IgnoreEntry[]` | Potiskuje nalaze — **`reason` je obavezan**; unosi istječu nakon 90 dana (eksplicitni `expires` datum, ili vrijeme zadnje izmjene config fajla za unose bez njega) |
|
|
502
|
-
| `plugins` | `string[]` | Paketi pravila trećih strana (vidi [Model povjerenja](#model-povjerenja)) |
|
|
510
|
+
Ili bilo kojem klijentu koji prima `mcpServers` blok:
|
|
503
511
|
|
|
504
512
|
```json
|
|
505
513
|
{
|
|
506
|
-
"
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
"ignore": [
|
|
510
|
-
{
|
|
511
|
-
"ruleId": "QA-TEST-004",
|
|
512
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
513
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
514
|
-
"expires": "2026-12-31"
|
|
515
|
-
}
|
|
516
|
-
]
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
517
517
|
}
|
|
518
518
|
```
|
|
519
519
|
|
|
520
|
-
|
|
521
|
-
isključenja putanja, isti dijalekt kao `exclude`. Koristi je za
|
|
522
|
-
mašinski šum; koristi `exclude` kad lista pripadne version kontroli,
|
|
523
|
-
uz ostatak konfiguracije.
|
|
524
|
-
- **CLI nadjačavanja** — `--strict` (uključi quarantine pravila),
|
|
525
|
-
`--width <cols>` i `--ascii` / `--no-ascii` (terminalski render),
|
|
526
|
-
`--tone blunt` (oštrije poruke), `--max-duration <sec>` (ograničen
|
|
527
|
-
djelomični skan).
|
|
528
|
-
- Potiskivanje pravila i životni ciklus deprecacije:
|
|
529
|
-
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
530
|
-
|
|
531
|
-
`ignore` unosi hrane i samostalnu komandu `mjolnir suppressions`, koja
|
|
532
|
-
izlista šta je trenutno potisnuto i kada ističe svaki unos.
|
|
533
|
-
|
|
534
|
-
---
|
|
535
|
-
|
|
536
|
-
## 📐 Exit kodovi i ugovori
|
|
537
|
-
|
|
538
|
-
Zamrznuti — sigurni za gradnju CI logike:
|
|
539
|
-
|
|
540
|
-
| Exit kod | Značenje |
|
|
541
|
-
| -------- | ---------------------------------------------------------------------------------- |
|
|
542
|
-
| `0` | Čisto — nema nalaza na ili iznad gatea |
|
|
543
|
-
| `1` | Nalazi na ili iznad gatea |
|
|
544
|
-
| `2` | Djelimičan skan (potrošen vremenski budžet, nečitljivi fajlovi) — nikad ne blokira |
|
|
545
|
-
| `10` | Greška upotrebe (loš flag, nedostaje cilj) |
|
|
546
|
-
| `20` | Interna greška |
|
|
547
|
-
|
|
548
|
-
JSON/SARIF izvještaj je `schemaVersion: 1`. ID-jevi pravila
|
|
549
|
-
(`QA-<FAMILY>-NNN`) su nepromjenjivi jednom isporučeni i nikad se ne
|
|
550
|
-
ponovo koriste.
|
|
551
|
-
|
|
552
|
-
---
|
|
553
|
-
|
|
554
|
-
## Model povjerenja
|
|
555
|
-
|
|
556
|
-
- **Local-first** — nula mrežnih poziva tokom skeniranja. Nikad. Nula
|
|
557
|
-
telemetrije.
|
|
558
|
-
- **Bez lažnih dokaza** — radije kažemo „nepoznato" nego „verifikovano".
|
|
559
|
-
Prazan repo dobija `score: null`, nikad lažnih 100.
|
|
560
|
-
- **Djelimična iskrenost** — ako je analiza prekinuta, izlaz to kaže.
|
|
561
|
-
Nikad „complete" kad nije.
|
|
562
|
-
- **FP vatrozid** — detekcija radi na pregledu koda bez komentara i
|
|
563
|
-
stringova (TypeScript pravila koriste AST kompajlera): obrazac unutar
|
|
564
|
-
prosačnog komentara ili doc-primjera-stringa je dokumentacija, ne
|
|
565
|
-
nalaz.
|
|
566
|
-
- **Izmjereno, ne tvrđeno** — u glavne tierove ulaze samo pravila sa
|
|
567
|
-
stopom lažnih pozitiva iz stvarnog OSS koda (vidi
|
|
568
|
-
[Koliko je od ovoga izmjereno](#koliko-je-od-ovoga-izmjereno));
|
|
569
|
-
podnožje skana i `mjolnir rules --unmeasured` kažu koje su koje.
|
|
570
|
-
- **Povjerenje u pluginove i kapija izvršavanja** — pluginovi su npm
|
|
571
|
-
paketi deklarirani pod
|
|
572
|
-
`"plugins"`; JS moduli žive u `mjolnir-rules/*.mjs`.
|
|
573
|
-
**Nema sandboxa**: plugin kod radi s punim Node
|
|
574
|
-
privilegijama, isti model povjerenja kao ESLint ili Vitest pluginovi.
|
|
575
|
-
Zato je izvršavanje koda **opt-in pri svakom skanu**: proslijedite
|
|
576
|
-
`--enable-plugins` (ili postavite `MJOLNIR_ENABLE_PLUGINS=1`), inače
|
|
577
|
-
se izvori NE učitavaju — glasna stderr obavijesta izlista tačno što
|
|
578
|
-
je preskočeno. Skeniranje nepouzdanog koda nikada ga ne izvršava.
|
|
579
|
-
JSON pravila manifesti (`mjolnir-rules/*.json`) nisu pogođeni:
|
|
580
|
-
deklariraju regex obrasce i po konstrukciji ne izvršavaju kod.
|
|
581
|
-
Core prefiksi ID-jeva pravila su rezervirani i odbijaju se od
|
|
582
|
-
pluginova i eksternih pravila radi sprečavanja spoofinga.
|
|
583
|
-
- **Eksterna pravila lokalna workspaceu** (folder-bazirana, nula
|
|
584
|
-
mreže) — `mjolnir-rules/` direktorij pored skan cilja učitava
|
|
585
|
-
vlastita pravila: JSON fajlovi deklariraju regex obrasce (nikakav kod
|
|
586
|
-
se ne izvršava), `.mjs`/`.js` moduli eksportuju `rules` (potpuno Node
|
|
587
|
-
povjerenje, kao pluginovi). Eksterna pravila nose iste metadata
|
|
588
|
-
povjerenja kao core; nikad ne mogu ući u core tier (core traži
|
|
589
|
-
izmjerenu FP stopu iz corpus sidecara — deklarirani `tier: "core"`
|
|
590
|
-
se stega na `extended`), poštuju tier limite i provjeravaju se na
|
|
591
|
-
drift: `mjolnir rules --md --external` renderira katalog iz
|
|
592
|
-
učitanih fajlova (provenijencija `external`), a generator matrice
|
|
593
|
-
prima `--external <root>`.
|
|
594
|
-
|
|
595
|
-
---
|
|
596
|
-
|
|
597
|
-
## 🏗️ Arhitektura
|
|
520
|
+
**Zaštitna ograda je važnija od udobnosti.** Svaki nalaz u predaji nosi svoju granicu. **E2** kaže _deterministički: provjerite lokaciju i primijenite ispravku_. **E1** kaže _POTREBNA POTVRDA: samo zapažanje ne dokazuje defekt_. Agent koji naslijepo ispravlja E1, utišava pravilo ili mijenja pravilo da podigne ocjenu radi upravo ono zbog čega ovaj alat postoji, pa predaja to kaže u promptu, odmah pored nalaza.
|
|
598
521
|
|
|
599
|
-
<
|
|
600
|
-
<summary>Raširi stablo</summary>
|
|
522
|
+
<br />
|
|
601
523
|
|
|
602
|
-
|
|
603
|
-
mjolnir/
|
|
604
|
-
├── src/
|
|
605
|
-
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
606
|
-
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
607
|
-
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
608
|
-
│ ├── playwright/ # Selector Health Score engine
|
|
609
|
-
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
610
|
-
│ ├── scope/ # git merge-base changed-scope engine
|
|
611
|
-
│ ├── scorer/ # transparent deduction table + prioritization
|
|
612
|
-
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
613
|
-
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
614
|
-
│ ├── config/ # mjolnir.config.json + suppressions
|
|
615
|
-
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
616
|
-
│ └── commands/ # every subcommand
|
|
617
|
-
└── tests/
|
|
618
|
-
├── fixtures/ # must-fire / must-not-fire per rule
|
|
619
|
-
└── golden/ # frozen score regression locks
|
|
620
|
-
```
|
|
524
|
+
## Povjerenje i sigurnost
|
|
621
525
|
|
|
622
|
-
|
|
526
|
+
**Prvo lokalno, nula telemetrije.** Nijedan API sposoban za mrežu (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) ne postoji nigdje u `src/`, a [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) obara build ako se neki pojavi. Zabranjuje i `eval` i `new Function`. Skeniranje nepouzdanog koda ga nikad ne izvršava: statička analiza čita izvorni tekst, a analiza pokretanja parsira datoteke izvještaja koje već postoje na disku.
|
|
527
|
+
|
|
528
|
+
Dvije napomene: sam `npx` preuzima paket prije nego što se išta pokrene, a garancija pokriva `src/`, ne dodatke trećih strana.
|
|
529
|
+
|
|
530
|
+
**Dodaci nisu u sandboxu.** JS dodaci (`mjolnir-rules/*.mjs` ili npm paketi navedeni pod `"plugins"`) rade s punim Node privilegijama, istim modelom povjerenja kao ESLint ili Vitest dodaci. Njihovo učitavanje je izričit izbor **po skeniranju**: bez `--enable-plugins` (ili `MJOLNIR_ENABLE_PLUGINS=1`) njihovi izvori se nikad ne učitavaju, a obavještenje na stderr navodi šta je preskočeno. JSON manifesti pravila ne izvršavaju kod, a prefiksi ID-jeva core pravila su rezervisani kako se nijedan dodatak ne bi mogao lažno predstaviti kao neko od njih. Ranjivosti prijavite preko [SECURITY.md](SECURITY.md).
|
|
531
|
+
|
|
532
|
+
**Radi na samom sebi.** Motor povjerenja u verifikaciju nema kredibilitet ako sam nije provjerljiv. Svako CI pokretanje skenira ovaj repozitorij buildom koji je proizvelo to isto pokretanje. Kapija pada na svakom nalazu ozbiljnosti error, kao i na **djelimičnom** skeniranju ili **pravilu koje se srušilo**, jer skraćeno samoskeniranje koje ništa ne prijavljuje jeste upravo lažna zelena boja zbog koje ovaj projekat postoji. `mjolnir doctor` u istom pokretanju ponovo revidira bazu pravila (zaštitni zid fixturea, poštenje nivoa, gornja granica nivoa core), a provjera s rezultatom INCONCLUSIVE pada potpuno isto kao neuspjela. Oba izvještaja se otpremaju kao artefakti builda.
|
|
533
|
+
|
|
534
|
+
### Izlazni kodovi i mašinski ugovor
|
|
623
535
|
|
|
624
|
-
|
|
625
|
-
bez I/O-a, bez globala. Novi ekosistem = jedan adapter + njegova
|
|
626
|
-
pravila.
|
|
627
|
-
- **TypeScript/Playwright koristi AST kompajlera** (ts-morph). Python,
|
|
628
|
-
Java i C# rade na zajedničkom regex sloju s maskiranim komentarima i
|
|
629
|
-
stringovima.
|
|
630
|
-
- Tree-sitter WASM AST sloj za Javu i C# postoji i sljedeći je korak
|
|
631
|
-
preciznosti — još nije povezan u sinhroni skan pipeline.
|
|
536
|
+
Zamrznuti, kako biste na njima mogli graditi CI logiku:
|
|
632
537
|
|
|
633
|
-
|
|
538
|
+
| Izlazni kod | Značenje |
|
|
539
|
+
| ----------- | ---------------------------------------------------------------------------------------- |
|
|
540
|
+
| `0` | Čisto: nema nalaza na nivou kapije ili iznad |
|
|
541
|
+
| `1` | Nalazi na nivou kapije ili iznad |
|
|
542
|
+
| `2` | Djelimično skeniranje (istekao vremenski budžet, nečitljive datoteke). Nikad ne blokira. |
|
|
543
|
+
| `10` | Greška u upotrebi (pogrešna zastavica, nedostaje cilj) |
|
|
544
|
+
| `20` | Interna greška |
|
|
634
545
|
|
|
635
|
-
|
|
546
|
+
`2` se namjerno razlikuje od `0`: skeniranje koje nije završilo nije "ništa pronašlo". Samo nije završilo s traženjem.
|
|
636
547
|
|
|
637
|
-
|
|
638
|
-
| ------------------------------------------------------ | ----------------------------------------------- |
|
|
639
|
-
| [docs/SCORING.md](docs/SCORING.md) | Normalizacija rezultata + ponderiranje dokazima |
|
|
640
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Izmjerene stope lažnih pozitiva + metodologija |
|
|
641
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Stanja pravila, potiskivanje, deprecacija |
|
|
642
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF izlaz + editor/CI postavka |
|
|
643
|
-
| [docs/rules/](docs/rules/) | Generirani katalog po pravilu |
|
|
644
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev postavka + workflow doprinosa |
|
|
645
|
-
| [CHANGELOG.md](CHANGELOG.md) | Historija izdanja |
|
|
646
|
-
| [SECURITY.md](SECURITY.md) | Prijavljivanje ranjivosti |
|
|
548
|
+
Sve što mašina troši (rezultati MCP alata, `--json`, SARIF 2.1) dolazi iz jednog kanonskog rezultata pod verzionisanom shemom koja se **samo proširuje** (`schemaVersion: 1`, `contractVersion: 1`), tako da nijedan potrošač ne mora rekonstruisati značenje iz renderovanog teksta. Pogledajte [mašinski ugovor](docs/machine-contract.md). ID-jevi pravila (`QA-<FAMILY>-NNN`) su nepromjenjivi nakon isporuke i nikad se ne koriste ponovo.
|
|
647
549
|
|
|
648
|
-
|
|
550
|
+
<br />
|
|
649
551
|
|
|
650
|
-
##
|
|
552
|
+
## Šta vam Mjölnir ne može reći
|
|
651
553
|
|
|
652
|
-
**
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
554
|
+
- **Ne pokreće vaše testove.** Čisto skeniranje nije skup testova koji prolazi.
|
|
555
|
+
- **Ne može vam reći da je asercija _pogrešna_.** `expect(total).toBe(41)` izgleda zdravo. Mjölnir pronalazi testove koji _ne mogu pasti_ i pipelineove koji _ne mogu postati crveni_, a ne testove koji provjeravaju pogrešnu stvar.
|
|
556
|
+
- **Ne dokazuje poslovnu ispravnost.** Ništa ovdje ne kaže da vaš proizvod radi ono što je zahtjev tražio.
|
|
557
|
+
- **100 nije dokaz dobrog skupa testova.** Da li vaš skup pokriva vaš stvarni rizik je drugo pitanje, a ovaj alat na njega ne odgovara.
|
|
558
|
+
- **5 od 79 pravila se isporučuje na procjeni**, a ne na izmjerenoj stopi. Svako od njih to kaže na vlastitom nalazu.
|
|
559
|
+
- **E1 nije E2.** Heuristički nalazi vrijede čitanja, ali ne i primjene naslijepo.
|
|
560
|
+
- **Prazan repozitorij dobija `null`, nikad 100.**
|
|
561
|
+
- **Datoteka nazvana `*.spec.ts` bez deklaracija testova ne računa se kao pokrivenost.** Repozitorij čije jedine spec datoteke sadrže importe ili tipove (nula poziva `it`/`test`) dobija `null`, a ne 100.
|
|
656
562
|
|
|
657
|
-
|
|
563
|
+
<br />
|
|
658
564
|
|
|
659
|
-
##
|
|
565
|
+
## Dokumentacija
|
|
660
566
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
567
|
+
Kompletna stranica dokumentacije nalazi se na <https://sergey-bar.github.io/Mjolnir/>.
|
|
568
|
+
|
|
569
|
+
| Dokument | Šta sadrži |
|
|
570
|
+
| ------------------------------------------------------ | ------------------------------------------------------ |
|
|
571
|
+
| [docs/SCORING.md](docs/SCORING.md) | Normalizacija ocjene i ponderisanje dokaza |
|
|
572
|
+
| [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Kanonski rječnik: jedna riječ po pojmu |
|
|
573
|
+
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Izmjerene stope lažno pozitivnih rezultata i metoda |
|
|
574
|
+
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Stanja pravila, nivoi, utišavanje, povlačenje |
|
|
575
|
+
| [docs/VERSIONING.md](docs/VERSIONING.md) | Semver politika, zamrznute površine, ciklus povlačenja |
|
|
576
|
+
| [docs/machine-contract.md](docs/machine-contract.md) | Kanonski mašinski čitljiv rezultat |
|
|
577
|
+
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF izlaz i podešavanje editora ili CI-ja |
|
|
578
|
+
| [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: Code Quality izvještaj, MR recept, kapija |
|
|
579
|
+
| [docs/rules/](docs/rules/) | Generisani katalog po pravilu |
|
|
580
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Razvojno okruženje i tok doprinosa |
|
|
581
|
+
| [SUPPORT.md](SUPPORT.md) | Gdje pitati, prijaviti i dobiti pomoć |
|
|
582
|
+
| [SECURITY.md](SECURITY.md) | Prijava ranjivosti |
|
|
583
|
+
| [CHANGELOG.md](CHANGELOG.md) | Historija izdanja |
|
|
584
|
+
|
|
585
|
+
### Status
|
|
586
|
+
|
|
587
|
+
**Verzija 1.** JSON shema i izlazni kodovi su zamrznuti ugovori. TypeScript i Python imaju najširu izmjerenu pokrivenost. Java i C# su noviji; čitajte ih kroz [tabelu zrelosti](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). Šta slijedi, bez izmišljenih datuma: [javna mapa puta](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
|
|
588
|
+
|
|
589
|
+
### Doprinos
|
|
590
|
+
|
|
591
|
+
Nova pravila su najlakši prvi doprinos. Jedna naredba pravi kostur pravila s njegovim must-fire **i** must-not-fire fixtureima. Generisano pravilo namjerno pada na vlastitim fixtureima dok se ne napiše stvarna detekcija, jer isporučeni kostur jeste pravilo koje niko nije izmjerio:
|
|
665
592
|
|
|
666
593
|
```bash
|
|
667
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
668
595
|
```
|
|
669
596
|
|
|
670
|
-
|
|
671
|
-
vatrozida su u [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
597
|
+
Razvojno okruženje, naredbe stalnih kapija te zakoni anti-creep i zaštitnog zida fixturea nalaze se u [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
672
598
|
|
|
673
|
-
|
|
599
|
+
<br />
|
|
674
600
|
|
|
675
601
|
<div align="center">
|
|
676
602
|
|
|
677
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="Pokrenite ga na svom repozitoriju." width="100%" />
|
|
678
604
|
|
|
679
605
|
```bash
|
|
680
606
|
npx mjolnir-qa@latest
|
|
681
607
|
```
|
|
682
608
|
|
|
683
|
-
|
|
609
|
+
[Pročitajte vodič](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Stranica dokumentacije](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
|
|
610
|
+
|
|
611
|
+
<br />
|
|
612
|
+
|
|
613
|
+
Ne pitajte jesu li testovi prošli.<br />
|
|
614
|
+
Pitajte dokazuju li dokazi da zaslužuju povjerenje.
|
|
684
615
|
|
|
685
|
-
|
|
616
|
+
<sub>Napravio [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · MIT licenca</sub>
|
|
686
617
|
|
|
687
618
|
</div>
|