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/README.he.md CHANGED
@@ -1,383 +1,431 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/readme/logo.png" alt="Mjölnir — Verification Trust Engine" width="800" />
3
+ <img src="assets/readme/hero.svg" alt="Mjölnir. הבדיקות אומרות לך מה עבר. Mjölnir אומר לך על מה אפשר לסמוך." width="100%" />
4
4
 
5
- ### הבדיקות שלך משקרות לך. אנחנו מוכיחים את זה.
5
+ <br />
6
6
 
7
- **Verification Trust Engine ל‑QA.** Mjölnir מבקר חבילות בדיקות וצינורות
8
- CI, מדווח ציון הגינות ומציג בדיוק היכן האמון נשבר.
7
+ Mjölnir מוצא בדיקות שלא יכולות להיכשל וצינורות CI שלא יכולים להאדים,<br />
8
+ ואז מדרג עד כמה אפשר לסמוך על התוצאה, עם הראיה לכל נקודה.
9
9
 
10
- [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=C19A34&labelColor=0A1119)](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=0A1119)](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
12
- [![license](https://img.shields.io/badge/license-MIT-C19A34.svg?style=flat-square&labelColor=0A1119)](LICENSE)
13
- [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-37ABBD.svg?style=flat-square&labelColor=0A1119)](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
- > 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-08.
12
+ [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
13
+ [![downloads](https://img.shields.io/npm/dm/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
14
+ [![ci](https://img.shields.io/github/actions/workflow/status/Sergey-Bar/Mjolnir/ci.yml?branch=main&style=flat-square&label=ci&labelColor=0A1119)](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
15
+ [![coverage](https://img.shields.io/codecov/c/github/Sergey-Bar/Mjolnir?style=flat-square&color=1F6F7C&labelColor=0A1119&label=coverage)](https://codecov.io/gh/Sergey-Bar/Mjolnir)
16
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Sergey-Bar/Mjolnir/badge)](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
17
+ [![license](https://img.shields.io/badge/license-MIT-1F6F7C.svg?style=flat-square&labelColor=0A1119)](LICENSE)
18
+ [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-1F6F7C.svg?style=flat-square&labelColor=0A1119)](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/demo.svg" alt="דוח ה‑--verbose המלא של Mjölnir על repo הדגמה: WORTHINESS 75/100 NEEDS WORK, פירוק אבחונים לפי קטגוריה, רשימת FIX THIS FIRST, וכל ממצא עם מזהה כלל ומספר שורה — על פני CI, Playwright, היגיינת בדיקות וכללי Python" width="900" />
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>פלט המלא של `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>
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
- 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.
102
+ </details>
57
103
 
58
104
  ### ממצא אחד, מקרוב
59
105
 
60
- הריצו `mjolnir explain QA-CI-001` על הממצא הראשון למעלה ותקבלו:
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
- ▚ QA-CI-001 — continue-on-error masks a failing verification gate
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
- Measured FP: not yet measured — this rule ships on assumption (see docs/FP-AUDIT.md)
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
- on this workflow cannot be trusted.
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
- זו יחידת הערך: לא חיסר סטייל, אלא מקום שבו ה‑CI שלך אומר לך שמשהו
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
- הריצו מול repo לדוח מלא ולציון הגינות:
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
- ```bash
91
- npx mjolnir-qa@latest
155
+ Docs: mjolnir rules --md (full catalog, this rule included)
92
156
  ```
93
157
 
94
- **ב‑CI המוצר הוא פקודה אחת.** הוא סורק רק את מה שהענף נגע בו ויוצא
95
- עם קוד שאינו אפס על בעיות חדשות:
158
+ זו יחידת הערך: מקום אחד שבו ה-CI מדווח על הצלחה שהוא לא הרוויח.
159
+
160
+ <br />
161
+
162
+ ## התחלה מהירה
96
163
 
97
164
  ```bash
98
- npx mjolnir-qa@latest --scope changed
165
+ npx mjolnir-qa@latest
99
166
  ```
100
167
 
101
- שימו את זה ב‑check של PR — `mjolnir ci install` כותב את ה‑workflow —
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
- | `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 |
172
+ ```bash
173
+ npx mjolnir-qa@latest --scope changed
174
+ ```
123
175
 
124
- </details>
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>מדי פעם / דוחות</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 |
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
- התקינו גלובלית במקום `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
- ---
226
+ דורש **Node.js ≥ 22.18** על Windows, macOS או Linux. מעדיפים התקנה גלובלית? `npm i -g mjolnir-qa`. הרף הזה מגיע משרשרת הבנייה (tsdown מכוון אליו וצינור השחרור מריץ מולו בדיקות עשן); תלויות זמן הריצה לא צריכות יותר מזה.
160
227
 
161
- ## 🔨 מה Mjölnir בודק
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
- כל כלל מגיע עם fixtures של must-fire **וגם** must-not-fire. כלל שמופעל
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
- <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 |
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
- </details>
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>איכות בדיקות</strong></summary>
194
-
195
- | ID | כלל | Severity |
196
- | ------------ | ------------------------------ | -------- |
197
- | QA-TQUAL-002 | assertion טאוטולוגי | error |
198
- | QA-TQUAL-009 | assertion של promise ללא await | error |
199
- | QA-TQUAL-011 | בדיקות שהועברו להערה | warning |
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
- <details>
204
- <summary><strong>Playwright 🎭</strong></summary>
301
+ כל כלל יוצא עם fixture של must-fire **וגם** של must-not-fire, וכלל שמופעל על ה-fixture השלילי של עצמו לא יכול לצאת. זה חומת האש נגד false positives; `mjolnir doctor` אוכף אותה ב-CI של המאגר הזה עצמו.
205
302
 
206
- | ID | כלל | Severity |
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
- </details>
305
+ ‏`mjolnir doctor:playwright` מדרג כל locator לפי האופן שבו הוא מוצא אלמנט: כמו שמשתמש היה מוצא (תפקיד, תווית, טקסט), דרך חוזה מפורש (`data-testid`), או במקרה מבני (שרשראות CSS, XPath). כל קובץ מקבל ציון מ-0 עד 100:
214
306
 
215
- <details>
216
- <summary><strong>שלמות CI</strong></summary>
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
- </details>
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
- <details>
245
- <summary><strong>Java / JUnit · TestNG ☕</strong></summary>
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
- | ID | כלל | Severity |
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
- </details>
321
+ <br />
256
322
 
257
- <details>
258
- <summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
323
+ ## ציון הראוּיוּת
259
324
 
260
- | ID | כלל | Severity |
261
- | --------- | ------------------------------------------ | -------- |
262
- | QA-CS-101 | בדיקה מדולגת (`[Ignore]`, `[Fact(Skip=)]`) | warning |
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
- </details>
329
+ <sub>כל ציון מ-0 עד 100, ממוקם על ידי `deriveScoreState` האמיתי. נוצר על ידי `npm run docs:gauge` ונעול מפני סטייה ב-CI.</sub>
269
330
 
270
- > הקטלוג החי המלא — כל כלל עם tier, confidence, סיכון false positive
271
- > וזמינות autofix — נוצר מהרישום:
272
- >
273
- > ```bash
274
- > mjolnir rules --md
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
- **78 מתוך 99 כללים נושאים שיעור false positives שנמדד מול קוד OSS אמיתי**
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
- ### רמות (tiers) של כללים ובשלות לפי שפה
343
+ <br />
290
344
 
291
- כל כלל הוא `core`, `extended` או `quarantine`, נקבע לפי שיעור ה‑false
292
- positives **הנמדד** שלו:
345
+ ## מודל הראיות
293
346
 
294
- | Tier | משמעות | סריקת ברירת מחדל | `--strict` |
295
- | ------------ | ---------------------------------- | :--------------: | :--------: |
296
- | `core` | ≤ 10% FP נמדד | ✅ | ✅ |
297
- | `extended` | ≤ 30% FP נמדד | ✅ | ✅ |
298
- | `quarantine` | מעל 30%, או עדיין לא נמדד (n < 10) | ❌ | ✅ |
347
+ כל ממצא נושא שתי תוויות: כמה Mjölnir בטוח, ועד כמה הממצא נבדק. זה ההבדל בין כלי שמדווח על דפוסים לבין כלי שאפשר להתנות בו שחרור גרסה.
299
348
 
300
- | שפה | Adapter | הכיסוי היום |
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
- ל‑TypeScript ול‑Python יש את הכיסוי הנמדד הרחב ביותר. Java ו‑C# יצאו,
308
- מתועדים, ומוחזקים מחוץ למספר הכותרת עד שחבילת צרכן אמיתית (לא הבדיקות
309
- של ספריית binding עצמה) תיבדק.
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/terminal-hero.svg" alt="פלט טרמינל של Mjölnir — WORTHINESS 75/100 NEEDS WORK, פירוק אבחונים לפי קטגוריה ורשימת FIX THIS FIRST" width="820" />
362
+ <img src="assets/readme/trust-ladder.svg" alt="סולם האמון מ-L0 עד L5. ‏L0 עד L2 מגיעים מקריאת הקוד; L3 עד L5 דורשים דוח ריצה אמיתי, מה שמסומן בשבר בסולם." width="100%" />
317
363
  </p>
318
364
 
319
- <sub>מחדש עם `npm run docs:hero`;
320
- [`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
321
- מפיל את ה‑CI אם החומר סוטה ממה שה‑reporter מדפיס בפועל.</sub>
365
+ | רמה | במילים פשוטות | מה זה דורש |
366
+ | ------ | -------------- | -------------------------------------- |
367
+ | **L0** | נרשם | קריאת הקוד |
368
+ | **L1** | נראה כמו הבעיה | קריאת הקוד: דפוס תאם |
369
+ | **L2** | הוכח בקוד | קריאת הקוד: הפגם מבני |
370
+ | **L3** | הקובץ רץ | דוח ריצה מראה שהקובץ של הממצא הורץ |
371
+ | **L4** | הבדיקה רצה | דוח ריצה מראה שהבדיקה של הממצא הורצה |
372
+ | **L5** | הריצה מסכימה | התוצאה של הריצה עצמה מאשרת את סוג הפגם |
322
373
 
323
- הציון שקוף: **error −8, warning −3, info −1**, ואז נרמל לפי החשיפה
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
- | Score | פסק דין |
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
- רוב הכללים הם **E1**. הסלוגן «we prove it» מתייחס למערכת הזו: ממצאי E2
346
- הם הוכחה מבנית; ממצאי E1 הם אזהרות ממוקמות היטב, לא הוכחות פורמליות.
384
+ הרמות נקבעות לפי שיעור ה-false positives הנמדד, לא לפי דעה:
347
385
 
348
- repo ריק מקבל `null`, לעולם לא 100 מזויף — ראו
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
- ## 🎭 Selector Health Score
395
+ קידום, הורדה ובשלות לפי שפה: [מחזור החיים של הכללים](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
354
396
 
355
- המדד הראשי לחבילות Playwright — עד כמה ה‑locators שלך עמידים:
397
+ ### למה זה לא linter
356
398
 
357
- ```text
358
- ▚ SELECTOR HEALTH — e2e/checkout.spec.ts
399
+ ‏Linters אומרים לכם אם הקוד מציית לכללים. Mjölnir אומר לכם אם אפשר לסמוך על האימות שלכם.
359
400
 
360
- [█████████████████░░░] 83 / 100
361
- role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
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
- Locators מבוססי role מקבלים מלא. שרשראות מחלקות CSS ו‑XPath מטביעים
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
- זיהוי חוסר יציבות סטטי הוא ניחוש. Mjölnir קורא **נתוני הרצה אמיתיים** —
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
- ▚ FLAKINESS LEADERBOARD
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
- בדיקה שעוברת רק מניסיון ≥ 2 אינה בדיקה שעוברת — זו בדיקה ברת מזל.
391
- היא מסומנת `TRUE-FLAKE` ללא קשר לסימן הירוק הסופי.
438
+ ‏`TRUE-FLAKE` לא אומר שהבדיקה הורצה שוב. הוא אומר שהבדיקה **נכשלה בניסיון אחד לפחות ואז הסתיימה בירוק**: הצלחה מקרית, שמסומנת לא משנה מה אומר הווי הסופי. `mjolnir triage` הופך את ההיסטוריה הזו להצעת הסגר, ו-`mjolnir pw-report` מסכם ריצה. אותם דוחות ריצה הם שמעלים ממצאים לרמות האמון L3 ומעלה.
392
439
 
393
- ---
440
+ <br />
394
441
 
395
- ## ⚡ Mjölnir אינו עוד linter
442
+ ## שלמות CI
396
443
 
397
- Linters אומרים לך אם הקוד מציית לכללים. Mjölnir אומר לך אם אפשר לסמוך
398
- על האימות שלך.
444
+ בדיקה יכולה לעבור בזמן שהצינור סביבה לא יכול להיכשל. Mjölnir קורא גם את ה-workflows: `continue-on-error`, `|| true`, קודי יציאה שאף פעם לא מועברים הלאה, steps שתמיד מצליחים, דוחות שנצרכים אבל אף פעם לא נוצרים, ושערים שמדולגים בדיוק באירועים שאמורים לחסום. כל ממצא מציין את ה-job, ה-step והשורה, ונושא רמת ראיה משלו.
399
445
 
400
- | | ESLint / SonarQube | כלי coverage | סקירה ידנית | **Mjölnir** |
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
- \*`eslint-plugin-jest` (`expect-expect`) ו‑`eslint-plugin-playwright`
410
- (`expect-expect`, `no-wait-for-timeout`) מכסים זאת לפריימוורקים שלהם.
448
+ ```bash
449
+ mjolnir ci install
450
+ ```
411
451
 
412
- **ניתוח ריצה** הוא קטגוריה נפרדת לצד linting סטטי:
452
+ או הוסיפו את ה-action מה-Marketplace ל-workflow שכבר יש לכם:
413
453
 
414
- | | Playwright retry reporter | Allure / ReportPortal | **Mjölnir forensics** |
415
- | ---------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
416
- | קורא נתוני ריצה אמיתיים לפסקי דין `TRUE-FLAKE` | חלקי\* | חלקי (tag) | ✅ |
417
- | דוח טריאז לחוסר יציבות מהיסטוריית ריצות | ❌ | ✅ | ✅ |
418
- | משתלב עם ציון ההגינות הסטטי | ❌ | ❌ | ✅ |
454
+ ```yaml
455
+ - uses: Sergey-Bar/Mjolnir@v1
456
+ with:
457
+ scope: changed
458
+ fail-on: error
459
+ ```
419
460
 
420
- \*Playwright עוקב אחר retries בפנים אך אינו מפיק דוח חוסר יציבות
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
- ## 🤖 למה לא פשוט סקירת קוד של AI?
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
- בעיה אחרת, שכבה אחרת. סקירת AI יכולה לזהות שינוי בדיקה חשוד ב‑diff; היא
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
- | | סקירת קוד AI (Copilot וכד') | **Mjölnir** |
432
- | -------------------------------- | :--------------------------: | :----------------------------: |
433
- | עלות לסריקה | Token (מתרחב עם גודל ה‑diff) | **אפס** (מקומי, מותקן) |
434
- | רואה את כל החבילה + כל תצורות CI | רק את ה‑diff שמציגים לו | **הכול, בכל פעם** |
435
- | דטרמיניסטי (אותו קלט → אותו פלט) | ❌ (לא דטרמיניסטי) | **✅** |
436
- | תופס תבניות שישנות חודשים | רק אם הן בהקשר | **✅** (סורק את כל הקבצים) |
437
- | זוכר ממצאים בין ריצות | ❌ (אין זיכרון בין הפעלות) | **✅** (baseline + diff) |
438
- | רץ ללא הדק אנושי | דרוש PR או prompt | **✅** (hook של CI, רץ בשניות) |
476
+ ### ייחוס בהיקף השינויים
439
477
 
440
- **השתמשו בשניהם.** AI תופס ניואנס, כוונה ופגמי עיצוב שאין regex
441
- מוצא. Mjölnir תופס את התבניות המבניות ש‑AI מפספס כי הן נראות
442
- «מכוונות» — `.only` שבוצע commit, exit code שנבלע, `continue-on-error`
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
- ## 🤖 שילוב CI
484
+ כשאי אפשר לקבוע את ה-merge-base (שכפול רדוד, HEAD מנותק, יעד מחוץ ל-git), הממצאים חוזרים לייחוס לקובץ שלם **והדוח אומר זאת.** נסיגה שקטה הייתה בדיוק סוג הפגם שהכלי הזה קיים כדי לתפוס.
448
485
 
449
- פקודה אחת מייצרת workflow ל‑PR — ייעוצי כברירת מחדל, לעולם לא חוסם:
486
+ <br />
450
487
 
451
- ```bash
452
- mjolnir ci install
453
- ```
488
+ ## סוכני AI
454
489
 
455
- או חברו אותו ישירות ל‑GitHub Code Scanning דרך SARIF:
490
+ ממצאים שווים משהו רק אם משהו פועל לפיהם.
456
491
 
457
- ```yaml
458
- - run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
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
- הגדרת עורך וצינור ל‑SARIF: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
496
+ **ה-AI כותב את התיקון. Mjölnir מאמת אותו.** ההוכחה מגיעה מהסריקה החוזרת, אף פעם לא מהדיווח של הסוכן עצמו על הצלחה.
465
497
 
466
- ### כיסוי scope ששונה
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
- `--scope changed` מייחס ממצאים לשורות שהענף שלך הוסיף מול merge-base
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
- | Key | טיפוס | השפעה |
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
- "gate": "error",
494
- "exclude": ["legacy/**"],
495
- "severityOverrides": { "QA-PW-141": "warning" },
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
- - **`.mjolnirignore`** — קובץ בסגנון gitignore פשוט להחרגות נתיבים,
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
- <details>
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
- </details>
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
- - **הכללים פונקציות טהורות** — `(SourceFileContext) → Finding[]`,
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
- **v0.5.x · בטא פתוחה.** סכמת ה‑JSON וקודי היציאה הם חוזים קפואים.
627
- ל‑TypeScript ול‑Python את הכיסוי הנמדד הרחב ביותר; Java ו‑C# חדשים
628
- יותר — קראו אותם דרך
629
- [טבלת ה‑tiers](#רמות-tiers-של-כללים-ובשלות-לפי-שפה).
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
- ואת ה‑fixtures שלו must-fire **וגם** must-not-fire (הכלל הנוצר נכשל
637
- במכוון ב‑fixtures שלו עד שתממשו זיהוי אמיתי — stub לא יכול לצאת):
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
- התקנת פיתוח מלאה, פקודות השער הקבוע וחוקי ה‑anti-creep / מחסום ה‑fixtures
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
- **Star ⭐ · Watch 👀 · Contribute 🤝**
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
- נבנה על ידי [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
616
+ <sub>נבנה על ידי [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · ברישיון MIT</sub>
659
617
 
660
618
  </div>