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.he.md
CHANGED
|
@@ -1,383 +1,431 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/readme/
|
|
3
|
+
<img src="assets/readme/hero.svg" alt="Mjölnir. הבדיקות אומרות לך מה עבר. Mjölnir אומר לך על מה אפשר לסמוך." width="100%" />
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<br />
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Mjölnir מוצא בדיקות שלא יכולות להיכשל וצינורות CI שלא יכולים להאדים,<br />
|
|
8
|
+
ואז מדרג עד כמה אפשר לסמוך על התוצאה, עם הראיה לכל נקודה.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
12
|
-
[](LICENSE)
|
|
13
|
-
[](https://nodejs.org)
|
|
14
|
-
|
|
15
|
-
[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.ar.md) | [Bosanski](README.bs.md)
|
|
10
|
+
<br />
|
|
16
11
|
|
|
17
|
-
|
|
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)
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
21
|
npx mjolnir-qa@latest
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
[ראו את זה עובד](#ראו-את-זה-עובד) · [התחלה מהירה](#התחלה-מהירה) · [מה הוא מוצא](#מה-mjölnir-מוצא) · [ציון](#ציון-הראוּיוּת) · [ראיות](#מודל-הראיות) · [ניתוח ריצות](#ניתוח-ריצות-בדיקה) · [CI](#שלמות-ci) · [סוכנים](#סוכני-ai) · [אבטחה](#אמון-ואבטחה) · [מגבלות](#מה-mjölnir-לא-יכול-להגיד-לכם) · [תיעוד](#תיעוד)
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>לקריאה בשפה אחרת — 22 תרגומים</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.ar.md) | [Bosanski](README.bs.md)
|
|
30
|
+
|
|
31
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
|
|
32
|
+
|
|
33
|
+
<!-- Source hash: 3541b09e8d04 -->
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
[התחלה מהירה](#-התחלה-מהירה) ·
|
|
27
|
-
[מה הוא בודק](#-מה-mjölnir-בודק) ·
|
|
28
|
-
[ניקוד](#איך-הניקוד-עובד) ·
|
|
29
|
-
[CI](#-שילוב-ci) · [הגדרות](#הגדרות) ·
|
|
30
|
-
[תיעוד](#-תיעוד)
|
|
35
|
+
</details>
|
|
31
36
|
|
|
32
37
|
</div>
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
<br />
|
|
40
|
+
|
|
41
|
+
## וי ירוק הוא טענה, לא הוכחה
|
|
42
|
+
|
|
43
|
+
וי ירוק אומר שהצינור לא נכשל. הוא לא אומר שהבדיקות רצו, או שהן יכלו להיכשל. כל אחד מאלה עובר בירוק:
|
|
44
|
+
|
|
45
|
+
- `.only` שנשאר ב-commit והריץ 3 בדיקות במקום 900
|
|
46
|
+
- `continue-on-error: true` על ה-job שהיה אמור לחסום
|
|
47
|
+
- `|| true` אחרי פקודת הבדיקות
|
|
48
|
+
- בדיקה שלא בודקת כלום, או שגוף הבדיקה שלה ריק
|
|
49
|
+
- עטיפת retry שהופכת כישלון אמיתי להצלחה מקרית
|
|
50
|
+
- דוח שה-workflow מעלה אבל אף פעם לא יצר
|
|
51
|
+
- sleep קבוע שמחזיק מצב מרוץ
|
|
52
|
+
|
|
53
|
+
אף אחד מהם לא צובע את הצינור באדום, וכל אחד נראה מכוון בסקירת קוד. בגלל זה הם שורדים. הנה Mjölnir קורא מקרה אמיתי:
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="assets/readme/scan.svg" alt="ה-workflow של ה-CI במאגר ההדגמה, נקרא שורה אחר שורה. Mjölnir מסמן כל ממצא בשורה שדווחה, עם הכלל, מה לא תקין, רמת הראיה ושיעור ה-false positives הנמדד שלו." width="800" />
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<sub>כל ממצא שסריקת ההדגמה דיווחה עבור ה-workflow הזה, בשורה שדווחה. נוצר על ידי `npm run docs:readme-brand` מתוך [`demo-report.json`](assets/readme/demo-report.json) ונעול מפני סטייה ב-CI.</sub>
|
|
60
|
+
|
|
61
|
+
**מצב קפדני.** הגילויים התוקפניים ביותר — `.only`, `continue-on-error`, בדיקות ריקות, ניצול חוזר לרעה — חיים בשכבה בהסגר. הם פועלים רק תחת `--strict` ומוגבלים לחומרת `info`: הם מסמנים, אף פעם לא חוסמים. הסריקה ברירת המחדל (`npx mjolnir-qa@latest` ללא `--strict`) מכסה רק כללים בסיסיים ומורחבים. הוסף `--strict` כשאתה רוצה גם את שכבת הייעוץ.
|
|
62
|
+
|
|
63
|
+
Mjölnir קורא את חבילת הבדיקות, את ה-workflows של ה-CI, ואם יש לכם, גם את הדוח של ריצה אמיתית. הוא לא מריץ את הבדיקות שלכם, לא מתקין תלויות ולא מריץ את הקוד שהוא סורק. וכשאין לו ראיות, הוא אומר את זה במקום להמציא ביטחון:
|
|
64
|
+
|
|
65
|
+
| מצב | מה Mjölnir מדווח |
|
|
66
|
+
| ----------------------------------------- | ----------------------------------------------------- |
|
|
67
|
+
| לא נמצאו הצהרות בדיקה | ציון `null`, מוצג כ-**UNKNOWN**. אף פעם לא 100 מומצא. |
|
|
68
|
+
| אין baseline או גרסה ברת השוואה | **UNKNOWN**, עם הסיבה. אף פעם לא 0 משוער. |
|
|
69
|
+
| הסריקה נקטעה (תקציב זמן, קבצים לא קריאים) | **PARTIAL**, יציאה `2`. אף פעם לא מוצג כנקי. |
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="assets/readme/how-it-works.svg" alt="איך Mjölnir עובד. הוא קורא באופן סטטי את חבילת הבדיקות ואת צינור ה-CI, וגם את הדוח של ריצה אמיתית כשיש כזה. הוא משקלל כל ממצא לפי רמת הראיה ורמת האמון שלו, כשרק ריצה אמיתית יכולה להגיע ל-L3 עד L5, ומפיק ממצאים, ציון ראוּיוּת ושער CI עם קודי יציאה קפואים. בלולאת הסוכן, ה-AI כותב את התיקון ו-Mjölnir סורק שוב כדי להוכיח אותו." width="880" />
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<sub>עוצב עבור הדף הזה ומוצג ביחס 1:1. נוצר על ידי `npm run docs:readme-brand` ונעול מפני סטייה ב-CI; הציון, הספירות ומזהה הכלל מגיעים מ-[`script.demo.json`](assets/video/script.demo.json), מ-[`demo-report.json`](assets/readme/demo-report.json) ומרישום הכללים, ואף פעם לא מוקלדים ידנית. אותה תמונה כפוסטר: [`architecture.svg`](assets/readme/architecture.svg).</sub>
|
|
76
|
+
|
|
77
|
+
<br />
|
|
78
|
+
|
|
79
|
+
## ראו את זה עובד
|
|
35
80
|
|
|
36
|
-
|
|
81
|
+
סריקה אמיתית של [`examples/demo-repo`](examples/demo-repo), חבילת Playwright קטנה עם workflow של CI. לכאן הלכו הנקודות שלה:
|
|
37
82
|
|
|
38
83
|
<p align="center">
|
|
39
|
-
<img src="assets/readme/
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="פירוט הניכויים של Mjölnir: WORTHINESS 80/100 WORTHY, הציון לפי קטגוריה, תיבת הניכויים לפי חומרה ורשימת FIX THIS FIRST" width="520" />
|
|
40
85
|
</p>
|
|
41
86
|
|
|
42
|
-
<sub
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
87
|
+
<sub>נוצר על ידי `npm run docs:hero` מסריקה אמיתית ונעול מפני סטייה ב-CI. דוח ה-`--verbose` המלא של אותה סריקה הוא [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>צפו בזה</strong> — סריקה, התיקון שהיא מדפיסה, והסריקה החוזרת שמוכיחה אותו</summary>
|
|
91
|
+
|
|
92
|
+
<br />
|
|
93
|
+
|
|
94
|
+
<p align="center">
|
|
95
|
+
<a href="assets/video/mjolnir-demo.mp4">
|
|
96
|
+
<img src="assets/video/mjolnir-demo-poster.png" alt="פריים מהקלטת ההדגמה: npx mjolnir-qa@latest סורק את מאגר ההדגמה בחלון טרמינל" width="900" />
|
|
97
|
+
</a>
|
|
98
|
+
</p>
|
|
47
99
|
|
|
48
|
-
|
|
100
|
+
<sub>רונדר פריים אחר פריים מסריקה אמיתית על ידי `npm run docs:video`; אף פעם לא הוקלט מהמסך. בחרו בפריים כדי לפתוח את [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
|
|
49
101
|
|
|
50
|
-
|
|
51
|
-
וקובץ בדיקות Python — ארבע שפות/פורמטים, מעבר אחד.
|
|
52
|
-
2. הוא מצא עדויות שמחלישות את האמון בחבילה — `continue-on-error`
|
|
53
|
-
שמסתיר job, `|| true` שבולע exit code, שינה מלאכותית קבועה, selector
|
|
54
|
-
שברירי, כתובות staging מקודדות מראש, המתנת `networkidle`.
|
|
55
|
-
3. הפך כל אחת לממצא מוחשי עם מזהה כלל, מיקום ותיקון — ולציון יחיד
|
|
56
|
-
שממנו ניתן להפעיל שער על PR.
|
|
102
|
+
</details>
|
|
57
103
|
|
|
58
104
|
### ממצא אחד, מקרוב
|
|
59
105
|
|
|
60
|
-
|
|
106
|
+
כל ממצא עונה על ארבע שאלות: איפה הוא, כמה Mjölnir בטוח, באיזו תדירות הכלל טועה, ואיך מתקנים.
|
|
107
|
+
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="הממצא הראשון של סריקת ההדגמה, בדיוק כפי שהטרמינל מדפיס אותו, עם ארבעת החלקים שלו מסומנים: איפה, כמה בטוח, באיזו תדירות הכלל טועה, והתיקון." width="100%" />
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
`mjolnir explain QA-CI-001` מדפיס את תיק האמון המלא של כלל, כולל שיעור ה-false positives הנמדד שלו וה-tier שהשיעור הזה זיכה אותו בו:
|
|
61
113
|
|
|
62
114
|
```text
|
|
63
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
64
116
|
|
|
65
117
|
Severity: error
|
|
66
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
67
120
|
Evidence: E2
|
|
68
|
-
|
|
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
|
|
69
126
|
|
|
70
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
71
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
72
129
|
|
|
73
130
|
WHY IT MATTERS
|
|
74
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
75
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
76
133
|
|
|
77
134
|
HOW TO FIX
|
|
78
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
79
|
-
```
|
|
80
136
|
|
|
81
|
-
|
|
82
|
-
עבר — כשהוא לא עבר.
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
83
138
|
|
|
84
|
-
|
|
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
|
|
85
146
|
|
|
86
|
-
|
|
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.
|
|
87
150
|
|
|
88
|
-
|
|
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.
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
npx mjolnir-qa@latest
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
92
156
|
```
|
|
93
157
|
|
|
94
|
-
|
|
95
|
-
|
|
158
|
+
זו יחידת הערך: מקום אחד שבו ה-CI מדווח על הצלחה שהוא לא הרוויח.
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## התחלה מהירה
|
|
96
163
|
|
|
97
164
|
```bash
|
|
98
|
-
npx mjolnir-qa@latest
|
|
165
|
+
npx mjolnir-qa@latest
|
|
99
166
|
```
|
|
100
167
|
|
|
101
|
-
|
|
102
|
-
וזהו. הכול האחר אופציונלי.
|
|
168
|
+
הוא סורק את התיקייה הנוכחית ומדפיס את ה-Trust Report: מה נמצא, עד כמה אפשר לסמוך על זה, למה, ומה לעשות הלאה. הוא יוצא עם `0` כשלא נמצא דבר ברמת השער או מעליה.
|
|
103
169
|
|
|
104
|
-
|
|
105
|
-
| ----------------------------------- | ------------------------------------------------- |
|
|
106
|
-
| `mjolnir` | סריקת repo מלאה + ציון הגינות |
|
|
107
|
-
| `mjolnir --scope changed` | רק מה שהענף שלך הביא — הצורה ל‑CI |
|
|
108
|
-
| `mjolnir ci install` | מייצר workflow ייעוצי ל‑PR |
|
|
109
|
-
| `mjolnir explain QA-CI-001` | מה / למה / תיקון + שיעור FP מדוד לכלל אחד |
|
|
110
|
-
| `mjolnir rules --unmeasured` | הכללים שרצים על הנחה, לא על מדידה |
|
|
111
|
-
| `mjolnir --json` / `--format sarif` | קריא למכונה / GitHub Code Scanning |
|
|
112
|
-
| `mjolnir --strict` | מריץ גם כללי tier quarantine (סיכון FP גבוה יותר) |
|
|
113
|
-
|
|
114
|
-
<details>
|
|
115
|
-
<summary><strong>כשמשהו לא יציב (flaky)</strong></summary>
|
|
170
|
+
ב-CI, סרקו רק את מה שהענף הכניס, כדי שחבילת בדיקות ישנה לא תטביע את ה-pull request הראשון שלכם:
|
|
116
171
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
| `mjolnir triage ./test-results/` | הצעת הסגר מהיסטוריית הרצות |
|
|
121
|
-
| `mjolnir pw-report ./test-results/` | סיכום ריצת Playwright — retries / flakes / האיטיים ביותר |
|
|
122
|
-
| `mjolnir doctor:playwright` | סריקה עמוקה ל‑Playwright בלבד + Selector Health Score |
|
|
172
|
+
```bash
|
|
173
|
+
npx mjolnir-qa@latest --scope changed
|
|
174
|
+
```
|
|
123
175
|
|
|
124
|
-
|
|
176
|
+
`mjolnir ci install` כותב את זה כ-workflow של GitHub Actions, עם ה-[action](https://github.com/Sergey-Bar/Mjolnir#readme) מקובע לתגית הראשית `v1` (או `npx` רגיל עם `--no-action`). הוא נשאר מייעץ עד שתחליטו שהוא צריך לחסום.
|
|
177
|
+
|
|
178
|
+
| פקודה | מה היא עושה |
|
|
179
|
+
| ----------------------------------- | -------------------------------------------------- |
|
|
180
|
+
| `mjolnir` | Trust Report: פסק דין, רמת ביטחון, הצעד הבא |
|
|
181
|
+
| `mjolnir --scope changed` | רק מה שהענף שלכם הכניס (הצורה ל-CI) |
|
|
182
|
+
| `mjolnir ci install` | יוצר את ה-workflow המייעץ ל-PR (מבוסס action) |
|
|
183
|
+
| `mjolnir explain QA-CI-001` | מה, למה ואיך מתקנים, וגם שיעור ה-FP הנמדד |
|
|
184
|
+
| `mjolnir why src/a.spec.ts:42` | למה סומנה בדיוק השורה הזו. אף פעם לא חוסם. |
|
|
185
|
+
| `mjolnir forensics ./test-results/` | ראיות זמן ריצה מריצה אמיתית |
|
|
186
|
+
| `mjolnir trust-report` | Trust Artifact עצמאי (md + json) |
|
|
187
|
+
| `mjolnir handoff` | תוכנית תיקון לסוכן קוד |
|
|
188
|
+
| `mjolnir --json` / `--format sarif` | פלט קריא למכונה, GitHub Code Scanning |
|
|
189
|
+
| `mjolnir --format codequality` | דוח GitLab Code Quality (ארטיפקט לווידג'ט של ה-MR) |
|
|
190
|
+
| `mjolnir --strict` | מריץ גם כללים ברמת quarantine (סיכון FP גבוה יותר) |
|
|
125
191
|
|
|
126
192
|
<details>
|
|
127
|
-
<summary><strong
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
| `mjolnir
|
|
134
|
-
| `mjolnir
|
|
135
|
-
| `mjolnir
|
|
136
|
-
| `mjolnir
|
|
137
|
-
| `mjolnir
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
193
|
+
<summary><strong>כל שאר הפקודות</strong> — מיון בדיקות לא יציבות, דיווח, ממשל</summary>
|
|
194
|
+
|
|
195
|
+
<br />
|
|
196
|
+
|
|
197
|
+
| פקודה | מה היא עושה |
|
|
198
|
+
| ----------------------------------- | ----------------------------------------------------------------------- |
|
|
199
|
+
| `mjolnir --classic` | באנר הציון מלפני ה-Trust Report |
|
|
200
|
+
| `mjolnir explain verdict` | למה פסק הדין של הסריקה השמורה הוא מה שהוא |
|
|
201
|
+
| `mjolnir triage ./test-results/` | מיון מודרך. כל שורה מסתיימת בצעד הבא. |
|
|
202
|
+
| `mjolnir pw-report ./test-results/` | סיכום ריצת Playwright: ניסיונות חוזרים, בדיקות לא יציבות, האיטיות ביותר |
|
|
203
|
+
| `mjolnir doctor:playwright` | סריקה עמוקה ל-Playwright בלבד, וגם Selector Health Score |
|
|
204
|
+
| `mjolnir fix --dry-run` / `fix` | תיקונים אוטומטיים בטוחים, כל אחד נסרק מחדש כדי להוכיח שהוא נקלט |
|
|
205
|
+
| `mjolnir baseline` / `diff` | צילום מצב של הממצאים, ואז דיווח רק על חדשים או מחמירים |
|
|
206
|
+
| `mjolnir impact --since <ref>` | מה commit הכניס ומה הוא פתר |
|
|
207
|
+
| `mjolnir summary` | הערות CI וסיכום step מתוך דוח |
|
|
208
|
+
| `mjolnir pr-comment` | הערת PR ממוקדת, ב-Markdown |
|
|
209
|
+
| `mjolnir debt` | מרשם חוב בדיקות עם מודל עלויות |
|
|
210
|
+
| `mjolnir handover` | מפת היכרות עם החבילה למהנדס QA חדש |
|
|
211
|
+
| `mjolnir init` | מזהה frameworks ומדפיס רשימת הגדרה |
|
|
212
|
+
| `mjolnir suppressions` | מפרט ממצאים מושתקים, לצורכי ממשל |
|
|
213
|
+
| `mjolnir rules --unmeasured` | הכללים שרצים על הנחה ולא על מדידה |
|
|
214
|
+
| `mjolnir rules --md` | קטלוג כללים מלא (JSON או Markdown) |
|
|
215
|
+
| `mjolnir doctor` | ביקורת עצמית של בסיס הכללים של Mjölnir עצמו |
|
|
216
|
+
| `mjolnir create-rule <ID>` | יוצר שלד לכלל חדש ול-fixtures שלו |
|
|
217
|
+
| `mjolnir stats` | מונים מקומיים של כל התיקונים שנראו אי פעם |
|
|
218
|
+
| `mjolnir badge` | JSON ל-endpoint של shields.io וקטע קוד |
|
|
219
|
+
| `mjolnir --cache` | סריקות חוזרות אינקרמנטליות בעזרת מטמון פסקי דין מקומי |
|
|
220
|
+
| `mjolnir --format mermaid` | דיאגרמת ארכיטקטורת בדיקות להערת PR |
|
|
221
|
+
|
|
222
|
+
`mjolnir help <command>` מדפיס שימוש, דוגמאות והצעד הבא לכל אחת מהן.
|
|
142
223
|
|
|
143
224
|
</details>
|
|
144
225
|
|
|
145
|
-
|
|
146
|
-
דורש Node.js ≥ 22.18. עובד על Windows, macOS ו‑Linux.
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## 👥 למי זה?
|
|
151
|
-
|
|
152
|
-
- **QA / SDET** שבבעלותם חבילת e2e או אינטגרציה וזקוקים לראיות שהחבילה
|
|
153
|
-
באמת ראויה לסימן הירוק שהיא מייצרת.
|
|
154
|
-
- **צוותי Platform / DevEx** האחראים לשלמות CI ולשערי שחרור — האנשים
|
|
155
|
-
שאכפת להם ש‑`continue-on-error` לא יצבע בשקט צינור אדום בירוק.
|
|
156
|
-
- **מתחזקי OSS** שרוצים שער אימות זול, תמיד דלוק, שרץ מקומית וב‑CI
|
|
157
|
-
ללא קריאות רשת.
|
|
158
|
-
|
|
159
|
-
---
|
|
226
|
+
דורש **Node.js ≥ 22.18** על Windows, macOS או Linux. מעדיפים התקנה גלובלית? `npm i -g mjolnir-qa`. הרף הזה מגיע משרשרת הבנייה (tsdown מכוון אליו וצינור השחרור מריץ מולו בדיקות עשן); תלויות זמן הריצה לא צריכות יותר מזה.
|
|
160
227
|
|
|
161
|
-
|
|
228
|
+
<br />
|
|
162
229
|
|
|
163
|
-
|
|
164
|
-
| --- | ------------------------------------------------------------------------------------------------------------ |
|
|
165
|
-
| ⚖️ | **ציון הגינות** — מספר אחד, טבלת חיסורים שקופה, ללא קופסה שחורה |
|
|
166
|
-
| 🎭 | **Selector Health Score** — מדרג את ה‑locators של Playwright שלך, לא רק את אחוזי ההצלחה |
|
|
167
|
-
| 🔬 | **פורנזיקת ריצה** — קורא נתוני ריצה אמיתיים של Playwright/JUnit כדי לתפוס `TRUE-FLAKE`, לא רק ניחושים סטטיים |
|
|
168
|
-
| 🚨 | **כללי שלמות CI** — תופס `continue-on-error`, `\|\| true` וטריקים אחרים של ירוק מזויף |
|
|
169
|
-
| 🐍 | **כל ארבעת ה‑Playwright bindings** — TypeScript, Python, Java, C#/.NET — וגם pytest, JUnit/TestNG וזרימות CI |
|
|
170
|
-
| 🔒 | **Local-first** — אפס קריאות רשת במהלך הסריקה, אפס טלמטריה, רץ בשניות |
|
|
230
|
+
## מה Mjölnir מוצא
|
|
171
231
|
|
|
172
|
-
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="עובד עם הסטאק שלכם: השפות, ה-frameworks של הבדיקות ומערכות ה-CI שהכללים שלו מכסים, מתוך רישום הכללים." width="100%" />
|
|
234
|
+
</p>
|
|
173
235
|
|
|
174
|
-
|
|
175
|
-
על ה‑fixture השלילי של עצמו לא יכול לצאת — זהו מחסום ה‑false positives.
|
|
236
|
+
**79 כללים** בארבע משפחות — היגיינת בדיקות, איכות בדיקות, Playwright ושלמות CI — עבור TypeScript ו-JavaScript, Python, Java, C# ו-YAML של GitHub Actions. הם מכסים את Playwright בכל ארבעת ה-bindings, וגם pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest ו-Mocha, עם כיסוי ראשוני ל-Cypress ול-Selenium. תשעה מהם, כדי להראות את הצורה:
|
|
176
237
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
| QA-TEST-
|
|
183
|
-
| QA-
|
|
184
|
-
| QA-
|
|
185
|
-
| QA-
|
|
186
|
-
| QA-
|
|
187
|
-
| QA-
|
|
188
|
-
| QA-TEST-010 | גוף בדיקה ריק | error |
|
|
238
|
+
| ID | כלל | חומרה | רמה |
|
|
239
|
+
| ------------ | -------------------------------------------------------------------- | ------- | ---------- |
|
|
240
|
+
| QA-CI-001 | `continue-on-error` מסתיר שער אימות שנכשל | error | quarantine |
|
|
241
|
+
| QA-CI-009 | קוד היציאה של הבדיקות לא מועבר הלאה (`\|` בלי pipefail, שרשראות `;`) | error | extended |
|
|
242
|
+
| QA-TEST-001 | בדיקה ממוקדת נשארה ב-commit (`.only`, `fit`) | error | quarantine |
|
|
243
|
+
| QA-TEST-003 | בדיקה בלי assertions | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | assertion על promise בלי await | error | quarantine |
|
|
245
|
+
| QA-PW-002 | assertion על locator בלי await | error | core |
|
|
246
|
+
| QA-PW-004 | סלקטורים שבירים של CSS/XPath | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | בדיקה מדולגת (`skip`, `xfail` לא קפדני) | warning | core |
|
|
248
|
+
| QA-CS-103 | מתודת בדיקה בלי assertions | error | core |
|
|
189
249
|
|
|
190
|
-
|
|
250
|
+
הקטלוג המלא נוצר מהרישום ואף פעם לא מתוחזק ידנית: `mjolnir rules --md`, [`docs/rules/`](docs/rules/), או [המדריך למה שהוא בודק](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
|
|
191
251
|
|
|
192
252
|
<details>
|
|
193
|
-
<summary><strong
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
|
253
|
+
<summary><strong>כל כלל שמוזכר ב-README הזה</strong>, בטבלה אחת</summary>
|
|
254
|
+
|
|
255
|
+
<br />
|
|
256
|
+
|
|
257
|
+
> כללי `quarantine` רצים רק תחת `--strict` ואף פעם לא חוסמים (הם מוגבלים ל-info). החומרה המוצגת היא החומרה שהמחבר קבע.
|
|
258
|
+
|
|
259
|
+
| ID | משפחה | כלל | חומרה | רמה |
|
|
260
|
+
| ------------ | ---------- | --------------------------------------------------------- | ------- | ---------- |
|
|
261
|
+
| QA-TEST-001 | היגיינה | בדיקה ממוקדת נשארה ב-commit (`.only`, `fit`) | error | quarantine |
|
|
262
|
+
| QA-TEST-002 | היגיינה | בדיקה מדולגת. עולה ל-`error` בלי סיבה מתועדת. | warning | quarantine |
|
|
263
|
+
| QA-TEST-003 | היגיינה | בדיקה בלי assertions | error | quarantine |
|
|
264
|
+
| QA-TEST-004 | היגיינה | sleep קבוע (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
|
|
265
|
+
| QA-TEST-006 | היגיינה | שימוש לרעה ב-retry שמסתיר חוסר יציבות | warning | quarantine |
|
|
266
|
+
| QA-TEST-010 | היגיינה | גוף בדיקה ריק | error | quarantine |
|
|
267
|
+
| QA-TQUAL-002 | איכות | assertion טאוטולוגי | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | איכות | assertion על promise בלי await | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | איכות | בדיקות בהערה | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | assertion על locator בלי await | error | core |
|
|
271
|
+
| QA-PW-003 | Playwright | `page.pause()` / `test.only()` נשארו ב-commit | error | core |
|
|
272
|
+
| QA-PW-004 | Playwright | סלקטורים שבירים של CSS/XPath | warning | quarantine |
|
|
273
|
+
| QA-PW-123 | Playwright | כתובות URL של סביבות מקודדות בקוד | warning | quarantine |
|
|
274
|
+
| QA-PW-140 | Playwright | צילום מסך בלי `maxDiffPixelRatio` | warning | core |
|
|
275
|
+
| QA-CI-001 | CI | `continue-on-error` מסתיר שער שנכשל | error | quarantine |
|
|
276
|
+
| QA-CI-002 | CI | `\|\| true` בולע קודי יציאה | error | extended |
|
|
277
|
+
| QA-CI-005 | CI | דוח נצרך אבל אף פעם לא נוצר | error | quarantine |
|
|
278
|
+
| QA-CI-007 | CI | עטיפות retry סביב בדיקות | warning | extended |
|
|
279
|
+
| QA-CI-008 | CI | step שתמיד מצליח מסתיר כישלונות | error | quarantine |
|
|
280
|
+
| QA-CI-009 | CI | קוד היציאה לא מועבר הלאה (`\|` בלי pipefail, שרשראות `;`) | error | extended |
|
|
281
|
+
| QA-CI-010 | CI | בדיקות מדולגות בדיוק איפה שהן חייבות לחסום | error | quarantine |
|
|
282
|
+
| QA-PY-002 | Python | בדיקה מדולגת (`skip`, `xfail` לא קפדני) | warning | core |
|
|
283
|
+
| QA-PY-003 | Python | פונקציית בדיקה בלי assertions | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | `time.sleep()` בבדיקות | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | assertion טאוטולוגי | error | quarantine |
|
|
286
|
+
| QA-JV-101 | Java | בדיקה מושבתת (`@Disabled`) | warning | core |
|
|
287
|
+
| QA-JV-102 | Java | sleep קבוע (`Thread.sleep()`) | warning | extended |
|
|
288
|
+
| QA-JV-103 | Java | מתודת בדיקה בלי assertions | error | extended |
|
|
289
|
+
| QA-JV-105 | Java | sleep קבוע עם `waitForTimeout()` של Playwright | warning | core |
|
|
290
|
+
| QA-JV-106 | Java | סלקטור שביר במקום locator מבוסס תפקיד | warning | quarantine |
|
|
291
|
+
| QA-CS-101 | C# | בדיקה מדולגת (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
|
|
292
|
+
| QA-CS-102 | C# | sleep קבוע (`Thread.Sleep` / `Task.Delay`) | warning | core |
|
|
293
|
+
| QA-CS-103 | C# | מתודת בדיקה בלי assertions | error | core |
|
|
294
|
+
| QA-CS-105 | C# | sleep קבוע עם `WaitForTimeoutAsync()` | warning | extended |
|
|
295
|
+
| QA-CS-106 | C# | סלקטור שביר במקום locator מבוסס תפקיד | warning | quarantine |
|
|
296
|
+
|
|
297
|
+
ל-Python יש גם את QA-PY-001…012 (היגיינת pytest) ואת QA-PY-101…108 (Playwright ל-Python). ל-Cypress ול-Selenium יש ערכות פתיחה של שלושה כללים כל אחת.
|
|
200
298
|
|
|
201
299
|
</details>
|
|
202
300
|
|
|
203
|
-
|
|
204
|
-
<summary><strong>Playwright 🎭</strong></summary>
|
|
301
|
+
כל כלל יוצא עם fixture של must-fire **וגם** של must-not-fire, וכלל שמופעל על ה-fixture השלילי של עצמו לא יכול לצאת. זה חומת האש נגד false positives; `mjolnir doctor` אוכף אותה ב-CI של המאגר הזה עצמו.
|
|
205
302
|
|
|
206
|
-
|
|
207
|
-
| --------- | ---------------------------------------- | -------- |
|
|
208
|
-
| QA-PW-002 | assertion של locator ללא await | error |
|
|
209
|
-
| QA-PW-003 | `page.pause()` / `test.only()` עם commit | error |
|
|
210
|
-
| QA-PW-004 | selectors שבירים של CSS/XPath | warning |
|
|
211
|
-
| QA-PW-123 | כתובות סביבה מקודדות מראש | warning |
|
|
303
|
+
### Selector Health Score
|
|
212
304
|
|
|
213
|
-
|
|
305
|
+
`mjolnir doctor:playwright` מדרג כל locator לפי האופן שבו הוא מוצא אלמנט: כמו שמשתמש היה מוצא (תפקיד, תווית, טקסט), דרך חוזה מפורש (`data-testid`), או במקרה מבני (שרשראות CSS, XPath). כל קובץ מקבל ציון מ-0 עד 100:
|
|
214
306
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
| ID | כלל | Severity |
|
|
219
|
-
| --------- | -------------------------------------------------------------- | -------- |
|
|
220
|
-
| QA-CI-001 | `continue-on-error` מסתיר כשלים | error |
|
|
221
|
-
| QA-CI-002 | `\|\| true` בולע exit codes | error |
|
|
222
|
-
| QA-CI-005 | דוח נצרך אך לעולם לא נוצר | error |
|
|
223
|
-
| QA-CI-007 | עטיפות retry סביב בדיקות | warning |
|
|
224
|
-
| QA-CI-008 | שלב שתמיד מצליח מסתיר כשלים | error |
|
|
225
|
-
| QA-CI-009 | exit code של הבדיקות לא מועבר (`\|` ללא pipefail, שרשראות `;`) | error |
|
|
226
|
-
| QA-CI-010 | בדיקות מדולגות בדיוק שם שהן חייבות לחסום (skip-on-PR guards) | error |
|
|
227
|
-
|
|
228
|
-
</details>
|
|
229
|
-
|
|
230
|
-
<details>
|
|
231
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
232
|
-
|
|
233
|
-
| ID | כלל | Severity |
|
|
234
|
-
| --------- | --------------------------------------- | -------- |
|
|
235
|
-
| QA-PY-002 | בדיקה מדולגת (`skip`, `xfail` לא קפדני) | warning |
|
|
236
|
-
| QA-PY-003 | פונקציית בדיקה ללא assertions | error |
|
|
237
|
-
| QA-PY-005 | `time.sleep()` בבדיקות | warning |
|
|
238
|
-
| QA-PY-012 | assertion טאוטולוגי | error |
|
|
239
|
-
|
|
240
|
-
סה״כ 20 כללי Python (QA-PY-001…012 היגיינת pytest + QA-PY-101…108 Playwright-Python).
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
241
309
|
|
|
242
|
-
|
|
310
|
+
e2e/login.spec.ts
|
|
311
|
+
[█████████████░░░░░░░] 65 / 100
|
|
312
|
+
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
243
313
|
|
|
244
|
-
|
|
245
|
-
|
|
314
|
+
e2e/checkout.spec.ts
|
|
315
|
+
[██████████████████░░] 88 / 100
|
|
316
|
+
role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
317
|
+
```
|
|
246
318
|
|
|
247
|
-
|
|
248
|
-
| --------- | ------------------------------------------- | -------- |
|
|
249
|
-
| QA-JV-101 | בדיקה מושבתת (`@Disabled`) | warning |
|
|
250
|
-
| QA-JV-102 | שינה קבועה (`Thread.sleep()`) | warning |
|
|
251
|
-
| QA-JV-103 | מתודת בדיקה ללא assertions | error |
|
|
252
|
-
| QA-JV-105 | שינה קבועה של Playwright `waitForTimeout()` | warning |
|
|
253
|
-
| QA-JV-106 | selector שביר במקום role locator | warning |
|
|
319
|
+
זה מודד **עמידות, לא נכונות**. `.btn.btn-primary > div:nth-child(2)` עובר היום וימשיך לעבור עד שמישהו ייגע ב-markup. ציון נמוך אף פעם לא טוען שהבדיקה שבורה, רק שהיא תלויה ב-markup שאף אחד לא הבטיח לשמור.
|
|
254
320
|
|
|
255
|
-
|
|
321
|
+
<br />
|
|
256
322
|
|
|
257
|
-
|
|
258
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
323
|
+
## ציון הראוּיוּת
|
|
259
324
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
| QA-CS-102 | שינה קבועה (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
264
|
-
| QA-CS-103 | מתודת בדיקה ללא assertions | error |
|
|
265
|
-
| QA-CS-105 | שינה קבועה `WaitForTimeoutAsync()` | warning |
|
|
266
|
-
| QA-CS-106 | selector שביר במקום role locator | warning |
|
|
325
|
+
<p align="center">
|
|
326
|
+
<img src="assets/readme/score-gauge.svg" alt="סולם הראוּיוּת מ-0 עד 100, עם סמן שעובר על כל ציון: UNWORTHY מתחת ל-50, NEEDS WORK מ-50 עד 79, WORTHY מ-80 עד 99, FORGED ב-100" width="720" />
|
|
327
|
+
</p>
|
|
267
328
|
|
|
268
|
-
|
|
329
|
+
<sub>כל ציון מ-0 עד 100, ממוקם על ידי `deriveScoreState` האמיתי. נוצר על ידי `npm run docs:gauge` ונעול מפני סטייה ב-CI.</sub>
|
|
269
330
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
> דפים לכל כלל נמצאים ב[`docs/rules/`](docs/rules/).
|
|
331
|
+
| ציון | פסק דין |
|
|
332
|
+
| --------- | ---------------------------------- |
|
|
333
|
+
| `0 – 49` | **UNWORTHY** |
|
|
334
|
+
| `50 – 79` | **NEEDS WORK** |
|
|
335
|
+
| `80 – 99` | **WORTHY** |
|
|
336
|
+
| `100` | **FORGED** |
|
|
337
|
+
| `null` | **UNKNOWN**: לא נמצאו הצהרות בדיקה |
|
|
278
338
|
|
|
279
|
-
|
|
339
|
+
**איך הוא מחושב.** החומרה קובעת ניכוי בסיס (`error −8`, `warning −3`, `info −1`) ורמת הראיה מקטינה אותו: E2 נספר במלואו, E1 בחצי (מעוגל כלפי מטה), E0 בכלל לא. הסכום מנורמל לפי החשיפה של החבילה, כלומר ניכויים לכל הצהרת בדיקה ולא לכל קובץ. הטרמינל מדפיס את אותם מספרים מוקטנים שהציון השתמש בהם; אין מודל שני נסתר. פרטים: [docs/SCORING.md](docs/SCORING.md) ו[מדריך הציון](https://sergey-bar.github.io/Mjolnir/guide/scoring).
|
|
280
340
|
|
|
281
|
-
|
|
282
|
-
(≥ 10 ממצאים שסווגו ידנית כל אחד; ראו
|
|
283
|
-
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). ה‑21 האחרים יוצאים על הערכת
|
|
284
|
-
המחבר. התחתית של כל סריקה אומרת כמה מהכללים ש_ירו_ נמדדו;
|
|
285
|
-
`mjolnir rules --unmeasured` מפרט את אלה שלא; עמוד `mjolnir explain`
|
|
286
|
-
של כל כלל מצהיר על מעמדו. אנחנו מפרסמים את השיעור גם כשהוא מכוער —
|
|
287
|
-
העבודה המתמשכת של הפרויקט.
|
|
341
|
+
**מה 100 לא אומר.** הוא לא אומר שהתוכנה נכונה, שהחבילה מספקת או שהמוצר נקי מתקלות. הוא אומר דבר אחד: **אף אחד מהכללים ש-Mjölnir הפעיל לא הניב ניכוי בסריקה הזו ובמודל הראיות הזה.**
|
|
288
342
|
|
|
289
|
-
|
|
343
|
+
<br />
|
|
290
344
|
|
|
291
|
-
|
|
292
|
-
positives **הנמדד** שלו:
|
|
345
|
+
## מודל הראיות
|
|
293
346
|
|
|
294
|
-
|
|
295
|
-
| ------------ | ---------------------------------- | :--------------: | :--------: |
|
|
296
|
-
| `core` | ≤ 10% FP נמדד | ✅ | ✅ |
|
|
297
|
-
| `extended` | ≤ 30% FP נמדד | ✅ | ✅ |
|
|
298
|
-
| `quarantine` | מעל 30%, או עדיין לא נמדד (n < 10) | ❌ | ✅ |
|
|
347
|
+
כל ממצא נושא שתי תוויות: כמה Mjölnir בטוח, ועד כמה הממצא נבדק. זה ההבדל בין כלי שמדווח על דפוסים לבין כלי שאפשר להתנות בו שחרור גרסה.
|
|
299
348
|
|
|
300
|
-
|
|
301
|
-
| --------------- | ----------- | ---------------------------------------------- |
|
|
302
|
-
| TypeScript / JS | AST של מהדר | הרחב, הנמדד ביותר — בעיקר `core`/`extended` |
|
|
303
|
-
| Python / pytest | שכבת regex | רחב, נבדק מול corpus — בעיקר `core`/`extended` |
|
|
304
|
-
| Java | שכבת regex | חדש יותר — בעיקר `extended`/`quarantine` |
|
|
305
|
-
| C# / .NET | שכבת regex | חדש יותר — בעיקר `extended`/`quarantine` |
|
|
349
|
+
**כמה בטוח — רמת הראיה.**
|
|
306
350
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
351
|
+
| רמה | שם | משמעות | ניכוי |
|
|
352
|
+
| ------ | ----------------- | ----------------------------------- | ----- |
|
|
353
|
+
| **E2** | הוכחה דטרמיניסטית | הפגם קיים בקוד כפי שהוא כתוב | מלא |
|
|
354
|
+
| **E1** | ראיה מדפוס | נמצאה התאמה לדפוס שקשור בחוזקה לפגם | חצי |
|
|
355
|
+
| **E0** | תצפית | שווה לדעת. לא טענה שמשהו לא בסדר. | אפס |
|
|
310
356
|
|
|
311
|
-
|
|
357
|
+
ביטחון בזיהוי הוא לא חוזק ההוכחה. כלל יכול להיות בטוח שמצא את מה שחיפש ועדיין להסתכל על היוריסטיקה. ממצאי E1 נועדו לקריאה ולשיקול דעת, אף פעם לא ליישום עיוור, והגבול הזה מוטבע על הממצא בטרמינל, ב-JSON ובמסירה לסוכן.
|
|
312
358
|
|
|
313
|
-
|
|
359
|
+
**עד כמה נבדק — רמת האמון.** רוב הממצאים מגיעים מקריאת הקוד שלכם. תנו ל-Mjölnir את הדוח של ריצת בדיקות אמיתית, והוא יוכל לאשר שהקוד באמת רץ.
|
|
314
360
|
|
|
315
361
|
<p align="center">
|
|
316
|
-
<img src="assets/readme/
|
|
362
|
+
<img src="assets/readme/trust-ladder.svg" alt="סולם האמון מ-L0 עד L5. L0 עד L2 מגיעים מקריאת הקוד; L3 עד L5 דורשים דוח ריצה אמיתי, מה שמסומן בשבר בסולם." width="100%" />
|
|
317
363
|
</p>
|
|
318
364
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
365
|
+
| רמה | במילים פשוטות | מה זה דורש |
|
|
366
|
+
| ------ | -------------- | -------------------------------------- |
|
|
367
|
+
| **L0** | נרשם | קריאת הקוד |
|
|
368
|
+
| **L1** | נראה כמו הבעיה | קריאת הקוד: דפוס תאם |
|
|
369
|
+
| **L2** | הוכח בקוד | קריאת הקוד: הפגם מבני |
|
|
370
|
+
| **L3** | הקובץ רץ | דוח ריצה מראה שהקובץ של הממצא הורץ |
|
|
371
|
+
| **L4** | הבדיקה רצה | דוח ריצה מראה שהבדיקה של הממצא הורצה |
|
|
372
|
+
| **L5** | הריצה מסכימה | התוצאה של הריצה עצמה מאשרת את סוג הפגם |
|
|
322
373
|
|
|
323
|
-
|
|
324
|
-
של החבילה (חיסורים לכל הצהרת בדיקה). חיסורים המשוקללים לפי ראיות
|
|
325
|
-
אומרים שאותות חלשים זולים יותר. הטרמינל מציג את אותם מספרים מהונחים
|
|
326
|
-
שהציון משתמש בהם — ללא קופסה שחורה. שיטה מלאה:
|
|
327
|
-
[docs/SCORING.md](docs/SCORING.md).
|
|
374
|
+
סריקה סטטית נעצרת ב-L2. רק דוח ריצה אמיתי (Playwright JSON, Jest או Vitest JSON, JUnit XML) יכול להעלות ממצא ל-L3 ומעלה, כך שממצא שאף פעם לא נראה רץ לעולם לא יכול לטעון שהוא רץ. הגדרות: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
|
|
328
375
|
|
|
329
|
-
|
|
376
|
+
### כמה מזה נמדד
|
|
330
377
|
|
|
331
|
-
|
|
332
|
-
| ------- | ---------------- |
|
|
333
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
334
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
335
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**ל-74 מתוך 79 כללים יש שיעור false positives שנמדד מול קוד OSS אמיתי** (לפחות 10 ממצאים שסווגו ידנית לכל אחד; ראו [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). 5 האחרים יוצאים על סמך הערכת המחבר ואומרים את זה, כלל אחר כלל, ב-`mjolnir explain`. `mjolnir rules --unmeasured` מפרט אותם, והתחתית של כל סריקה מדווחת כמה מהכללים ש*הופעלו* בפועל נמדדו.
|
|
336
379
|
|
|
337
|
-
|
|
380
|
+
השיעורים נשארים פומביים גם כשהם גרועים. QA-TEST-001 (`.only` שנשאר ב-commit) יוצא רע בביקורת על מאגרים אמיתיים ולכן יושב ב-quarantine. המספר העדכני לכל כלל, כולל QA-PW-141, נמצא בביקורת.
|
|
338
381
|
|
|
339
|
-
|
|
340
|
-
| --- | --------------- | --------------- | ------------------------------------------- |
|
|
341
|
-
| E2 | פגם דטרמיניסטי | חיסור מלא | `.only` שבוצע commit — ניתן להוכחה מבנית |
|
|
342
|
-
| E1 | תבנית היוריסטית | חצי חיסור | `sleep()` שנתפס ב‑regex — אות חזק, לא הוכחה |
|
|
343
|
-
| E0 | תצפית | אפס (info בלבד) | מדווח אך לעולם לא שער ל‑CI ולא מחסר |
|
|
382
|
+
### רמות האמון של הכללים
|
|
344
383
|
|
|
345
|
-
|
|
346
|
-
הם הוכחה מבנית; ממצאי E1 הם אזהרות ממוקמות היטב, לא הוכחות פורמליות.
|
|
384
|
+
הרמות נקבעות לפי שיעור ה-false positives הנמדד, לא לפי דעה:
|
|
347
385
|
|
|
348
|
-
|
|
349
|
-
|
|
386
|
+
| רמה | FP נמדד | התנהגות |
|
|
387
|
+
| -------------- | ---------------------- | ------------------------------------------- |
|
|
388
|
+
| **core** | ≤ 10% | דוח ברירת מחדל, חוסם |
|
|
389
|
+
| **extended** | ≤ 30% | דוח ברירת מחדל, ביטחון נמוך יותר |
|
|
390
|
+
| **quarantine** | > 30% או שהוצהר במפורש | רק `--strict`, מוגבל ל-info, אף פעם לא חוסם |
|
|
391
|
+
| _לא נמדד_ | n < 10 | לא יכול לעלות ל-core עד שנמדד |
|
|
350
392
|
|
|
351
|
-
|
|
393
|
+
רצועות FP יכולות רק להוריד רמה — הן אף פעם לא מקדמות כלל מתוך `quarantine` אם הוא הוצהר שם במפורש. כלל שהוכנס במפורש ל-quarantine נשאר ב-quarantine ללא קשר לשיעור ה-FP הנמדד שלו.
|
|
352
394
|
|
|
353
|
-
|
|
395
|
+
קידום, הורדה ובשלות לפי שפה: [מחזור החיים של הכללים](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
354
396
|
|
|
355
|
-
|
|
397
|
+
### למה זה לא linter
|
|
356
398
|
|
|
357
|
-
|
|
358
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
Linters אומרים לכם אם הקוד מציית לכללים. Mjölnir אומר לכם אם אפשר לסמוך על האימות שלכם.
|
|
359
400
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
401
|
+
| | Linters (ESLint, SonarQube) | כלי כיסוי | סקירת קוד ב-AI | **Mjölnir** |
|
|
402
|
+
| ------------------------------------------------------------ | :---------------------------: | :-------: | :------------: | :-------------: |
|
|
403
|
+
| מדרג את **מערכת האימות**, לא את קוד המוצר | לא | לא | לא | כן |
|
|
404
|
+
| שלמות ה-workflows של ה-CI (`continue-on-error`, `\|\| true`) | לא | לא | רק ה-diff | כן |
|
|
405
|
+
| מדרג את עמידות ה-locators של Playwright (Selector Health) | לא | לא | לא | כן |
|
|
406
|
+
| קורא נתוני ריצה אמיתיים לפסקי דין `TRUE-FLAKE` | לא | לא | לא | כן |
|
|
407
|
+
| מפרסם שיעור false positives נמדד לכל כלל | לא | לא | לא | כן |
|
|
408
|
+
| מסמן בדיקות בלי assertions | כן\* | לא | לפעמים | כן |
|
|
409
|
+
| תופס sleep קבוע (`waitForTimeout`, `time.sleep`) | כן\* | לא | לפעמים | כן |
|
|
410
|
+
| דטרמיניסטי (אותו קלט, אותו פלט) | כן | כן | לא | כן |
|
|
411
|
+
| עלות לסריקה | חינם | חינם | טוקנים | **אפס** (מקומי) |
|
|
412
|
+
|
|
413
|
+
<sub>\*מכוסה על ידי `eslint-plugin-jest` ו-`eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) ועל ידי כללי ה-assertions של SonarQube עצמו. העמודות מתארות את התנהגות ברירת המחדל באימות חבילות בדיקות; תוספים, תוכניות בתשלום וכללים מותאמים משנים חלק מהתשובות. זה סיכום מיצוב, לא benchmark.</sub>
|
|
363
414
|
|
|
364
|
-
|
|
365
|
-
את הציון — הם נשברים בכל refactor של DOM בלי לומר לך איזו התנהגות
|
|
366
|
-
נפגעה.
|
|
415
|
+
השתמשו גם בסקירת AI. היא תופסת ניואנסים, כוונה ופגמי תכנון שאף דפוס לא ימצא. Mjölnir תופס את מה שסקירת AI מפספסת כי זה נראה מכוון: `.only` שנשאר ב-commit, קוד יציאה שנבלע, `continue-on-error` על job של בדיקות. אלה דורשים סריקה, לא הסקה.
|
|
367
416
|
|
|
368
|
-
|
|
417
|
+
<br />
|
|
369
418
|
|
|
370
|
-
##
|
|
419
|
+
## ניתוח ריצות בדיקה
|
|
371
420
|
|
|
372
|
-
|
|
373
|
-
דוחות JSON של Playwright ו‑XML של JUnit מכל ראנר:
|
|
421
|
+
ניתוח סטטי מסיק מסקנות על קוד שאף פעם לא רץ. ניתוח הריצות קורא את מה שקרה בפועל: Playwright JSON, Jest JSON, Vitest JSON ו-JUnit XML מכל runner.
|
|
374
422
|
|
|
375
423
|
```bash
|
|
376
424
|
mjolnir forensics ./test-results/
|
|
377
425
|
```
|
|
378
426
|
|
|
379
427
|
```text
|
|
380
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
381
429
|
|
|
382
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
383
431
|
|
|
@@ -387,274 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
387
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
388
436
|
```
|
|
389
437
|
|
|
390
|
-
|
|
391
|
-
היא מסומנת `TRUE-FLAKE` ללא קשר לסימן הירוק הסופי.
|
|
438
|
+
`TRUE-FLAKE` לא אומר שהבדיקה הורצה שוב. הוא אומר שהבדיקה **נכשלה בניסיון אחד לפחות ואז הסתיימה בירוק**: הצלחה מקרית, שמסומנת לא משנה מה אומר הווי הסופי. `mjolnir triage` הופך את ההיסטוריה הזו להצעת הסגר, ו-`mjolnir pw-report` מסכם ריצה. אותם דוחות ריצה הם שמעלים ממצאים לרמות האמון L3 ומעלה.
|
|
392
439
|
|
|
393
|
-
|
|
440
|
+
<br />
|
|
394
441
|
|
|
395
|
-
##
|
|
442
|
+
## שלמות CI
|
|
396
443
|
|
|
397
|
-
|
|
398
|
-
על האימות שלך.
|
|
444
|
+
בדיקה יכולה לעבור בזמן שהצינור סביבה לא יכול להיכשל. Mjölnir קורא גם את ה-workflows: `continue-on-error`, `|| true`, קודי יציאה שאף פעם לא מועברים הלאה, steps שתמיד מצליחים, דוחות שנצרכים אבל אף פעם לא נוצרים, ושערים שמדולגים בדיוק באירועים שאמורים לחסום. כל ממצא מציין את ה-job, ה-step והשורה, ונושא רמת ראיה משלו.
|
|
399
445
|
|
|
400
|
-
|
|
401
|
-
| ---------------------------------------------------- | :----------------: | :----------: | :---------: | :---------: |
|
|
402
|
-
| שלמות זרימות CI (`continue-on-error`, `\|\| true`) | ❌ | ❌ | נדיר | ✅ |
|
|
403
|
-
| חוצה שפות (TS, Python, Java, C#) מכלי אחד | ❌ | ❌ | ❌ | ✅ |
|
|
404
|
-
| מדרג עמידות locators של Playwright (Selector Health) | ❌ | ❌ | נדיר | ✅ |
|
|
405
|
-
| מסמן בדיקות ללא assertions אמיתיים | ✅ (פלאגין)\* | ❌ | לפעמים | ✅ |
|
|
406
|
-
| תופס שינה קבועה (`waitForTimeout`, `time.sleep`) | ✅ (פלאגין)\* | ❌ | לפעמים | ✅ |
|
|
407
|
-
| רץ בשניות, אפס קריאות רשת בזמן הסריקה | ✅ | ✅ | — | ✅ |
|
|
446
|
+
צרו את ה-workflow ל-PR, מייעץ כברירת מחדל:
|
|
408
447
|
|
|
409
|
-
|
|
410
|
-
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
411
451
|
|
|
412
|
-
|
|
452
|
+
או הוסיפו את ה-action מה-Marketplace ל-workflow שכבר יש לכם:
|
|
413
453
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
419
460
|
|
|
420
|
-
|
|
421
|
-
עצמאי עם תוויות פסק דין.
|
|
461
|
+
קבעו את `@v1` כדי לעקוב אחרי הקו הראשי, או תגית מדויקת (`@v0.5.32`) לשער שניתן לשחזר. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) מכסה את ה-Marketplace, את Smithery ואת רישומי ה-MCP.
|
|
422
462
|
|
|
423
|
-
|
|
463
|
+
כדי להכניס ממצאים ל-GitHub Code Scanning, העלו SARIF (דורש `security-events: write` ברמת workflow או job):
|
|
424
464
|
|
|
425
|
-
|
|
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
|
+
```
|
|
426
473
|
|
|
427
|
-
|
|
428
|
-
אינה מוכיחה שמערכת האימות כולה ראויה לאמון — והיא רואה רק את ה‑diff
|
|
429
|
-
שמציגים לה.
|
|
474
|
+
ב-GitLab, `--format codequality` כותב את דוח ה-Code Quality שהווידג'ט של ה-MR וההערות על ה-diff קוראים ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). הגדרת עורך וצינור: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
430
475
|
|
|
431
|
-
|
|
432
|
-
| -------------------------------- | :--------------------------: | :----------------------------: |
|
|
433
|
-
| עלות לסריקה | Token (מתרחב עם גודל ה‑diff) | **אפס** (מקומי, מותקן) |
|
|
434
|
-
| רואה את כל החבילה + כל תצורות CI | רק את ה‑diff שמציגים לו | **הכול, בכל פעם** |
|
|
435
|
-
| דטרמיניסטי (אותו קלט → אותו פלט) | ❌ (לא דטרמיניסטי) | **✅** |
|
|
436
|
-
| תופס תבניות שישנות חודשים | רק אם הן בהקשר | **✅** (סורק את כל הקבצים) |
|
|
437
|
-
| זוכר ממצאים בין ריצות | ❌ (אין זיכרון בין הפעלות) | **✅** (baseline + diff) |
|
|
438
|
-
| רץ ללא הדק אנושי | דרוש PR או prompt | **✅** (hook של CI, רץ בשניות) |
|
|
476
|
+
### ייחוס בהיקף השינויים
|
|
439
477
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
על job בדיקות. אלה לא באגים שדורשים הסקה; אלה עובדות שדורשות סריקה.
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
444
481
|
|
|
445
|
-
|
|
482
|
+
ממצאים מיוחסים לשורות שהענף שלכם הוסיף, ביחס ל-**merge-base**. ההיקף הוא אותה קבוצת קבצים שסריקה מלאה מגלה (קבצי spec של TS/JS ותצורות adapter, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), וגם שינויים שלא בוצע להם commit ושאינם במעקב, כך שזה עובד עוד לפני ה-commit. הבסיס נקבע בסדר `main → master → origin/main → origin/master → origin/HEAD`; אפשר לדרוס אותו עם `--base <ref>`.
|
|
446
483
|
|
|
447
|
-
|
|
484
|
+
כשאי אפשר לקבוע את ה-merge-base (שכפול רדוד, HEAD מנותק, יעד מחוץ ל-git), הממצאים חוזרים לייחוס לקובץ שלם **והדוח אומר זאת.** נסיגה שקטה הייתה בדיוק סוג הפגם שהכלי הזה קיים כדי לתפוס.
|
|
448
485
|
|
|
449
|
-
|
|
486
|
+
<br />
|
|
450
487
|
|
|
451
|
-
|
|
452
|
-
mjolnir ci install
|
|
453
|
-
```
|
|
488
|
+
## סוכני AI
|
|
454
489
|
|
|
455
|
-
|
|
490
|
+
ממצאים שווים משהו רק אם משהו פועל לפיהם.
|
|
456
491
|
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
- uses: github/codeql-action/upload-sarif@v3
|
|
460
|
-
with:
|
|
461
|
-
sarif_file: mjolnir.sarif
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
462
494
|
```
|
|
463
495
|
|
|
464
|
-
|
|
496
|
+
**ה-AI כותב את התיקון. Mjölnir מאמת אותו.** ההוכחה מגיעה מהסריקה החוזרת, אף פעם לא מהדיווח של הסוכן עצמו על הצלחה.
|
|
465
497
|
|
|
466
|
-
|
|
498
|
+
| פקודה | מה הסוכן מקבל |
|
|
499
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
500
|
+
| `mjolnir mcp` | שרת [MCP](https://modelcontextprotocol.io) מעל stdio. `scan`, `explain` ו-`diff` הופכים לכלים שאפשר לקרוא להם. |
|
|
501
|
+
| `mjolnir handoff` | דוח `--json` שמור הופך לתוכנית Markdown דטרמיניסטית: מה זוהה, גבול הראיה לכל ממצא, מה **אסור** שישתנה, ואיך מאמתים. |
|
|
502
|
+
| `mjolnir install` | כותב אל משטחי הסוכנים שכבר יש במאגר שלכם (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`), כך שהסוכן סורק שוב לפני שהוא טוען שסיים. |
|
|
467
503
|
|
|
468
|
-
|
|
469
|
-
מול `main`. הוא מכסה קבצי בדיקות (`*.spec.*`, `*.test.*`) וגם קבצי
|
|
470
|
-
workflow של GitHub ותצורות Playwright ב‑diff. כאשר ה‑merge-base לא
|
|
471
|
-
ניתן לפתרון — shallow clone, detached HEAD, יעד שאינו git, ענף ברירת
|
|
472
|
-
מחדל אחר — הוא מדרדר בכנות: הממצאים חוזרים לייחוס לקובץ שלם והדוח אומר
|
|
473
|
-
זאת. דריסת ה‑ref הבסיסי עם `--base <ref>`.
|
|
504
|
+
הוסיפו אותו ללקוח שמגיע עם CLI משלו:
|
|
474
505
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
Mjölnir הוא zero-config. `mjolnir.config.json` אופציונלי (או
|
|
480
|
-
`.mjolnir.json`) בשורש ה‑repo מכוונן חומרה, שערים והיקף — הוא אף פעם
|
|
481
|
-
לא משנה סמנטיקת זיהוי.
|
|
506
|
+
```bash
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
508
|
+
```
|
|
482
509
|
|
|
483
|
-
|
|
484
|
-
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
485
|
-
| `exclude` | `string[]` | globs התעלמות נוספים (תת‑קבוצה של gitignore), מעל ברירות המחדל המובנות |
|
|
486
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | אילו רמות חומרה יוצאות עם קוד לא אפס (ברירת מחדל `error`; `advisory` לעולם לא חוסם) |
|
|
487
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | מדרג מחדש את ממצאי כלל ל‑repo שלך |
|
|
488
|
-
| `ignore` | `IgnoreEntry[]` | מדכא ממצאים — **`reason` נדרש**; רשומות פגות אחרי 90 יום (תאריך `expires` מפורש, או זמן שינוי אחרון של קובץ התצורה לרשומות בלי) |
|
|
489
|
-
| `plugins` | `string[]` | חבילות כללים של צד שלישי (ראו [מודל האמון](#מודל-האמון)) |
|
|
510
|
+
או לכל לקוח שמקבל בלוק `mcpServers`:
|
|
490
511
|
|
|
491
512
|
```json
|
|
492
513
|
{
|
|
493
|
-
"
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
"ignore": [
|
|
497
|
-
{
|
|
498
|
-
"ruleId": "QA-TEST-004",
|
|
499
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
500
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
501
|
-
"expires": "2026-12-31"
|
|
502
|
-
}
|
|
503
|
-
]
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
504
517
|
}
|
|
505
518
|
```
|
|
506
519
|
|
|
507
|
-
|
|
508
|
-
אותה לשון כמו `exclude`. השתמשו בו לרעש של מכונה; השתמשו ב‑`exclude`
|
|
509
|
-
כשהרשימה שייכת לניהול גרסאות לצד שאר התצורה.
|
|
510
|
-
- **עקיפות CLI** — `--strict` (לכלול כללי הסגר), `--width <cols>` ו‑
|
|
511
|
-
`--ascii` / `--no-ascii` (רינדור טרמינל), `--tone blunt` (הודעות
|
|
512
|
-
ישירות יותר), `--max-duration <sec>` (סריקה חלקית מוגבלת).
|
|
513
|
-
- דיכוי כללים ומחזור חיי הוצאה משימוש: [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
514
|
-
|
|
515
|
-
רשומות `ignore` מזינות גם את הפקודה העצמאית `mjolnir suppressions`,
|
|
516
|
-
שמפרטת מה נדכא כעת ומתי כל רשומה פגה.
|
|
517
|
-
|
|
518
|
-
---
|
|
519
|
-
|
|
520
|
-
## 📐 קודי יציאה וחוזים
|
|
521
|
-
|
|
522
|
-
קפואים — בטוחים לבניית לוגיקת CI עליהם:
|
|
523
|
-
|
|
524
|
-
| קוד יציאה | משמעות |
|
|
525
|
-
| --------- | -------------------------------------------------------------- |
|
|
526
|
-
| `0` | נקי — אין ממצאים בשער או מעליו |
|
|
527
|
-
| `1` | ממצאים בשער או מעליו |
|
|
528
|
-
| `2` | סריקה חלקית (נגמר תקציב הזמן, קבצים לא קריאים) — לעולם לא חוסם |
|
|
529
|
-
| `10` | שגיאת שימוש (flag פגום, יעד חסר) |
|
|
530
|
-
| `20` | שגיאה פנימית |
|
|
531
|
-
|
|
532
|
-
דוח ה‑JSON/SARIF הוא `schemaVersion: 1`. מזהי כללים (`QA-<FAMILY>-NNN`)
|
|
533
|
-
אינם משתנים אחרי ההשקה ולעולם אינם נעשים בשימוש חוזר.
|
|
534
|
-
|
|
535
|
-
---
|
|
536
|
-
|
|
537
|
-
## מודל האמון
|
|
538
|
-
|
|
539
|
-
- **Local-first** — אפס קריאות רשת בזמן הסריקה. אף פעם. אפס טלמטריה.
|
|
540
|
-
- **אין הוכחה מזויפת** — נעדיף לומר «לא ידוע» מאשר «אומת». repo ריק
|
|
541
|
-
מקבל `score: null`, לעולם לא 100 מזויף.
|
|
542
|
-
- **כנות חלקית** — אם הניתוח קוצר, הפלט אומר זאת. לעולם לא «complete»
|
|
543
|
-
כשאינו.
|
|
544
|
-
- **מחסום FP** — הזיהוי רץ על תצוגת קוד חסרת הערות/מחרוזות (כללי
|
|
545
|
-
TypeScript משתמשים ב‑AST של המהדר): תבנית בתוך הערת פרוזה או מחרוזת
|
|
546
|
-
דוגמה לתיעוד היא תיעוד, לא ממצא.
|
|
547
|
-
- **נמדד, לא נטען** — רק כללים עם שיעור false positives מקוד OSS אמיתי
|
|
548
|
-
יוצאים ב‑tiers הכותרת (ראו [כמה מזה נמדד](#כמה-מזה-נמדד)); תחתית הסריקה
|
|
549
|
-
ו‑`mjolnir rules --unmeasured` אומרים לך מי מי.
|
|
550
|
-
- **אמון ב‑plugins ושער הרצת הקוד** — plugins הם חבילות npm המוצהרות תחת
|
|
551
|
-
`"plugins"`; מודולי JS חיים ב‑`mjolnir-rules/*.mjs`.
|
|
552
|
-
**אין sandbox**: קוד plugin רץ בהרשאות Node מלאות, אותו מודל אמון
|
|
553
|
-
כמו plugins של ESLint או Vitest. בגלל זה, הרצת קוד היא **opt‑in בכל
|
|
554
|
-
סריקה**: העבירו `--enable-plugins` (או הגדירו
|
|
555
|
-
`MJOLNIR_ENABLE_PLUGINS=1`), אחרת המקורות לא נטענים — הודעת stderr
|
|
556
|
-
רועשת מפרטת בדיוק מה דולג. סריקת קוד לא מהימן לא מריצה אותו לעולם.
|
|
557
|
-
מניפסטי כללים ב‑JSON (`mjolnir-rules/*.json`) אינם מושפעים: הם
|
|
558
|
-
מצהירים תבניות regex ולא מריצים קוד כלל בעיצובם. קידומות מזהי
|
|
559
|
-
כללים core שמורות
|
|
560
|
-
ונדחות מ‑plugins ומכללים חיצוניים למניעת התחזות.
|
|
561
|
-
- **כללים חיצוניים מקומיים ל‑workspace** (מבוססי תיקייה, אפס רשת) —
|
|
562
|
-
תיקיית `mjolnir-rules/` ליד יעד הסריקה טוענת כללים מותאמים: קבצי JSON
|
|
563
|
-
מצהירים תבניות regex (שום קוד לא מורץ), מודולי `.mjs`/`.js` מייצאים
|
|
564
|
-
`rules` (אמון Node מלא, כמו plugins). כללים חיצוניים נושאים את אותם
|
|
565
|
-
metadata של אמון כמו core; הם לעולם לא יכולים לצאת ב‑tier ה‑core
|
|
566
|
-
(core דורש שיעור FP נמדד מה‑sidecar של ה‑corpus — הצהרת
|
|
567
|
-
`tier: "core"` נלחצת ל‑`extended`), מצייתים לתקרות tier ונבדקים
|
|
568
|
-
מול סטייה: `mjolnir rules --md --external` מציג את הקטלוג מהקבצים
|
|
569
|
-
שנטענו (מקור `external`), ומחולל המטריצות מקבל `--external <root>`.
|
|
570
|
-
|
|
571
|
-
---
|
|
572
|
-
|
|
573
|
-
## 🏗️ ארכיטקטורה
|
|
520
|
+
**מעקה הבטיחות חשוב יותר מהנוחות.** כל ממצא במסירה נושא את הגבול שלו. **E2** אומר _דטרמיניסטי: בדקו את המיקום והחילו את התיקון_. **E1** אומר _נדרש אישור: התצפית לבדה לא מוכיחה את הפגם_. סוכן שמתקן E1 בעיוורון, משתיק כלל או עורך כלל כדי להעלות את הציון עושה בדיוק את מה שהכלי הזה קיים כדי לתפוס, ולכן המסירה אומרת זאת בפרומפט, ליד הממצא.
|
|
574
521
|
|
|
575
|
-
<
|
|
576
|
-
<summary>פתח עץ</summary>
|
|
522
|
+
<br />
|
|
577
523
|
|
|
578
|
-
|
|
579
|
-
mjolnir/
|
|
580
|
-
├── src/
|
|
581
|
-
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
582
|
-
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
583
|
-
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
584
|
-
│ ├── playwright/ # Selector Health Score engine
|
|
585
|
-
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
586
|
-
│ ├── scope/ # git merge-base changed-scope engine
|
|
587
|
-
│ ├── scorer/ # transparent deduction table + prioritization
|
|
588
|
-
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
589
|
-
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
590
|
-
│ ├── config/ # mjolnir.config.json + suppressions
|
|
591
|
-
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
592
|
-
│ └── commands/ # every subcommand
|
|
593
|
-
└── tests/
|
|
594
|
-
├── fixtures/ # must-fire / must-not-fire per rule
|
|
595
|
-
└── golden/ # frozen score regression locks
|
|
596
|
-
```
|
|
524
|
+
## אמון ואבטחה
|
|
597
525
|
|
|
598
|
-
|
|
526
|
+
**מקומי קודם כול, אפס טלמטריה.** אין שום API עם יכולת רשת (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) בשום מקום ב-`src/`, ו-[`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) מכשיל את הבנייה אם מופיע כזה. הוא גם אוסר על `eval` ועל `new Function`. סריקת קוד לא מהימן אף פעם לא מריצה אותו: ניתוח סטטי קורא טקסט מקור, וניתוח הריצות מפענח קובצי דוח שכבר קיימים בדיסק.
|
|
527
|
+
|
|
528
|
+
שתי הסתייגויות: `npx` עצמו מוריד את החבילה לפני שמשהו רץ, והערבות מכסה את `src/`, לא תוספים של צד שלישי.
|
|
529
|
+
|
|
530
|
+
**תוספים לא רצים בארגז חול.** תוספי JS (`mjolnir-rules/*.mjs`, או חבילות npm שמופיעות תחת `"plugins"`) רצים עם הרשאות Node מלאות, אותו מודל אמון כמו תוספים של ESLint או Vitest. טעינתם דורשת הסכמה מפורשת **בכל סריקה**: בלי `--enable-plugins` (או `MJOLNIR_ENABLE_PLUGINS=1`) המקורות שלהם אף פעם לא נטענים, והודעה ב-stderr מפרטת מה דולג. מניפסטים של כללים ב-JSON לא מריצים קוד, והקידומות של מזהי כללי core שמורות כך שתוסף לא יוכל להתחזות לאחד מהם. דווחו על פרצות דרך [SECURITY.md](SECURITY.md).
|
|
531
|
+
|
|
532
|
+
**הוא רץ על עצמו.** למנוע אמון באימות אין שום מעמד אם הוא עצמו לא ניתן לאימות. כל ריצת CI סורקת את המאגר הזה עם הבנייה שאותה ריצה הפיקה. השער נכשל על כל ממצא בחומרת error, וגם על סריקה **חלקית** או על **כלל שקרס**, כי סריקה עצמית קטועה שלא מדווחת כלום היא בדיוק הירוק המזויף שהפרויקט הזה קיים כדי לתפוס. `mjolnir doctor` מבקר מחדש את בסיס הכללים באותה ריצה (חומת ה-fixtures, יושרת הרמות, תקרת רמת ה-core), ובדיקה שתוצאתה INCONCLUSIVE נכשלת בדיוק כמו בדיקה שנכשלה. שני הדוחות מועלים כארטיפקטים של הבנייה.
|
|
533
|
+
|
|
534
|
+
### קודי יציאה וחוזה המכונה
|
|
599
535
|
|
|
600
|
-
|
|
601
|
-
ללא I/O, ללא globals. אקוסיסטם חדש = adapter אחד + הכללים שלו.
|
|
602
|
-
- **TypeScript/Playwright משתמש ב‑AST של המהדר** (ts-morph). Python,
|
|
603
|
-
Java ו‑C# רצים על שכבת regex משותפת עם מסכה על הערות/מחרוזות.
|
|
604
|
-
- שכבת AST של tree-sitter WASM עבור Java ו‑C# קיימת והיא הצעד הבא
|
|
605
|
-
בדיוק — עדיין לא מחוברת לצינור הסריקה הסינכרוני.
|
|
536
|
+
קפואים, כדי שתוכלו לבנות עליהם לוגיקת CI:
|
|
606
537
|
|
|
607
|
-
|
|
538
|
+
| קוד יציאה | משמעות |
|
|
539
|
+
| --------- | --------------------------------------------------------------- |
|
|
540
|
+
| `0` | נקי: אין ממצאים ברמת השער או מעליה |
|
|
541
|
+
| `1` | יש ממצאים ברמת השער או מעליה |
|
|
542
|
+
| `2` | סריקה חלקית (תקציב הזמן נגמר, קבצים לא קריאים). אף פעם לא חוסם. |
|
|
543
|
+
| `10` | שגיאת שימוש (דגל שגוי, יעד חסר) |
|
|
544
|
+
| `20` | שגיאה פנימית |
|
|
608
545
|
|
|
609
|
-
|
|
546
|
+
`2` שונה במכוון מ-`0`: סריקה שלא הסתיימה לא "מצאה כלום". היא פשוט לא סיימה לחפש.
|
|
610
547
|
|
|
611
|
-
|
|
612
|
-
| ------------------------------------------------------ | ------------------------------------ |
|
|
613
|
-
| [docs/SCORING.md](docs/SCORING.md) | נרמול הציון + שקילת ראיות |
|
|
614
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | שיעורי false positives נמדדים + שיטה |
|
|
615
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | מצבי כללים, דיכוי, הוצאה משימוש |
|
|
616
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | פלט SARIF + הגדרת עורך/CI |
|
|
617
|
-
| [docs/rules/](docs/rules/) | קטלוג שנוצר לכל כלל |
|
|
618
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | התקנת פיתוח + תהליך תרומה |
|
|
619
|
-
| [CHANGELOG.md](CHANGELOG.md) | היסטוריית מהדורות |
|
|
620
|
-
| [SECURITY.md](SECURITY.md) | דיווח פרצות אבטחה |
|
|
548
|
+
כל מה שמכונה צורכת (תוצאות של כלי MCP, `--json`, SARIF 2.1) מגיע מתוצאה קנונית אחת תחת סכמה עם גרסאות, **שמתרחבת רק בהוספה** (`schemaVersion: 1`, `contractVersion: 1`), כך שאף צרכן לא צריך לשחזר משמעות מטקסט מרונדר. ראו [את חוזה המכונה](docs/machine-contract.md). מזהי כללים (`QA-<FAMILY>-NNN`) אינם ניתנים לשינוי אחרי שיצאו ואף פעם לא ממוחזרים.
|
|
621
549
|
|
|
622
|
-
|
|
550
|
+
<br />
|
|
623
551
|
|
|
624
|
-
##
|
|
552
|
+
## מה Mjölnir לא יכול להגיד לכם
|
|
625
553
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
554
|
+
- **הוא לא מריץ את הבדיקות שלכם.** סריקה נקייה היא לא חבילה שעוברת.
|
|
555
|
+
- **הוא לא יכול להגיד לכם ש-assertion _שגוי_.** `expect(total).toBe(41)` נראה בריא. Mjölnir מוצא בדיקות ש*לא יכולות להיכשל* וצינורות ש*לא יכולים להאדים*, לא בדיקות שבודקות את הדבר הלא נכון.
|
|
556
|
+
- **הוא לא מוכיח נכונות עסקית.** שום דבר כאן לא אומר שהמוצר שלכם עושה את מה שהדרישה ביקשה.
|
|
557
|
+
- **100 הוא לא הוכחה לחבילה טובה.** האם החבילה שלכם מכסה את הסיכון האמיתי שלכם זו שאלה אחרת, והכלי הזה לא עונה עליה.
|
|
558
|
+
- **5 מתוך 79 כללים יוצאים על סמך הערכה**, לא שיעור נמדד. כל אחד מהם אומר זאת על הממצא שלו.
|
|
559
|
+
- **E1 הוא לא E2.** ממצאים היוריסטיים שווים קריאה, לא יישום עיוור.
|
|
560
|
+
- **מאגר ריק מקבל `null`, אף פעם לא 100.**
|
|
561
|
+
- **קובץ בשם `*.spec.ts` בלי הצהרות בדיקה לא נחשב כיסוי.** מאגר שקובצי ה-spec היחידים שלו מכילים imports או טיפוסים (אפס קריאות `it`/`test`) מקבל `null`, לא 100.
|
|
630
562
|
|
|
631
|
-
|
|
563
|
+
<br />
|
|
632
564
|
|
|
633
|
-
##
|
|
565
|
+
## תיעוד
|
|
634
566
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
567
|
+
אתר התיעוד המלא נמצא בכתובת <https://sergey-bar.github.io/Mjolnir/>.
|
|
568
|
+
|
|
569
|
+
| מסמך | מה יש בו |
|
|
570
|
+
| ------------------------------------------------------ | ------------------------------------------------- |
|
|
571
|
+
| [docs/SCORING.md](docs/SCORING.md) | נרמול הציון ושקלול הראיות |
|
|
572
|
+
| [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | אוצר מילים קנוני: מילה אחת לכל מושג |
|
|
573
|
+
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | שיעורי false positives נמדדים והשיטה |
|
|
574
|
+
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | מצבי כללים, רמות, השתקה, הוצאה משימוש |
|
|
575
|
+
| [docs/VERSIONING.md](docs/VERSIONING.md) | מדיניות semver, ממשקים קפואים, מחזור הוצאה משימוש |
|
|
576
|
+
| [docs/machine-contract.md](docs/machine-contract.md) | התוצאה הקנונית הקריאה למכונה |
|
|
577
|
+
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | פלט SARIF והגדרת עורך או CI |
|
|
578
|
+
| [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: דוח Code Quality, מתכון ל-MR, שער |
|
|
579
|
+
| [docs/rules/](docs/rules/) | קטלוג כללים שנוצר אוטומטית |
|
|
580
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | סביבת פיתוח ותהליך תרומה |
|
|
581
|
+
| [SUPPORT.md](SUPPORT.md) | איפה לשאול, לדווח ולקבל עזרה |
|
|
582
|
+
| [SECURITY.md](SECURITY.md) | דיווח על פרצות |
|
|
583
|
+
| [CHANGELOG.md](CHANGELOG.md) | היסטוריית גרסאות |
|
|
584
|
+
|
|
585
|
+
### סטטוס
|
|
586
|
+
|
|
587
|
+
**גרסה 1.** סכמת ה-JSON וקודי היציאה הם חוזים קפואים. ל-TypeScript ול-Python יש את הכיסוי הנמדד הרחב ביותר. Java ו-C# חדשות יותר; קראו אותן דרך [טבלת הבשלות](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). מה הלאה, בלי תאריכים מומצאים: [מפת הדרכים הפומבית](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
|
|
588
|
+
|
|
589
|
+
### תרומה
|
|
590
|
+
|
|
591
|
+
כללים חדשים הם התרומה הראשונה הקלה ביותר. פקודה אחת בונה שלד של הכלל עם ה-fixtures שלו, must-fire **וגם** must-not-fire. הכלל שנוצר נכשל בכוונה ב-fixtures של עצמו עד שנכתב זיהוי אמיתי, כי שלד שיוצא לאוויר הוא כלל שאף אחד לא מדד:
|
|
638
592
|
|
|
639
593
|
```bash
|
|
640
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
641
595
|
```
|
|
642
596
|
|
|
643
|
-
|
|
644
|
-
נמצאים ב[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
597
|
+
סביבת הפיתוח, פקודות השערים הקבועים וחוקי ה-anti-creep וחומת ה-fixtures נמצאים ב-[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
645
598
|
|
|
646
|
-
|
|
599
|
+
<br />
|
|
647
600
|
|
|
648
601
|
<div align="center">
|
|
649
602
|
|
|
650
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="הריצו אותו על המאגר שלכם." width="100%" />
|
|
651
604
|
|
|
652
605
|
```bash
|
|
653
606
|
npx mjolnir-qa@latest
|
|
654
607
|
```
|
|
655
608
|
|
|
656
|
-
|
|
609
|
+
[לקריאת המדריך](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [אתר התיעוד](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
|
|
610
|
+
|
|
611
|
+
<br />
|
|
612
|
+
|
|
613
|
+
אל תשאלו אם הבדיקות עברו.<br />
|
|
614
|
+
שאלו אם הראיות מוכיחות שמגיע להן אמון.
|
|
657
615
|
|
|
658
|
-
|
|
616
|
+
<sub>נבנה על ידי [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · ברישיון MIT</sub>
|
|
659
617
|
|
|
660
618
|
</div>
|