mjolnir-qa 0.4.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1199 -28
- package/README.ar.md +667 -0
- package/README.bn.md +678 -0
- package/README.br.md +706 -0
- package/README.bs.md +690 -0
- package/README.da.md +698 -0
- package/README.de.md +711 -0
- package/README.es.md +709 -0
- package/README.fr.md +714 -0
- package/README.gr.md +705 -0
- package/README.he.md +664 -0
- package/README.it.md +709 -0
- package/README.ja.md +692 -0
- package/README.ko.md +681 -0
- package/README.md +425 -152
- package/README.no.md +696 -0
- package/README.pl.md +699 -0
- package/README.ru.md +701 -0
- package/README.th.md +672 -0
- package/README.tr.md +699 -0
- package/README.uk.md +693 -0
- package/README.vi.md +680 -0
- package/README.zh.md +652 -0
- package/README.zht.md +652 -0
- package/dist/cli.d.mts +469 -22
- package/dist/cli.mjs +9780 -5230
- package/package.json +25 -7
package/README.gr.md
ADDED
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/readme/logo.png" alt="Mjölnir — Verification Trust Engine" width="800" />
|
|
4
|
+
|
|
5
|
+
### Τα τεστ σου λένε ψέματα. Το αποδεικνύουμε.
|
|
6
|
+
|
|
7
|
+
**Verification Trust Engine για QA.** Το Mjölnir ελέγχει suites τεστ και
|
|
8
|
+
CI pipelines, αναφέρει δείκτη αξιοπιστίας και δείχνει ακριβώς πού
|
|
9
|
+
σπάει η εμπιστοσύνη.
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
12
|
+
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
[](https://nodejs.org)
|
|
15
|
+
|
|
16
|
+
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](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) | Ελληνικά | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
17
|
+
|
|
18
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-04.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx mjolnir-qa@latest
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Είναι τα τεστ σου άξια εμπιστοσύνης;**
|
|
25
|
+
|
|
26
|
+
[Δες το σε δράση](#-δες-το-σε-δράση) ·
|
|
27
|
+
[Γρήγορη εκκίνηση](#-γρήγορη-εκκίνηση) ·
|
|
28
|
+
[Τι ελέγχει](#-τι-ελέγχει-το-mjölnir) ·
|
|
29
|
+
[Σκόρ](#πώς-λειτουργεί-το-σκόρ) ·
|
|
30
|
+
[CI](#-ενσωμάτωση-ci) · [Διαμόρφωση](#διαμόρφωση) ·
|
|
31
|
+
[Τεκμηρίωση](#-τεκμηρίωση)
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🎬 Δες το σε δράση
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<img src="assets/readme/demo.svg" alt="Η πλήρης αναφορά --verbose του Mjölnir σε ένα demo repo: WORTHINESS 75/100 NEEDS WORK, ανάλυση διαγνώσεων ανά κατηγορία, λίστα FIX THIS FIRST και κάθε εύρημα με ID κανόνα και αριθμό γραμμής σε CI, Playwright, υγιεινή τεστ και κανόνες Python" width="900" />
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<sub>Η πλήρης έξοδος του `npx mjolnir-qa ./examples/demo-repo --verbose`,
|
|
44
|
+
αποδομένη από τον πραγματικό reporter — τίποτα περικομμένο.
|
|
45
|
+
Αναδημιουργείται με `npm run docs:demo`;
|
|
46
|
+
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
+
ρίχνει το CI αν ο artifact αποκλίνει από ό,τι τυπώνει το εργαλείο.</sub>
|
|
48
|
+
|
|
49
|
+
**Τι μόλις συνέβη:**
|
|
50
|
+
|
|
51
|
+
1. Το Mjölnir ανακάλυψε τα Playwright specs, τη διαμόρφωσή του, το CI
|
|
52
|
+
workflow και ένα αρχείο τεστ Python — τέσσερις γλώσσες/μορφές, ένα
|
|
53
|
+
πέρασμα.
|
|
54
|
+
2. Βρήκε στοιχεία που εξασθενούν την εμπιστοσύνη στη σουίτα — ένα
|
|
55
|
+
`continue-on-error` που κρύβει job, ένα `|| true` που καταπίνει exit
|
|
56
|
+
code, σκληρά sleeps, εύθραυστο selector, σκληρά staging URL,
|
|
57
|
+
αναμονή `networkidle`.
|
|
58
|
+
3. Μετέτρεψε το καθένα σε συγκεκριμένο εύρημα με ID κανόνα, τοποθεσία
|
|
59
|
+
και fix — και σε ένα σκόρ με το οποίο μπορείς να gated ένα PR.
|
|
60
|
+
|
|
61
|
+
### Ένα εύρημα από κοντά
|
|
62
|
+
|
|
63
|
+
Τρέξε `mjolnir explain QA-CI-001` στο πρώτο εύρημα παραπάνω και θα
|
|
64
|
+
πάρεις:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
▚▞ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
68
|
+
|
|
69
|
+
Severity: error
|
|
70
|
+
Confidence: high
|
|
71
|
+
Evidence: E2
|
|
72
|
+
Measured FP: not yet measured — this rule ships on assumption (see docs/FP-AUDIT.md)
|
|
73
|
+
|
|
74
|
+
WHAT WAS FOUND (real detector output, not a mockup)
|
|
75
|
+
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
76
|
+
|
|
77
|
+
WHY IT MATTERS
|
|
78
|
+
This job can fail every day and CI will still show green. The checkmark
|
|
79
|
+
on this workflow cannot be trusted.
|
|
80
|
+
|
|
81
|
+
HOW TO FIX
|
|
82
|
+
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Αυτή είναι η μονάδα αξίας: όχι νίττα στυλ, αλλά ένα σημείο όπου το CI
|
|
86
|
+
σου σου λέει ότι κάτι πέρασε ενώ δεν πέρασε.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ⚡ Γρήγορη εκκίνηση
|
|
91
|
+
|
|
92
|
+
Τρέξ' το σε ένα repo για πλήρη αναφορά και δείκτη αξιοπιστίας:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npx mjolnir-qa@latest
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Στο CI το προϊόν είναι μία εντολή.** Σκανάρει μόνο ό,τι άγγιξε το
|
|
99
|
+
branch και βγαίνει μη μηδενικά σε νέα προβλήματα:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx mjolnir-qa@latest --scope changed
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Ρίξε αυτό σε ένα PR check — το `mjolnir ci install` γράφει το workflow —
|
|
106
|
+
και τελείωσες. Όλα τα άλλα είναι προαιρετικά.
|
|
107
|
+
|
|
108
|
+
| Εντολή | Τι κάνει |
|
|
109
|
+
| ----------------------------------- | ------------------------------------------------------------ |
|
|
110
|
+
| `mjolnir` | Πλήρες σκαν repo + δείκτης αξιοπιστίας |
|
|
111
|
+
| `mjolnir --scope changed` | Μόνο ό,τι引入ε το branch σου — η μορφή CI |
|
|
112
|
+
| `mjolnir ci install` | Δημιουργεί το συμβουλευτικό PR workflow |
|
|
113
|
+
| `mjolnir explain QA-CI-001` | Τι / γιατί / fix + μετρημένο ποσοστό FP για έναν κανόνα |
|
|
114
|
+
| `mjolnir rules --unmeasured` | Οι κανόνες που τρέχουν με υπόθεση, όχι με μέτρημα |
|
|
115
|
+
| `mjolnir --json` / `--format sarif` | Μηχανικά αναγνώσιμο / GitHub Code Scanning |
|
|
116
|
+
| `mjolnir --strict` | Εκτελεί και κανόνες tier quarantine (υψηλότερος κίνδυνος FP) |
|
|
117
|
+
|
|
118
|
+
<details>
|
|
119
|
+
<summary><strong>Όταν κάτι είναι flaky</strong></summary>
|
|
120
|
+
|
|
121
|
+
| Εντολή | Τι κάνει |
|
|
122
|
+
| ----------------------------------- | --------------------------------------------------------------- |
|
|
123
|
+
| `mjolnir forensics ./test-results/` | Πραγματικά δεδομένα runs → ετυμηγορίες `TRUE-FLAKE`, `FLAKY.md` |
|
|
124
|
+
| `mjolnir triage ./test-results/` | Πρόταση καραντίνας από ιστορικό εκτέλεσης |
|
|
125
|
+
| `mjolnir pw-report ./test-results/` | Σύνοψη run Playwright — retries / flakes / τα πιο αργά |
|
|
126
|
+
| `mjolnir doctor:playwright` | Βαθύ σκαν μόνο Playwright + Selector Health Score |
|
|
127
|
+
|
|
128
|
+
</details>
|
|
129
|
+
|
|
130
|
+
<details>
|
|
131
|
+
<summary><strong>Σπάνια / αναφορές</strong></summary>
|
|
132
|
+
|
|
133
|
+
| Εντολή | Τι κάνει |
|
|
134
|
+
| ------------------------------- | ------------------------------------------------------- |
|
|
135
|
+
| `mjolnir fix --dry-run` / `fix` | Ασφαλή αυτόματα fix με απόδειξη |
|
|
136
|
+
| `mjolnir baseline` / `diff` | Στιγμιότυπο ευρημάτων, μετά αναφορά μόνο νέων/χειρότερα |
|
|
137
|
+
| `mjolnir impact --since <ref>` | Τι άλλαξε από προηγούμενο commit |
|
|
138
|
+
| `mjolnir debt` | Μητρώο τεχνολογικού χρέους τεστ με μοντέλο κόστους |
|
|
139
|
+
| `mjolnir handover` | Χάρτης onboarding της σουίτας για νέο QA |
|
|
140
|
+
| `mjolnir stats` | Τοπικοί σωρευτικοί μετρητές όλων των fix που είδε |
|
|
141
|
+
| `mjolnir badge` | shields.io endpoint JSON + snippet |
|
|
142
|
+
| `mjolnir rules --md` | Πλήρης κατάλογος κανόνων (JSON ή Markdown) |
|
|
143
|
+
| `mjolnir doctor` | Αυτοέλεγχος της ίδιας της βάσης κανόνων του Mjölnir |
|
|
144
|
+
| `mjolnir create-rule <ID>` | Σκαφφάρει νέο κανόνα + fixtures |
|
|
145
|
+
| `mjolnir --format mermaid` | Διάγραμμα αρχιτεκτονικής τεστ για σχόλιο PR |
|
|
146
|
+
|
|
147
|
+
</details>
|
|
148
|
+
|
|
149
|
+
Εγκατάσταση globally αντί για `npx` αν προτιμάς: `npm i -g mjolnir-qa`.
|
|
150
|
+
Απαιτεί Node.js ≥ 22.18. Λειτουργεί σε Windows, macOS και Linux.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 👥 Για ποιον είναι;
|
|
155
|
+
|
|
156
|
+
- **QA / SDET** που έχουν e2e ή integration σουίτα και χρειάζονται
|
|
157
|
+
αποδείξεις ότι η σουίτα αξίζει πραγματικά το πράσινο τσεκ που
|
|
158
|
+
παράγει.
|
|
159
|
+
- **Ομάδες Platform / DevEx** υπεύθυνες για ακεραιότητα CI και release
|
|
160
|
+
gates — οι άνθρωποι που νοιάζονται να μην μετατρέψει ποτέ ένα
|
|
161
|
+
`continue-on-error` βουβά κόκκινο pipeline σε πράσινο.
|
|
162
|
+
- **Maintainers OSS** που θέλουν φτηνή, πάντα ενεργή πύλη επαλήθευσης
|
|
163
|
+
που τρέχει τοπικά και σε CI χωρίς κλήσεις δικτύου.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🔨 Τι ελέγχει το Mjölnir
|
|
168
|
+
|
|
169
|
+
| | |
|
|
170
|
+
| --- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
171
|
+
| ⚖️ | **Δείκτης αξιοπιστίας** — ένας αριθμός, διαφανής πίνακας αφαιρέσεων, καμία μαύρη κάψουλα |
|
|
172
|
+
| 🎭 | **Selector Health Score** — βαθμολογεί τα Playwright locators σου, όχι μόνο το pass rate |
|
|
173
|
+
| 🔬 | **Δικαστική ανάλυση runtime** — διαβάζει πραγματικά δεδομένα Playwright/JUnit για να πιάσει `TRUE-FLAKE`, όχι μόνο στατικές εικασίες |
|
|
174
|
+
| 🚨 | **Κανόνες ακεραιότητας CI** — πιάνει `continue-on-error`, `\|\| true` και άλλα κόλπα ψεύτικου πράσινου |
|
|
175
|
+
| 🐍 | **Και τα τέσσερα Playwright bindings** — TypeScript, Python, Java, C#/.NET — plus pytest, JUnit/TestNG και CI workflows |
|
|
176
|
+
| 🔒 | **Local-first** — μηδενικές κλήσεις δικτύου κατά το σκαν, μηδενική τηλεμετρία, τρέχει σε δευτερόλεπτα |
|
|
177
|
+
|
|
178
|
+
### Οι κανόνες
|
|
179
|
+
|
|
180
|
+
Κάθε κανόνας έρχεται με fixtures must-fire **και** must-not-fire.
|
|
181
|
+
Κανόνας που ενεργοποιείται στη δική του αρνητική fixture δεν μπορεί να
|
|
182
|
+
να κυκλοφορήσει — αυτός είναι ο τείχος των false positives.
|
|
183
|
+
|
|
184
|
+
<details>
|
|
185
|
+
<summary><strong>Υγιεινή τεστ</strong></summary>
|
|
186
|
+
|
|
187
|
+
| ID | Κανόνας | Severity |
|
|
188
|
+
| ----------- | ----------------------------------------------------- | -------- |
|
|
189
|
+
| QA-TEST-001 | Commitμένος focused τεστ (`.only`, `fit`) | error |
|
|
190
|
+
| QA-TEST-002 | Παραλειμένο τεστ χωρίς δικαιολογία | error |
|
|
191
|
+
| QA-TEST-002 | Παραλειμένο τεστ με καταγεγραμμένη δικαιολογία | warning |
|
|
192
|
+
| QA-TEST-003 | Τεστ χωρίς assertions | error |
|
|
193
|
+
| QA-TEST-004 | Σκληρό sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning |
|
|
194
|
+
| QA-TEST-006 | Κατάχρηση retry που κρύβει flakiness | warning |
|
|
195
|
+
| QA-TEST-010 | Κενό σώμα τεστ | error |
|
|
196
|
+
|
|
197
|
+
</details>
|
|
198
|
+
|
|
199
|
+
<details>
|
|
200
|
+
<summary><strong>Ποιότητα τεστ</strong></summary>
|
|
201
|
+
|
|
202
|
+
| ID | Κανόνας | Severity |
|
|
203
|
+
| ------------ | ----------------------------- | -------- |
|
|
204
|
+
| QA-TQUAL-001 | Επαλήθευση μόνο με mocks | info |
|
|
205
|
+
| QA-TQUAL-002 | Ταυτολογική assertion | error |
|
|
206
|
+
| QA-TQUAL-009 | Assertion promise χωρίς await | error |
|
|
207
|
+
| QA-TQUAL-011 | Σχολιασμένα τεστ | warning |
|
|
208
|
+
|
|
209
|
+
</details>
|
|
210
|
+
|
|
211
|
+
<details>
|
|
212
|
+
<summary><strong>Playwright 🎭</strong></summary>
|
|
213
|
+
|
|
214
|
+
| ID | Κανόνας | Severity |
|
|
215
|
+
| --------- | ---------------------------------------------- | -------- |
|
|
216
|
+
| QA-PW-002 | Assertion locator χωρίς await | error |
|
|
217
|
+
| QA-PW-003 | `page.pause()` / `test.only()` στο commit | error |
|
|
218
|
+
| QA-PW-004 | Εύθραυστοι CSS/XPath selectors | warning |
|
|
219
|
+
| QA-PW-005 | Επιχειρησιακή λογική μέσα σε `page.evaluate()` | info |
|
|
220
|
+
| QA-PW-114 | Legacy element handles (`page.$`) | info |
|
|
221
|
+
| QA-PW-118 | Αναμονές `networkidle` (flaky by design) | info |
|
|
222
|
+
| QA-PW-123 | Σκληρά URL περιβάλλοντος | warning |
|
|
223
|
+
|
|
224
|
+
</details>
|
|
225
|
+
|
|
226
|
+
<details>
|
|
227
|
+
<summary><strong>Ακεραιότητα CI</strong></summary>
|
|
228
|
+
|
|
229
|
+
| ID | Κανόνας | Severity |
|
|
230
|
+
| --------- | --------------------------------------------------------------------- | -------- |
|
|
231
|
+
| QA-CI-001 | Το `continue-on-error` κρύβει αποτυχίες | error |
|
|
232
|
+
| QA-CI-002 | Το `\|\| true` καταπίνει exit codes | error |
|
|
233
|
+
| QA-CI-005 | Αναφορά καταναλώνεται αλλά ποτέ δεν παράγεται | error |
|
|
234
|
+
| QA-CI-007 | Περιτύλιξη retry γύρω από τεστ | warning |
|
|
235
|
+
| QA-CI-008 | Step πάντα επιτυχές κρύβει αποτυχίες | error |
|
|
236
|
+
| QA-CI-009 | Exit code του τεστ δεν προωθείται (`\|` χωρίς pipefail, αλυσίδες `;`) | error |
|
|
237
|
+
| QA-CI-010 | Τεστ παραλείπονται εκεί που πρέπει να μπλοκάρουν (skip-on-PR guards) | error |
|
|
238
|
+
|
|
239
|
+
</details>
|
|
240
|
+
|
|
241
|
+
<details>
|
|
242
|
+
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
243
|
+
|
|
244
|
+
| ID | Κανόνας | Severity |
|
|
245
|
+
| --------- | --------------------------------------------- | -------- |
|
|
246
|
+
| QA-PY-002 | Παραλειμένο τεστ (`skip`, μη αυστηρό `xfail`) | warning |
|
|
247
|
+
| QA-PY-003 | Συνάρτηση τεστ χωρίς assertions | error |
|
|
248
|
+
| QA-PY-005 | `time.sleep()` σε τεστ | warning |
|
|
249
|
+
| QA-PY-006 | Κενό σώμα τεστ (`pass`) | info |
|
|
250
|
+
| QA-PY-010 | Εξάρτηση από τύχη/χρόνο χωρίς freeze | info |
|
|
251
|
+
| QA-PY-012 | Ταυτολογική assertion | error |
|
|
252
|
+
|
|
253
|
+
Συνολικά 20 κανόνες Python (QA-PY-001…012 υγιεινή pytest + QA-PY-101…108 Playwright-Python).
|
|
254
|
+
|
|
255
|
+
</details>
|
|
256
|
+
|
|
257
|
+
<details>
|
|
258
|
+
<summary><strong>Java / JUnit · TestNG ☕</strong></summary>
|
|
259
|
+
|
|
260
|
+
| ID | Κανόνας | Severity |
|
|
261
|
+
| --------- | ------------------------------------------ | -------- |
|
|
262
|
+
| QA-JV-101 | Απενεργοποιημένο τεστ (`@Disabled`) | warning |
|
|
263
|
+
| QA-JV-102 | Σκληρό sleep (`Thread.sleep()`) | warning |
|
|
264
|
+
| QA-JV-103 | Μέθοδος τεστ χωρίς assertions | error |
|
|
265
|
+
| QA-JV-105 | Σκληρό sleep Playwright `waitForTimeout()` | warning |
|
|
266
|
+
| QA-JV-106 | Εύθραυστος selector αντί για role locator | warning |
|
|
267
|
+
| QA-JV-108 | Σκληρό URL περιβάλλοντος στο τεστ | info |
|
|
268
|
+
| QA-JV-111 | Μαζικό mock `page.route("**")` | info |
|
|
269
|
+
|
|
270
|
+
</details>
|
|
271
|
+
|
|
272
|
+
<details>
|
|
273
|
+
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
274
|
+
|
|
275
|
+
| ID | Κανόνας | Severity |
|
|
276
|
+
| --------- | ---------------------------------------------- | -------- |
|
|
277
|
+
| QA-CS-101 | Παραλειμένο τεστ (`[Ignore]`, `[Fact(Skip=)]`) | warning |
|
|
278
|
+
| QA-CS-102 | Σκληρό sleep (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
279
|
+
| QA-CS-103 | Μέθοδος τεστ χωρίς assertions | error |
|
|
280
|
+
| QA-CS-105 | Σκληρό sleep `WaitForTimeoutAsync()` | warning |
|
|
281
|
+
| QA-CS-106 | Εύθραυστος selector αντί για role locator | warning |
|
|
282
|
+
| QA-CS-108 | Σκληρό URL περιβάλλοντος στο τεστ | info |
|
|
283
|
+
| QA-CS-111 | Μαζικό mock `page.RouteAsync("**")` | info |
|
|
284
|
+
|
|
285
|
+
</details>
|
|
286
|
+
|
|
287
|
+
> Ο πλήρης ζωντανός κατάλογος — κάθε κανόνας με tier, confidence,
|
|
288
|
+
> κίνδυνο false positive και διαθεσιμότητα autofix — παράγεται από το
|
|
289
|
+
> μητρώο:
|
|
290
|
+
>
|
|
291
|
+
> ```bash
|
|
292
|
+
> mjolnir rules --md
|
|
293
|
+
> ```
|
|
294
|
+
>
|
|
295
|
+
> Οι σελίδες ανά κανόνα ζουν στο [`docs/rules/`](docs/rules/).
|
|
296
|
+
|
|
297
|
+
### Πόσο από αυτό είναι μετρημένο
|
|
298
|
+
|
|
299
|
+
**74 από 99 κανόνες φέρουν ποσοστό false positive μετρημένο σε πραγματικό
|
|
300
|
+
κώδικα OSS** (≥ 10 χειροκίνητα ταξινομημένα ευρήματα ο καθένας· βλ.
|
|
301
|
+
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Οι άλλοι 19 κυκλοφορούν πάνω στην
|
|
302
|
+
εκτίμηση του συγγραφέα. Το υποσέλιδο κάθε σκαν σου λέει πόσοι από τους
|
|
303
|
+
_ενεργούς_ κανόνες είναι μετρημένοι· `mjolnir rules --unmeasured`
|
|
304
|
+
παραθέτει τους άμετρητους· η σελίδα `mjolnir explain` κάθε κανόνα
|
|
305
|
+
δηλώνει την κατάστασή του. Δημοσιεύουμε το ποσοστό ακόμα κι όταν είναι
|
|
306
|
+
άσχημο — ο QA-CS-103 αυτοελέγχεται στο 95 % και είναι σε καραντίνα γι'
|
|
307
|
+
αυτό. Να μεγαλώσει αυτό το 78 είναι η συνεχιζόμενη δουλειά του έργου.
|
|
308
|
+
|
|
309
|
+
### Tiers κανόνων και ωριμότητα γλωσσών
|
|
310
|
+
|
|
311
|
+
Κάθε κανόνας είναι `core`, `extended` ή `quarantine`, ανατεθειμένος από
|
|
312
|
+
το **μετρημένο** ποσοστό false positive του:
|
|
313
|
+
|
|
314
|
+
| Tier | Σημασία | Προεπιλεγμένο σκαν | `--strict` |
|
|
315
|
+
| ------------ | -------------------------------------- | :----------------: | :--------: |
|
|
316
|
+
| `core` | ≤ 10 % μετρημένο FP | ✅ | ✅ |
|
|
317
|
+
| `extended` | ≤ 30 % μετρημένο FP | ✅ | ✅ |
|
|
318
|
+
| `quarantine` | πάνω από 30 %, ή ακόμα άμετρο (n < 10) | ❌ | ✅ |
|
|
319
|
+
|
|
320
|
+
| Γλώσσα | Adapter | Κάλυψη σήμερα |
|
|
321
|
+
| --------------- | ----------------- | ------------------------------------------------------------------ |
|
|
322
|
+
| TypeScript / JS | AST μεταγλωττιστή | η ευρύτερη, η πιο μετρημένη — ως επί το πλείστον `core`/`extended` |
|
|
323
|
+
| Python / pytest | Στρώμα regex | ευρεία, ελεγμένη σε corpus — ως επί το πλείστον `core`/`extended` |
|
|
324
|
+
| Java | Στρώμα regex | νεότερη — ως επί το πλείστον `extended`/`quarantine` |
|
|
325
|
+
| C# / .NET | Στρώμα regex | νεότερη — ως επί το πλείστον `extended`/`quarantine` |
|
|
326
|
+
|
|
327
|
+
TypeScript και Python έχουν την ευρύτερη μετρημένη κάλυψη. Η Java και η
|
|
328
|
+
C# κυκλοφορούν, είναι τεκμηριωμένες και μένουν εκτός του headline αριθμού
|
|
329
|
+
μέχρι μια πραγματική σουίτα καταναλωτή (όχι τα ίδια τα τεστ μιας
|
|
330
|
+
βιβλιοθήκης binding) να ελεγχθεί.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## Πώς λειτουργεί το σκόρ
|
|
335
|
+
|
|
336
|
+
<p align="center">
|
|
337
|
+
<img src="assets/readme/terminal-hero.svg" alt="Έξοδος τερματικού Mjölnir — WORTHINESS 75/100 NEEDS WORK, ανάλυση διαγνώσεων ανά κατηγορία και λίστα FIX THIS FIRST" width="820" />
|
|
338
|
+
</p>
|
|
339
|
+
|
|
340
|
+
<sub>Αναδημιουργείται με `npm run docs:hero`;
|
|
341
|
+
[`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
|
|
342
|
+
ρίχνει το CI αν ο artifact αποκλίνει από ό,τι τυπώνει ο reporter.</sub>
|
|
343
|
+
|
|
344
|
+
Το σκόρ είναι διαφανές: **error −8, warning −3, info −1**, μετά
|
|
345
|
+
κανονικοποίηση με την έκθεση της σουίτας (αφαιρέσεις ανά δήλωση τεστ).
|
|
346
|
+
Οι αφαίρεσεις σταθμισμένες με αποδείξεις σημαίνουν ότι τα αδύναμα σήματα
|
|
347
|
+
κοστίζουν λιγότερο. Το τερματικό δείχνει τους ίδιους εκπτώτους αριθμούς
|
|
348
|
+
που χρησιμοποιεί το σκόρ — καμία μαύρη κάψουλα. Πλήρης μέθοδος:
|
|
349
|
+
[docs/SCORING.md](docs/SCORING.md).
|
|
350
|
+
|
|
351
|
+
**Ετυμηγορίες**
|
|
352
|
+
|
|
353
|
+
| Score | Ετυμηγορία |
|
|
354
|
+
| ------- | ---------------- |
|
|
355
|
+
| ≥ 80 | ✓ **WORTHY** |
|
|
356
|
+
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
357
|
+
| < 50 | ✖ **UNWORTHY** |
|
|
358
|
+
|
|
359
|
+
**Επίπεδα αποδείξεων** — κάθε εύρημα φέρει ένα· ορίζει το βάρος του
|
|
360
|
+
ευρήματος στο σκόρ:
|
|
361
|
+
|
|
362
|
+
| Επίπεδο | Σημασία | Επίδραση στο σκόρ | Παράδειγμα |
|
|
363
|
+
| ------- | -------------------- | ----------------- | --------------------------------------------------- |
|
|
364
|
+
| E2 | Καθορισμένο ελάττωμα | Πλήρης αφαίρεση | Commitμένο `.only` — δομικά αποδείξιμο |
|
|
365
|
+
| E1 | Ευρετικό μοτίβο | Μισή αφαίρεση | Regex-βρεμένο `sleep()` — ισχυρό σήμα, όχι απόδειξη |
|
|
366
|
+
| E0 | Παρατήρηση | Μηδέν (μόνο info) | Αναφέρεται αλλά δεν gated ποτέ CI ούτε αφαιρεί |
|
|
367
|
+
|
|
368
|
+
Οι περισσότεροι κανόνες είναι **E1**. Το σύνθημα «we prove it»
|
|
369
|
+
αναφέρεται σε αυτό το σύστημα: τα ευρήματα E2 είναι δομική απόδειξη·
|
|
370
|
+
τα ευρήματα E1 είναι σωστά τοποθετημένες προειδοποιήσεις, όχι τυπικές
|
|
371
|
+
αποδείξεις.
|
|
372
|
+
|
|
373
|
+
Ένα άδειο repo σκοράρει `null`, ποτέ ψεύτικα 100 — δες
|
|
374
|
+
[Μοντέλο εμπιστοσύνης](#μοντέλο-εμπιστοσύνης).
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## 🎭 Selector Health Score
|
|
379
|
+
|
|
380
|
+
Η headline μετρική για σουίτες Playwright — πόσο ανθεκτικοί είναι οι
|
|
381
|
+
locators σου:
|
|
382
|
+
|
|
383
|
+
```text
|
|
384
|
+
▚▞ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
385
|
+
|
|
386
|
+
[█████████████████░░░] 83 / 100
|
|
387
|
+
role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Locators με βάση τα roles παίρνουν πλήρες σκόρ. Οι αλυσίδες CSS class
|
|
391
|
+
και το XPath βυθίζουν το σκόρ — σπάνε σε κάθε refactor DOM χωρίς να σου
|
|
392
|
+
λένε ποια συμπεριφορά παλινδρόμησε.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## 🔬 Αποδείξεις runtime
|
|
397
|
+
|
|
398
|
+
Η στατική ανίχνευση flakiness είναι μαντεψιά. Το Mjölnir διαβάζει
|
|
399
|
+
**πραγματικά δεδομένα εκτέλεσης** — αναφορές JSON Playwright και XML
|
|
400
|
+
JUnit από οποιονδήποτε runner:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
mjolnir forensics ./test-results/
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
```text
|
|
407
|
+
▚▞ FLAKINESS LEADERBOARD
|
|
408
|
+
|
|
409
|
+
3 tests · 1 failed · 1 flaky · 1 retried
|
|
410
|
+
|
|
411
|
+
TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
|
|
412
|
+
████████████████████ 6.0s · 2 attempts
|
|
413
|
+
FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
414
|
+
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Τεστ που περνά μόνο από την προσπάθεια ≥ 2 δεν είναι τεστ που περνά —
|
|
418
|
+
είναι τυχερό τεστ. Χαρακτηρίζεται `TRUE-FLAKE` ανεξάρτητα από το τελικό
|
|
419
|
+
πράσινο τσεκ.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## ⚡ Το Mjölnir δεν είναι ακόμα ένα linter
|
|
424
|
+
|
|
425
|
+
Τα linters σου λένε αν ο κώδικας ακολουθεί κανόνες. Το Mjölnir σου λέει
|
|
426
|
+
αν η επαλήθευσή σου μπορεί να εμπιστευτεί.
|
|
427
|
+
|
|
428
|
+
| | ESLint / SonarQube | Εργαλεία coverage | Χειροκίνητο review | **Mjölnir** |
|
|
429
|
+
| -------------------------------------------------------------- | :----------------: | :---------------: | :----------------: | :---------: |
|
|
430
|
+
| Ακεραιότητα CI workflow (`continue-on-error`, `\|\| true`) | ❌ | ❌ | σπάνια | ✅ |
|
|
431
|
+
| Cross-γλώσσα (TS, Python, Java, C#) από ένα εργαλείο | ❌ | ❌ | ❌ | ✅ |
|
|
432
|
+
| Βαθμολογεί ανθεκτικότητα Playwright locators (Selector Health) | ❌ | ❌ | σπάνια | ✅ |
|
|
433
|
+
| Σημαίνει τεστ χωρίς πραγματικές assertions | ✅ (plugin)\* | ❌ | καμιά φορά | ✅ |
|
|
434
|
+
| Πιάνει σκληρά sleeps (`waitForTimeout`, `time.sleep`) | ✅ (plugin)\* | ❌ | καμιά φορά | ✅ |
|
|
435
|
+
| Τρέχει σε δευτερόλεπτα, μηδέν κλήσεις δικτύου κατά το σκαν | ✅ | ✅ | — | ✅ |
|
|
436
|
+
|
|
437
|
+
\*Το `eslint-plugin-jest` (`expect-expect`) και το
|
|
438
|
+
`eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`)
|
|
439
|
+
καλύπτουν αυτά για τα αντίστοιχα frameworks τους.
|
|
440
|
+
|
|
441
|
+
**Η ανάλυση runtime** είναι ξεχωριστή κατηγορία δίπλα στο στατικό
|
|
442
|
+
linting:
|
|
443
|
+
|
|
444
|
+
| | Playwright retry reporter | Allure / ReportPortal | **Mjölnir forensics** |
|
|
445
|
+
| -------------------------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
|
|
446
|
+
| Διαβάζει πραγματικά δεδομένα runs για ετυμηγορίες `TRUE-FLAKE` | μερικώς\* | μερικώς (tag) | ✅ |
|
|
447
|
+
| Αναφορά triage flakiness από ιστορικό εκτέλεσης | ❌ | ✅ | ✅ |
|
|
448
|
+
| Ενσωματώνεται με τον στατικό δείκτη αξιοπιστίας | ❌ | ❌ | ✅ |
|
|
449
|
+
|
|
450
|
+
\*Το Playwright παρακολουθεί εσωτερικά τα retries αλλά δεν παράγει
|
|
451
|
+
αυτόνομη αναφορά flakiness με ετικέτες ετυμηγοριών.
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## 🤖 Γιατί όχι απλώς AI code review;
|
|
456
|
+
|
|
457
|
+
Διαφορετικό πρόβλημα, διαφορετικό στρώμα. Το AI review μπορεί να πιάσει
|
|
458
|
+
ύποπτη αλλαγή τεστ σε ένα diff· δεν αποδεικνύει ότι το σύστημα
|
|
459
|
+
επαλήθευσης συνολικά αξίζει εμπιστοσύνη — και βλέπει μόνο το diff που
|
|
460
|
+
του δείχνεις.
|
|
461
|
+
|
|
462
|
+
| | AI code review (Copilot κ.λπ.) | **Mjölnir** |
|
|
463
|
+
| -------------------------------------------- | :--------------------------------------: | :-------------------------------: |
|
|
464
|
+
| Κόστος ανά σκαν | Tokens (κλιμακώνεται με το μέγεθος diff) | **Μηδέν** (τοπικό, εγκατεστημένο) |
|
|
465
|
+
| Βλέπει όλη τη σουίτα + όλες τις ρυθμίσεις CI | Μόνο το PR diff που δείχνεις | **Όλα, κάθε φορά** |
|
|
466
|
+
| Καθοριστικό (ίδιο input → ίδιο output) | ❌ (μη καθοριστικό) | **✅** |
|
|
467
|
+
| Πιάνει μοτίβα που κοιμούνται μήνες | Μόνο αν είναι στο context | **✅** (σκανάρει όλα τα αρχεία) |
|
|
468
|
+
| Θυμάται ευρήματα μεταξύ runs | ❌ (καμία μνήμη μεταξύ συνεδριών) | **✅** (baseline + diff) |
|
|
469
|
+
| Τρέχει χωρίς ανθρώπινο έναυσμα | Χρειάζεται PR ή prompt | **✅** (CI hook, 3 δευτερόλεπτα) |
|
|
470
|
+
|
|
471
|
+
**Χρησιμοποίησέ τα και τα δύο.** Το AI πιάνει νύαντσε, πρόθεση και
|
|
472
|
+
σχεδιαστικά ελαττώματα που καμία regex δεν βρίσκει. Το Mjölnir πιάνει
|
|
473
|
+
τα δομικά μοτίβα που το AI παραβλέπει επειδή φαίνονται «εσκεμμένα» —
|
|
474
|
+
ένα commitμένο `.only`, ένα καταπιμένο exit code, ένα `continue-on-error`
|
|
475
|
+
σε τεστ job. Δεν είναι bugs που χρειάζονται συλλογισμό· είναι γεγονότα
|
|
476
|
+
που χρειάζονται σκαν.
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## 🤖 Ενσωμάτωση CI
|
|
481
|
+
|
|
482
|
+
Μία εντολή παράγει PR workflow — συμβουλευτικό από προεπιλογή, ποτέ
|
|
483
|
+
μπλοκάρισμα:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
mjolnir ci install
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Ή σύνδεσέ το εγγενώς σε GitHub Code Scanning μέσω SARIF:
|
|
490
|
+
|
|
491
|
+
```yaml
|
|
492
|
+
- run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
|
|
493
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
494
|
+
with:
|
|
495
|
+
sarif_file: mjolnir.sarif
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Ρύθμιση editor και pipeline για SARIF:
|
|
499
|
+
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
500
|
+
|
|
501
|
+
### Κάλυψη changed-scope
|
|
502
|
+
|
|
503
|
+
Το `--scope changed` αποδίδει ευρήματα σε γραμμές που πρόσθεσε το branch
|
|
504
|
+
σου σε σχέση με το merge-base με το `main`. Καλύπτει αρχεία τεστ
|
|
505
|
+
(`*.spec.*`, `*.test.*`) συν αρχεία GitHub workflow και ρυθμίσεις
|
|
506
|
+
Playwright στο diff. Όταν το merge-base δεν λύνεται — shallow clone,
|
|
507
|
+
detached HEAD, μη-git στόχος, διαφορετικό default branch — υποβαθμίζει
|
|
508
|
+
ειλικρινά: τα ευρήματα επιστρέφουν σε απόδοση κατά σύνολο αρχείου και η
|
|
509
|
+
αναφορά το λέει. Υπενόμησε την base ref με `--base <ref>`.
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Διαμόρφωση
|
|
514
|
+
|
|
515
|
+
Το Mjölnir είναι zero-config. Ένα προαιρετικό `mjolnir.config.json` (ή
|
|
516
|
+
`.mjolnir.json`) στη ρίζα του repo ρυθμίζει severity, gating και scope —
|
|
517
|
+
δεν αλλάζει ποτέ τη σημασιολογία ανίχνευσης.
|
|
518
|
+
|
|
519
|
+
| Key | Τύπος | Επίδραση |
|
|
520
|
+
| ------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
521
|
+
| `exclude` | `string[]` | Επιπλέον ignore globs (υποσύνολο gitignore), πάνω από τα ενσωματωμένα defaults |
|
|
522
|
+
| `gate` | `"advisory" \| "error" \| "warning"` | Ποια severity βγαίνουν μη μηδενικά (default `error`; το `advisory` δεν μπλοκάρει ποτέ) |
|
|
523
|
+
| `severityOverrides` | `{ "<RULE-ID>": severity }` | Επανατάσσει τα ευρήματα ενός κανόνα για το repo σου |
|
|
524
|
+
| `ignore` | `IgnoreEntry[]` | Καταστέλλει ευρήματα — **το `reason` απαιτείται**· οι εγγραφές λήγουν μετά από 90 ημέρες (ρητό `expires` date, ή time last-modified του αρχείου ρυθμίσεων για εγγραφές χωρίς) |
|
|
525
|
+
| `plugins` | `string[]` | Πακέτα κανόνων τρίτων (δες [Μοντέλο εμπιστοσύνης](#μοντέλο-εμπιστοσύνης)) |
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
{
|
|
529
|
+
"gate": "error",
|
|
530
|
+
"exclude": ["legacy/**"],
|
|
531
|
+
"severityOverrides": { "QA-PW-118": "warning" },
|
|
532
|
+
"ignore": [
|
|
533
|
+
{
|
|
534
|
+
"ruleId": "QA-TEST-004",
|
|
535
|
+
"files": ["e2e/legacy-login.spec.ts"],
|
|
536
|
+
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
537
|
+
"expires": "2026-12-31"
|
|
538
|
+
}
|
|
539
|
+
]
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
- **`.mjolnirignore`** — απλό αρχείο τύπου gitignore για εξαιρέσεις
|
|
544
|
+
διαδρομών, ίδια διάλεκτος με το `exclude`. Χρησιμοποίησέ το για θόρυβο
|
|
545
|
+
ανά μηχανή· χρησιμοποίησε `exclude` όταν η λίστα ανήκει στον version
|
|
546
|
+
control, δίπλα στην υπόλοιπη ρύθμιση.
|
|
547
|
+
- **CLI overrides** — `--strict` (συμπερίληψη κανόνων καραντίνας),
|
|
548
|
+
`--width <cols>` και `--ascii` / `--no-ascii` (απόδοση τερματικού),
|
|
549
|
+
`--tone blunt` (πιο άκαμπτα μηνύματα), `--max-duration <sec>`
|
|
550
|
+
(περιορισμένη μερική σκαν).
|
|
551
|
+
- Καταστολή κανόνων και κύκλος ζωής deprecation:
|
|
552
|
+
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
553
|
+
|
|
554
|
+
Οι εγγραφές `ignore` τροφοδοτούν και την αυτόνομη εντολή
|
|
555
|
+
`mjolnir suppressions`, που παραθέτει τι είναι κατασταλμένο τώρα και
|
|
556
|
+
πότε λήγει κάθε εγγραφή.
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## 📐 Exit codes & συμβόλαια
|
|
561
|
+
|
|
562
|
+
Παγωμένα — ασφαλή για χτίσιμο CI λογικής:
|
|
563
|
+
|
|
564
|
+
| Exit code | Σημασία |
|
|
565
|
+
| --------- | ------------------------------------------------------------------------------------- |
|
|
566
|
+
| `0` | Καθαρό — κανένα εύρημα στο ή πάνω από το gate |
|
|
567
|
+
| `1` | Ευρήματα στο ή πάνω από το gate |
|
|
568
|
+
| `2` | Μερικό σκαν (τέλος χρονικού προϋπολογισμού, δυσανάγνωστα αρχεία) — δεν μπλοκάρει ποτέ |
|
|
569
|
+
| `10` | Λάθος χρήσης (bad flag, λείπει στόχος) |
|
|
570
|
+
| `20` | Εσωτερικό λάθος |
|
|
571
|
+
|
|
572
|
+
Η αναφορά JSON/SARIF είναι `schemaVersion: 1`. Τα IDs κανόνων
|
|
573
|
+
(`QA-<FAMILY>-NNN`) είναι αμετάβλητα μόλις κυκλοφορήσουν και δεν
|
|
574
|
+
επαναχρησιμοποιούνται ποτέ.
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Μοντέλο εμπιστοσύνης
|
|
579
|
+
|
|
580
|
+
- **Local-first** — μηδέν κλήσεις δικτύου κατά το σκαν. Ποτέ. Μηδενική
|
|
581
|
+
τηλεμετρία.
|
|
582
|
+
- **Καμία ψεύτικη απόδειξη** — προτιμούμε να πούμε «άγνωστο» παρά
|
|
583
|
+
«επαληθευμένο». Άδειο repo παίρνει `score: null`, ποτέ ψεύτικα 100.
|
|
584
|
+
- **Μερική ειλικρίνεια** — αν η ανάλυση κόπηκε, η έξοδος το λέει.
|
|
585
|
+
Ποτέ «complete» όταν δεν είναι.
|
|
586
|
+
- **FP τείχος** — η ανίχνευση τρέχει σε άποψη κώδικα χωρίς
|
|
587
|
+
σχόλια/strings (οι κανόνες TypeScript χρησιμοποιούν AST
|
|
588
|
+
μεταγλωττιστή): ένα μοτίβο μέσα σε σχόλιο πρόζας ή doc-παράδειγμα
|
|
589
|
+
string είναι τεκμηρίωση, όχι εύρημα.
|
|
590
|
+
- **Μετρημένο, όχι δηλωμένο** — μόνο κανόνες με ποσοστό false positive
|
|
591
|
+
από πραγματικό OSS κώδικα κυκλοφορούν στα headline tiers (δες
|
|
592
|
+
[Πόσο από αυτό είναι μετρημένο](#πόσο-από-αυτό-είναι-μετρημένο)); το
|
|
593
|
+
υποσέλιδο σκαν και το `mjolnir rules --unmeasured` σου λένε ποιος
|
|
594
|
+
ποιος.
|
|
595
|
+
- **Εμπιστοσύνη plugins** — τα plugins είναι πακέτα npm δηλωμένα κάτω
|
|
596
|
+
από `"plugins"`. **Δεν υπάρχει sandbox**: ο κώδικας plugin τρέχει με
|
|
597
|
+
πλήρη δικαιώματα Node, το ίδιο μοντέλο εμπιστοσύνης με plugins ESLint
|
|
598
|
+
ή Vitest. Core προθέματα rule-ID είναι δεσμευμένα και απορρίπτονται
|
|
599
|
+
από plugins κατά της πλαστοπροσωπίας.
|
|
600
|
+
- **Εξωτερικοί κανόνες τοπικοί στο workspace** (φάκελος, μηδέν δίκτυο) —
|
|
601
|
+
ένας φάκελος `mjolnir-rules/` δίπλα στον στόχο σκαν φορτώνει custom
|
|
602
|
+
κανόνες: JSON αρχεία δηλώνουν regex μοτίβα (κανένας κώδικας δεν
|
|
603
|
+
εκτελείται), `.mjs`/`.js` modules εξάγουν `rules` (πλήρης εμπιστοσύνη
|
|
604
|
+
Node, όπως plugins). Οι εξωτερικοί κανόνες φέρουν τα ίδια trust
|
|
605
|
+
metadata με το core· δεν μπορούν ποτέ να κυκλοφορήσουν στο core tier
|
|
606
|
+
(το core απαιτεί μετρημένο FP από το corpus sidecar — δηλωμένο
|
|
607
|
+
`tier: "core"` σφίγγεται σε `extended`), τηρούν tier πλαφόν και
|
|
608
|
+
ελέγχονται για drift: `mjolnir rules --md --external` απεικονίζει τον
|
|
609
|
+
κατάλογο από τα φορτωμένα αρχεία (provenance `external`), και ο
|
|
610
|
+
generator matrix δέχεται `--external <root>`.
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## 🏗️ Αρχιτεκτονική
|
|
615
|
+
|
|
616
|
+
<details>
|
|
617
|
+
<summary>Ανάπτυξη δέντρου</summary>
|
|
618
|
+
|
|
619
|
+
```
|
|
620
|
+
mjolnir/
|
|
621
|
+
├── src/
|
|
622
|
+
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
623
|
+
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
624
|
+
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
625
|
+
│ ├── playwright/ # Selector Health Score engine
|
|
626
|
+
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
627
|
+
│ ├── scope/ # git merge-base changed-scope engine
|
|
628
|
+
│ ├── scorer/ # transparent deduction table + prioritization
|
|
629
|
+
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
630
|
+
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
631
|
+
│ ├── config/ # mjolnir.config.json + suppressions
|
|
632
|
+
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
633
|
+
│ └── commands/ # every subcommand
|
|
634
|
+
└── tests/
|
|
635
|
+
├── fixtures/ # must-fire / must-not-fire per rule
|
|
636
|
+
└── golden/ # frozen score regression locks
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
</details>
|
|
640
|
+
|
|
641
|
+
- **Οι κανόνες είναι καθαρές συναρτήσεις** —
|
|
642
|
+
`(SourceFileContext) → Finding[]`, χωρίς I/O, χωρίς globals. Νέο
|
|
643
|
+
οικοσύστημα = ένας adapter + οι κανόνες του.
|
|
644
|
+
- **TypeScript/Playwright χρησιμοποιεί AST μεταγλωττιστή** (ts-morph).
|
|
645
|
+
Python, Java και C# τρέχουν σε κοινό regex στρώμα με μεταμφιεσμένα
|
|
646
|
+
σχόλια/strings.
|
|
647
|
+
- Ένα στρώμα AST tree-sitter WASM για Java και C# υπάρχει και είναι το
|
|
648
|
+
επόμενο βήμα ακρίβειας — δεν είναι ακόμα συνδεμένο στον σύγχρονο
|
|
649
|
+
σκαν pipeline.
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## 📚 Τεκμηρίωση
|
|
654
|
+
|
|
655
|
+
| Έγγραφο | Τι περιέχει |
|
|
656
|
+
| ------------------------------------------------------ | ------------------------------------------- |
|
|
657
|
+
| [docs/SCORING.md](docs/SCORING.md) | Κανονικοποίηση σκόρ + στάθμιση αποδείξεων |
|
|
658
|
+
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Μετρημένα ποσοστά false positive + μέθοδος |
|
|
659
|
+
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Καταστάσεις κανόνων, καταστολή, deprecation |
|
|
660
|
+
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Έξοδος SARIF + ρύθμιση editor/CI |
|
|
661
|
+
| [docs/rules/](docs/rules/) | Δημιουργημένος κατάλογος ανά κανόνα |
|
|
662
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup + workflow συμβολής |
|
|
663
|
+
| [CHANGELOG.md](CHANGELOG.md) | Ιστορικό εκδόσεων |
|
|
664
|
+
| [SECURITY.md](SECURITY.md) | Αναφορά ευπαθειών |
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## 📈 Κατάσταση
|
|
669
|
+
|
|
670
|
+
**v0.5.x · ανοιχτή beta.** Το JSON schema και τα exit codes είναι
|
|
671
|
+
παγωμένα συμβόλαια. TypeScript και Python έχουν την ευρύτερη μετρημένη
|
|
672
|
+
κάλυψη· Java και C# είναι νεότερα — διαβάστε τα μέσω του
|
|
673
|
+
[πίνακα tiers](#tiers-κανόνων-και-ωριμότητα-γλωσσών).
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
## 🤝 Συνεισφορά
|
|
678
|
+
|
|
679
|
+
Νέοι κανόνες είναι ο ευκολότερος πρώτος συνεισφορά — μία εντολή
|
|
680
|
+
σκαφφάρει τον κανόνα συν τα fixtures must-fire **και** must-not-fire (ο
|
|
681
|
+
δημιουργημένος κανόνας αστοχεί σκόπιμα στα fixtures μέχρι να
|
|
682
|
+
υλοποιήσεις πραγματική ανίχνευση — stub δεν μπορεί να κυκλοφορήσει):
|
|
683
|
+
|
|
684
|
+
```bash
|
|
685
|
+
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Πλήρες dev setup, οι εντολές standing gate και οι νόμοι anti-creep /
|
|
689
|
+
τείχος fixtures είναι στο [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
690
|
+
|
|
691
|
+
---
|
|
692
|
+
|
|
693
|
+
<div align="center">
|
|
694
|
+
|
|
695
|
+
**Σταμάτα να στέλνεις τεστ που δεν εμπιστεύεσαι.**
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
npx mjolnir-qa@latest
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
**Star ⭐ · Watch 👀 · Contribute 🤝**
|
|
702
|
+
|
|
703
|
+
Κατασκευάστηκε από [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
|
|
704
|
+
|
|
705
|
+
</div>
|