mjolnir-qa 1.0.9 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +204 -0
- package/README.ar.md +434 -478
- package/README.bn.md +434 -491
- package/README.br.md +434 -520
- package/README.bs.md +431 -500
- package/README.da.md +433 -509
- package/README.de.md +432 -522
- package/README.es.md +428 -517
- package/README.fr.md +426 -520
- package/README.gr.md +433 -517
- package/README.he.md +433 -475
- package/README.it.md +436 -525
- package/README.ja.md +436 -506
- package/README.ko.md +434 -494
- package/README.md +453 -438
- package/README.no.md +435 -509
- package/README.pl.md +433 -511
- package/README.ru.md +434 -515
- package/README.th.md +434 -484
- package/README.tr.md +427 -504
- package/README.uk.md +433 -505
- package/README.vi.md +436 -494
- package/README.zh.md +433 -462
- package/README.zht.md +433 -462
- package/dist/cli.d.mts +716 -110
- package/dist/cli.mjs +9815 -22027
- package/dist/mcp/stdio.mjs +2164 -886
- package/dist/rolldown-runtime-8H4AJuhK.mjs +14 -0
- package/dist/scan-pipeline-C0ka-RmX.mjs +2 -0
- package/dist/scan-pipeline-D3Yk2cef.mjs +15309 -0
- package/package.json +14 -8
package/README.ar.md
CHANGED
|
@@ -1,384 +1,431 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/readme/
|
|
3
|
+
<img src="assets/readme/hero.svg" alt="Mjölnir. الاختبارات تخبرك بما نجح. Mjölnir يخبرك بما يمكنك الوثوق به." width="100%" />
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<br />
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
يعثر Mjölnir على الاختبارات التي لا يمكن أن تفشل وخطوط CI التي لا يمكن أن تتحول إلى الأحمر،<br />
|
|
8
|
+
ثم يقيّم إلى أي حد يمكن الوثوق بالنتيجة، مع الدليل على كل نقطة.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
12
|
-
[](LICENSE)
|
|
13
|
-
[](https://nodejs.org)
|
|
14
|
-
|
|
15
|
-
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | [Español](README.es.md) | [Français](README.fr.md) | [Italiano](README.it.md) | [Dansk](README.da.md) | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | العربية | [Bosanski](README.bs.md)
|
|
10
|
+
<br />
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
13
|
+
[](https://www.npmjs.com/package/mjolnir-qa)
|
|
14
|
+
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
15
|
+
[](https://codecov.io/gh/Sergey-Bar/Mjolnir)
|
|
16
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
|
|
17
|
+
[](LICENSE)
|
|
18
|
+
[](https://nodejs.org)
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
21
|
npx mjolnir-qa@latest
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
[شاهده وهو يعمل](#شاهده-وهو-يعمل) · [البدء السريع](#البدء-السريع) · [ما الذي يكتشفه](#ما-الذي-يكتشفه-mjölnir) · [الدرجة](#درجة-الجدارة) · [الأدلة](#نموذج-الأدلة) · [تحليل التشغيلات](#تحليل-تشغيلات-الاختبار) · [CI](#سلامة-ci) · [الوكلاء](#وكلاء-الذكاء-الاصطناعي) · [الأمان](#الثقة-والأمان) · [الحدود](#ما-لا-يستطيع-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.he.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
|
+
علامة الصح الخضراء تعني أن خط CI لم يفشل. لا تعني أن الاختبارات عملت، ولا أنها كان يمكن أن تفشل. كل واحدة من هذه تمر باللون الأخضر:
|
|
44
|
+
|
|
45
|
+
- `.only` بقي في commit فشغّل 3 اختبارات بدل 900
|
|
46
|
+
- `continue-on-error: true` على الـ job الذي كان يُفترض أن يمنع الدمج
|
|
47
|
+
- `|| true` بعد أمر الاختبار
|
|
48
|
+
- اختبار لا يتحقق من أي شيء، أو جسمه فارغ
|
|
49
|
+
- غلاف إعادة محاولة يحوّل فشلًا حقيقيًا إلى نجاح بالحظ
|
|
50
|
+
- تقرير يرفعه الـ workflow لكنه لم يُنشأ قط
|
|
51
|
+
- sleep ثابت يُبقي حالة تسابق متماسكة
|
|
52
|
+
|
|
53
|
+
لا يحوّل أيٌّ منها خط CI إلى الأحمر، وكل واحد منها يبدو مقصودًا عند المراجعة. لهذا تبقى. هذا Mjölnir يقرأ مثالًا حقيقيًا:
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="assets/readme/scan.svg" alt="workflow الـ CI في مستودع العرض، مقروءًا سطرًا بسطر. يعلّم Mjölnir كل نتيجة عند السطر الذي أبلغ عنه، مع قاعدتها وما الخطأ ومستوى الدليل ومعدل الإيجابيات الكاذبة المقيس لها." 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 مجموعة الاختبارات وملفات workflow الخاصة بـ CI، وتقرير تشغيل حقيقي إن وُجد. لا يشغّل اختباراتك، ولا يثبّت اعتمادياتك، ولا ينفّذ الشيفرة التي يفحصها. وعندما لا يملك دليلًا، يقول ذلك بدل أن يختلق ثقة:
|
|
64
|
+
|
|
65
|
+
| الحالة | ما يبلّغ عنه Mjölnir |
|
|
66
|
+
| -------------------------------------------------------- | ---------------------------------------------------------- |
|
|
67
|
+
| لم يُعثر على تعريفات اختبارات | الدرجة `null`، وتُعرض كـ **UNKNOWN**. لا 100 مختلقة أبدًا. |
|
|
68
|
+
| لا يوجد خط أساس أو مراجعة قابلة للمقارنة | **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 برموز خروج مجمّدة. وفي حلقة الوكيل، يكتب الذكاء الاصطناعي الإصلاح ويعيد 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
|
+
## شاهده وهو يعمل
|
|
80
|
+
|
|
81
|
+
فحص حقيقي لـ [`examples/demo-repo`](examples/demo-repo)، وهي مجموعة Playwright صغيرة مع workflow لـ CI. هنا ذهبت نقاطها:
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="تفصيل الخصومات في Mjölnir: WORTHINESS 80/100 WORTHY، والدرجة حسب الفئة، ومربع الخصومات حسب الخطورة، وقائمة FIX THIS FIRST" width="520" />
|
|
85
|
+
</p>
|
|
86
|
+
|
|
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>
|
|
35
91
|
|
|
36
|
-
|
|
92
|
+
<br />
|
|
37
93
|
|
|
38
94
|
<p align="center">
|
|
39
|
-
<
|
|
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>
|
|
40
98
|
</p>
|
|
41
99
|
|
|
42
|
-
<sub
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
46
|
-
يُسقط CI إذا انحرفت المخرجات عمّا تطبعه الأداة.</sub>
|
|
100
|
+
<sub>رُسم إطارًا بإطار من فحص حقيقي بواسطة `npm run docs:video`؛ ولم يُسجَّل من الشاشة قط. اختر الإطار لفتح [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
|
|
101
|
+
|
|
102
|
+
</details>
|
|
47
103
|
|
|
48
|
-
|
|
104
|
+
### نتيجة واحدة عن قرب
|
|
49
105
|
|
|
50
|
-
|
|
51
|
-
Python — أربع لغات/صيغ في تمريرة واحدة.
|
|
52
|
-
2. وجد أدلة تُضعف الثقة في الطقم — `continue-on-error` يُخفي مهمة، و
|
|
53
|
-
`|| true` يبتلع رمز الخروج، وسبات صارم، ومحدِّد هشّ، وعناوين تجريبية
|
|
54
|
-
مضمّنة، وانتظار `networkidle`.
|
|
55
|
-
3. حوّل كلًّا منها إلى اكتشاف ملموس بمعرّف قاعدة وموقع وإصلاح — وإلى
|
|
56
|
-
درجة واحدة يمكنك بوابت PR على أساسها.
|
|
106
|
+
كل نتيجة تجيب عن أربعة أسئلة: أين هي، ومدى تأكد Mjölnir، وكم مرة تخطئ القاعدة، وكيف تُصلح.
|
|
57
107
|
|
|
58
|
-
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="النتيجة الأولى من فحص العرض، تمامًا كما تطبعها الطرفية، مع تعليم أجزائها الأربعة: أين، ومدى التأكد، وكم مرة تخطئ القاعدة، والإصلاح." width="100%" />
|
|
110
|
+
</p>
|
|
59
111
|
|
|
60
|
-
|
|
112
|
+
يطبع `mjolnir explain QA-CI-001` سجل الثقة الكامل لقاعدة ما، بما في ذلك معدل الإيجابيات الكاذبة المقيس لها والمستوى الذي منحها إياه هذا المعدل:
|
|
61
113
|
|
|
62
114
|
```text
|
|
63
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
64
116
|
|
|
65
117
|
Severity: error
|
|
66
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
67
120
|
Evidence: E2
|
|
68
|
-
|
|
121
|
+
QA impact: False-green risk (FALSE-GREEN)
|
|
122
|
+
Measured FP: 11% (19 hand-classified corpus verdicts)
|
|
123
|
+
FP risk: low (author estimate)
|
|
124
|
+
Languages: yaml
|
|
125
|
+
Frameworks: github-actions, azure-pipelines
|
|
69
126
|
|
|
70
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
71
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
72
129
|
|
|
73
130
|
WHY IT MATTERS
|
|
74
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
75
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
76
133
|
|
|
77
134
|
HOW TO FIX
|
|
78
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
79
|
-
```
|
|
80
136
|
|
|
81
|
-
|
|
82
|
-
ما قدّم — وهو لم يقدّم.
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
83
138
|
|
|
84
|
-
|
|
139
|
+
WHAT WOULD CHANGE THE VERDICT
|
|
140
|
+
- a run report next to the scan target (mjolnir.report.json or test-results/)
|
|
141
|
+
corroborating this file lifts its findings to L3–L5
|
|
142
|
+
- a documented suppression (mjolnir.config.json) lowers the finding count
|
|
143
|
+
without claiming correctness
|
|
144
|
+
- quarantine findings run only under --strict and are advisory (E0) — they can
|
|
145
|
+
never gate CI
|
|
85
146
|
|
|
86
|
-
|
|
147
|
+
NEXT ACTION
|
|
148
|
+
Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
|
|
149
|
+
occurrence of this rule is listed in the scan output.
|
|
87
150
|
|
|
88
|
-
|
|
151
|
+
HOW TO VERIFY THE FIX
|
|
152
|
+
Re-run `mjolnir` on the changed file(s) — this finding should no longer
|
|
153
|
+
appear. `mjolnir --scope changed` scopes the check to just what you touched.
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
npx mjolnir-qa@latest
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
92
156
|
```
|
|
93
157
|
|
|
94
|
-
|
|
95
|
-
|
|
158
|
+
هذه هي وحدة القيمة: موضع واحد يبلّغ فيه CI عن نجاح لم يستحقه.
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## البدء السريع
|
|
96
163
|
|
|
97
164
|
```bash
|
|
98
|
-
npx mjolnir-qa@latest
|
|
165
|
+
npx mjolnir-qa@latest
|
|
99
166
|
```
|
|
100
167
|
|
|
101
|
-
|
|
102
|
-
كل ما عدا ذلك اختياري.
|
|
168
|
+
يفحص الدليل الحالي ويطبع Trust Report: ما الذي وجده، وإلى أي حد يمكنك الوثوق به، ولماذا، وما الخطوة التالية. ويخرج بالرمز `0` عندما لا يُعثر على شيء عند مستوى البوابة أو فوقه.
|
|
103
169
|
|
|
104
|
-
|
|
105
|
-
| ----------------------------------- | ---------------------------------------------------- |
|
|
106
|
-
| `mjolnir` | فحص المستودع كاملًا + درجة الجدارة |
|
|
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>
|
|
170
|
+
في CI، افحص فقط ما أدخله الفرع، حتى لا تُغرق مجموعة اختبارات قديمة أول pull request لك:
|
|
116
171
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
| `mjolnir triage ./test-results/` | اقتراح حجر صحي من سجل التنفيذ |
|
|
121
|
-
| `mjolnir pw-report ./test-results/` | ملخص تشغيل Playwright — المحاولات / المتذبذبات / الأبطأ |
|
|
122
|
-
| `mjolnir doctor:playwright` | فحص عميق لـ Playwright وحده + Selector Health Score |
|
|
172
|
+
```bash
|
|
173
|
+
npx mjolnir-qa@latest --scope changed
|
|
174
|
+
```
|
|
123
175
|
|
|
124
|
-
|
|
176
|
+
يكتب `mjolnir ci install` ذلك كـ workflow لـ GitHub Actions، باستخدام [الـ action](https://github.com/Sergey-Bar/Mjolnir#readme) المثبّت على الوسم الرئيسي `v1` (أو `npx` عادي مع `--no-action`). ويبقى استشاريًا إلى أن تقرر أنه يجب أن يمنع الدمج.
|
|
177
|
+
|
|
178
|
+
| الأمر | ما الذي يفعله |
|
|
179
|
+
| ----------------------------------- | ------------------------------------------------------------ |
|
|
180
|
+
| `mjolnir` | Trust Report: الحكم، ودرجة الثقة، والإجراء التالي |
|
|
181
|
+
| `mjolnir --scope changed` | فقط ما أدخله فرعك (صيغة CI) |
|
|
182
|
+
| `mjolnir ci install` | ينشئ workflow استشاريًا لطلبات الدمج (قائمًا على الـ 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 (عنصر لأداة طلب الدمج) |
|
|
190
|
+
| `mjolnir --strict` | يشغّل أيضًا قواعد مستوى quarantine (خطر FP أعلى) |
|
|
125
191
|
|
|
126
192
|
<details>
|
|
127
|
-
<summary><strong
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
| `mjolnir
|
|
134
|
-
| `mjolnir
|
|
135
|
-
| `mjolnir
|
|
136
|
-
| `mjolnir
|
|
137
|
-
| `mjolnir
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
193
|
+
<summary><strong>كل الأوامر الأخرى</strong> — فرز الاختبارات غير المستقرة، والتقارير، والحوكمة</summary>
|
|
194
|
+
|
|
195
|
+
<br />
|
|
196
|
+
|
|
197
|
+
| الأمر | ما الذي يفعله |
|
|
198
|
+
| ----------------------------------- | ------------------------------------------------------------------------- |
|
|
199
|
+
| `mjolnir --classic` | لافتة الدرجة السابقة لـ Trust Report |
|
|
200
|
+
| `mjolnir explain verdict` | لماذا جاء حكم الفحص المحفوظ على ما هو عليه |
|
|
201
|
+
| `mjolnir triage ./test-results/` | فرز موجَّه. كل صف ينتهي بإجراء تالٍ. |
|
|
202
|
+
| `mjolnir pw-report ./test-results/` | ملخص تشغيل Playwright: إعادات المحاولة، والاختبارات غير المستقرة، والأبطأ |
|
|
203
|
+
| `mjolnir doctor:playwright` | فحص معمّق خاص بـ Playwright مع Selector Health Score |
|
|
204
|
+
| `mjolnir fix --dry-run` / `fix` | إصلاحات تلقائية آمنة، يُعاد فحص كل منها لإثبات أنه نجح |
|
|
205
|
+
| `mjolnir baseline` / `diff` | لقطة للنتائج، ثم الإبلاغ عن الجديد أو الأسوأ فقط |
|
|
206
|
+
| `mjolnir impact --since <ref>` | ما أدخله commit وما حلّه |
|
|
207
|
+
| `mjolnir summary` | تعليقات CI وملخص للخطوة من تقرير |
|
|
208
|
+
| `mjolnir pr-comment` | تعليق محدد النطاق على طلب الدمج، بصيغة Markdown |
|
|
209
|
+
| `mjolnir debt` | سجل الدَّين التقني للاختبارات مع نموذج تكلفة |
|
|
210
|
+
| `mjolnir handover` | خريطة تعريفية بمجموعة الاختبارات لمهندس QA جديد |
|
|
211
|
+
| `mjolnir init` | يكتشف أُطر العمل ويطبع قائمة تحقق للإعداد |
|
|
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 لنقطة نهاية shields.io ومقتطف |
|
|
219
|
+
| `mjolnir --cache` | إعادات فحص تزايدية عبر ذاكرة تخزين مؤقت محلية للأحكام |
|
|
220
|
+
| `mjolnir --format mermaid` | مخطط لبنية الاختبارات لتعليق على طلب الدمج |
|
|
221
|
+
|
|
222
|
+
يطبع `mjolnir help <command>` طريقة الاستخدام والأمثلة والخطوة التالية لأي منها.
|
|
142
223
|
|
|
143
224
|
</details>
|
|
144
225
|
|
|
145
|
-
|
|
146
|
-
يتطلب Node.js ≥ 22.18. يعمل على Windows وmacOS وLinux.
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## 👥 لمن هذا؟
|
|
151
|
-
|
|
152
|
-
- **QA / SDET** يملكون طقم e2e أو تكامل، ويحتاجون دليلًا على أن الطقم
|
|
153
|
-
يستحق فعليًا علامة النجاح الخضراء التي يُنتجها.
|
|
154
|
-
- **فرق Platform / DevEx** المسؤولة عن نزاهة CI وبوابات الإصدار —
|
|
155
|
-
الأشخاص الذين يهتمون ألا يحوّل `continue-on-error` خطًّا أحمر إلى
|
|
156
|
-
أخضر بصمت.
|
|
157
|
-
- **مشرفو OSS** يريدون بوابة تحقق رخيصة دائمة التشغيل تعمل محليًا وفي
|
|
158
|
-
CI دون أي نداءات شبكة.
|
|
159
|
-
|
|
160
|
-
---
|
|
226
|
+
يتطلب **Node.js ≥ 22.18** على Windows أو macOS أو Linux. تفضّل التثبيت العام؟ `npm i -g mjolnir-qa`. يأتي هذا الحد الأدنى من سلسلة أدوات البناء (يستهدفه tsdown ويُجري خط الإصدار اختبارات دخان عليه)؛ ولا تحتاج اعتماديات وقت التشغيل أكثر من ذلك.
|
|
161
227
|
|
|
162
|
-
|
|
228
|
+
<br />
|
|
163
229
|
|
|
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** — صفر نداءات شبكة أثناء الفحص، صفر قياس عن بُعد، يجري في ثوانٍ |
|
|
230
|
+
## ما الذي يكتشفه Mjölnir
|
|
172
231
|
|
|
173
|
-
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="يعمل مع حزمة تقنياتك: اللغات وأُطر الاختبار وأنظمة CI التي تغطيها قواعده، من سجل القواعد." width="100%" />
|
|
234
|
+
</p>
|
|
174
235
|
|
|
175
|
-
|
|
176
|
-
تنطلق على تجهيزتها السالبة ذاتها لا يمكن أن تُشحن — ذلك هو جدار الإنذارات
|
|
177
|
-
الكاذبة.
|
|
236
|
+
**79 قاعدة** في أربع عائلات — نظافة الاختبارات، وجودة الاختبارات، وPlaywright، وسلامة CI — عبر TypeScript وJavaScript وPython وJava وC# وYAML الخاص بـ GitHub Actions. تغطي Playwright في روابطه الأربعة، إضافة إلى pytest وJUnit وTestNG وNUnit وxUnit وMSTest وJest وVitest وMocha، مع تغطية مبدئية لـ Cypress وSelenium. تسع منها، لإظهار الشكل:
|
|
178
237
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
|
183
|
-
|
|
|
184
|
-
| QA-TEST-
|
|
185
|
-
| QA-
|
|
186
|
-
| QA-
|
|
187
|
-
| QA-
|
|
188
|
-
| QA-
|
|
189
|
-
| QA-
|
|
190
|
-
| 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 | اختبار بلا تأكيدات | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | تأكيد على promise دون await | error | quarantine |
|
|
245
|
+
| QA-PW-002 | تأكيد على locator دون await | error | core |
|
|
246
|
+
| QA-PW-004 | محددات CSS/XPath هشة | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | اختبار متخطى (`skip`، `xfail` غير صارم) | warning | core |
|
|
248
|
+
| QA-CS-103 | دالة اختبار بلا تأكيدات | error | core |
|
|
191
249
|
|
|
192
|
-
|
|
250
|
+
يُولَّد الفهرس الكامل من السجل ولا يُصان يدويًا أبدًا: `mjolnir rules --md`، أو [`docs/rules/`](docs/rules/)، أو [دليل ما الذي يفحصه](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
|
|
193
251
|
|
|
194
252
|
<details>
|
|
195
|
-
<summary><strong
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
|
253
|
+
<summary><strong>كل قاعدة مذكورة في هذا الملف</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 | النظافة | اختبار بلا تأكيدات | error | quarantine |
|
|
264
|
+
| QA-TEST-004 | النظافة | sleep ثابت (`waitForTimeout`، `sleep()`، `delay()`) | warning | extended |
|
|
265
|
+
| QA-TEST-006 | النظافة | إساءة استخدام إعادة المحاولة لإخفاء عدم الاستقرار | warning | quarantine |
|
|
266
|
+
| QA-TEST-010 | النظافة | جسم اختبار فارغ | error | quarantine |
|
|
267
|
+
| QA-TQUAL-002 | الجودة | تأكيد تحصيل حاصل | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | الجودة | تأكيد على promise دون await | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | الجودة | اختبارات معلّقة كتعليقات | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | تأكيد على 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 | أغلفة إعادة المحاولة حول الاختبارات | warning | extended |
|
|
279
|
+
| QA-CI-008 | CI | خطوة تنجح دائمًا تخفي الإخفاقات | 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 | دالة اختبار بلا تأكيدات | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | `time.sleep()` في الاختبارات | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | تأكيد تحصيل حاصل | 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 | دالة اختبار بلا تأكيدات | 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# | دالة اختبار بلا تأكيدات | 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 مجموعة مبدئية من ثلاث قواعد.
|
|
202
298
|
|
|
203
299
|
</details>
|
|
204
300
|
|
|
205
|
-
|
|
206
|
-
<summary><strong>Playwright 🎭</strong></summary>
|
|
301
|
+
تُطلق كل قاعدة مع ملف fixture من نوع must-fire **و**آخر من نوع must-not-fire، ولا يمكن إطلاق قاعدة تنطلق على ملف fixture السلبي الخاص بها. هذا هو جدار الحماية من الإيجابيات الكاذبة؛ ويفرضه `mjolnir doctor` في CI الخاص بهذا المستودع.
|
|
207
302
|
|
|
208
|
-
|
|
209
|
-
| --------- | ------------------------------------ | -------- |
|
|
210
|
-
| QA-PW-002 | تأكيد محدِّد بلا await | error |
|
|
211
|
-
| QA-PW-003 | `page.pause()` / `test.only()` مودعة | error |
|
|
212
|
-
| QA-PW-004 | محدِّدات CSS/XPath هشّة | warning |
|
|
213
|
-
| QA-PW-123 | عناوين بيئات مضمّنة | warning |
|
|
303
|
+
### Selector Health Score
|
|
214
304
|
|
|
215
|
-
|
|
305
|
+
يقيّم `mjolnir doctor:playwright` كل locator حسب طريقة عثوره على العنصر: كما يفعل المستخدم (الدور، التسمية، النص)، أو عبر عقد صريح (`data-testid`)، أو بمصادفة بنيوية (سلاسل CSS، XPath). يحصل كل ملف على درجة من 0 إلى 100:
|
|
216
306
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
| ID | القاعدة | Severity |
|
|
221
|
-
| --------- | ----------------------------------------------------------- | -------- |
|
|
222
|
-
| QA-CI-001 | `continue-on-error` يُخفي الإخفاقات | error |
|
|
223
|
-
| QA-CI-002 | `\|\| true` يبتلع رموز الخروج | error |
|
|
224
|
-
| QA-CI-005 | تقرير يُستهلك ولا يُولَّد أبدًا | error |
|
|
225
|
-
| QA-CI-007 | أغلفة محاولات حول الاختبارات | warning |
|
|
226
|
-
| QA-CI-008 | خطوة دائمة النجاح تُخفي الإخفاقات | error |
|
|
227
|
-
| QA-CI-009 | رمز خروج الاختبار لا يُمرَّر (`\|` بلا pipefail، سلاسل `;`) | error |
|
|
228
|
-
| QA-CI-010 | اختبارات تُتجاوز حيث يجب أن تحجب (حرّاس skip-on-PR) | error |
|
|
229
|
-
|
|
230
|
-
</details>
|
|
231
|
-
|
|
232
|
-
<details>
|
|
233
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
234
|
-
|
|
235
|
-
| ID | القاعدة | Severity |
|
|
236
|
-
| --------- | ---------------------------------------- | -------- |
|
|
237
|
-
| QA-PY-002 | اختبار متجاوز (`skip`، `xfail` غير صارم) | warning |
|
|
238
|
-
| QA-PY-003 | دالة اختبار بلا تأكيدات | error |
|
|
239
|
-
| QA-PY-005 | `time.sleep()` في الاختبارات | warning |
|
|
240
|
-
| QA-PY-012 | تأكيد مُبرهن ذاتيًا | error |
|
|
241
|
-
|
|
242
|
-
20 قاعدة Python إجمالًا (QA-PY-001…012 نظافة pytest + QA-PY-101…108 Playwright-Python).
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
243
309
|
|
|
244
|
-
|
|
310
|
+
e2e/login.spec.ts
|
|
311
|
+
[█████████████░░░░░░░] 65 / 100
|
|
312
|
+
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
245
313
|
|
|
246
|
-
|
|
247
|
-
|
|
314
|
+
e2e/checkout.spec.ts
|
|
315
|
+
[██████████████████░░] 88 / 100
|
|
316
|
+
role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
317
|
+
```
|
|
248
318
|
|
|
249
|
-
|
|
250
|
-
| --------- | ------------------------------------------ | -------- |
|
|
251
|
-
| QA-JV-101 | اختبار معطَّل (`@Disabled`) | warning |
|
|
252
|
-
| QA-JV-102 | سبات صارم (`Thread.sleep()`) | warning |
|
|
253
|
-
| QA-JV-103 | طريقة اختبار بلا تأكيدات | error |
|
|
254
|
-
| QA-JV-105 | سبات صارم في Playwright `waitForTimeout()` | warning |
|
|
255
|
-
| QA-JV-106 | محدِّد هشّ بدل role locator | warning |
|
|
319
|
+
هذا يقيس **المتانة، لا الصحة**. ينجح `.btn.btn-primary > div:nth-child(2)` اليوم ويظل ينجح إلى أن يلمس أحدٌ الترميز. الدرجة المنخفضة لا تدّعي أبدًا أن الاختبار معطوب، بل فقط أنه يعتمد على ترميز لم يعد أحد بالحفاظ عليه.
|
|
256
320
|
|
|
257
|
-
|
|
321
|
+
<br />
|
|
258
322
|
|
|
259
|
-
|
|
260
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
323
|
+
## درجة الجدارة
|
|
261
324
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
| QA-CS-102 | سبات صارم (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
266
|
-
| QA-CS-103 | طريقة اختبار بلا تأكيدات | error |
|
|
267
|
-
| QA-CS-105 | سبات صارم `WaitForTimeoutAsync()` | warning |
|
|
268
|
-
| QA-CS-106 | محدِّد هشّ بدل 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>
|
|
269
328
|
|
|
270
|
-
|
|
329
|
+
<sub>كل درجة من 0 إلى 100، موضوعة بواسطة `deriveScoreState` الحقيقي. مولَّد بواسطة `npm run docs:gauge` ومقفل ضد الانحراف في CI.</sub>
|
|
271
330
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
> صفحات كل قاعدة تقع تحت [`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**: لم يُعثر على تعريفات اختبارات |
|
|
280
338
|
|
|
281
|
-
|
|
339
|
+
**كيف تُحسب.** تحدد الخطورة خصمًا أساسيًا (`error −8`، `warning −3`، `info −1`) ويخفّضه مستوى الدليل: E2 يُحتسب كاملًا، وE1 نصفه (مقرّبًا للأسفل)، وE0 لا شيء. يُطبَّع المجموع حسب تعرّض مجموعة الاختبارات، أي الخصومات لكل تعريف اختبار لا لكل ملف. تطبع الطرفية الأرقام المخفّضة نفسها التي استخدمتها الدرجة؛ ولا يوجد نموذج ثانٍ مخفي. التفاصيل: [docs/SCORING.md](docs/SCORING.md) و[دليل الدرجة](https://sergey-bar.github.io/Mjolnir/guide/scoring).
|
|
282
340
|
|
|
283
|
-
|
|
284
|
-
(≥ 10 اكتشافات مصنفة يدويًا لكل منها؛ راجع
|
|
285
|
-
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). الـ21 الأخرى تُشحن على تقدير
|
|
286
|
-
المؤلف. ذيل كل فحص يخبرك كم من القواعد التي _انطلقت_ مقيسة؛ و
|
|
287
|
-
`mjolnir rules --unmeasured` يسرد غير المقيسة؛ وصفحة `mjolnir explain`
|
|
288
|
-
يدقّق عند 95% ولذلك هو في الحجر الصحي. تنمية ذلك العدد هي العمل
|
|
289
|
-
المستمر للمشروع.
|
|
341
|
+
**ما لا تعنيه 100.** لا تعني أن البرنامج صحيح، ولا أن مجموعة الاختبارات كافية، ولا أن المنتج خالٍ من العيوب. تعني شيئًا واحدًا: **لم تُنتج أيٌّ من القواعد التي قيّمها Mjölnir خصمًا في هذا الفحص وضمن نموذج الأدلة هذا.**
|
|
290
342
|
|
|
291
|
-
|
|
343
|
+
<br />
|
|
292
344
|
|
|
293
|
-
|
|
294
|
-
إنذاراتها الكاذبة **المقيس**:
|
|
345
|
+
## نموذج الأدلة
|
|
295
346
|
|
|
296
|
-
|
|
297
|
-
| ------------ | ------------------------------- | :-------------: | :--------: |
|
|
298
|
-
| `core` | ≤ 10% إنذارات مقيسة | ✅ | ✅ |
|
|
299
|
-
| `extended` | ≤ 30% إنذارات مقيسة | ✅ | ✅ |
|
|
300
|
-
| `quarantine` | فوق 30%، أو لم يقس بعد (n < 10) | ❌ | ✅ |
|
|
347
|
+
تحمل كل نتيجة وسمين: مدى تأكد Mjölnir، وإلى أي حد جرى التحقق من النتيجة. هذا هو الفرق بين أداة تبلّغ عن أنماط وأداة يمكنك أن تربط بها قرار الإصدار.
|
|
301
348
|
|
|
302
|
-
|
|
303
|
-
| --------------- | ----------- | ---------------------------------------------------- |
|
|
304
|
-
| TypeScript / JS | AST المترجم | الأوسع والأكثر قياسًا — غالبًا `core`/`extended` |
|
|
305
|
-
| Python / pytest | طبقة regex | واسعة، مدقَّقة على corpus — غالبًا `core`/`extended` |
|
|
306
|
-
| Java | طبقة regex | أحدث — غالبًا `extended`/`quarantine` |
|
|
307
|
-
| C# / .NET | طبقة regex | أحدث — غالبًا `extended`/`quarantine` |
|
|
349
|
+
**مدى التأكد — مستوى الدليل.**
|
|
308
350
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
351
|
+
| المستوى | الاسم | المعنى | الخصم |
|
|
352
|
+
| ------- | --------- | --------------------------------------------- | ----- |
|
|
353
|
+
| **E2** | دليل حتمي | العيب موجود في الشيفرة كما هي مكتوبة | كامل |
|
|
354
|
+
| **E1** | دليل نمطي | تطابق نمط مرتبط ارتباطًا وثيقًا بالعيب | نصف |
|
|
355
|
+
| **E0** | ملاحظة | تستحق المعرفة. ليست ادعاءً بأن شيئًا ما خاطئ. | صفر |
|
|
312
356
|
|
|
313
|
-
|
|
357
|
+
الثقة في الاكتشاف ليست قوة الدليل. قد تكون القاعدة متأكدة من أنها طابقت ما كانت تبحث عنه، ومع ذلك تنظر إلى استدلال تقريبي. نتائج E1 موجودة لتُقرأ ويُحكم عليها، لا لتُطبّق دون تمحيص، وهذا الحد مختوم على النتيجة في الطرفية وفي JSON وفي التسليم إلى الوكيل.
|
|
314
358
|
|
|
315
|
-
|
|
359
|
+
**إلى أي حد جرى التحقق — مستوى الثقة.** معظم النتائج تأتي من قراءة شيفرتك. أعطِ Mjölnir تقرير تشغيل اختبارات حقيقي ويمكنه أن يؤكد أن الشيفرة عملت فعلًا.
|
|
316
360
|
|
|
317
361
|
<p align="center">
|
|
318
|
-
<img src="assets/readme/
|
|
362
|
+
<img src="assets/readme/trust-ladder.svg" alt="سلّم الثقة من L0 إلى L5. تأتي L0 حتى L2 من قراءة الشيفرة؛ وتحتاج L3 حتى L5 إلى تقرير تشغيل حقيقي، ويُشار إلى ذلك بانقطاع في السلّم." width="100%" />
|
|
319
363
|
</p>
|
|
320
364
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
365
|
+
| المستوى | بكلمات بسيطة | ما الذي يتطلبه |
|
|
366
|
+
| ------- | ---------------- | ------------------------------------------- |
|
|
367
|
+
| **L0** | مُلاحَظ | قراءة الشيفرة |
|
|
368
|
+
| **L1** | يبدو أنه المشكلة | قراءة الشيفرة: تطابق نمط |
|
|
369
|
+
| **L2** | مُثبت في الشيفرة | قراءة الشيفرة: العيب بنيوي |
|
|
370
|
+
| **L3** | الملف عمل | تقرير التشغيل يُظهر أن ملف النتيجة نُفّذ |
|
|
371
|
+
| **L4** | الاختبار عمل | تقرير التشغيل يُظهر أن اختبار النتيجة نُفّذ |
|
|
372
|
+
| **L5** | التشغيل يؤكد | نتيجة التشغيل نفسها تؤكد فئة العيب |
|
|
324
373
|
|
|
325
|
-
|
|
326
|
-
الطقم (خصم لكل إعلان اختبار). الخصوم المرجَّحة بالأدلة تعني أن الإشارات
|
|
327
|
-
الضعيفة أرخص. تعرض الطرفية الأرقام المخفَّضة نفسها التي تستخدمها الدرجة —
|
|
328
|
-
لا صندوق أسود. المنهج الكامل: [docs/SCORING.md](docs/SCORING.md).
|
|
374
|
+
يتوقف الفحص الساكن عند L2. وحده تقرير تشغيل حقيقي (Playwright JSON، أو Jest أو Vitest JSON، أو JUnit XML) يمكنه رفع نتيجة إلى L3 أو أعلى، فالنتيجة التي لم تُرَ وهي تعمل لا يمكنها أبدًا أن تدّعي أنها عملت. التعريفات: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
|
|
329
375
|
|
|
330
|
-
|
|
376
|
+
### كم من هذا مقيس
|
|
331
377
|
|
|
332
|
-
|
|
333
|
-
| ------- | ---------------- |
|
|
334
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
335
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
336
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**74 من أصل 79 قاعدة لديها معدل إيجابيات كاذبة مقيس على شيفرة OSS حقيقية** (10 نتائج مصنّفة يدويًا على الأقل لكل منها؛ انظر [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). أما الـ 5 الأخرى فتُطلق بتقدير المؤلف وتقول ذلك، قاعدةً قاعدة، في `mjolnir explain`. يسردها `mjolnir rules --unmeasured`، ويبلّغ تذييل كل فحص عن عدد القواعد المقيسة من بين تلك التي _انطلقت_ فعلًا.
|
|
337
379
|
|
|
338
|
-
|
|
339
|
-
الدرجة:
|
|
380
|
+
تبقى المعدلات علنية حتى عندما تكون سيئة. نتيجة تدقيق QA-TEST-001 (`.only` بقي في commit) سيئة على المستودعات الحقيقية ولذلك يقبع في quarantine. الرقم الحالي لكل قاعدة، بما فيها QA-PW-141، موجود في التدقيق.
|
|
340
381
|
|
|
341
|
-
|
|
342
|
-
| ------- | ------------ | ---------------- | ------------------------------------------------- |
|
|
343
|
-
| E2 | عيب حتمي | خصم كامل | `.only` مودعة — قابلة للإثبات بنيويًّا |
|
|
344
|
-
| E1 | نمط استدلالي | نصف الخصم | `sleep()` أعادته regex — إشارة قوية، ليست برهانًا |
|
|
345
|
-
| E0 | ملاحظة | صفر (إخباري فقط) | يُبلَّغ عنه لكنه لا يبوّت CI أبدًا ولا يخصم |
|
|
382
|
+
### مستويات الثقة بالقواعد
|
|
346
383
|
|
|
347
|
-
|
|
348
|
-
E2 إثبات بنيوي؛ واكتشافات E1 تحذيرات موزونة الموضع، لا براهين رسمية.
|
|
384
|
+
تتبع المستويات معدل الإيجابيات الكاذبة المقيس، لا الرأي:
|
|
349
385
|
|
|
350
|
-
|
|
351
|
-
|
|
386
|
+
| المستوى | FP المقيس | السلوك |
|
|
387
|
+
| -------------- | ------------------------- | ------------------------------------------------------ |
|
|
388
|
+
| **core** | ≤ 10% | التقرير الافتراضي، يمنع الدمج |
|
|
389
|
+
| **extended** | ≤ 30% | التقرير الافتراضي، ثقة أقل |
|
|
390
|
+
| **quarantine** | > 30% أو مُعلن عنه صراحةً | مع `--strict` فقط، محدود عند info، لا يمنع الدمج أبدًا |
|
|
391
|
+
| _غير مقيسة_ | n < 10 | لا يمكن ترقيتها إلى core قبل قياسها |
|
|
352
392
|
|
|
353
|
-
|
|
393
|
+
يمكن لأحزمة FP أن تخفض مستوى القاعدة فقط — لا تُرقى قاعدة من `quarantine` أبدًا إذا أُعلن عنها هناك صراحةً. تبقى القاعدة المُحجرة صراحةً في quarantine بغض النظر عن معدل الإيجابيات الكاذبة المقيس.
|
|
354
394
|
|
|
355
|
-
|
|
395
|
+
الترقية والتخفيض والنضج حسب اللغة: [دورة حياة القواعد](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
356
396
|
|
|
357
|
-
|
|
397
|
+
### لماذا هذا ليس linter
|
|
358
398
|
|
|
359
|
-
|
|
360
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
أدوات linter تخبرك إن كانت الشيفرة تتبع القواعد. Mjölnir يخبرك إن كان يمكن الوثوق بعملية التحقق لديك.
|
|
361
400
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
401
|
+
| | أدوات linter (ESLint، SonarQube) | أدوات التغطية | مراجعة الشيفرة بالذكاء الاصطناعي | **Mjölnir** |
|
|
402
|
+
| ------------------------------------------------------------- | :-------------------------------: | :-----------: | :------------------------------: | :--------------: |
|
|
403
|
+
| يقيّم **نظام التحقق**، لا شيفرة المنتج | لا | لا | لا | نعم |
|
|
404
|
+
| سلامة ملفات workflow في CI (`continue-on-error`، `\|\| true`) | لا | لا | الفرق فقط | نعم |
|
|
405
|
+
| يقيّم متانة locators في Playwright (Selector Health) | لا | لا | لا | نعم |
|
|
406
|
+
| يقرأ بيانات تشغيل حقيقية لأحكام `TRUE-FLAKE` | لا | لا | لا | نعم |
|
|
407
|
+
| ينشر معدل إيجابيات كاذبة مقيسًا لكل قاعدة | لا | لا | لا | نعم |
|
|
408
|
+
| يعلّم الاختبارات التي بلا تأكيدات | نعم\* | لا | أحيانًا | نعم |
|
|
409
|
+
| يلتقط sleep الثابت (`waitForTimeout`، `time.sleep`) | نعم\* | لا | أحيانًا | نعم |
|
|
410
|
+
| حتمي (المدخلات نفسها، المخرجات نفسها) | نعم | نعم | لا | نعم |
|
|
411
|
+
| التكلفة لكل فحص | مجاني | مجاني | رموز (tokens) | **صفر** (محليًا) |
|
|
412
|
+
|
|
413
|
+
<sub>\*تغطيه `eslint-plugin-jest` و`eslint-plugin-playwright` (`expect-expect`، `no-wait-for-timeout`) وقواعد التأكيد الخاصة بـ SonarQube. تصف الأعمدة السلوك الافتراضي للتحقق من مجموعات الاختبار؛ والإضافات والخطط المدفوعة والقواعد المخصصة تغيّر بعض الإجابات. هذا ملخص تموضع، وليس اختبار أداء مقارنًا.</sub>
|
|
365
414
|
|
|
366
|
-
|
|
367
|
-
تبطئ الدرجة — تتحطم مع أي إعادة هيكلة DOM دون إخبارك بأي سلوك ارتدّ.
|
|
415
|
+
استخدم مراجعة الذكاء الاصطناعي أيضًا. فهي تلتقط الفروق الدقيقة والنية وعيوب التصميم التي لا يجدها أي نمط. ويلتقط Mjölnir ما تغفله مراجعة الذكاء الاصطناعي لأنه يبدو مقصودًا: `.only` بقي في commit، ورمز خروج مبتلع، و`continue-on-error` على job اختبار. هذه تحتاج إلى فحص، لا إلى استدلال.
|
|
368
416
|
|
|
369
|
-
|
|
417
|
+
<br />
|
|
370
418
|
|
|
371
|
-
##
|
|
419
|
+
## تحليل تشغيلات الاختبار
|
|
372
420
|
|
|
373
|
-
|
|
374
|
-
تقارير JSON من Playwright وXML من JUnit من أي مشغّل:
|
|
421
|
+
التحليل الساكن يستدل على شيفرة لم تعمل قط. أما تحليل التشغيلات فيقرأ ما حدث فعلًا: Playwright JSON وJest JSON وVitest JSON وJUnit XML من أي أداة تشغيل.
|
|
375
422
|
|
|
376
423
|
```bash
|
|
377
424
|
mjolnir forensics ./test-results/
|
|
378
425
|
```
|
|
379
426
|
|
|
380
427
|
```text
|
|
381
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
382
429
|
|
|
383
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
384
431
|
|
|
@@ -388,275 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
388
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
389
436
|
```
|
|
390
437
|
|
|
391
|
-
الاختبار
|
|
392
|
-
محظوظ. يوسم `TRUE-FLAKE` بغضّ النظر عن علامة النجاح الخضراء النهائية.
|
|
438
|
+
لا يعني `TRUE-FLAKE` أن الاختبار أُعيدت محاولته. بل يعني أن الاختبار **فشل في محاولة واحدة على الأقل ثم انتهى باللون الأخضر**: نجاح بالحظ، يُعلَّم مهما قالت علامة الصح النهائية. يحوّل `mjolnir triage` هذا السجل إلى اقتراح عزل، ويلخّص `mjolnir pw-report` التشغيل. وتقارير التشغيل نفسها هي ما يرفع النتائج إلى مستويات الثقة L3 فما فوق.
|
|
393
439
|
|
|
394
|
-
|
|
440
|
+
<br />
|
|
395
441
|
|
|
396
|
-
##
|
|
442
|
+
## سلامة CI
|
|
397
443
|
|
|
398
|
-
|
|
399
|
-
الثقة بتحقّقك.
|
|
444
|
+
قد ينجح اختبار بينما خط CI المحيط به لا يستطيع أن يفشل. يقرأ Mjölnir ملفات workflow أيضًا: `continue-on-error`، و`|| true`، ورموز خروج لا تُمرَّر أبدًا، وخطوات تنجح دائمًا، وتقارير تُستهلك ولا تُنشأ، وبوابات تُتخطى في الأحداث نفسها التي يجب أن تمنع الدمج. كل نتيجة تسمّي الـ job والخطوة والسطر، وتحمل مستوى دليلها الخاص.
|
|
400
445
|
|
|
401
|
-
|
|
402
|
-
| ---------------------------------------------------- | :----------------: | :-----------: | :--------------: | :---------: |
|
|
403
|
-
| نزاهة أسيرات CI (`continue-on-error`، `\|\| true`) | ❌ | ❌ | نادرًا | ✅ |
|
|
404
|
-
| عبر اللغات (TS، Python، Java، C#) من أداة واحدة | ❌ | ❌ | ❌ | ✅ |
|
|
405
|
-
| يقيّم صمود محدِّدات Playwright (Selector Health) | ❌ | ❌ | نادرًا | ✅ |
|
|
406
|
-
| يميّز الاختبارات بلا تأكيدات حقيقية | ✅ (إضافة)\* | ❌ | أحيانًا | ✅ |
|
|
407
|
-
| يلتقط السبات الصارم (`waitForTimeout`، `time.sleep`) | ✅ (إضافة)\* | ❌ | أحيانًا | ✅ |
|
|
408
|
-
| يجري في ثوانٍ، صفر نداءات شبكة أثناء الفحص | ✅ | ✅ | — | ✅ |
|
|
446
|
+
أنشئ workflow طلبات الدمج، استشاريًا افتراضيًا:
|
|
409
447
|
|
|
410
|
-
|
|
411
|
-
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
412
451
|
|
|
413
|
-
|
|
452
|
+
أو أضف الـ action من Marketplace إلى workflow لديك بالفعل:
|
|
414
453
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
420
460
|
|
|
421
|
-
|
|
422
|
-
بملصقات أحكام.
|
|
461
|
+
ثبّت `@v1` لتتبع الخط الرئيسي، أو وسمًا دقيقًا (`@v0.5.32`) لبوابة قابلة لإعادة الإنتاج. يغطي [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) كلًّا من Marketplace وSmithery وسجلات MCP.
|
|
423
462
|
|
|
424
|
-
|
|
463
|
+
لوضع النتائج في GitHub Code Scanning، ارفع SARIF (يتطلب `security-events: write` على مستوى الـ workflow أو الـ job):
|
|
425
464
|
|
|
426
|
-
|
|
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
|
+
```
|
|
427
473
|
|
|
428
|
-
|
|
429
|
-
في فرق؛ لكنها لا تثبت أن نظام التحقق ككل جدير بالثقة — وهي لا ترى إلا
|
|
430
|
-
الفرق الذي تريه لها.
|
|
474
|
+
على GitLab، يكتب `--format codequality` تقرير Code Quality الذي تقرؤه أداة طلب الدمج وتعليقات الفرق ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). إعداد المحرر وخط CI: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
431
475
|
|
|
432
|
-
|
|
433
|
-
| ----------------------------- | :--------------------------------------: | :-------------------------------: |
|
|
434
|
-
| الكلفة لكل فحص | رموز (تتدرج بحجم الفرق) | **صفر** (محلي، مثبَّت) |
|
|
435
|
-
| يرى الطقم كله + كل إعدادات CI | الفرق الذي تريه فقط | **كل شيء، كل مرة** |
|
|
436
|
-
| حتمي (مدخل واحد → مخرج واحد) | ❌ (غير حتمي) | **✅** |
|
|
437
|
-
| يلتقط أنماطًا راقدة أشهرًا | فقط إن وردت في السياق | **✅** (يفحص كل الملفات) |
|
|
438
|
-
| يتذكر الاكتشافات بين الجولات | ❌ (لا ذاكرة عبر الجلسات) | **✅** (baseline + diff) |
|
|
439
|
-
| يعمل دون استداء بشري | يحتاج PR أو موجهًا | **✅** (خُطّاف CI، يعمل في ثوانٍ) |
|
|
476
|
+
### إسناد النتائج إلى نطاق التغييرات
|
|
440
477
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
و`continue-on-error` على مهمة اختبار. ليست أخطاء تحتاج تفكيرًا؛ بل حقائق
|
|
445
|
-
تحتاج فحصًا.
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
446
481
|
|
|
447
|
-
|
|
482
|
+
تُسند النتائج إلى الأسطر التي أضافها فرعك، مقيسةً مقابل **merge-base**. النطاق هو مجموعة الملفات نفسها التي يكتشفها الفحص الكامل (ملفات spec لـ TS/JS وإعدادات المحوّلات، `test_*.py`، `*Test.java`، `*Tests.cs`، `.github/workflows/*.yml`)، إضافة إلى التغييرات غير المُثبتة وغير المتتبَّعة، لذا يعمل قبل أن تُجري commit. يُحدَّد الأساس بالترتيب `main → master → origin/main → origin/master → origin/HEAD`؛ ويمكنك تجاوزه بـ `--base <ref>`.
|
|
448
483
|
|
|
449
|
-
|
|
484
|
+
عندما يتعذر تحديد merge-base (نسخة ضحلة، أو HEAD منفصل، أو هدف خارج git)، تعود النتائج إلى الإسناد إلى الملف كاملًا **ويقول التقرير ذلك.** فالتراجع الصامت سيكون تمامًا نوع العيب الذي وُجدت هذه الأداة لالتقاطه.
|
|
450
485
|
|
|
451
|
-
|
|
486
|
+
<br />
|
|
452
487
|
|
|
453
|
-
|
|
454
|
-
mjolnir ci install
|
|
455
|
-
```
|
|
488
|
+
## وكلاء الذكاء الاصطناعي
|
|
456
489
|
|
|
457
|
-
|
|
490
|
+
لا قيمة للنتائج إلا إذا تصرّف شيء بناءً عليها.
|
|
458
491
|
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
- uses: github/codeql-action/upload-sarif@v3
|
|
462
|
-
with:
|
|
463
|
-
sarif_file: mjolnir.sarif
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
464
494
|
```
|
|
465
495
|
|
|
466
|
-
|
|
467
|
-
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
496
|
+
**الذكاء الاصطناعي يكتب الإصلاح. Mjölnir يتحقق منه.** يأتي الدليل من إعادة الفحص، لا من تقرير الوكيل نفسه عن نجاحه.
|
|
468
497
|
|
|
469
|
-
|
|
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`) حتى يعيد الوكيل الفحص قبل أن يدّعي أنه انتهى. |
|
|
470
503
|
|
|
471
|
-
|
|
472
|
-
بنقطة دمج `main`. يغطي ملفات الاختبار (`*.spec.*`، `*.test.*`) زائد
|
|
473
|
-
ملفات أسيرات GitHub وإعدادات Playwright في الفرق. عندما يتعذّر فهم
|
|
474
|
-
نقطة الدمج — نسخة سطحية، HEAD منفصل، هدف بلا git، فرع افتراضي مختلف —
|
|
475
|
-
يتدهور بصدق: تعود الاكتشافات إلى الإسناد بملف كامل والتقرير يقول ذلك.
|
|
476
|
-
استبدل المرجع الأساس بـ `--base <ref>`.
|
|
504
|
+
أضفه إلى عميل يأتي مع CLI خاص به:
|
|
477
505
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
Mjölnir صفر إعداد. ملف `mjolnir.config.json` اختياري (أو `.mjolnir.json`)
|
|
483
|
-
في جذر المستودع يضبط الشدة والحجب والنطاق — لا يغيّر دلالات الكشف أبدًا.
|
|
506
|
+
```bash
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
508
|
+
```
|
|
484
509
|
|
|
485
|
-
|
|
486
|
-
| ------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
487
|
-
| `exclude` | `string[]` | أنماط تجاهل إضافية (مجموعة فرعية من gitignore)، فوق الافتراضيات المدمجة |
|
|
488
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | أي شدّات تخرج برمز غير صفري (الافتراضي `error`؛ `advisory` لا يحجب أبدًا) |
|
|
489
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | يعيد ترتيب اكتشافات قاعدة لمستودعك |
|
|
490
|
-
| `ignore` | `IgnoreEntry[]` | يكتم الاكتشافات — **`reason` إلزامي**؛ تنتهي صلاحية المدخلات بعد 90 يومًا (تاريخ `expires` صريح، أو زمن آخر تعديل لملف الإعداد لمن لا يذكره) |
|
|
491
|
-
| `plugins` | `string[]` | حزم قواعد من طرف ثالث (انظر [نموذج الثقة](#نموذج-الثقة)) |
|
|
510
|
+
أو إلى أي عميل يقبل كتلة `mcpServers`:
|
|
492
511
|
|
|
493
512
|
```json
|
|
494
513
|
{
|
|
495
|
-
"
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
"ignore": [
|
|
499
|
-
{
|
|
500
|
-
"ruleId": "QA-TEST-004",
|
|
501
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
502
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
503
|
-
"expires": "2026-12-31"
|
|
504
|
-
}
|
|
505
|
-
]
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
506
517
|
}
|
|
507
518
|
```
|
|
508
519
|
|
|
509
|
-
|
|
510
|
-
بنفس لهجة `exclude`. استخدمه للضجيج الخاص بالجهاز؛ واستخدم `exclude`
|
|
511
|
-
عندما تعود القائمة للتحكم بالإصدارات إلى جانب بقية الإعداد.
|
|
512
|
-
- **تجاوزات سطر الأوامر** — `--strict` (تضمين قواعد الحجر الصحي)،
|
|
513
|
-
`--width <cols>` و`--ascii` / `--no-ascii` (عرض الطرفية)،
|
|
514
|
-
`--tone blunt` (رسائل أقسح)، `--max-duration <sec>` (فحص جزئي محدود).
|
|
515
|
-
- كتم القواعد ودورة إخراجها من الخدمة:
|
|
516
|
-
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md).
|
|
517
|
-
|
|
518
|
-
مدخلات `ignore` تُغذّي أيضًا الأمر المستقل `mjolnir suppressions` الذي
|
|
519
|
-
يسرد ما هو مكتوم الآن ومتى تنتهي صلاحية كل مدخل.
|
|
520
|
-
|
|
521
|
-
---
|
|
522
|
-
|
|
523
|
-
## 📐 رموز الخروج والعقود
|
|
524
|
-
|
|
525
|
-
مجمَّدة — آمنة لبناء منطق CI فوقها:
|
|
526
|
-
|
|
527
|
-
| رمز الخروج | المعنى |
|
|
528
|
-
| ---------- | ---------------------------------------------------------------------- |
|
|
529
|
-
| `0` | نظيف — لا اكتشافات عند البوابة أو فوقها |
|
|
530
|
-
| `1` | اكتشافات عند البوابة أو فوقها |
|
|
531
|
-
| `2` | فحص جزئي (نفدت ميزانية الوقت، ملفات غير قابلة للقراءة) — لا يحجب أبدًا |
|
|
532
|
-
| `10` | خطأ استعمال (راية خاطئة، غياب هدف) |
|
|
533
|
-
| `20` | خطأ داخلي |
|
|
534
|
-
|
|
535
|
-
تقرير JSON/SARIF هو `schemaVersion: 1`. معرّفات القواعد
|
|
536
|
-
(`QA-<FAMILY>-NNN`) لا تتغير بعد الإطلاق ولا تُعاد استخدامها أبدًا.
|
|
537
|
-
|
|
538
|
-
---
|
|
539
|
-
|
|
540
|
-
## نموذج الثقة
|
|
541
|
-
|
|
542
|
-
- **Local-first** — صفر نداءات شبكة أثناء الفحص. قطعًا. صفر قياس عن بُعد.
|
|
543
|
-
- **لا برهان كاذب** — نقول «مجهول» قبل «متحقَّق منه». المستودع الفارغ
|
|
544
|
-
يأخذ `score: null`، لا 100 مزوّرة.
|
|
545
|
-
- **صدق جزئي** — إذا قُطع التحليل قَصِرًا، يقول الناتج ذلك. لا «complete»
|
|
546
|
-
أبدًا حين لا يكون.
|
|
547
|
-
- **جدار الإنذارات الكاذبة** — يعمل الكشف على رؤية كود خالية من
|
|
548
|
-
التعليقات/النصوص (قواعد TypeScript تستخدم AST المترجم): النمط داخل
|
|
549
|
-
تعليق نثري أو نص مثال توثيقي توثيق، لا اكتشاف.
|
|
550
|
-
- **مقيس، لا مُدَّعى** — فقط القواعد ذات معدل إنذارات كاذبة من كود OSS
|
|
551
|
-
حقيقي تُشحن في الطبقات الرئيسية (انظر
|
|
552
|
-
[كم من هذا مقيس](#كم-من-هذا-مقيس))؛ ذيل الفحص و`mjolnir rules --unmeasured`
|
|
553
|
-
يخبرانك أيُّها أي.
|
|
554
|
-
- **الثقة بالإضافات وبوابة التنفيذ** — الإضافات حزم npm معلنة تحت
|
|
555
|
-
`"plugins"`؛ وحدات JS تعيش في `mjolnir-rules/*.mjs`.
|
|
556
|
-
**لا غرفة رمل**: كود الإضافة يجري بكامل صلاحيات Node، النموذج نفسه
|
|
557
|
-
لإضافات ESLint أو Vitest. لهذا فإن تنفيذ الكود **اختياري في كل فحص**:
|
|
558
|
-
مرّر `--enable-plugins` (أو اضبط `MJOLNIR_ENABLE_PLUGINS=1`)، وإلا
|
|
559
|
-
فلن تُحمَّل المصادر — تنبيه صريح على stderr يسرد بالضبط ما تم تخطيه.
|
|
560
|
-
فحص كود غير موثوق لا ينفّذه أبدًا. بيانات القواعد JSON
|
|
561
|
-
(`mjolnir-rules/*.json`) غير متأثرة: تعلن أنماط regex ولا تنفذ أي
|
|
562
|
-
كود بحكم تصميمها. بادئات معرّفات القواعد الأساسية محجوزة
|
|
563
|
-
وتُرفض من الإضافات والقواعد الخارجية منعًا للانتحال.
|
|
564
|
-
- **قواعد خارجية محلية للمساحة** (مجلدية، صفر شبكة) — مجلد
|
|
565
|
-
`mjolnir-rules/` بجوار هدف الفحص يحمّل قواعد مخصصة: ملفات JSON تعلن
|
|
566
|
-
أنماط regex (لا يُنفَّذ كود)، ووحدات `.mjs`/`.js` تصدّر `rules` (ثقة
|
|
567
|
-
Node كاملة، كالإضافات). القواعد الخارجية تحمل البيانات الوصفية للثقة
|
|
568
|
-
نفسها كالأساسية؛ لا يمكنها أبدًا أن تُشحن في الطبقة الأساسية (الأساسية
|
|
569
|
-
تشترط معدل إنذارات مقيسًا من ملف corpus الجانبي — التصريح بـ
|
|
570
|
-
`tier: "core"` يُقصر إلى `extended`)، وتلتزم سقوف الطبقات وتُفحص ضد
|
|
571
|
-
الانحراف: `mjolnir rules --md --external` يعرض الكتالوج من الملفات
|
|
572
|
-
المحمّلة (المصدر `external`)، ومولّد المصفوفة يقبل `--external <root>`.
|
|
573
|
-
|
|
574
|
-
---
|
|
575
|
-
|
|
576
|
-
## 🏗️ المعمارية
|
|
520
|
+
**الحاجز الواقي أهم من الراحة.** كل نتيجة في التسليم تحمل حدّها. يقول **E2** _حتمي: تحقق من الموضع وطبّق الإصلاح_. ويقول **E1** _يتطلب تأكيدًا: الملاحظة وحدها لا تثبت العيب_. الوكيل الذي يصلح E1 دون تمحيص، أو يكتم قاعدة، أو يعدّل قاعدة لرفع الدرجة، يفعل تمامًا ما وُجدت هذه الأداة لالتقاطه، ولذلك يقول التسليم ذلك في الموجِّه، بجوار النتيجة.
|
|
577
521
|
|
|
578
|
-
<
|
|
579
|
-
<summary>فصّل الشجرة</summary>
|
|
522
|
+
<br />
|
|
580
523
|
|
|
581
|
-
|
|
582
|
-
mjolnir/
|
|
583
|
-
├── src/
|
|
584
|
-
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
585
|
-
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
586
|
-
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
587
|
-
│ ├── playwright/ # Selector Health Score engine
|
|
588
|
-
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
589
|
-
│ ├── scope/ # git merge-base changed-scope engine
|
|
590
|
-
│ ├── scorer/ # transparent deduction table + prioritization
|
|
591
|
-
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
592
|
-
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
593
|
-
│ ├── config/ # mjolnir.config.json + suppressions
|
|
594
|
-
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
595
|
-
│ └── commands/ # every subcommand
|
|
596
|
-
└── tests/
|
|
597
|
-
├── fixtures/ # must-fire / must-not-fire per rule
|
|
598
|
-
└── golden/ # frozen score regression locks
|
|
599
|
-
```
|
|
524
|
+
## الثقة والأمان
|
|
600
525
|
|
|
601
|
-
|
|
526
|
+
**محلي أولًا، بلا أي قياس عن بُعد.** لا توجد أي واجهة برمجية قادرة على الاتصال بالشبكة (`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
|
+
### رموز الخروج وعقد الآلة
|
|
602
535
|
|
|
603
|
-
|
|
604
|
-
بلا متغيرات عامة. إضافة بيئة جديدة = مهايئ واحد + قواعده.
|
|
605
|
-
- **TypeScript/Playwright تستخدم AST المترجم** (ts-morph). Python وJava
|
|
606
|
-
وC# تجري على طبقة regex مشتركة مع إخفاء التعليقات/النصوص.
|
|
607
|
-
- طبقة AST من tree-sitter WASM لـ Java وC# موجودة وهي خطوة الدقة التالية —
|
|
608
|
-
لم تُوصَّل بعد إلى خط الفحص المتزامن.
|
|
536
|
+
مجمّدة، حتى تتمكن من بناء منطق CI عليها:
|
|
609
537
|
|
|
610
|
-
|
|
538
|
+
| رمز الخروج | المعنى |
|
|
539
|
+
| ---------- | --------------------------------------------------------------------- |
|
|
540
|
+
| `0` | نظيف: لا نتائج عند مستوى البوابة أو فوقه |
|
|
541
|
+
| `1` | نتائج عند مستوى البوابة أو فوقه |
|
|
542
|
+
| `2` | فحص جزئي (نفدت ميزانية الوقت، ملفات غير مقروءة). لا يمنع الدمج أبدًا. |
|
|
543
|
+
| `10` | خطأ في الاستخدام (خيار غير صالح، هدف مفقود) |
|
|
544
|
+
| `20` | خطأ داخلي |
|
|
611
545
|
|
|
612
|
-
|
|
546
|
+
`2` مختلف عن `0` عمدًا: الفحص الذي لم يكتمل لم "يجد لا شيء". هو ببساطة لم ينتهِ من البحث.
|
|
613
547
|
|
|
614
|
-
|
|
615
|
-
| ------------------------------------------------------ | ----------------------------------------- |
|
|
616
|
-
| [docs/SCORING.md](docs/SCORING.md) | تطبيع الدرجة + ترجيح الأدلة |
|
|
617
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | معدلات الإنذارات الكاذبة المقيسة + المنهج |
|
|
618
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | حالات القواعد، الكتم، الإخراج من الخدمة |
|
|
619
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | ناتج SARIF + إعداد المحرر/CI |
|
|
620
|
-
| [docs/rules/](docs/rules/) | كتالوج مولَّد لكل قاعدة |
|
|
621
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | تجهيز التطوير + مساهَمة العمل |
|
|
622
|
-
| [CHANGELOG.md](CHANGELOG.md) | سجل الإصدارات |
|
|
623
|
-
| [SECURITY.md](SECURITY.md) | الإبلاغ عن الثغرات |
|
|
548
|
+
كل ما تستهلكه الآلة (نتائج أدوات MCP، و`--json`، وSARIF 2.1) يأتي من نتيجة معيارية واحدة وفق مخطط ذي إصدارات **لا يتوسع إلا بالإضافة** (`schemaVersion: 1`، `contractVersion: 1`)، فلا يضطر أي مستهلك إلى إعادة بناء المعنى من نص معروض. انظر [عقد الآلة](docs/machine-contract.md). معرّفات القواعد (`QA-<FAMILY>-NNN`) لا تتغير بعد إطلاقها ولا يُعاد استخدامها أبدًا.
|
|
624
549
|
|
|
625
|
-
|
|
550
|
+
<br />
|
|
626
551
|
|
|
627
|
-
##
|
|
552
|
+
## ما لا يستطيع Mjölnir أن يخبرك به
|
|
628
553
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
554
|
+
- **لا يشغّل اختباراتك.** الفحص النظيف ليس مجموعة اختبارات ناجحة.
|
|
555
|
+
- **لا يستطيع أن يخبرك بأن تأكيدًا ما _خاطئ_.** يبدو `expect(total).toBe(41)` سليمًا. يجد Mjölnir اختبارات _لا يمكن أن تفشل_ وخطوط CI _لا يمكن أن تتحول إلى الأحمر_، لا الاختبارات التي تتحقق من الشيء الخطأ.
|
|
556
|
+
- **لا يثبت صحة منطق العمل.** لا شيء هنا يقول إن منتجك يفعل ما طلبته المتطلبات.
|
|
557
|
+
- **الـ 100 ليست دليلًا على مجموعة اختبارات جيدة.** أما إن كانت مجموعتك تغطي مخاطرك الحقيقية فذلك سؤال مختلف، وهذه الأداة لا تجيب عنه.
|
|
558
|
+
- **5 من أصل 79 قاعدة تُطلق بناءً على تقدير**، لا على معدل مقيس. وكل واحدة منها تقول ذلك في نتيجتها.
|
|
559
|
+
- **E1 ليس E2.** النتائج الاستدلالية تستحق القراءة، لا التطبيق دون تمحيص.
|
|
560
|
+
- **المستودع الفارغ يحصل على `null`، لا على 100 أبدًا.**
|
|
561
|
+
- **الملف المسمى `*.spec.ts` الذي لا يحتوي تعريفات اختبارات لا يُحتسب تغطية.** المستودع الذي لا تحتوي ملفات spec الوحيدة فيه إلا على imports أو أنواع (صفر استدعاءات `it`/`test`) يحصل على `null`، لا على 100.
|
|
632
562
|
|
|
633
|
-
|
|
563
|
+
<br />
|
|
634
564
|
|
|
635
|
-
##
|
|
565
|
+
## التوثيق
|
|
636
566
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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) | معدلات الإيجابيات الكاذبة المقيسة والمنهجية |
|
|
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، ووصفة طلب الدمج، والبوابة |
|
|
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 الخاصة بها عمدًا إلى أن يُكتب اكتشاف حقيقي، لأن الهيكل الفارغ الذي يُطلق هو قاعدة لم يقسها أحد:
|
|
640
592
|
|
|
641
593
|
```bash
|
|
642
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
643
595
|
```
|
|
644
596
|
|
|
645
|
-
|
|
646
|
-
جدار التجهيزات في [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
597
|
+
إعداد بيئة التطوير، وأوامر البوابات الدائمة، وقانونا anti-creep وجدار حماية الـ fixtures موجودة في [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
647
598
|
|
|
648
|
-
|
|
599
|
+
<br />
|
|
649
600
|
|
|
650
601
|
<div align="center">
|
|
651
602
|
|
|
652
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="شغّله على مستودعك." width="100%" />
|
|
653
604
|
|
|
654
605
|
```bash
|
|
655
606
|
npx mjolnir-qa@latest
|
|
656
607
|
```
|
|
657
608
|
|
|
658
|
-
|
|
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
|
+
اسأل إن كانت الأدلة تثبت أنها تستحق الثقة.
|
|
659
615
|
|
|
660
|
-
|
|
616
|
+
<sub>من تطوير [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · برخصة MIT</sub>
|
|
661
617
|
|
|
662
618
|
</div>
|