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.ar.md ADDED
@@ -0,0 +1,667 @@
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 لضمان الجودة.** يراجع 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.he.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 على مستودع تجريبي: 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
+ معروض من المُبلِّغ الحقيقي — لا شيء مقتطع. يُعاد توليده بـ
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
+ `|| true` يبتلع رمز الخروج، وسبات صارم، ومحدِّد هشّ، وعناوين تجريبية
54
+ مضمّنة، وانتظار `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
+ شغّله على مستودع للحصول على تقرير كامل ودرجة جدارة:
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
+ ضعه في فحص PR — `mjolnir ci install` يكتب سير العمل — وانتهى الأمر.
102
+ كل ما عدا ذلك اختياري.
103
+
104
+ | الأمر | ما يفعله |
105
+ | ----------------------------------- | ---------------------------------------------------- |
106
+ | `mjolnir` | فحص المستودع كاملًا + درجة الجدارة |
107
+ | `mjolnir --scope changed` | ما أدخله فرعك فقط — صيغة CI |
108
+ | `mjolnir ci install` | يولّد سير عمل PR استشاريًا |
109
+ | `mjolnir explain QA-CI-001` | ماذا / لماذا / الإصلاح + معدل FP المقيس لقاعدة واحدة |
110
+ | `mjolnir rules --unmeasured` | القواعد العاملة بالافتراض لا بالقياس |
111
+ | `mjolnir --json` / `--format sarif` | قابل للقراءة آليًا / GitHub Code Scanning |
112
+ | `mjolnir --strict` | يشغّل أيضًا قواعد طبقة الحجر الصحي (خطر FP أعلى) |
113
+
114
+ <details>
115
+ <summary><strong>عندما يتبدّد استقرار شيء ما</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 — المحاولات / المتذبذبات / الأبطأ |
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>` | ما تغيّر منذ إيداع سابق |
134
+ | `mjolnir debt` | سجل دَّين الاختبارات مع نموذج كلفة |
135
+ | `mjolnir handover` | خريطة تهيئة الطقم لمسؤول جودة جديد |
136
+ | `mjolnir stats` | عدّادات محلية تراكمية للإصلاحات المرصودة |
137
+ | `mjolnir badge` | JSON لنقطة نهاية shields.io + مقطع كود |
138
+ | `mjolnir rules --md` | كتالوج القواعد الكامل (JSON أو Markdown) |
139
+ | `mjolnir doctor` | تدقيق ذاتي لقاعدة قواعد Mjölnir نفسها |
140
+ | `mjolnir create-rule <ID>` | هيكلة قاعدة جديدة + تجهيزاتها |
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
+ أخضر بصمت.
157
+ - **مشرفو OSS** يريدون بوابة تحقق رخيصة دائمة التشغيل تعمل محليًا وفي
158
+ CI دون أي نداءات شبكة.
159
+
160
+ ---
161
+
162
+ ## 🔨 ماذا يفحص Mjölnir
163
+
164
+ | | |
165
+ | --- | --------------------------------------------------------------------------------------------------------------------- |
166
+ | ⚖️ | **درجة الجدارة** — رقم واحد، جدول خصم شفاف، بلا صندوق أسود |
167
+ | 🎭 | **Selector Health Score** — يقيّم محدِّدات Playwright لديك، لا معدل نجاحك فقط |
168
+ | 🔬 | **الأدلة الجنائية للتنفيذ** — يقرأ بيانات تشغيل Playwright/JUnit الحقيقية ليلتقط `TRUE-FLAKE`، لا مجرد تخمينات ثابتة |
169
+ | 🚨 | **قواعد نزاهة CI** — يلتقط `continue-on-error` و`\|\| true` وحيل الأخضر الكاذب الأخرى |
170
+ | 🐍 | **ترابطات Playwright الأربعة جميعًا** — TypeScript وPython وJava وC#/.NET — إضافة إلى pytest وJUnit/TestNG وأسيرات CI |
171
+ | 🔒 | **Local-first** — صفر نداءات شبكة أثناء الفحص، صفر قياس عن بُعد، يجري في ثوانٍ |
172
+
173
+ ### القواعد
174
+
175
+ كل قاعدة تأتي مع تجهيزات must-fire **و**must-not-fire. القاعدة التي
176
+ تنطلق على تجهيزتها السالبة ذاتها لا يمكن أن تُشحن — ذلك هو جدار الإنذارات
177
+ الكاذبة.
178
+
179
+ <details>
180
+ <summary><strong>نظافة الاختبارات</strong></summary>
181
+
182
+ | ID | القاعدة | Severity |
183
+ | ----------- | -------------------------------------------------- | -------- |
184
+ | QA-TEST-001 | اختبار مركّز مُودَع (`.only`، `fit`) | error |
185
+ | QA-TEST-002 | اختبار متجاوز بلا مسوّغ | error |
186
+ | QA-TEST-002 | اختبار متجاوز مع مسوّغ مسجَّل | warning |
187
+ | QA-TEST-003 | اختبار بلا تأكيدات | error |
188
+ | QA-TEST-004 | سبات صارم (`waitForTimeout`، `sleep()`، `delay()`) | warning |
189
+ | QA-TEST-006 | إساءة استخدام المحاولات تُخفي التذبذب | warning |
190
+ | QA-TEST-010 | جسد اختبار فارغ | error |
191
+
192
+ </details>
193
+
194
+ <details>
195
+ <summary><strong>جودة الاختبارات</strong></summary>
196
+
197
+ | ID | القاعدة | Severity |
198
+ | ------------ | ------------------------- | -------- |
199
+ | QA-TQUAL-001 | تحقق بالمحاكاة فقط | info |
200
+ | QA-TQUAL-002 | تأكيد مُبرهن ذاتيًا | error |
201
+ | QA-TQUAL-009 | تأكيد وعد بلا await | error |
202
+ | QA-TQUAL-011 | اختبارات معطَّلة بالتعليق | warning |
203
+
204
+ </details>
205
+
206
+ <details>
207
+ <summary><strong>Playwright 🎭</strong></summary>
208
+
209
+ | ID | القاعدة | Severity |
210
+ | --------- | ----------------------------------------- | -------- |
211
+ | QA-PW-002 | تأكيد محدِّد بلا await | error |
212
+ | QA-PW-003 | `page.pause()` / `test.only()` مودعة | error |
213
+ | QA-PW-004 | محدِّدات CSS/XPath هشّة | warning |
214
+ | QA-PW-005 | منطق عمل داخل `page.evaluate()` | info |
215
+ | QA-PW-114 | مقابض عناصر قديمة (`page.$`) | info |
216
+ | QA-PW-118 | انتظارات `networkidle` (متذبذبة بطبيعتها) | info |
217
+ | QA-PW-123 | عناوين بيئات مضمّنة | warning |
218
+
219
+ </details>
220
+
221
+ <details>
222
+ <summary><strong>نزاهة CI</strong></summary>
223
+
224
+ | ID | القاعدة | Severity |
225
+ | --------- | ----------------------------------------------------------- | -------- |
226
+ | QA-CI-001 | `continue-on-error` يُخفي الإخفاقات | error |
227
+ | QA-CI-002 | `\|\| true` يبتلع رموز الخروج | error |
228
+ | QA-CI-005 | تقرير يُستهلك ولا يُولَّد أبدًا | error |
229
+ | QA-CI-007 | أغلفة محاولات حول الاختبارات | warning |
230
+ | QA-CI-008 | خطوة دائمة النجاح تُخفي الإخفاقات | error |
231
+ | QA-CI-009 | رمز خروج الاختبار لا يُمرَّر (`\|` بلا pipefail، سلاسل `;`) | error |
232
+ | QA-CI-010 | اختبارات تُتجاوز حيث يجب أن تحجب (حرّاس skip-on-PR) | error |
233
+
234
+ </details>
235
+
236
+ <details>
237
+ <summary><strong>Python / pytest 🐍</strong></summary>
238
+
239
+ | ID | القاعدة | Severity |
240
+ | --------- | ---------------------------------------- | -------- |
241
+ | QA-PY-002 | اختبار متجاوز (`skip`، `xfail` غير صارم) | warning |
242
+ | QA-PY-003 | دالة اختبار بلا تأكيدات | error |
243
+ | QA-PY-005 | `time.sleep()` في الاختبارات | warning |
244
+ | QA-PY-006 | جسد اختبار فارغ (`pass`) | info |
245
+ | QA-PY-010 | اعتماد على العشوائية/الزمن بلا freeze | info |
246
+ | QA-PY-012 | تأكيد مُبرهن ذاتيًا | error |
247
+
248
+ 20 قاعدة Python إجمالًا (QA-PY-001…012 نظافة pytest + QA-PY-101…108 Playwright-Python).
249
+
250
+ </details>
251
+
252
+ <details>
253
+ <summary><strong>Java / JUnit · TestNG ☕</strong></summary>
254
+
255
+ | ID | القاعدة | Severity |
256
+ | --------- | ------------------------------------------ | -------- |
257
+ | QA-JV-101 | اختبار معطَّل (`@Disabled`) | warning |
258
+ | QA-JV-102 | سبات صارم (`Thread.sleep()`) | warning |
259
+ | QA-JV-103 | طريقة اختبار بلا تأكيدات | error |
260
+ | QA-JV-105 | سبات صارم في Playwright `waitForTimeout()` | warning |
261
+ | QA-JV-106 | محدِّد هشّ بدل role locator | warning |
262
+ | QA-JV-108 | عنوان بيئة مضمّن في اختبار | info |
263
+ | QA-JV-111 | محاكاة شاملة `page.route("**")` | info |
264
+
265
+ </details>
266
+
267
+ <details>
268
+ <summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
269
+
270
+ | ID | القاعدة | Severity |
271
+ | --------- | ------------------------------------------- | -------- |
272
+ | QA-CS-101 | اختبار متجاوز (`[Ignore]`، `[Fact(Skip=)]`) | warning |
273
+ | QA-CS-102 | سبات صارم (`Thread.Sleep` / `Task.Delay`) | warning |
274
+ | QA-CS-103 | طريقة اختبار بلا تأكيدات | error |
275
+ | QA-CS-105 | سبات صارم `WaitForTimeoutAsync()` | warning |
276
+ | QA-CS-106 | محدِّد هشّ بدل role locator | warning |
277
+ | QA-CS-108 | عنوان بيئة مضمّن في اختبار | info |
278
+ | QA-CS-111 | محاكاة شاملة `page.RouteAsync("**")` | info |
279
+
280
+ </details>
281
+
282
+ > الكتالوج الحي الكامل — كل قاعدة بطبقتها وثقتها وخطر إنذارها الكاذب
283
+ > وتوافر إصلاحها الآلي — يُولَّد من السجل:
284
+ >
285
+ > ```bash
286
+ > mjolnir rules --md
287
+ > ```
288
+ >
289
+ > صفحات كل قاعدة تقع تحت [`docs/rules/`](docs/rules/).
290
+
291
+ ### كم من هذا مقيس
292
+
293
+ **74 من 99 قاعدة تحمل معدل إنذارات كاذبة مقيسًا على كود OSS حقيقي**
294
+ (≥ 10 اكتشافات مصنفة يدويًا لكل منها؛ راجع
295
+ [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). الـ19 الأخرى تُشحن على تقدير
296
+ المؤلف. ذيل كل فحص يخبرك كم من القواعد التي _انطلقت_ مقيسة؛ و
297
+ `mjolnir rules --unmeasured` يسرد غير المقيسة؛ وصفحة `mjolnir explain`
298
+ لكل قاعدة تُصرّح بحالتها. ننشر المعدل حتى حين يكون قبيحًا — QA-CS-103
299
+ يدقّق عند 95% ولذلك هو في الحجر الصحي. تنمية الـ78 تلك هي العمل
300
+ المستمر للمشروع.
301
+
302
+ ### طبقات القواعد ونضج اللغات
303
+
304
+ كل قاعدة هي `core` أو `extended` أو `quarantine`، تُخصَّص وفق معدل
305
+ إنذاراتها الكاذبة **المقيس**:
306
+
307
+ | الطبقة | المعنى | الفحص الافتراضي | `--strict` |
308
+ | ------------ | ------------------------------- | :-------------: | :--------: |
309
+ | `core` | ≤ 10% إنذارات مقيسة | ✅ | ✅ |
310
+ | `extended` | ≤ 30% إنذارات مقيسة | ✅ | ✅ |
311
+ | `quarantine` | فوق 30%، أو لم يقس بعد (n < 10) | ❌ | ✅ |
312
+
313
+ | اللغة | المهايئ | التغطية اليوم |
314
+ | --------------- | ----------- | ---------------------------------------------------- |
315
+ | TypeScript / JS | AST المترجم | الأوسع والأكثر قياسًا — غالبًا `core`/`extended` |
316
+ | Python / pytest | طبقة regex | واسعة، مدقَّقة على corpus — غالبًا `core`/`extended` |
317
+ | Java | طبقة regex | أحدث — غالبًا `extended`/`quarantine` |
318
+ | C# / .NET | طبقة regex | أحدث — غالبًا `extended`/`quarantine` |
319
+
320
+ TypeScript وPython يمتلكان أوسع تغطية مقيسة. Java وC# مُشحونان وموثَّقان
321
+ وتبقيان خارج الرقم الرئيسي حتى يُدقَّق طقم مستهلك حقيقي (لا اختبارات
322
+ مكتبة الترابط نفسها).
323
+
324
+ ---
325
+
326
+ ## كيف يعمل التنقيط
327
+
328
+ <p align="center">
329
+ <img src="assets/readme/terminal-hero.svg" alt="ناتج الطرفية لـ Mjölnir — WORTHINESS 75/100 NEEDS WORK، تفصيل تشخيصات بحسب الفئة وقائمة FIX THIS FIRST" width="820" />
330
+ </p>
331
+
332
+ <sub>يُعاد توليده بـ `npm run docs:hero`؛
333
+ [`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
334
+ يُسقط CI إذا انحرفت المخرجات عمّا يطبعه المُبلِّغ فعليًا.</sub>
335
+
336
+ الدرجة شفافة: **error −8، warning −3، info −1**، ثم تُطبَّع بمستوى تعرض
337
+ الطقم (خصم لكل إعلان اختبار). الخصوم المرجَّحة بالأدلة تعني أن الإشارات
338
+ الضعيفة أرخص. تعرض الطرفية الأرقام المخفَّضة نفسها التي تستخدمها الدرجة —
339
+ لا صندوق أسود. المنهج الكامل: [docs/SCORING.md](docs/SCORING.md).
340
+
341
+ **الأحكام**
342
+
343
+ | Score | الحكم |
344
+ | ------- | ---------------- |
345
+ | ≥ 80 | ✓ **WORTHY** |
346
+ | 50 – 79 | ⚠ **NEEDS WORK** |
347
+ | < 50 | ✖ **UNWORTHY** |
348
+
349
+ **مستويات الدليل** — كل اكتشاف يحمل واحدًا؛ وهو يحدد وزن الاكتشاف في
350
+ الدرجة:
351
+
352
+ | المستوى | المعنى | الأثر على الدرجة | مثال |
353
+ | ------- | ------------ | ---------------- | ------------------------------------------------- |
354
+ | E2 | عيب حتمي | خصم كامل | `.only` مودعة — قابلة للإثبات بنيويًّا |
355
+ | E1 | نمط استدلالي | نصف الخصم | `sleep()` أعادته regex — إشارة قوية، ليست برهانًا |
356
+ | E0 | ملاحظة | صفر (إخباري فقط) | يُبلَّغ عنه لكنه لا يبوّت CI أبدًا ولا يخصم |
357
+
358
+ معظم القواعد **E1**. شعار «we prove it» يشير إلى هذا النظام: اكتشافات
359
+ E2 إثبات بنيوي؛ واكتشافات E1 تحذيرات موزونة الموضع، لا براهين رسمية.
360
+
361
+ المستودع الفارغ يحصد `null`، لا 100 مزوّرة أبدًا — انظر
362
+ [نموذج الثقة](#نموذج-الثقة).
363
+
364
+ ---
365
+
366
+ ## 🎭 Selector Health Score
367
+
368
+ المقياس الرئيسي لأطقم Playwright — ما مدى صمود محدِّداتك:
369
+
370
+ ```text
371
+ ▚▞ SELECTOR HEALTH — e2e/checkout.spec.ts
372
+
373
+ [█████████████████░░░] 83 / 100
374
+ role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
375
+ ```
376
+
377
+ المحدِّدات القائمة على الدور تحصد الدرجة الكاملة. سلاسل أصناف CSS وXPath
378
+ تبطئ الدرجة — تتحطم مع أي إعادة هيكلة DOM دون إخبارك بأي سلوك ارتدّ.
379
+
380
+ ---
381
+
382
+ ## 🔬 أدلة التنفيذ
383
+
384
+ الكشف الثابت عن التذبذب مجرد تخمين. يقرأ Mjölnir **بيانات تنفيذ حقيقية** —
385
+ تقارير JSON من Playwright وXML من JUnit من أي مشغّل:
386
+
387
+ ```bash
388
+ mjolnir forensics ./test-results/
389
+ ```
390
+
391
+ ```text
392
+ ▚▞ FLAKINESS LEADERBOARD
393
+
394
+ 3 tests · 1 failed · 1 flaky · 1 retried
395
+
396
+ TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
397
+ ████████████████████ 6.0s · 2 attempts
398
+ FAILING declines an expired card (e2e/checkout.spec.ts)
399
+ ████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
400
+ ```
401
+
402
+ الاختبار الذي ينجح من المحاولة ≥ 2 فقط ليس اختبارًا ناجحًا — إنه اختبار
403
+ محظوظ. يوسم `TRUE-FLAKE` بغضّ النظر عن علامة النجاح الخضراء النهائية.
404
+
405
+ ---
406
+
407
+ ## ⚡ Mjölnir ليس أداة lint أخرى
408
+
409
+ أدوات lint تخبرك إن كان الكود يتبع القواعد. Mjölnir يخبرك إن كان يمكن
410
+ الثقة بتحقّقك.
411
+
412
+ | | ESLint / SonarQube | أدوات التغطية | المراجعة اليدوية | **Mjölnir** |
413
+ | ---------------------------------------------------- | :----------------: | :-----------: | :--------------: | :---------: |
414
+ | نزاهة أسيرات CI (`continue-on-error`، `\|\| true`) | ❌ | ❌ | نادرًا | ✅ |
415
+ | عبر اللغات (TS، Python، Java، C#) من أداة واحدة | ❌ | ❌ | ❌ | ✅ |
416
+ | يقيّم صمود محدِّدات Playwright (Selector Health) | ❌ | ❌ | نادرًا | ✅ |
417
+ | يميّز الاختبارات بلا تأكيدات حقيقية | ✅ (إضافة)\* | ❌ | أحيانًا | ✅ |
418
+ | يلتقط السبات الصارم (`waitForTimeout`، `time.sleep`) | ✅ (إضافة)\* | ❌ | أحيانًا | ✅ |
419
+ | يجري في ثوانٍ، صفر نداءات شبكة أثناء الفحص | ✅ | ✅ | — | ✅ |
420
+
421
+ \*`eslint-plugin-jest` (`expect-expect`) و`eslint-plugin-playwright`
422
+ (`expect-expect`، `no-wait-for-timeout`) يغطيان ذلك لإطاريهما.
423
+
424
+ **التحليل التنفيذي** فئة منفصلة عن الـlint الثابت:
425
+
426
+ | | Playwright retry reporter | Allure / ReportPortal | **Mjölnir forensics** |
427
+ | -------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
428
+ | يقرأ بيانات تشغيل حقيقية لأحكام `TRUE-FLAKE` | جزئيًّا\* | جزئيًّا (tag) | ✅ |
429
+ | تقرير فرز التذبذب من سجل التنفيذ | ❌ | ✅ | ✅ |
430
+ | يتكامل مع درجة الجدارة الثابتة | ❌ | ❌ | ✅ |
431
+
432
+ \*Playwright يتتبع المحاولات داخليًا لكنه لا ينتج تقرير تذبذب مستقلًّا
433
+ بملصقات أحكام.
434
+
435
+ ---
436
+
437
+ ## 🤖 لماذا لا تكتفون بمراجعة الكود بالذكاء الاصطناعي؟
438
+
439
+ مشكلة مختلفة، طبقة مختلفة. المراجعة الآلية قد تلتقط تغيير اختبار مشبوهًا
440
+ في فرق؛ لكنها لا تثبت أن نظام التحقق ككل جدير بالثقة — وهي لا ترى إلا
441
+ الفرق الذي تريه لها.
442
+
443
+ | | مراجعة بالذكاء الاصطناعي (Copilot وغيره) | **Mjölnir** |
444
+ | ----------------------------- | :--------------------------------------: | :-------------------------: |
445
+ | الكلفة لكل فحص | رموز (تتدرج بحجم الفرق) | **صفر** (محلي، مثبَّت) |
446
+ | يرى الطقم كله + كل إعدادات CI | الفرق الذي تريه فقط | **كل شيء، كل مرة** |
447
+ | حتمي (مدخل واحد → مخرج واحد) | ❌ (غير حتمي) | **✅** |
448
+ | يلتقط أنماطًا راقدة أشهرًا | فقط إن وردت في السياق | **✅** (يفحص كل الملفات) |
449
+ | يتذكر الاكتشافات بين الجولات | ❌ (لا ذاكرة عبر الجلسات) | **✅** (baseline + diff) |
450
+ | يعمل دون استداء بشري | يحتاج PR أو موجهًا | **✅** (خُطّاف CI، 3 ثوانٍ) |
451
+
452
+ **استخدم كليهما.** يلتقط الذكاء الاصطناعي الدقائق والقصد وعيوب التصميم
453
+ التي لا يعثر عليها أي regex. يلتقط Mjölnir الأنماط البنيوية التي يغفلها
454
+ الذكاء الاصطناعي لأنها تبدو «مقصودة» — `.only` مودعة، ورمز خروج مبتلع،
455
+ و`continue-on-error` على مهمة اختبار. ليست أخطاء تحتاج تفكيرًا؛ بل حقائق
456
+ تحتاج فحصًا.
457
+
458
+ ---
459
+
460
+ ## 🤖 تكامل CI
461
+
462
+ أمر واحد يولّد سير عمل PR — استشاري افتراضيًا، ولا يحجب أبدًا:
463
+
464
+ ```bash
465
+ mjolnir ci install
466
+ ```
467
+
468
+ أو اربطه أصلًا في GitHub Code Scanning عبر SARIF:
469
+
470
+ ```yaml
471
+ - run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
472
+ - uses: github/codeql-action/upload-sarif@v3
473
+ with:
474
+ sarif_file: mjolnir.sarif
475
+ ```
476
+
477
+ إعداد المحرر والخط لـ SARIF:
478
+ [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
479
+
480
+ ### تغطية النطاق المتغيّر
481
+
482
+ `--scope changed` يسند الاكتشافات إلى الأسطر التي أضافها فرعك مقارنة
483
+ بنقطة دمج `main`. يغطي ملفات الاختبار (`*.spec.*`، `*.test.*`) زائد
484
+ ملفات أسيرات GitHub وإعدادات Playwright في الفرق. عندما يتعذّر فهم
485
+ نقطة الدمج — نسخة سطحية، HEAD منفصل، هدف بلا git، فرع افتراضي مختلف —
486
+ يتدهور بصدق: تعود الاكتشافات إلى الإسناد بملف كامل والتقرير يقول ذلك.
487
+ استبدل المرجع الأساس بـ `--base <ref>`.
488
+
489
+ ---
490
+
491
+ ## الإعداد
492
+
493
+ Mjölnir صفر إعداد. ملف `mjolnir.config.json` اختياري (أو `.mjolnir.json`)
494
+ في جذر المستودع يضبط الشدة والحجب والنطاق — لا يغيّر دلالات الكشف أبدًا.
495
+
496
+ | المفتاح | النوع | الأثر |
497
+ | ------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
498
+ | `exclude` | `string[]` | أنماط تجاهل إضافية (مجموعة فرعية من gitignore)، فوق الافتراضيات المدمجة |
499
+ | `gate` | `"advisory" \| "error" \| "warning"` | أي شدّات تخرج برمز غير صفري (الافتراضي `error`؛ `advisory` لا يحجب أبدًا) |
500
+ | `severityOverrides` | `{ "<RULE-ID>": severity }` | يعيد ترتيب اكتشافات قاعدة لمستودعك |
501
+ | `ignore` | `IgnoreEntry[]` | يكتم الاكتشافات — **`reason` إلزامي**؛ تنتهي صلاحية المدخلات بعد 90 يومًا (تاريخ `expires` صريح، أو زمن آخر تعديل لملف الإعداد لمن لا يذكره) |
502
+ | `plugins` | `string[]` | حزم قواعد من طرف ثالث (انظر [نموذج الثقة](#نموذج-الثقة)) |
503
+
504
+ ```json
505
+ {
506
+ "gate": "error",
507
+ "exclude": ["legacy/**"],
508
+ "severityOverrides": { "QA-PW-118": "warning" },
509
+ "ignore": [
510
+ {
511
+ "ruleId": "QA-TEST-004",
512
+ "files": ["e2e/legacy-login.spec.ts"],
513
+ "reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
514
+ "expires": "2026-12-31"
515
+ }
516
+ ]
517
+ }
518
+ ```
519
+
520
+ - **`.mjolnirignore`** — ملف بأسلوب gitignore بسيط لاستثناء المسارات،
521
+ بنفس لهجة `exclude`. استخدمه للضجيج الخاص بالجهاز؛ واستخدم `exclude`
522
+ عندما تعود القائمة للتحكم بالإصدارات إلى جانب بقية الإعداد.
523
+ - **تجاوزات سطر الأوامر** — `--strict` (تضمين قواعد الحجر الصحي)،
524
+ `--width <cols>` و`--ascii` / `--no-ascii` (عرض الطرفية)،
525
+ `--tone blunt` (رسائل أقسح)، `--max-duration <sec>` (فحص جزئي محدود).
526
+ - كتم القواعد ودورة إخراجها من الخدمة:
527
+ [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
528
+
529
+ مدخلات `ignore` تُغذّي أيضًا الأمر المستقل `mjolnir suppressions` الذي
530
+ يسرد ما هو مكتوم الآن ومتى تنتهي صلاحية كل مدخل.
531
+
532
+ ---
533
+
534
+ ## 📐 رموز الخروج والعقود
535
+
536
+ مجمَّدة — آمنة لبناء منطق CI فوقها:
537
+
538
+ | رمز الخروج | المعنى |
539
+ | ---------- | ---------------------------------------------------------------------- |
540
+ | `0` | نظيف — لا اكتشافات عند البوابة أو فوقها |
541
+ | `1` | اكتشافات عند البوابة أو فوقها |
542
+ | `2` | فحص جزئي (نفدت ميزانية الوقت، ملفات غير قابلة للقراءة) — لا يحجب أبدًا |
543
+ | `10` | خطأ استعمال (راية خاطئة، غياب هدف) |
544
+ | `20` | خطأ داخلي |
545
+
546
+ تقرير JSON/SARIF هو `schemaVersion: 1`. معرّفات القواعد
547
+ (`QA-<FAMILY>-NNN`) لا تتغير بعد الإطلاق ولا تُعاد استخدامها أبدًا.
548
+
549
+ ---
550
+
551
+ ## نموذج الثقة
552
+
553
+ - **Local-first** — صفر نداءات شبكة أثناء الفحص. قطعًا. صفر قياس عن بُعد.
554
+ - **لا برهان كاذب** — نقول «مجهول» قبل «متحقَّق منه». المستودع الفارغ
555
+ يأخذ `score: null`، لا 100 مزوّرة.
556
+ - **صدق جزئي** — إذا قُطع التحليل قَصِرًا، يقول الناتج ذلك. لا «complete»
557
+ أبدًا حين لا يكون.
558
+ - **جدار الإنذارات الكاذبة** — يعمل الكشف على رؤية كود خالية من
559
+ التعليقات/النصوص (قواعد TypeScript تستخدم AST المترجم): النمط داخل
560
+ تعليق نثري أو نص مثال توثيقي توثيق، لا اكتشاف.
561
+ - **مقيس، لا مُدَّعى** — فقط القواعد ذات معدل إنذارات كاذبة من كود OSS
562
+ حقيقي تُشحن في الطبقات الرئيسية (انظر
563
+ [كم من هذا مقيس](#كم-من-هذا-مقيس))؛ ذيل الفحص و`mjolnir rules --unmeasured`
564
+ يخبرانك أيُّها أي.
565
+ - **الثقة بالإضافات** — الإضافات حزم npm معلنة تحت `"plugins"`.
566
+ **لا غرفة رمل**: كود الإضافة يجري بكامل صلاحيات Node، النموذج نفسه
567
+ لإضافات ESLint أو Vitest. بادئات معرّفات القواعد الأساسية محجوزة
568
+ وتُرفض من الإضافات منعًا للانتحال.
569
+ - **قواعد خارجية محلية للمساحة** (مجلدية، صفر شبكة) — مجلد
570
+ `mjolnir-rules/` بجوار هدف الفحص يحمّل قواعد مخصصة: ملفات JSON تعلن
571
+ أنماط regex (لا يُنفَّذ كود)، ووحدات `.mjs`/`.js` تصدّر `rules` (ثقة
572
+ Node كاملة، كالإضافات). القواعد الخارجية تحمل البيانات الوصفية للثقة
573
+ نفسها كالأساسية؛ لا يمكنها أبدًا أن تُشحن في الطبقة الأساسية (الأساسية
574
+ تشترط معدل إنذارات مقيسًا من ملف corpus الجانبي — التصريح بـ
575
+ `tier: "core"` يُقصر إلى `extended`)، وتلتزم سقوف الطبقات وتُفحص ضد
576
+ الانحراف: `mjolnir rules --md --external` يعرض الكتالوج من الملفات
577
+ المحمّلة (المصدر `external`)، ومولّد المصفوفة يقبل `--external <root>`.
578
+
579
+ ---
580
+
581
+ ## 🏗️ المعمارية
582
+
583
+ <details>
584
+ <summary>فصّل الشجرة</summary>
585
+
586
+ ```
587
+ mjolnir/
588
+ ├── src/
589
+ │ ├── engine/ # LanguageAdapter interface + rule runner
590
+ │ ├── adapters/ # typescript · python · java · csharp · github-actions
591
+ │ ├── rules/ # rules across 8 families + the measured-FP table
592
+ │ ├── playwright/ # Selector Health Score engine
593
+ │ ├── discovery/ # workspace, frameworks, ignore resolution
594
+ │ ├── scope/ # git merge-base changed-scope engine
595
+ │ ├── scorer/ # transparent deduction table + prioritization
596
+ │ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
597
+ │ ├── forensics/ # run-data ingestion · flake verdicts · triage
598
+ │ ├── config/ # mjolnir.config.json + suppressions
599
+ │ ├── plugins/ # third-party rule loading (no sandbox)
600
+ │ └── commands/ # every subcommand
601
+ └── tests/
602
+ ├── fixtures/ # must-fire / must-not-fire per rule
603
+ └── golden/ # frozen score regression locks
604
+ ```
605
+
606
+ </details>
607
+
608
+ - **القواعد دوال نقية** — `(SourceFileContext) → Finding[]`، بلا I/O،
609
+ بلا متغيرات عامة. إضافة بيئة جديدة = مهايئ واحد + قواعده.
610
+ - **TypeScript/Playwright تستخدم AST المترجم** (ts-morph). Python وJava
611
+ وC# تجري على طبقة regex مشتركة مع إخفاء التعليقات/النصوص.
612
+ - طبقة AST من tree-sitter WASM لـ Java وC# موجودة وهي خطوة الدقة التالية —
613
+ لم تُوصَّل بعد إلى خط الفحص المتزامن.
614
+
615
+ ---
616
+
617
+ ## 📚 الوثائق
618
+
619
+ | المستند | ما فيه |
620
+ | ------------------------------------------------------ | ----------------------------------------- |
621
+ | [docs/SCORING.md](docs/SCORING.md) | تطبيع الدرجة + ترجيح الأدلة |
622
+ | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | معدلات الإنذارات الكاذبة المقيسة + المنهج |
623
+ | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | حالات القواعد، الكتم، الإخراج من الخدمة |
624
+ | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | ناتج SARIF + إعداد المحرر/CI |
625
+ | [docs/rules/](docs/rules/) | كتالوج مولَّد لكل قاعدة |
626
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | تجهيز التطوير + مساهَمة العمل |
627
+ | [CHANGELOG.md](CHANGELOG.md) | سجل الإصدارات |
628
+ | [SECURITY.md](SECURITY.md) | الإبلاغ عن الثغرات |
629
+
630
+ ---
631
+
632
+ ## 📈 الحالة
633
+
634
+ **v0.5.x · بيتا مفتوحة.** مخطط JSON ورموز الخروج عقود مجمَّدة. TypeScript
635
+ وPython لهما أوسع تغطية مقيسة؛ Java وC# أحدث — اقرأهما عبر
636
+ [جدول الطبقات](#طبقات-القواعد-ونضج-اللغات).
637
+
638
+ ---
639
+
640
+ ## 🤝 المساهمة
641
+
642
+ القواعد الجديدة أسهل مساهمة أولى — أمر واحد يهيكل القاعدة مع تجهيزاتها
643
+ must-fire **و**must-not-fire (القاعدة المولَّدة تفشل في تجهيزاتها عمدًا
644
+ حتى تنفّذ كشفًا حقيقيًا — الهيكل الفارغ لا يُشحن):
645
+
646
+ ```bash
647
+ mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
648
+ ```
649
+
650
+ التجهيز التطويري الكامل، وأوامر البوابة الدائمة، وقوانين منع التوسع /
651
+ جدار التجهيزات في [CONTRIBUTING.md](CONTRIBUTING.md).
652
+
653
+ ---
654
+
655
+ <div align="center">
656
+
657
+ **كفّوا عن شحن اختبارات لا تثقون بها.**
658
+
659
+ ```bash
660
+ npx mjolnir-qa@latest
661
+ ```
662
+
663
+ **Star ⭐ · Watch 👀 · Contribute 🤝**
664
+
665
+ بُني على يد [Sergey Bar](https://www.linkedin.com/in/sergeybar/)
666
+
667
+ </div>