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