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.th.md
CHANGED
|
@@ -1,386 +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
|
-
|
|
9
|
-
ความไว้วางใจพังตรงไหน
|
|
7
|
+
Mjölnir ค้นหาเทสต์ที่ไม่มีวันล้มเหลวและไปป์ไลน์ที่ไม่มีวันเป็นสีแดง<br />
|
|
8
|
+
แล้วให้คะแนนว่าผลลัพธ์เชื่อถือได้แค่ไหน พร้อมหลักฐานของทุกคะแนน
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
[](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
|
|
13
|
-
[](LICENSE)
|
|
14
|
-
[](https://nodejs.org)
|
|
15
|
-
|
|
16
|
-
[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) | ไทย | [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) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
10
|
+
<br />
|
|
17
11
|
|
|
18
|
-
|
|
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)
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npx mjolnir-qa@latest
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
[ดูการทำงานจริง](#ดูการทำงานจริง) · [เริ่มต้นอย่างรวดเร็ว](#เริ่มต้นอย่างรวดเร็ว) · [สิ่งที่ตรวจพบ](#สิ่งที่-mjölnir-ตรวจพบ) · [คะแนน](#คะแนนความน่าเชื่อถือ) · [หลักฐาน](#แบบจำลองหลักฐาน) · [นิติวิเคราะห์การรัน](#นิติวิเคราะห์ขณะรัน) · [CI](#ความสมบูรณ์ของ-ci) · [เอเจนต์](#เอเจนต์-ai) · [ความปลอดภัย](#ความเชื่อถือและความปลอดภัย) · [ข้อจำกัด](#สิ่งที่-mjölnir-บอกคุณไม่ได้) · [เอกสาร](#เอกสารประกอบ)
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>อ่านในภาษาอื่น — 22 ภาษา</summary>
|
|
28
|
+
|
|
29
|
+
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | [Español](README.es.md) | [Français](README.fr.md) | [Italiano](README.it.md) | [Dansk](README.da.md) | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | ไทย | [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) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
30
|
+
|
|
31
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
|
|
32
|
+
|
|
33
|
+
<!-- Source hash: 3541b09e8d04 -->
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
[เริ่มเร็ว](#-เริ่มเร็ว) ·
|
|
28
|
-
[มันตรวจอะไร](#-mjölnir-ตรวจอะไร) ·
|
|
29
|
-
[การให้คะแนน](#การให้คะแนนทำงานอย่างไร) ·
|
|
30
|
-
[CI](#-การเชื่อมต่อ-ci) · [การตั้งค่า](#การตั้งค่า) ·
|
|
31
|
-
[เอกสาร](#-เอกสาร)
|
|
35
|
+
</details>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
<br />
|
|
40
|
+
|
|
41
|
+
## เครื่องหมายถูกสีเขียวคือคำกล่าวอ้าง ไม่ใช่ข้อพิสูจน์
|
|
42
|
+
|
|
43
|
+
เครื่องหมายถูกสีเขียวหมายความว่าไปป์ไลน์ไม่ล้มเหลว ไม่ได้หมายความว่าเทสต์ถูกรันจริง หรือว่าเทสต์มีโอกาสล้มเหลวได้ ทุกกรณีต่อไปนี้ผ่านเป็นสีเขียวทั้งสิ้น:
|
|
44
|
+
|
|
45
|
+
- `.only` ที่ถูกคอมมิตไว้ ทำให้รันเทสต์เพียง 3 ตัวแทนที่จะเป็น 900 ตัว
|
|
46
|
+
- `continue-on-error: true` บน job ที่ควรทำหน้าที่เป็นด่านกั้น
|
|
47
|
+
- `|| true` ต่อท้ายคำสั่งรันเทสต์
|
|
48
|
+
- เทสต์ที่ไม่ได้ตรวจสอบอะไรเลย หรือมีเนื้อหาว่างเปล่า
|
|
49
|
+
- ตัวครอบการรันซ้ำที่เปลี่ยนความล้มเหลวจริงให้กลายเป็นการผ่านแบบฟลุก
|
|
50
|
+
- รายงานที่ workflow อัปโหลดแต่ไม่เคยถูกสร้างขึ้นมาจริง
|
|
51
|
+
- sleep แบบตายตัวที่ประคอง race condition เอาไว้
|
|
52
|
+
|
|
53
|
+
ไม่มีข้อใดทำให้ไปป์ไลน์เป็นสีแดง และทุกข้อดูเหมือนตั้งใจเมื่ออยู่ในการรีวิว นั่นคือเหตุผลที่มันรอดมาได้ นี่คือ Mjölnir กำลังอ่านกรณีจริง:
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="assets/readme/scan.svg" alt="CI workflow ของรีโพสาธิต อ่านทีละบรรทัด 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`, การทดสอบว่าง, การใช้ retry ในทางที่ผิด — อยู่ในชั้นกักกัน ทำงานเฉพาะภายใต้ `--strict` และจำกัดที่ความรุนแรง `info`: ตั้งค่าสถานะ แต่ไม่เคยบล็อก การสแกนเริ่มต้น (`npx mjolnir-qa@latest` โดยไม่มี `--strict`) ครอบคลุมเฉพาะกฎหลักและกฎขยาย เพิ่ม `--strict` เมื่อคุณต้องการชั้นที่ปรึกษาด้วย
|
|
62
|
+
|
|
63
|
+
Mjölnir อ่านชุดเทสต์ CI workflow และรายงานจากการรันจริงหากคุณมี มันไม่รันเทสต์ของคุณ ไม่ติดตั้ง dependency และไม่รันโค้ดที่มันสแกน และเมื่อไม่มีหลักฐาน มันจะบอกตรง ๆ แทนที่จะแต่งความมั่นใจขึ้นมา:
|
|
64
|
+
|
|
65
|
+
| สถานการณ์ | สิ่งที่ Mjölnir รายงาน |
|
|
66
|
+
| ------------------------------------------------- | -------------------------------------------------------------- |
|
|
67
|
+
| ไม่พบการประกาศเทสต์ | คะแนน `null` แสดงเป็น **UNKNOWN** ไม่มีวันเป็น 100 ที่แต่งขึ้น |
|
|
68
|
+
| ไม่มี baseline หรือรีวิชันที่เปรียบเทียบได้ | **UNKNOWN** พร้อมระบุเหตุผล ไม่มีวันสมมติเป็น 0 |
|
|
69
|
+
| การสแกนถูกตัดจบกลางคัน (งบเวลา ไฟล์ที่อ่านไม่ได้) | **PARTIAL** รหัสออก `2` ไม่มีวันแสดงว่าสะอาด |
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="assets/readme/how-it-works.svg" alt="Mjölnir ทำงานอย่างไร มันอ่านชุดเทสต์และไปป์ไลน์ CI แบบสถิต และอ่านรายงานจากการรันจริงเมื่อมี มันถ่วงน้ำหนักทุกข้อค้นพบตามระดับหลักฐานและระดับความเชื่อถือ โดยมีเพียงการรันจริงเท่านั้นที่ไปถึง L3 ถึง L5 ได้ แล้วสร้างข้อค้นพบ คะแนนความน่าเชื่อถือ และด่าน CI ที่ใช้รหัสออกซึ่งถูกตรึงไว้ ในลูปของเอเจนต์ AI เขียนการแก้ไข แล้ว Mjölnir สแกนซ้ำเพื่อพิสูจน์" width="880" />
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<sub>จัดทำขึ้นสำหรับหน้านี้และแสดงในขนาด 1:1 สร้างโดย `npm run docs:readme-brand` และถูกล็อกไม่ให้คลาดเคลื่อนใน CI คะแนน จำนวน และ ID ของกฎมาจาก [`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
|
+
## ดูการทำงานจริง
|
|
36
80
|
|
|
37
|
-
|
|
81
|
+
การสแกนจริงของ [`examples/demo-repo`](examples/demo-repo) ซึ่งเป็นชุดเทสต์ Playwright ขนาดเล็กที่มี CI workflow คะแนนของมันหายไปตรงนี้:
|
|
38
82
|
|
|
39
83
|
<p align="center">
|
|
40
|
-
<img src="assets/readme/
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="รายละเอียดการหักคะแนนของ Mjölnir: WORTHINESS 80/100 WORTHY คะแนนแยกตามหมวดหมู่ กล่องการหักคะแนนตามความรุนแรง และรายการ FIX THIS FIRST" width="520" />
|
|
41
85
|
</p>
|
|
42
86
|
|
|
43
|
-
<sub
|
|
44
|
-
เรนเดอร์จาก reporter จริง — ไม่ตัดทอนอะไรเลย สร้างใหม่ด้วย
|
|
45
|
-
`npm run docs:demo`;
|
|
46
|
-
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
-
จะทำให้ CI ล้ม หากสินค้าเองเหลื่อมจากสิ่งที่เครื่องมือพิมพ์</sub>
|
|
87
|
+
<sub>สร้างโดย `npm run docs:hero` จากการสแกนจริง และถูกล็อกไม่ให้คลาดเคลื่อนใน CI รายงาน `--verbose` ฉบับเต็มของการสแกนเดียวกันคือ [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`)</sub>
|
|
48
88
|
|
|
49
|
-
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>ดูวิดีโอ</strong> — การสแกน การแก้ไขที่มันพิมพ์ออกมา และการสแกนซ้ำที่พิสูจน์การแก้ไขนั้น</summary>
|
|
50
91
|
|
|
51
|
-
|
|
52
|
-
Python — สี่ภาษา/ฟอร์แมต ในหนึ่งรอบ
|
|
53
|
-
2. มันพบหลักฐานที่บั่นทอนความไว้วางใจต่อชุดทดสอบ — `continue-on-error`
|
|
54
|
-
ที่ปกปิด job, `|| true` ที่กลืน exit code, hard sleep, selector เปราะ,
|
|
55
|
-
URL staging ฝังตาย, การรอ `networkidle`
|
|
56
|
-
3. มันเปลี่ยนแต่ละเรื่องเป็น finding ที่จับต้องได้ พร้อม rule ID,
|
|
57
|
-
ตำแหน่ง และวิธีแก้ — และเป็นคะแนนเดียวที่คุณ gate PR ได้
|
|
92
|
+
<br />
|
|
58
93
|
|
|
59
|
-
|
|
94
|
+
<p align="center">
|
|
95
|
+
<a href="assets/video/mjolnir-demo.mp4">
|
|
96
|
+
<img src="assets/video/mjolnir-demo-poster.png" alt="เฟรมหนึ่งจากวิดีโอสาธิต: npx mjolnir-qa@latest กำลังสแกนรีโพสาธิตในหน้าต่างเทอร์มินัล" width="900" />
|
|
97
|
+
</a>
|
|
98
|
+
</p>
|
|
60
99
|
|
|
61
|
-
|
|
100
|
+
<sub>เรนเดอร์ทีละเฟรมจากการสแกนจริงด้วย `npm run docs:video` ไม่เคยอัดหน้าจอ เลือกเฟรมเพื่อเปิด [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4)</sub>
|
|
101
|
+
|
|
102
|
+
</details>
|
|
103
|
+
|
|
104
|
+
### ข้อค้นพบหนึ่งข้อแบบใกล้ชิด
|
|
105
|
+
|
|
106
|
+
ทุกข้อค้นพบตอบคำถามสี่ข้อ: อยู่ที่ไหน Mjölnir มั่นใจแค่ไหน กฎนี้ผิดบ่อยแค่ไหน และแก้อย่างไร
|
|
107
|
+
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="ข้อค้นพบแรกของการสแกนสาธิต ตรงตามที่เทอร์มินัลพิมพ์ออกมา พร้อมทำเครื่องหมายสี่ส่วน: ตำแหน่ง ความมั่นใจ ความถี่ที่กฎผิด และการแก้ไข" width="100%" />
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
`mjolnir explain QA-CI-001` พิมพ์ประวัติความน่าเชื่อถือทั้งหมดของกฎ รวมถึงอัตราผลบวกลวงที่วัดได้และระดับที่อัตรานั้นทำให้กฎได้รับ:
|
|
62
113
|
|
|
63
114
|
```text
|
|
64
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
65
116
|
|
|
66
117
|
Severity: error
|
|
67
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
68
120
|
Evidence: E2
|
|
69
|
-
|
|
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
|
|
70
126
|
|
|
71
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
72
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
73
129
|
|
|
74
130
|
WHY IT MATTERS
|
|
75
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
76
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
77
133
|
|
|
78
134
|
HOW TO FIX
|
|
79
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
80
|
-
```
|
|
81
136
|
|
|
82
|
-
|
|
83
|
-
บอกว่าบางอย่างผ่าน ทั้งที่ไม่ได้ผ่าน
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
84
138
|
|
|
85
|
-
|
|
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
|
|
86
146
|
|
|
87
|
-
|
|
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.
|
|
88
150
|
|
|
89
|
-
|
|
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.
|
|
90
154
|
|
|
91
|
-
|
|
92
|
-
npx mjolnir-qa@latest
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
93
156
|
```
|
|
94
157
|
|
|
95
|
-
|
|
96
|
-
|
|
158
|
+
นี่คือหน่วยของคุณค่า: จุดหนึ่งที่ CI รายงานว่าผ่านทั้งที่ไม่ได้ผ่านจริง
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## เริ่มต้นอย่างรวดเร็ว
|
|
97
163
|
|
|
98
164
|
```bash
|
|
99
|
-
npx mjolnir-qa@latest
|
|
165
|
+
npx mjolnir-qa@latest
|
|
100
166
|
```
|
|
101
167
|
|
|
102
|
-
|
|
103
|
-
ส่วนที่เหลือเป็นทางเลือกทั้งหมด
|
|
168
|
+
มันสแกนไดเรกทอรีปัจจุบันและพิมพ์ Trust Report: สิ่งที่พบ เชื่อถือได้แค่ไหน เพราะอะไร และควรทำอะไรต่อ มันออกด้วยรหัส `0` เมื่อไม่พบสิ่งใดที่ระดับด่านหรือสูงกว่า
|
|
104
169
|
|
|
105
|
-
|
|
106
|
-
| ----------------------------------- | ---------------------------------------------------- |
|
|
107
|
-
| `mjolnir` | สแกนทั้ง repo + คะแนนความน่าเชื่อถือ |
|
|
108
|
-
| `mjolnir --scope changed` | เฉพาะสิ่งที่ branch คุณแนะนำ — รูปแบบ CI |
|
|
109
|
-
| `mjolnir ci install` | สร้าง CI workflow แบบที่ปรึกษาสำหรับ PR |
|
|
110
|
-
| `mjolnir explain QA-CI-001` | อะไร / ทำไม / วิธีแก้ + อัตรา FP ที่วัดได้ของกฎเดียว |
|
|
111
|
-
| `mjolnir rules --unmeasured` | กฎที่ทำงานด้วยข้อสมมติ ไม่ใช่การวัด |
|
|
112
|
-
| `mjolnir --json` / `--format sarif` | เครื่องอ่านได้ / GitHub Code Scanning |
|
|
113
|
-
| `mjolnir --strict` | รันกฎ tier quarantine ด้วย (ความเสี่ยง FP สูงกว่า) |
|
|
114
|
-
|
|
115
|
-
<details>
|
|
116
|
-
<summary><strong>เมื่ออะไรบางอย่าง flaky</strong></summary>
|
|
170
|
+
ใน CI ให้สแกนเฉพาะสิ่งที่ branch นำเข้ามา เพื่อไม่ให้ชุดเทสต์เก่าท่วม pull request แรกของคุณ:
|
|
117
171
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| `mjolnir triage ./test-results/` | ข้อเสนอการกักกันจากประวัติการรัน |
|
|
122
|
-
| `mjolnir pw-report ./test-results/` | สรุปการรัน Playwright — retry / flake / ช้าสุด |
|
|
123
|
-
| `mjolnir doctor:playwright` | สแกนลึกเฉพาะ Playwright + Selector Health Score |
|
|
172
|
+
```bash
|
|
173
|
+
npx mjolnir-qa@latest --scope changed
|
|
174
|
+
```
|
|
124
175
|
|
|
125
|
-
|
|
176
|
+
`mjolnir ci install` เขียนสิ่งนี้เป็น GitHub Actions workflow โดยใช้ [action](https://github.com/Sergey-Bar/Mjolnir#readme) ที่ปักไว้กับแท็กหลัก `v1` (หรือใช้ `npx` ธรรมดาด้วย `--no-action`) มันจะอยู่ในโหมดให้คำแนะนำจนกว่าคุณจะตัดสินใจให้มันบล็อก
|
|
177
|
+
|
|
178
|
+
| คำสั่ง | สิ่งที่ทำ |
|
|
179
|
+
| ----------------------------------- | -------------------------------------------------------- |
|
|
180
|
+
| `mjolnir` | Trust Report: คำตัดสิน ความมั่นใจ ขั้นตอนถัดไป |
|
|
181
|
+
| `mjolnir --scope changed` | เฉพาะสิ่งที่ branch ของคุณนำเข้ามา (รูปแบบสำหรับ CI) |
|
|
182
|
+
| `mjolnir ci install` | สร้าง PR 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 (อาร์ติแฟกต์สำหรับวิดเจ็ต MR) |
|
|
190
|
+
| `mjolnir --strict` | รันกฎระดับ quarantine ด้วย (ความเสี่ยง FP สูงกว่า) |
|
|
126
191
|
|
|
127
192
|
<details>
|
|
128
|
-
<summary><strong
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
| `mjolnir
|
|
135
|
-
| `mjolnir
|
|
136
|
-
| `mjolnir
|
|
137
|
-
| `mjolnir
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
142
|
-
| `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>` | สิ่งที่คอมมิตหนึ่งนำเข้ามาและแก้ไขไป |
|
|
207
|
+
| `mjolnir summary` | คำอธิบายประกอบ CI และสรุป step จากรายงาน |
|
|
208
|
+
| `mjolnir pr-comment` | คอมเมนต์ PR ที่จำกัดขอบเขต เป็น 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>` | สร้างโครงของกฎใหม่และ fixture ของมัน |
|
|
217
|
+
| `mjolnir stats` | ตัวนับสะสมในเครื่องของการแก้ไขทั้งหมดที่เคยพบ |
|
|
218
|
+
| `mjolnir badge` | JSON สำหรับ endpoint ของ shields.io และโค้ดตัวอย่าง |
|
|
219
|
+
| `mjolnir --cache` | สแกนซ้ำแบบเพิ่มทีละส่วนผ่านแคชคำตัดสินในเครื่อง |
|
|
220
|
+
| `mjolnir --format mermaid` | แผนภาพสถาปัตยกรรมเทสต์สำหรับคอมเมนต์ PR |
|
|
221
|
+
|
|
222
|
+
`mjolnir help <command>` พิมพ์วิธีใช้ ตัวอย่าง และขั้นตอนถัดไปของทุกคำสั่ง
|
|
143
223
|
|
|
144
224
|
</details>
|
|
145
225
|
|
|
146
|
-
|
|
147
|
-
ต้องใช้ Node.js ≥ 22.18 ทำงานบน Windows, macOS และ Linux
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## 👥 สำหรับใคร?
|
|
152
|
-
|
|
153
|
-
- **QA / SDET** เจ้าของชุด e2e หรือ integration ที่ต้องการหลักฐานว่า
|
|
154
|
-
ชุดทดสอบสมควรได้เครื่องหมายเขียวที่มันผลิตจริง
|
|
155
|
-
- **ทีม Platform / DevEx** ผู้รับผิดชอบความสมบูรณ์ของ CI และ release
|
|
156
|
-
gates — คนที่ใส่ใจว่า `continue-on-error` จะไม่หลอกเปลี่ยน pipeline
|
|
157
|
-
แดงให้เขียวอย่างเงียบ ๆ
|
|
158
|
-
- **ผู้ดูแล OSS** ที่อยากได้เกตตรวจสอบที่ถูก เปิดตลอดเวลา รันได้ทั้ง
|
|
159
|
-
ในเครื่องและใน CI โดยไม่มีการเรียกเครือข่าย
|
|
160
|
-
|
|
161
|
-
---
|
|
226
|
+
ต้องใช้ **Node.js ≥ 22.18** บน Windows, macOS หรือ Linux อยากติดตั้งแบบ global หรือไม่? `npm i -g mjolnir-qa` เวอร์ชันขั้นต่ำนี้มาจากชุดเครื่องมือ build (tsdown กำหนดเป้าหมายไว้ที่เวอร์ชันนี้ และไปป์ไลน์รีลีสทำ smoke test กับเวอร์ชันนี้) dependency ตอนรันไม่ต้องการมากกว่านั้น
|
|
162
227
|
|
|
163
|
-
|
|
228
|
+
<br />
|
|
164
229
|
|
|
165
|
-
|
|
166
|
-
| --- | --------------------------------------------------------------------------------------------------------------- |
|
|
167
|
-
| ⚖️ | **คะแนนความน่าเชื่อถือ** — ตัวเลขเดียว ตารางหักโปร่งใส ไม่มีกล่องดำ |
|
|
168
|
-
| 🎭 | **Selector Health Score** — ให้เกรด locator ของ Playwright คุณ ไม่ใช่แค่อัตราผ่าน |
|
|
169
|
-
| 🔬 | **นิติวิทยาศาสตร์ runtime** — อ่านข้อมูลรันจริงของ Playwright/JUnit เพื่อจับ `TRUE-FLAKE` ไม่ใช่แค่เดาแบบสถิต |
|
|
170
|
-
| 🚨 | **กฎความสมบูรณ์ของ CI** — จับ `continue-on-error`, `\|\| true` และเทคนิคเขียวลวงอื่น ๆ |
|
|
171
|
-
| 🐍 | **ทั้งสี่ Playwright bindings** — TypeScript, Python, Java, C#/.NET — บวก pytest, JUnit/TestNG และ CI workflows |
|
|
172
|
-
| 🔒 | **Local-first** — ศูนย์การเรียกเครือข่ายระหว่างสแกน ศูนย์เทเลเมทรี รันเสร็จในไม่กี่วินาที |
|
|
230
|
+
## สิ่งที่ Mjölnir ตรวจพบ
|
|
173
231
|
|
|
174
|
-
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="ใช้งานได้กับสแตกของคุณ: ภาษา เฟรมเวิร์กเทสต์ และระบบ CI ที่กฎครอบคลุม จากทะเบียนกฎ" width="100%" />
|
|
234
|
+
</p>
|
|
175
235
|
|
|
176
|
-
|
|
177
|
-
fixture ลบของตัวเองจะปล่อยไม่ได้ — นั่นคือกำแพงกัน false positive
|
|
236
|
+
**79 กฎ** ในสี่ตระกูล ได้แก่ สุขอนามัยของเทสต์ คุณภาพของเทสต์ Playwright และความสมบูรณ์ของ CI ครอบคลุม TypeScript และ JavaScript, Python, Java, C# และ YAML ของ GitHub Actions รองรับ Playwright ครบทั้งสี่ binding รวมถึง 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 | คอมมิตเทสต์ที่โฟกัสไว้ (`.only`, `fit`) | error | quarantine |
|
|
243
|
+
| QA-TEST-003 | เทสต์ที่ไม่มี assertion | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | assertion ของ promise ที่ไม่ได้ await | error | quarantine |
|
|
245
|
+
| QA-PW-002 | assertion ของ locator ที่ไม่ได้ await | error | core |
|
|
246
|
+
| QA-PW-004 | selector CSS/XPath ที่เปราะบาง | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | เทสต์ที่ถูกข้าม (`skip`, `xfail` ที่ไม่เข้มงวด) | warning | core |
|
|
248
|
+
| QA-CS-103 | เมธอดเทสต์ที่ไม่มี assertion | 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>ทุกกฎที่กล่าวถึงใน README นี้</strong> ในตารางเดียว</summary>
|
|
254
|
+
|
|
255
|
+
<br />
|
|
256
|
+
|
|
257
|
+
> กฎ `quarantine` รันเฉพาะภายใต้ `--strict` และไม่บล็อกเลย (ถูกจำกัดไว้ที่ info) ความรุนแรงที่แสดงคือค่าที่ผู้เขียนกำหนด
|
|
258
|
+
|
|
259
|
+
| ID | ตระกูล | กฎ | ความรุนแรง | ระดับ |
|
|
260
|
+
| ------------ | ---------- | ---------------------------------------------------------------- | ---------- | ---------- |
|
|
261
|
+
| QA-TEST-001 | สุขอนามัย | คอมมิตเทสต์ที่โฟกัสไว้ (`.only`, `fit`) | error | quarantine |
|
|
262
|
+
| QA-TEST-002 | สุขอนามัย | เทสต์ที่ถูกข้าม จะยกระดับเป็น `error` หากไม่มีเหตุผลที่ติดตามได้ | warning | quarantine |
|
|
263
|
+
| QA-TEST-003 | สุขอนามัย | เทสต์ที่ไม่มี assertion | 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 | คุณภาพ | assertion ที่เป็นจริงเสมอ | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | คุณภาพ | assertion ของ promise ที่ไม่ได้ await | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | คุณภาพ | เทสต์ที่ถูกคอมเมนต์ทิ้งไว้ | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | assertion ของ locator ที่ไม่ได้ await | error | core |
|
|
271
|
+
| QA-PW-003 | Playwright | คอมมิต `page.pause()` / `test.only()` ไว้ | error | core |
|
|
272
|
+
| QA-PW-004 | Playwright | selector 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 | step ที่สำเร็จเสมอปิดบังความล้มเหลว | error | quarantine |
|
|
280
|
+
| QA-CI-009 | CI | รหัสออกไม่ถูกส่งต่อ (`\|` โดยไม่มี pipefail, สายคำสั่ง `;`) | error | extended |
|
|
281
|
+
| QA-CI-010 | CI | เทสต์ถูกข้ามในจุดที่ต้องบล็อก | error | quarantine |
|
|
282
|
+
| QA-PY-002 | Python | เทสต์ที่ถูกข้าม (`skip`, `xfail` ที่ไม่เข้มงวด) | warning | core |
|
|
283
|
+
| QA-PY-003 | Python | ฟังก์ชันเทสต์ที่ไม่มี assertion | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | `time.sleep()` ในเทสต์ | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | assertion ที่เป็นจริงเสมอ | error | quarantine |
|
|
286
|
+
| QA-JV-101 | Java | เทสต์ที่ถูกปิดใช้งาน (`@Disabled`) | warning | core |
|
|
287
|
+
| QA-JV-102 | Java | sleep แบบตายตัว (`Thread.sleep()`) | warning | extended |
|
|
288
|
+
| QA-JV-103 | Java | เมธอดเทสต์ที่ไม่มี assertion | error | extended |
|
|
289
|
+
| QA-JV-105 | Java | sleep แบบตายตัวด้วย `waitForTimeout()` ของ Playwright | warning | core |
|
|
290
|
+
| QA-JV-106 | Java | selector ที่เปราะบางแทน 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# | เมธอดเทสต์ที่ไม่มี assertion | error | core |
|
|
294
|
+
| QA-CS-105 | C# | sleep แบบตายตัวด้วย `WaitForTimeoutAsync()` | warning | extended |
|
|
295
|
+
| QA-CS-106 | C# | selector ที่เปราะบางแทน 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 | assertion ของ locator ที่ไม่ await | error |
|
|
211
|
-
| QA-PW-003 | `page.pause()` / `test.only()` ถูก commit | error |
|
|
212
|
-
| QA-PW-004 | selector CSS/XPath เปราะ | warning |
|
|
213
|
-
| QA-PW-123 | URL สภาพแวดล้อมฝังตาย | 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` กลืน exit code | error |
|
|
224
|
-
| QA-CI-005 | รายงานถูกใช้แต่ไม่เคยถูกสร้าง | error |
|
|
225
|
-
| QA-CI-007 | ครอบ retry รอบการทดสอบ | warning |
|
|
226
|
-
| QA-CI-008 | step สำเร็จเสมอ ปกปิดความล้มเหลว | error |
|
|
227
|
-
| QA-CI-009 | exit code ของทดสอบไม่ถูกส่งต่อ (`\|` ไม่มี pipefail, โซ่ `;`) | error |
|
|
228
|
-
| QA-CI-010 | ข้ามทดสอบในที่ที่ต้องบล็อก (skip-on-PR guards) | 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 | ฟังก์ชันทดสอบไม่มี assertion | error |
|
|
239
|
-
| QA-PY-005 | `time.sleep()` ในการทดสอบ | warning |
|
|
240
|
-
| QA-PY-012 | assertion พรรคพวกตัวเอง | error |
|
|
241
|
-
|
|
242
|
-
กฎ Python รวม 20 ข้อ (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 | hard sleep (`Thread.sleep()`) | warning |
|
|
253
|
-
| QA-JV-103 | วิธีทดสอบไม่มี assertion | error |
|
|
254
|
-
| QA-JV-105 | hard sleep Playwright `waitForTimeout()` | warning |
|
|
255
|
-
| QA-JV-106 | selector เปราะแทน role locator | warning |
|
|
319
|
+
สิ่งนี้วัด **ความทนทาน ไม่ใช่ความถูกต้อง** `.btn.btn-primary > div:nth-child(2)` ผ่านในวันนี้ และจะผ่านต่อไปจนกว่าจะมีคนแตะ markup คะแนนต่ำไม่เคยอ้างว่าเทสต์พัง เพียงบอกว่ามันพึ่งพา markup ที่ไม่มีใครสัญญาว่าจะคงไว้
|
|
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 | hard sleep (`Thread.Sleep` / `Task.Delay`) | warning |
|
|
266
|
-
| QA-CS-103 | วิธีทดสอบไม่มี assertion | error |
|
|
267
|
-
| QA-CS-105 | hard sleep `WaitForTimeoutAsync()` | warning |
|
|
268
|
-
| QA-CS-106 | selector เปราะแทน role locator | warning |
|
|
325
|
+
<p align="center">
|
|
326
|
+
<img src="assets/readme/score-gauge.svg" alt="สเกลความน่าเชื่อถือจาก 0 ถึง 100 พร้อมตัวชี้ที่กวาดผ่านทุกคะแนน: UNWORTHY ต่ำกว่า 50, NEEDS WORK ตั้งแต่ 50 ถึง 79, WORTHY ตั้งแต่ 80 ถึง 99, FORGED ที่ 100" width="720" />
|
|
327
|
+
</p>
|
|
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 findings ที่จัดหมวดด้วยมือต่อกฎ; ดู
|
|
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
|
-
positive **ที่วัดได้**:
|
|
345
|
+
## แบบจำลองหลักฐาน
|
|
295
346
|
|
|
296
|
-
|
|
297
|
-
| ------------ | ----------------------------------- | :------: | :--------: |
|
|
298
|
-
| `core` | ≤ 10 % FP ที่วัดได้ | ✅ | ✅ |
|
|
299
|
-
| `extended` | ≤ 30 % FP ที่วัดได้ | ✅ | ✅ |
|
|
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
|
-
exposure ของชุดทดสอบ (การหักต่อการประกาศทดสอบ) การหักที่ถ่วงน้ำหนักด้วย
|
|
327
|
-
หลักฐาน หมายความว่าสัญญาณอ่อนแพงกว่า แสดงผลใน terminal ใช้ตัวเลขที่
|
|
328
|
-
ลดแล้วชุดเดียวกับที่คะแนนใช้ — ไม่มีกล่องดำ วิธีเต็ม:
|
|
329
|
-
[docs/SCORING.md](docs/SCORING.md)
|
|
374
|
+
การสแกนแบบสถิตหยุดที่ L2 มีเพียงรายงานการรันจริง (Playwright JSON, Jest หรือ Vitest JSON, JUnit XML) เท่านั้นที่ยกข้อค้นพบขึ้นไปถึง L3 หรือสูงกว่าได้ ดังนั้นข้อค้นพบที่ไม่เคยถูกเห็นว่ารันจริงจะอ้างไม่ได้เลยว่ามันถูกรัน นิยาม: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md)
|
|
330
375
|
|
|
331
|
-
|
|
376
|
+
### มีการวัดไปมากแค่ไหน
|
|
332
377
|
|
|
333
|
-
|
|
334
|
-
| ------- | ---------------- |
|
|
335
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
336
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
337
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**74 จาก 79 กฎมีอัตราผลบวกลวงที่วัดกับโค้ด OSS จริง** (อย่างน้อย 10 ข้อค้นพบที่จัดประเภทด้วยมือต่อกฎ ดู [docs/FP-AUDIT.md](docs/FP-AUDIT.md)) อีก 5 กฎปล่อยออกมาด้วยค่าประมาณของผู้เขียนและบอกไว้ชัดเจนทีละกฎใน `mjolnir explain` `mjolnir rules --unmeasured` แสดงรายการกฎเหล่านั้น และท้ายการสแกนทุกครั้งจะรายงานว่ามีกฎกี่ข้อในบรรดาที่ _ทำงานจริง_ ที่ผ่านการวัดแล้ว
|
|
338
379
|
|
|
339
|
-
|
|
340
|
-
ในคะแนน:
|
|
380
|
+
อัตราต่าง ๆ ยังคงเปิดเผยแม้จะแย่ QA-TEST-001 (`.only` ที่ถูกคอมมิต) ได้ผลตรวจสอบไม่ดีบนรีโพจริงจึงถูกจัดไว้ใน quarantine ตัวเลขล่าสุดของทุกกฎ รวมถึง QA-PW-141 อยู่ในผลการตรวจสอบ
|
|
341
381
|
|
|
342
|
-
|
|
343
|
-
| ----- | --------------------- | --------------------- | ----------------------------------------------------- |
|
|
344
|
-
| E2 | ข้อบกพร่องเชิงกำหนด | หักเต็มจำนวน | commit `.only` — พิสูจน์เชิงโครงสร้างได้ |
|
|
345
|
-
| E1 | รูปแบบเชิงเฮิร์ริสติก | หักครึ่งหนึ่ง | `sleep()` ที่ regex เจอ — สัญญาณแข็งแรง ไม่ใช่หลักฐาน |
|
|
346
|
-
| E0 | การสังเกต | ศูนย์ (info เท่านั้น) | รายงานแต่ไม่ gate CI และไม่หักเลย |
|
|
382
|
+
### ระดับความเชื่อถือของกฎ
|
|
347
383
|
|
|
348
|
-
|
|
349
|
-
E2 คือหลักฐานเชิงโครงสร้าง; finding E1 คือคำเตือนที่วางตำแหน่งถูกต้อง
|
|
350
|
-
ไม่ใช่หลักฐานทางการ
|
|
384
|
+
ระดับเป็นไปตามอัตราผลบวกลวงที่วัดได้ ไม่ใช่ความเห็น:
|
|
351
385
|
|
|
352
|
-
|
|
353
|
-
|
|
386
|
+
| ระดับ | FP ที่วัดได้ | พฤติกรรม |
|
|
387
|
+
| -------------- | ------------------------------ | --------------------------------------------- |
|
|
388
|
+
| **core** | ≤ 10% | รายงานค่าเริ่มต้น บล็อกได้ |
|
|
389
|
+
| **extended** | ≤ 30% | รายงานค่าเริ่มต้น ความมั่นใจต่ำกว่า |
|
|
390
|
+
| **quarantine** | > 30% หรือประกาศไว้อย่างชัดเจน | เฉพาะ `--strict` จำกัดไว้ที่ info ไม่บล็อกเลย |
|
|
391
|
+
| _ยังไม่ได้วัด_ | n < 10 | เลื่อนขึ้นเป็น core ไม่ได้จนกว่าจะวัด |
|
|
354
392
|
|
|
355
|
-
|
|
393
|
+
ช่วง FP สามารถลดระดับ tier ได้เท่านั้น — จะไม่เลื่อนระดับกฎออกจาก `quarantine` หากกฎนั้นถูกประกาศไว้ที่นั่นอย่างชัดเจน กฎที่ถูก quarantined อย่างชัดเจนจะยังคงอยู่ใน quarantine โดยไม่คำนึงถึงอัตรา FP ที่วัดได้
|
|
356
394
|
|
|
357
|
-
|
|
395
|
+
การเลื่อนระดับ การลดระดับ และความพร้อมรายภาษา: [วงจรชีวิตของกฎ](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle)
|
|
358
396
|
|
|
359
|
-
|
|
397
|
+
### ทำไมนี่จึงไม่ใช่ linter
|
|
360
398
|
|
|
361
|
-
|
|
362
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
Linter บอกคุณว่าโค้ดทำตามกฎหรือไม่ Mjölnir บอกคุณว่าการตรวจสอบของคุณเชื่อถือได้หรือไม่
|
|
363
400
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
401
|
+
| | Linter (ESLint, SonarQube) | เครื่องมือวัด coverage | รีวิวโค้ดด้วย AI | **Mjölnir** |
|
|
402
|
+
| ------------------------------------------------------------- | :------------------------: | :--------------------: | :--------------: | :-------------------: |
|
|
403
|
+
| ให้คะแนน **ระบบการตรวจสอบ** ไม่ใช่โค้ดผลิตภัณฑ์ | ไม่ | ไม่ | ไม่ | ใช่ |
|
|
404
|
+
| ความสมบูรณ์ของ CI workflow (`continue-on-error`, `\|\| true`) | ไม่ | ไม่ | เฉพาะ diff | ใช่ |
|
|
405
|
+
| ให้คะแนนความทนทานของ locator ใน Playwright (Selector Health) | ไม่ | ไม่ | ไม่ | ใช่ |
|
|
406
|
+
| อ่านข้อมูลการรันจริงเพื่อตัดสิน `TRUE-FLAKE` | ไม่ | ไม่ | ไม่ | ใช่ |
|
|
407
|
+
| เผยแพร่อัตราผลบวกลวงที่วัดได้ของแต่ละกฎ | ไม่ | ไม่ | ไม่ | ใช่ |
|
|
408
|
+
| ทำเครื่องหมายเทสต์ที่ไม่มี assertion | ใช่\* | ไม่ | บางครั้ง | ใช่ |
|
|
409
|
+
| จับ sleep แบบตายตัว (`waitForTimeout`, `time.sleep`) | ใช่\* | ไม่ | บางครั้ง | ใช่ |
|
|
410
|
+
| กำหนดแน่นอน (อินพุตเดียวกัน เอาต์พุตเดียวกัน) | ใช่ | ใช่ | ไม่ | ใช่ |
|
|
411
|
+
| ต้นทุนต่อการสแกน | ฟรี | ฟรี | โทเค็น | **ศูนย์** (ในเครื่อง) |
|
|
367
412
|
|
|
368
|
-
|
|
369
|
-
มันแตกทุกครั้งที่ refactor DOM โดยไม่บอกว่าพฤติกรรมใดถดถอย
|
|
413
|
+
<sub>\*ครอบคลุมโดย `eslint-plugin-jest` และ `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) และโดยกฎ assertion ของ SonarQube เอง คอลัมน์ต่าง ๆ อธิบายพฤติกรรมเริ่มต้นสำหรับการตรวจสอบชุดเทสต์ ปลั๊กอิน แพ็กเกจแบบเสียเงิน และกฎที่กำหนดเองจะเปลี่ยนบางคำตอบ นี่เป็นบทสรุปการวางตำแหน่ง ไม่ใช่ benchmark</sub>
|
|
370
414
|
|
|
371
|
-
|
|
415
|
+
ใช้การรีวิวด้วย AI ด้วย มันจับรายละเอียดปลีกย่อย เจตนา และข้อบกพร่องด้านการออกแบบที่ไม่มีรูปแบบใดหาเจอ ส่วน Mjölnir จับสิ่งที่การรีวิวด้วย AI มองข้ามเพราะดูเหมือนตั้งใจ: `.only` ที่ถูกคอมมิต รหัสออกที่ถูกกลืน `continue-on-error` บน job เทสต์ สิ่งเหล่านี้ต้องการการสแกน ไม่ใช่การใช้เหตุผล
|
|
372
416
|
|
|
373
|
-
|
|
417
|
+
<br />
|
|
374
418
|
|
|
375
|
-
|
|
376
|
-
|
|
419
|
+
## นิติวิเคราะห์ขณะรัน
|
|
420
|
+
|
|
421
|
+
การวิเคราะห์แบบสถิตให้เหตุผลเกี่ยวกับโค้ดที่ไม่เคยรัน นิติวิเคราะห์อ่านสิ่งที่เกิดขึ้นจริง: Playwright JSON, Jest JSON, Vitest JSON และ JUnit XML จาก runner ใดก็ได้
|
|
377
422
|
|
|
378
423
|
```bash
|
|
379
424
|
mjolnir forensics ./test-results/
|
|
380
425
|
```
|
|
381
426
|
|
|
382
427
|
```text
|
|
383
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
384
429
|
|
|
385
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
386
431
|
|
|
@@ -390,279 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
390
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
391
436
|
```
|
|
392
437
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
438
|
+
`TRUE-FLAKE` ไม่ได้หมายความว่าเทสต์ถูกรันซ้ำ แต่หมายความว่าเทสต์ **ล้มเหลวอย่างน้อยหนึ่งครั้งแล้วจบลงเป็นสีเขียว** คือการผ่านแบบฟลุก ซึ่งจะถูกทำเครื่องหมายไม่ว่าเครื่องหมายถูกสุดท้ายจะบอกอะไร `mjolnir triage` เปลี่ยนประวัตินั้นเป็นข้อเสนอให้กักกัน และ `mjolnir pw-report` สรุปการรัน รายงานการรันชุดเดียวกันนี้คือสิ่งที่ยกข้อค้นพบขึ้นสู่ระดับความเชื่อถือ L3 ขึ้นไป
|
|
439
|
+
|
|
440
|
+
<br />
|
|
396
441
|
|
|
397
|
-
|
|
442
|
+
## ความสมบูรณ์ของ CI
|
|
443
|
+
|
|
444
|
+
เทสต์หนึ่งอาจผ่าน ขณะที่ไปป์ไลน์รอบตัวมันไม่มีทางล้มเหลวได้ Mjölnir อ่าน workflow ด้วย: `continue-on-error`, `|| true` รหัสออกที่ไม่เคยถูกส่งต่อ step ที่สำเร็จเสมอ รายงานที่ถูกใช้แต่ไม่เคยถูกสร้าง และด่านที่ถูกข้ามในเหตุการณ์ที่ควรบล็อก แต่ละข้อค้นพบระบุ job, step และบรรทัด พร้อมระดับหลักฐานของตัวเอง
|
|
445
|
+
|
|
446
|
+
สร้าง PR workflow ซึ่งเป็นแบบให้คำแนะนำโดยค่าเริ่มต้น:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
หรือเพิ่ม action จาก Marketplace ลงใน workflow ที่คุณมีอยู่แล้ว:
|
|
453
|
+
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
398
460
|
|
|
399
|
-
|
|
461
|
+
ปัก `@v1` เพื่อติดตามสายเวอร์ชันหลัก หรือปักแท็กที่แน่นอน (`@v0.5.32`) เพื่อด่านที่ทำซ้ำได้ [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) ครอบคลุม Marketplace, Smithery และทะเบียน MCP
|
|
400
462
|
|
|
401
|
-
|
|
402
|
-
น่าเชื่อถือหรือไม่
|
|
463
|
+
หากต้องการส่งข้อค้นพบเข้า GitHub Code Scanning ให้อัปโหลด SARIF (ต้องมี `security-events: write` ที่ระดับ workflow หรือ job):
|
|
403
464
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
+
```
|
|
412
473
|
|
|
413
|
-
|
|
414
|
-
(`expect-expect`, `no-wait-for-timeout`) ครอบคลุมสิ่งเหล่านี้ให้ framework
|
|
415
|
-
ตามลัพธ์ของมัน
|
|
474
|
+
บน GitLab `--format codequality` เขียนรายงาน Code Quality ที่วิดเจ็ต MR และคำอธิบายประกอบ diff อ่าน ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)) การตั้งค่าเอดิเตอร์และไปป์ไลน์: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md)
|
|
416
475
|
|
|
417
|
-
|
|
476
|
+
### การระบุที่มาในขอบเขตที่เปลี่ยนแปลง
|
|
418
477
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
| รายงาน triage ความไม่นิ่งจากประวัติการรัน | ❌ | ✅ | ✅ |
|
|
423
|
-
| เชื่อมกับคะแนนความน่าเชื่อถือแบบสถิต | ❌ | ❌ | ✅ |
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
424
481
|
|
|
425
|
-
|
|
426
|
-
ยืนเดี่ยวพร้อมป้ายคำพิพากษา
|
|
482
|
+
ข้อค้นพบถูกระบุไปยังบรรทัดที่ branch ของคุณเพิ่มเข้ามา โดยวัดเทียบกับ **merge-base** ขอบเขตคือชุดไฟล์เดียวกับที่การสแกนเต็มค้นพบ (spec ของ TS/JS และการตั้งค่า adapter, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`) รวมกับการเปลี่ยนแปลงที่ยังไม่คอมมิตและที่ไม่ได้ติดตาม จึงใช้ได้ตั้งแต่ก่อนคอมมิต ฐานถูกหาตามลำดับ `main → master → origin/main → origin/master → origin/HEAD` และแทนที่ได้ด้วย `--base <ref>`
|
|
427
483
|
|
|
428
|
-
|
|
484
|
+
เมื่อหา merge-base ไม่ได้ (shallow clone, detached HEAD, เป้าหมายอยู่นอก git) ข้อค้นพบจะถอยกลับไปใช้การระบุที่มาทั้งไฟล์ **และรายงานจะบอกไว้** การถอยกลับแบบเงียบ ๆ ก็คือข้อบกพร่องประเภทเดียวกับที่เครื่องมือนี้มีไว้จับ
|
|
429
485
|
|
|
430
|
-
|
|
486
|
+
<br />
|
|
431
487
|
|
|
432
|
-
|
|
433
|
-
diff ได้ แต่มันไม่พิสูจน์ว่าระบบตรวจสอบทั้งหมดน่าไว้วางใจ — และมันเห็น
|
|
434
|
-
แค่ diff ที่คุณให้ดู
|
|
488
|
+
## เอเจนต์ AI
|
|
435
489
|
|
|
436
|
-
|
|
437
|
-
| ------------------------------------------- | :--------------------------: | :------------------------------------: |
|
|
438
|
-
| ต้นทุนต่อการสแกน | Tokens (ขยายตามขนาด diff) | **ศูนย์** (ทำงานในเครื่อง ติดตั้งแล้ว) |
|
|
439
|
-
| เห็นทั้งชุดทดสอบ + ทุก config CI | เฉพาะ PR diff ที่คุณให้ดู | **ทุกอย่าง ทุกครั้ง** |
|
|
440
|
-
| กำหนดตาย (input เดียวกัน → output เดียวกัน) | ❌ (ไม่กำหนดตาย) | **✅** |
|
|
441
|
-
| จับรูปแบบที่หลับมาหลายเดือน | เฉพาะถ้าอยู่ในบริบท | **✅** (สแกนทุกไฟล์) |
|
|
442
|
-
| จำ finding ข้ามการรัน | ❌ (ไม่มีความจำข้ามเซสชัน) | **✅** (baseline + diff) |
|
|
443
|
-
| รันโดยไม่ต้องมีคนสั่ง | ต้องมี PR หรือ prompt | **✅** (hook CI, รันในไม่กี่วินาที) |
|
|
490
|
+
ข้อค้นพบจะมีค่าก็ต่อเมื่อมีสิ่งใดลงมือทำตามมัน
|
|
444
491
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
`continue-on-error` บน job ทดสอบ นี่ไม่ใช่บั๊กที่ต้องใช้การใคร่ครวญ;
|
|
449
|
-
นี่คือข้อเท็จจริงที่ต้องใช้การสแกน
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
494
|
+
```
|
|
450
495
|
|
|
451
|
-
|
|
496
|
+
**AI เขียนการแก้ไข Mjölnir ตรวจสอบมัน** ข้อพิสูจน์มาจากการสแกนซ้ำ ไม่ใช่จากรายงานความสำเร็จของเอเจนต์เอง
|
|
452
497
|
|
|
453
|
-
|
|
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`) เพื่อให้เอเจนต์สแกนซ้ำก่อนจะบอกว่าทำเสร็จแล้ว |
|
|
454
503
|
|
|
455
|
-
|
|
504
|
+
เพิ่มลงในไคลเอนต์ที่มี CLI ของตัวเอง:
|
|
456
505
|
|
|
457
506
|
```bash
|
|
458
|
-
mjolnir
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
459
508
|
```
|
|
460
509
|
|
|
461
|
-
|
|
510
|
+
หรือในไคลเอนต์ใดก็ได้ที่รับบล็อก `mcpServers`:
|
|
462
511
|
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
512
|
+
```json
|
|
513
|
+
{
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
517
|
+
}
|
|
468
518
|
```
|
|
469
519
|
|
|
470
|
-
|
|
471
|
-
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md)
|
|
520
|
+
**ราวกันตกสำคัญกว่าความสะดวก** ทุกข้อค้นพบในการส่งต่อมีขอบเขตของตัวเอง **E2** บอกว่า _กำหนดแน่นอน: ตรวจสอบตำแหน่งแล้วใช้การแก้ไข_ **E1** บอกว่า _ต้องยืนยัน: ข้อสังเกตเพียงอย่างเดียวไม่ได้พิสูจน์ข้อบกพร่อง_ เอเจนต์ที่แก้ E1 อย่างไม่ไตร่ตรอง ระงับกฎ หรือแก้ไขกฎเพื่อดันคะแนน กำลังทำสิ่งที่เครื่องมือนี้มีไว้จับพอดี ดังนั้นการส่งต่อจึงบอกไว้ใน prompt ข้างข้อค้นพบนั้นเลย
|
|
472
521
|
|
|
473
|
-
|
|
522
|
+
<br />
|
|
474
523
|
|
|
475
|
-
|
|
476
|
-
merge-base กับ `main` ครอบคลุมไฟล์ทดสอบ (`*.spec.*`, `*.test.*`) บวก
|
|
477
|
-
ไฟล์ GitHub workflow และ config Playwright ใน diff เมื่อ merge-base
|
|
478
|
-
หาค่าไม่ได้ — shallow clone, detached HEAD, เป้าหมายไม่ใช่ git,
|
|
479
|
-
default branch ต่างกัน — มันลดรูปอย่างซื่อสัตย์: finding กลับไปผูก
|
|
480
|
-
ทั้งไฟล์ และรายงานก็บอก แทนที่ base ref ได้ด้วย `--base <ref>`
|
|
524
|
+
## ความเชื่อถือและความปลอดภัย
|
|
481
525
|
|
|
482
|
-
|
|
526
|
+
**ในเครื่องเป็นหลัก ไม่มีการเก็บข้อมูลการใช้งาน** ไม่มี API ที่เชื่อมต่อเครือข่ายได้ (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) อยู่ที่ใดใน `src/` และ [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) จะทำให้ build ล้มเหลวหากมีสักตัวปรากฏขึ้น มันยังห้าม `eval` และ `new Function` ด้วย การสแกนโค้ดที่ไม่น่าเชื่อถือจะไม่รันโค้ดนั้นเลย: การวิเคราะห์แบบสถิตอ่านข้อความซอร์ส และนิติวิเคราะห์แยกวิเคราะห์ไฟล์รายงานที่มีอยู่บนดิสก์แล้ว
|
|
483
527
|
|
|
484
|
-
|
|
528
|
+
ข้อควรทราบสองข้อ: `npx` เองดาวน์โหลดแพ็กเกจก่อนที่อะไรจะรัน และการรับประกันนี้ครอบคลุม `src/` ไม่รวมปลั๊กอินจากบุคคลที่สาม
|
|
485
529
|
|
|
486
|
-
|
|
487
|
-
ทางเลือกที่ราก repo ปรับ severity, gating และ scope — ไม่เคยเปลี่ยน
|
|
488
|
-
ความหมายการตรวจจับ
|
|
530
|
+
**ปลั๊กอินไม่ได้รันใน sandbox** ปลั๊กอิน JS (`mjolnir-rules/*.mjs` หรือแพ็กเกจ npm ที่ระบุไว้ใต้ `"plugins"`) รันด้วยสิทธิ์ Node เต็มรูปแบบ ซึ่งเป็นแบบจำลองความเชื่อถือเดียวกับปลั๊กอินของ ESLint หรือ Vitest การโหลดปลั๊กอินต้องเลือกเปิดเอง **ในทุกการสแกน**: หากไม่มี `--enable-plugins` (หรือ `MJOLNIR_ENABLE_PLUGINS=1`) ซอร์สของปลั๊กอินจะไม่ถูกโหลดเลย และประกาศบน stderr จะแสดงรายการสิ่งที่ถูกข้าม manifest ของกฎที่เป็น JSON ไม่รันโค้ดใด ๆ และคำนำหน้า ID ของกฎ core ถูกสงวนไว้ เพื่อไม่ให้ปลั๊กอินปลอมตัวเป็นกฎเหล่านั้นได้ รายงานช่องโหว่ผ่าน [SECURITY.md](SECURITY.md)
|
|
489
531
|
|
|
490
|
-
|
|
491
|
-
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
492
|
-
| `exclude` | `string[]` | glob ignore เพิ่มเติม (ส่วนย่อยของ gitignore) บนค่าดีฟอลต์ที่มีให้ |
|
|
493
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | ความรุนแรงระดับใดที่ออกด้วยเลขไม่ใช่ศูนย์ (ดีฟอลต์ `error`; `advisory` ไม่เคยบล็อก) |
|
|
494
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | จัดลำดับ finding ของกฎใหม่สำหรับ repo ของคุณ |
|
|
495
|
-
| `ignore` | `IgnoreEntry[]` | กด finding — **`reason` จำเป็น**; รายการหมดอายุใน 90 วัน (วันที่ `expires` ชัดเจน หรือเวลาแก้ไขล่าสุดของไฟล์ config สำหรับรายการที่ไม่ระบุ) |
|
|
496
|
-
| `plugins` | `string[]` | แพ็กเกจกฎบุคคลที่สาม (ดู [โมเดลความไว้วางใจ](#โมเดลความไว้วางใจ)) |
|
|
532
|
+
**มันรันกับตัวเอง** เอนจินความเชื่อถือในการตรวจสอบจะไม่มีความน่าเชื่อถือเลย หากตัวมันเองตรวจสอบไม่ได้ ทุกการรัน CI สแกนรีโพนี้ด้วย build ที่การรันเดียวกันนั้นสร้างขึ้น ด่านจะล้มเหลวเมื่อพบข้อค้นพบระดับ error ใด ๆ และเมื่อการสแกนเป็นแบบ **บางส่วน** หรือมี **กฎที่พัง** เพราะการสแกนตัวเองที่ถูกตัดจบและไม่รายงานอะไรเลย ก็คือสีเขียวปลอมที่โปรเจกต์นี้มีไว้จับ `mjolnir doctor` ตรวจสอบฐานกฎซ้ำในการรันเดียวกัน (ไฟร์วอลล์ fixture ความซื่อตรงของระดับ เพดานของระดับ core) และการตรวจที่ได้ผล INCONCLUSIVE จะล้มเหลวเหมือนกับการตรวจที่ล้มเหลวทุกประการ รายงานทั้งสองถูกอัปโหลดเป็นอาร์ติแฟกต์ของ build
|
|
497
533
|
|
|
498
|
-
|
|
499
|
-
{
|
|
500
|
-
"gate": "error",
|
|
501
|
-
"exclude": ["legacy/**"],
|
|
502
|
-
"severityOverrides": { "QA-PW-141": "warning" },
|
|
503
|
-
"ignore": [
|
|
504
|
-
{
|
|
505
|
-
"ruleId": "QA-TEST-004",
|
|
506
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
507
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
508
|
-
"expires": "2026-12-31"
|
|
509
|
-
}
|
|
510
|
-
]
|
|
511
|
-
}
|
|
512
|
-
```
|
|
534
|
+
### รหัสออกและสัญญาสำหรับเครื่อง
|
|
513
535
|
|
|
514
|
-
|
|
515
|
-
ภาษาเดียวกับ `exclude` ใช้มันสำหรับสัญญาณรบกวนเฉพาะเครื่อง; ใช้
|
|
516
|
-
`exclude` เมื่อรายการควรอยู่ใน version control ร่วมกับ config ที่เหลือ
|
|
517
|
-
- **CLI overrides** — `--strict` (รวมกฎกักกัน), `--width <cols>` และ
|
|
518
|
-
`--ascii` / `--no-ascii` (เรนเดอร์เทอร์มินัล), `--tone blunt`
|
|
519
|
-
(ข้อความตรงขึ้น), `--max-duration <sec>` (สแกนบางส่วนที่จำกัดเวลา)
|
|
520
|
-
- การกดกฎและวงจรชีวิตการเลิกใช้: [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md)
|
|
521
|
-
|
|
522
|
-
รายการ `ignore` ยังหล่อเลี้ยงคำสั่ง `mjolnir suppressions` แบบเดี่ยว
|
|
523
|
-
ซึ่งแสดงสิ่งที่ถูกกดอยู่ และเมื่อใดรายการแต่ละรายการหมดอายุ
|
|
524
|
-
|
|
525
|
-
---
|
|
526
|
-
|
|
527
|
-
## 📐 รหัสออก & สัญญา
|
|
528
|
-
|
|
529
|
-
แช่แข็ง — ปลอดภัยที่จะสร้างตรรกะ CI บน:
|
|
530
|
-
|
|
531
|
-
| รหัสออก | ความหมาย |
|
|
532
|
-
| ------- | ----------------------------------------------------- |
|
|
533
|
-
| `0` | สะอาด — ไม่มี finding ที่ระดับเกตหรือสูงกว่า |
|
|
534
|
-
| `1` | มี finding ที่ระดับเกตหรือสูงกว่า |
|
|
535
|
-
| `2` | สแกนบางส่วน (หมดงบเวลา, ไฟล์อ่านไม่ได้) — ไม่เคยบล็อก |
|
|
536
|
-
| `10` | ใช้งานผิด (flag ผิด, ไม่ระบุเป้าหมาย) |
|
|
537
|
-
| `20` | ข้อผิดพลาดภายใน |
|
|
538
|
-
|
|
539
|
-
รายงาน JSON/SARIF คือ `schemaVersion: 1` rule ID (`QA-<FAMILY>-NNN`)
|
|
540
|
-
หลังปล่อยแล้วเปลี่ยนไม่ได้ และไม่เคยถูกนำกลับมาใช้
|
|
541
|
-
|
|
542
|
-
---
|
|
543
|
-
|
|
544
|
-
## โมเดลความไว้วางใจ
|
|
545
|
-
|
|
546
|
-
- **Local-first** — ศูนย์การเรียกเครือข่ายระหว่างสแกน เด็ดขาด ศูนย์
|
|
547
|
-
เทเลเมทรี
|
|
548
|
-
- **ไม่มีหลักฐานปลอม** — เราพูด «ไม่รู้» มากกว่า «ตรวจแล้ว» repo ว่าง
|
|
549
|
-
ได้ `score: null` ไม่ใช่ 100 ปลอม
|
|
550
|
-
- **ความซื่อสัตย์บางส่วน** — ถ้าการวิเคราะห์ถูกตัดสั้น ผลลัพธ์บอก
|
|
551
|
-
ไม่เคย «เสร็จ» เมื่อไม่ได้เสร็จ
|
|
552
|
-
- **กำแพง FP** — การตรวจจับทำงานบนมุมมองโค้ดที่ปราศจากคอมเมนต์/สตริง
|
|
553
|
-
(กฎ TypeScript ใช้ AST คอมไพเลอร์): รูปแบบในคอมเมนต์ร้อยเรียงหรือ
|
|
554
|
-
สตริงตัวอย่างเอกสาร คือเอกสาร ไม่ใช่ finding
|
|
555
|
-
- **วัด ไม่ใช่อ้าง** — เฉพาะกฎที่มีอัตรา false positive จากโค้ด OSS จริง
|
|
556
|
-
จึงอยู่ใน tier พาดหัว (ดู [วัดไปแล้วเท่าไร](#วัดไปแล้วเท่าไร));
|
|
557
|
-
ส่วนท้ายการสแกนและ `mjolnir rules --unmeasured` บอกว่ากฎไหนสถานะไหน
|
|
558
|
-
- **ความไว้วางใจต่อปลั๊กอินและประตูการรันโค้ด** — ปลั๊กอินคือแพ็กเกจ npm ประกาศใต้
|
|
559
|
-
`"plugins"`; โมดูล JS อยู่ใน `mjolnir-rules/*.mjs`
|
|
560
|
-
**ไม่มี sandbox**: โค้ดปลั๊กอินรันด้วยสิทธิ์ Node เต็ม
|
|
561
|
-
โมเดลความไว้วางใจเดียวกับปลั๊กอิน ESLint หรือ Vitest ด้วยเหตุนี้
|
|
562
|
-
การรันโค้ดจึงเป็น **opt-in ในทุกการสแกน**: ส่ง `--enable-plugins`
|
|
563
|
-
(หรือตั้ง `MJOLNIR_ENABLE_PLUGINS=1`) ไม่งั้นซอร์สจะไม่ถูกโหลด —
|
|
564
|
-
แจ้งเตือนบน stderr อย่างชัดเจนว่าข้ามอะไรไปบ้าง การสแกนโค้ดที่ไม่
|
|
565
|
-
น่าเชื่อถือไม่เคยรันมัน ไฟล์ JSON rule manifest (`mjolnir-rules/*.json`)
|
|
566
|
-
ไม่ได้รับผลกระทบ: ประกาศ regex pattern และไม่รันโค้ดโดยการออกแบบ
|
|
567
|
-
คำนำหน้า rule ID ของ core สงวนไว้และถูกปฏิเสธจากปลั๊กอินและกฎภายนอก
|
|
568
|
-
เพื่อกันการอ้างปลอม
|
|
569
|
-
- **กฎภายนอกประจำ workspace** (อิงโฟลเดอร์ ศูนย์เครือข่าย) — ไดเรกทอรี
|
|
570
|
-
`mjolnir-rules/` ติดกับเป้าสแกนโหลดกฎกำหนดเอง: ไฟล์ JSON ประกาศรูปแบบ
|
|
571
|
-
regex (ไม่รันโค้ด) โมดูล `.mjs`/`.js` export `rules` (ความไว้วางใจ
|
|
572
|
-
Node เต็ม เหมือนปลั๊กอิน) กฎภายนอกพก trust metadata เดียวกับ core;
|
|
573
|
-
ไม่เคยขึ้นไปใน tier core (core ต้องมีอัตรา FP ที่วัดจาก sidecar
|
|
574
|
-
corpus — `tier: "core"` ที่ประกาศมาถูกบีบลงเหลือ `extended`),
|
|
575
|
-
ทำตามเพดาน tier และถูกตรวจเรื่องเหลื่อมล้ำ: `mjolnir rules --md
|
|
576
|
-
--external` เรนเดอร์แคตตาล็อกจากไฟล์ที่โหลด (แหล่งที่มา `external`)
|
|
577
|
-
และตัวสร้างเมทริกซ์รับ `--external <root>`
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
|
-
## 🏗️ สถาปัตยกรรม
|
|
536
|
+
ถูกตรึงไว้ คุณจึงสร้างตรรกะ CI บนมันได้:
|
|
582
537
|
|
|
583
|
-
|
|
584
|
-
|
|
538
|
+
| รหัสออก | ความหมาย |
|
|
539
|
+
| ------- | -------------------------------------------------------- |
|
|
540
|
+
| `0` | สะอาด: ไม่มีข้อค้นพบที่ระดับด่านหรือสูงกว่า |
|
|
541
|
+
| `1` | มีข้อค้นพบที่ระดับด่านหรือสูงกว่า |
|
|
542
|
+
| `2` | การสแกนบางส่วน (หมดงบเวลา ไฟล์ที่อ่านไม่ได้) ไม่บล็อกเลย |
|
|
543
|
+
| `10` | ข้อผิดพลาดในการใช้งาน (แฟล็กผิด ไม่ได้ระบุเป้าหมาย) |
|
|
544
|
+
| `20` | ข้อผิดพลาดภายใน |
|
|
585
545
|
|
|
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
|
-
```
|
|
546
|
+
`2` ถูกแยกจาก `0` โดยเจตนา: การสแกนที่ยังไม่เสร็จไม่ได้ "ไม่พบอะไรเลย" มันแค่ยังค้นหาไม่เสร็จ
|
|
605
547
|
|
|
606
|
-
|
|
548
|
+
ทุกสิ่งที่เครื่องใช้ (ผลลัพธ์จากเครื่องมือ MCP, `--json`, SARIF 2.1) มาจากผลลัพธ์มาตรฐานเดียวภายใต้ schema ที่มีเวอร์ชันและ **ขยายได้ด้วยการเพิ่มเท่านั้น** (`schemaVersion: 1`, `contractVersion: 1`) จึงไม่มีผู้ใช้รายใดต้องสร้างความหมายขึ้นใหม่จากข้อความที่เรนเดอร์แล้ว ดู [สัญญาสำหรับเครื่อง](docs/machine-contract.md) ID ของกฎ (`QA-<FAMILY>-NNN`) เปลี่ยนไม่ได้เมื่อปล่อยแล้วและไม่ถูกนำกลับมาใช้ซ้ำ
|
|
607
549
|
|
|
608
|
-
|
|
609
|
-
ไม่มี I/O ไม่มี global เพิ่มระบบนิเวศใหม่ = หนึ่ง adapter + กฎของมัน
|
|
610
|
-
- **TypeScript/Playwright ใช้ AST คอมไพเลอร์** (ts-morph) Python, Java
|
|
611
|
-
และ C# รันบนชั้น regex ร่วมกันที่ปิดบังคอมเมนต์/สตริง
|
|
612
|
-
- ชั้น AST tree-sitter WASM สำหรับ Java และ C# มีอยู่และเป็นก้าวความ
|
|
613
|
-
แม่นยำถัดไป — ยังไม่ได้เสียบเข้ากับ pipeline สแกนแบบซิงโครนัส
|
|
550
|
+
<br />
|
|
614
551
|
|
|
615
|
-
|
|
552
|
+
## สิ่งที่ Mjölnir บอกคุณไม่ได้
|
|
616
553
|
|
|
617
|
-
|
|
554
|
+
- **มันไม่รันเทสต์ของคุณ** การสแกนที่สะอาดไม่ใช่ชุดเทสต์ที่ผ่าน
|
|
555
|
+
- **มันบอกไม่ได้ว่า assertion _ผิด_** `expect(total).toBe(41)` ดูปกติดี Mjölnir หาเทสต์ที่ _ล้มเหลวไม่ได้_ และไปป์ไลน์ที่ _เป็นสีแดงไม่ได้_ ไม่ใช่เทสต์ที่ตรวจสอบผิดเรื่อง
|
|
556
|
+
- **มันไม่ได้พิสูจน์ความถูกต้องทางธุรกิจ** ไม่มีสิ่งใดในที่นี้บอกว่าผลิตภัณฑ์ของคุณทำตามที่ข้อกำหนดต้องการ
|
|
557
|
+
- **100 ไม่ใช่ข้อพิสูจน์ว่าชุดเทสต์ดี** ชุดเทสต์ของคุณครอบคลุมความเสี่ยงจริงหรือไม่เป็นอีกคำถามหนึ่ง และเครื่องมือนี้ไม่ได้ตอบคำถามนั้น
|
|
558
|
+
- **5 จาก 79 กฎปล่อยออกมาด้วยค่าประมาณ** ไม่ใช่อัตราที่วัดได้ แต่ละกฎบอกไว้บนข้อค้นพบของตัวเอง
|
|
559
|
+
- **E1 ไม่ใช่ E2** ข้อค้นพบเชิงฮิวริสติกควรค่าแก่การอ่าน ไม่ใช่นำไปใช้อย่างไม่ไตร่ตรอง
|
|
560
|
+
- **รีโพว่างได้คะแนน `null` ไม่มีวันได้ 100**
|
|
561
|
+
- **ไฟล์ชื่อ `*.spec.ts` ที่ไม่มีการประกาศเทสต์ไม่นับเป็น coverage** รีโพที่ไฟล์ spec มีเพียง import หรือ type (ไม่มีการเรียก `it`/`test` เลย) ได้คะแนน `null` ไม่ใช่ 100
|
|
618
562
|
|
|
619
|
-
|
|
620
|
-
| ------------------------------------------------------ | ----------------------------------------------- |
|
|
621
|
-
| [docs/SCORING.md](docs/SCORING.md) | การ normalize คะแนน + การถ่วงน้ำหนักด้วยหลักฐาน |
|
|
622
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | อัตรา false positive ที่วัดได้ + วิธีวัด |
|
|
623
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | สถานะกฎ การกด การเลิกใช้ |
|
|
624
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | ผลลัพธ์ SARIF + การตั้งค่า editor/CI |
|
|
625
|
-
| [docs/rules/](docs/rules/) | แคตตาล็อกต่อกฎที่สร้างอัตโนมัติ |
|
|
626
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | การตั้งค่า dev + ขั้นตอนการร่วมพัฒนา |
|
|
627
|
-
| [CHANGELOG.md](CHANGELOG.md) | ประวัติการเผยแพร่ |
|
|
628
|
-
| [SECURITY.md](SECURITY.md) | รายงานช่องโหว่ |
|
|
563
|
+
<br />
|
|
629
564
|
|
|
630
|
-
|
|
565
|
+
## เอกสารประกอบ
|
|
631
566
|
|
|
632
|
-
|
|
567
|
+
เว็บไซต์เอกสารฉบับเต็มอยู่ที่ <https://sergey-bar.github.io/Mjolnir/>
|
|
633
568
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
[
|
|
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 สูตรสำหรับ MR ด่าน |
|
|
579
|
+
| [docs/rules/](docs/rules/) | แค็ตตาล็อกรายกฎที่สร้างอัตโนมัติ |
|
|
580
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | การตั้งค่าสำหรับพัฒนาและขั้นตอนการมีส่วนร่วม |
|
|
581
|
+
| [SUPPORT.md](SUPPORT.md) | ที่สำหรับถาม รายงาน และขอความช่วยเหลือ |
|
|
582
|
+
| [SECURITY.md](SECURITY.md) | การรายงานช่องโหว่ |
|
|
583
|
+
| [CHANGELOG.md](CHANGELOG.md) | ประวัติการออกรุ่น |
|
|
638
584
|
|
|
639
|
-
|
|
585
|
+
### สถานะ
|
|
640
586
|
|
|
641
|
-
|
|
587
|
+
**เวอร์ชัน 1** schema ของ JSON และรหัสออกเป็นสัญญาที่ถูกตรึงไว้ TypeScript และ Python มีการครอบคลุมที่วัดได้กว้างที่สุด Java และ C# ใหม่กว่า ให้อ่านผ่าน [ตารางความพร้อม](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle) สิ่งที่จะมาต่อไป โดยไม่มีวันที่ที่แต่งขึ้น: [แผนงานสาธารณะ](https://sergey-bar.github.io/Mjolnir/reference/roadmap)
|
|
642
588
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
589
|
+
### การมีส่วนร่วม
|
|
590
|
+
|
|
591
|
+
กฎใหม่คือการมีส่วนร่วมครั้งแรกที่ง่ายที่สุด คำสั่งเดียวสร้างโครงของกฎพร้อม fixture แบบ must-fire **และ** must-not-fire กฎที่สร้างขึ้นจะล้มเหลวกับ fixture ของตัวเองโดยเจตนาจนกว่าจะมีการเขียนการตรวจจับจริง เพราะโครงเปล่าที่ถูกปล่อยออกไปคือกฎที่ไม่มีใครวัด:
|
|
646
592
|
|
|
647
593
|
```bash
|
|
648
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
649
595
|
```
|
|
650
596
|
|
|
651
|
-
|
|
652
|
-
กำแพง fixture อยู่ใน [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
597
|
+
การตั้งค่าสำหรับพัฒนา คำสั่งด่านถาวร และกฎ anti-creep กับไฟร์วอลล์ fixture อยู่ใน [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
653
598
|
|
|
654
|
-
|
|
599
|
+
<br />
|
|
655
600
|
|
|
656
601
|
<div align="center">
|
|
657
602
|
|
|
658
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="ลองรันกับรีโพของคุณ" width="100%" />
|
|
659
604
|
|
|
660
605
|
```bash
|
|
661
606
|
npx mjolnir-qa@latest
|
|
662
607
|
```
|
|
663
608
|
|
|
664
|
-
|
|
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
|
+
ให้ถามว่าหลักฐานพิสูจน์ได้หรือไม่ว่าเทสต์เหล่านั้นสมควรได้รับความเชื่อถือ
|
|
665
615
|
|
|
666
|
-
|
|
616
|
+
<sub>สร้างโดย [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · สัญญาอนุญาต MIT</sub>
|
|
667
617
|
|
|
668
618
|
</div>
|