mjolnir-qa 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.vi.md DELETED
@@ -1,647 +0,0 @@
1
- <div align="center">
2
-
3
- <img src="assets/readme/hero.svg" alt="Mjölnir. Test cho bạn biết cái gì đã qua. Mjölnir cho bạn biết cái gì đáng tin." width="100%" />
4
-
5
- <br />
6
-
7
- Mjölnir tìm ra những test không thể thất bại và những pipeline không thể chuyển đỏ,<br />
8
- rồi chấm điểm mức độ đáng tin của kết quả, kèm bằng chứng cho từng điểm.
9
-
10
- <br />
11
-
12
- [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
13
- [![downloads](https://img.shields.io/npm/dm/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
14
- [![ci](https://img.shields.io/github/actions/workflow/status/Sergey-Bar/Mjolnir/ci.yml?branch=main&style=flat-square&label=ci&labelColor=0A1119)](https://github.com/Sergey-Bar/Mjolnir/actions/workflows/ci.yml)
15
- [![coverage](https://img.shields.io/codecov/c/github/Sergey-Bar/Mjolnir?style=flat-square&color=1F6F7C&labelColor=0A1119&label=coverage)](https://codecov.io/gh/Sergey-Bar/Mjolnir)
16
- [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Sergey-Bar/Mjolnir/badge)](https://scorecard.dev/viewer/?uri=github.com/Sergey-Bar/Mjolnir)
17
- [![license](https://img.shields.io/badge/license-MIT-1F6F7C.svg?style=flat-square&labelColor=0A1119)](LICENSE)
18
- [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-1F6F7C.svg?style=flat-square&labelColor=0A1119)](https://nodejs.org)
19
-
20
- ```bash
21
- npx mjolnir-qa@3.0.0
22
- ```
23
-
24
- [Xem cách hoạt động](#xem-cách-hoạt-động) · [Bắt đầu nhanh](#bắt-đầu-nhanh) · [Phát hiện gì](#mjölnir-phát-hiện-gì) · [Điểm](#điểm-đáng-tin) · [Bằng chứng](#mô-hình-bằng-chứng) · [Phân tích lần chạy](#phân-tích-pháp-chứng-lúc-chạy) · [CI](#tính-toàn-vẹn-ci) · [Tác tử](#tác-tử-ai) · [Bảo mật](#tin-cậy-và-bảo-mật) · [Giới hạn](#những-điều-mjölnir-không-thể-cho-bạn-biết) · [Tài liệu](#tài-liệu)
25
-
26
- <details>
27
- <summary>Đọc bằng ngôn ngữ khác — 22 bản dịch</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.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-26.
32
-
33
- <!-- Source hash: `de04dfb1677b` -->
34
-
35
- </details>
36
-
37
- </div>
38
-
39
- <br />
40
-
41
- ## Release status (English canonical)
42
-
43
- The published line is `3.0.0`; this working tree is the `4.0.0-rc.1`
44
- candidate. `3.0.0` must not be republished or retagged. The M26–M50 program is
45
- tracked in
46
- [`docs/ROADMAP.yaml`](docs/ROADMAP.yaml); provisional capability contracts
47
- are not automatically enabled or certified. Repository-owned checks pass, but
48
- Trust certification remains `NOT_CERTIFIED` until the protected holdout,
49
- real-world, platform/consumer, remote-workflow, support-matrix, and corpus
50
- evidence gates pass. Run `npm run m26:readiness` before treating any candidate
51
- as releasable. This document does not publish a tag or authorize a release.
52
-
53
- > Machine-assisted canonical text. Translate this block before treating it as localized copy.
54
-
55
- ## Dấu tích xanh là một lời khẳng định, không phải bằng chứng
56
-
57
- Dấu tích xanh nghĩa là pipeline không thất bại. Nó không có nghĩa là test đã chạy, hay test đã có thể thất bại. Mỗi trường hợp dưới đây đều qua với màu xanh:
58
-
59
- - một `.only` bị commit khiến chỉ 3 test chạy thay vì 900
60
- - `continue-on-error: true` trên job lẽ ra phải chặn
61
- - `|| true` phía sau lệnh chạy test
62
- - một test không khẳng định gì, hoặc có thân rỗng
63
- - một lớp bọc thử lại biến thất bại thật thành lần qua may mắn
64
- - một báo cáo mà workflow tải lên nhưng chưa từng được tạo ra
65
- - một lệnh sleep cố định đang níu giữ một race condition
66
-
67
- Không cái nào khiến pipeline chuyển đỏ, và cái nào trông cũng có vẻ cố ý khi review. Đó là lý do chúng sống sót. Đây là Mjölnir đang đọc một ví dụ thật:
68
-
69
- <p align="center">
70
- <img src="assets/readme/scan.svg" alt="Workflow CI của kho demo, đọc từng dòng. Mjölnir đánh dấu mỗi phát hiện tại dòng nó báo cáo, kèm quy tắc, điều sai, mức bằng chứng và tỷ lệ dương tính giả đã đo." width="800" />
71
- </p>
72
-
73
- <sub>Mọi phát hiện mà lần quét demo báo cáo cho workflow này, tại dòng được báo cáo. Được tạo bởi `npm run docs:readme-brand` từ [`demo-report.json`](assets/readme/demo-report.json) và được khóa chống sai lệch trong CI.</sub>
74
-
75
- **Chế độ nghiêm ngặt.** Các phát hiện hung hăng nhất — `.only`, `continue-on-error`, kiểm tra trống, lạm dụng thử lại — nằm ở tầng cách ly. Chúng chỉ chạy với `--strict` và bị giới hạn ở mức nghiêm trọng `info`: chúng đánh dấu, không bao giờ chặn. Quét mặc định (`npx mjolnir-qa@3.0.0` không có `--strict`) chỉ bao gồm các quy tắc cốt lõi và mở rộng. Thêm `--strict` khi bạn cũng muốn lớp tư vấn.
76
-
77
- Mjölnir đọc bộ test, các workflow CI và, nếu bạn có, báo cáo của một lần chạy thật. Nó không chạy test của bạn, không cài dependency và không thực thi mã mà nó quét. Khi không có bằng chứng, nó nói thẳng như vậy thay vì bịa ra sự tự tin:
78
-
79
- | Tình huống | Mjölnir báo cáo gì |
80
- | --------------------------------------------------------- | ----------------------------------------------------------------------------- |
81
- | Không tìm thấy khai báo test | Điểm `null`, hiển thị là **UNKNOWN**. Không bao giờ là một con số 100 bịa ra. |
82
- | Không có baseline hay phiên bản để so sánh | **UNKNOWN**, kèm lý do. Không bao giờ giả định là 0. |
83
- | Lần quét bị cắt ngang (hết thời gian, tệp không đọc được) | **PARTIAL**, mã thoát `2`. Không bao giờ được trình bày là sạch. |
84
-
85
- <p align="center">
86
- <img src="assets/readme/how-it-works.svg" alt="Cách Mjölnir hoạt động. Nó đọc tĩnh bộ test và pipeline CI, cùng với báo cáo của một lần chạy thật khi có. Nó cân mỗi phát hiện theo mức bằng chứng và mức tin cậy, trong đó chỉ lần chạy thật mới đạt được L3 đến L5, rồi tạo ra các phát hiện, điểm đáng tin và một cổng CI dựa trên mã thoát đã đóng băng. Trong vòng lặp của tác tử, AI viết bản sửa và Mjölnir quét lại để chứng minh nó." width="880" />
87
- </p>
88
-
89
- <sub>Được dựng riêng cho trang này và hiển thị ở tỷ lệ 1:1. Được tạo bởi `npm run docs:readme-brand` và được khóa chống sai lệch trong CI; điểm, số đếm và ID quy tắc đến từ [`script.demo.json`](assets/video/script.demo.json), [`demo-report.json`](assets/readme/demo-report.json) và sổ đăng ký quy tắc, không bao giờ gõ tay. Cùng bức hình ở dạng poster: [`architecture.svg`](assets/readme/architecture.svg).</sub>
90
-
91
- <br />
92
-
93
- ## Xem cách hoạt động
94
-
95
- Một lần quét thật trên [`examples/demo-repo`](examples/demo-repo), một bộ test Playwright nhỏ có workflow CI. Đây là nơi điểm của nó bị trừ:
96
-
97
- <p align="center">
98
- <img src="assets/readme/terminal-hero.svg" alt="Bảng phân tích trừ điểm của Mjölnir: WORTHINESS 80/100 WORTHY, điểm theo từng hạng mục, ô trừ điểm theo mức nghiêm trọng và danh sách FIX THIS FIRST" width="520" />
99
- </p>
100
-
101
- <sub>Được tạo bởi `npm run docs:hero` từ một lần quét thật và được khóa chống sai lệch trong CI. Báo cáo `--verbose` đầy đủ của cùng lần quét là [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
102
-
103
- <details>
104
- <summary><strong>Xem video</strong> — một lần quét, bản sửa mà nó in ra, và lần quét lại chứng minh bản sửa đó</summary>
105
-
106
- <br />
107
-
108
- <p align="center">
109
- <a href="assets/video/mjolnir-demo.mp4">
110
- <img src="assets/video/mjolnir-demo-poster.png" alt="Một khung hình từ bản ghi demo: npx mjolnir-qa@3.0.0 đang quét kho demo trong cửa sổ terminal" width="900" />
111
- </a>
112
- </p>
113
-
114
- <sub>Được dựng từng khung hình từ một lần quét thật bằng `npm run docs:video`; không bao giờ quay màn hình. Chọn khung hình để mở [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
115
-
116
- </details>
117
-
118
- ### Cận cảnh một phát hiện
119
-
120
- Mỗi phát hiện trả lời bốn câu hỏi: nó ở đâu, Mjölnir chắc chắn đến mức nào, quy tắc sai thường xuyên đến đâu, và cách sửa.
121
-
122
- <p align="center">
123
- <img src="assets/readme/finding-anatomy.svg" alt="Phát hiện đầu tiên của lần quét demo, đúng như terminal in ra, với bốn phần được đánh dấu: ở đâu, chắc chắn đến mức nào, quy tắc sai thường xuyên đến đâu, và bản sửa." width="100%" />
124
- </p>
125
-
126
- `mjolnir explain QA-CI-001` in ra toàn bộ hồ sơ tin cậy của một quy tắc, gồm cả tỷ lệ dương tính giả đã đo và cấp mà tỷ lệ đó mang lại cho nó:
127
-
128
- ```text
129
- ▍ QA-CI-001 — continue-on-error masks a failing verification gate
130
-
131
- Severity: error
132
- Confidence: high
133
- Tier: quarantine
134
- Evidence: E2
135
- QA impact: False-green risk (FALSE-GREEN)
136
- Measured FP: 11% (19 hand-classified corpus verdicts)
137
- FP risk: low (author estimate)
138
- Languages: yaml
139
- Frameworks: github-actions, azure-pipelines
140
-
141
- WHAT WAS FOUND (real detector output, not a mockup)
142
- Job `security-scan` runs a verification gate under `continue-on-error: true`.
143
-
144
- WHY IT MATTERS
145
- This job can fail every day and CI will still show green. The checkmark on
146
- this workflow cannot be trusted.
147
-
148
- HOW TO FIX
149
- Remove continue-on-error, or scope it to individual non-blocking steps only.
150
-
151
- Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
152
-
153
- WHAT WOULD CHANGE THE VERDICT
154
- - a run report next to the scan target (mjolnir.report.json or test-results/)
155
- corroborating this file lifts its findings to L3–L5
156
- - a documented suppression (mjolnir.config.json) lowers the finding count
157
- without claiming correctness
158
- - quarantine findings run only under --strict and are advisory (E0) — they can
159
- never gate CI
160
-
161
- NEXT ACTION
162
- Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
163
- occurrence of this rule is listed in the scan output.
164
-
165
- HOW TO VERIFY THE FIX
166
- Re-run `mjolnir` on the changed file(s) — this finding should no longer
167
- appear. `mjolnir --scope changed` scopes the check to just what you touched.
168
-
169
- Docs: mjolnir rules --md (full catalog, this rule included)
170
- ```
171
-
172
- Đó là đơn vị giá trị: một chỗ mà CI báo cáo một lần qua mà nó không xứng đáng có.
173
-
174
- <br />
175
-
176
- ## Bắt đầu nhanh
177
-
178
- ```bash
179
- npx mjolnir-qa@3.0.0
180
- ```
181
-
182
- Nó quét thư mục hiện tại và in ra Trust Report: nó tìm thấy gì, bạn có thể tin đến mức nào, vì sao, và bước tiếp theo là gì. Nó thoát với `0` khi không tìm thấy gì ở mức cổng hoặc cao hơn.
183
-
184
- Trong CI, chỉ quét những gì nhánh đưa vào, để một bộ test cũ không nhấn chìm pull request đầu tiên của bạn:
185
-
186
- ```bash
187
- npx mjolnir-qa@3.0.0 --scope changed
188
- ```
189
-
190
- `mjolnir ci install` ghi điều đó thành một workflow GitHub Actions, dùng [action](https://github.com/Sergey-Bar/Mjolnir#readme) được ghim vào tag chính `v3` (hoặc `npx` thuần với `--no-action`). Nó chỉ mang tính tư vấn cho đến khi bạn quyết định nó nên chặn.
191
-
192
- | Lệnh | Chức năng |
193
- | --------------------------------------------- | ------------------------------------------------------ |
194
- | `mjolnir` | Trust Report: kết luận, độ tin, hành động tiếp theo |
195
- | `mjolnir --scope changed` | Chỉ những gì nhánh của bạn đưa vào (dạng dùng cho CI) |
196
- | `mjolnir ci install` | Tạo workflow PR mang tính tư vấn (dựa trên action) |
197
- | `mjolnir business-case` | ROI estimate: projected savings per finding |
198
- | `mjolnir release-report` | Release readiness: GO, CONDITIONAL GO, or NO-GO |
199
- | `mjolnir release-trust` | 12-dimension release assurance verdict |
200
- | `mjolnir report` | Generate a Playwright-compatible report |
201
- | `mjolnir trend` | Record, show, or diff local quality snapshots |
202
- | `mjolnir policy` | Initialize, validate, or check policy gates |
203
- | `mjolnir quarantine` | Review deterministic proposals (prototype) |
204
- | `mjolnir analyze --cross-file` | Bounded cross-file analysis |
205
- | `mjolnir ci-adapter github .` | Generate CI templates for supported providers |
206
- | `mjolnir dashboard` | Generate a self-contained quality dashboard |
207
- | `mjolnir exec-report` | Executive KPIs and recommendations (advisory) |
208
- | `mjolnir enterprise` | Self-hosted templates (prototype) |
209
- | `mjolnir maturity` | Assess maturity or display maturity levels |
210
- | `mjolnir mutation tests/mutation-report.json` | Analyze mutation reports; never promotes trust |
211
- | `mjolnir mcp` | Read-only MCP tools over stdio |
212
- | `mjolnir explain QA-CI-001` | Cái gì, vì sao và cách sửa, kèm tỷ lệ FP đã đo |
213
- | `mjolnir why src/a.spec.ts:42` | Vì sao chính dòng này bị đánh dấu. Không bao giờ chặn. |
214
- | `mjolnir forensics ./test-results/` | Bằng chứng runtime từ một lần chạy thật |
215
- | `mjolnir trust-report` | Trust Artifact độc lập (md + json) |
216
- | `mjolnir handoff` | Kế hoạch khắc phục cho tác tử lập trình |
217
- | `mjolnir --json` / `--format sarif` | Đầu ra máy đọc được, GitHub Code Scanning |
218
- | `mjolnir --format codequality` | Báo cáo GitLab Code Quality (artifact cho widget MR) |
219
- | `mjolnir --strict` | Chạy cả các quy tắc cấp quarantine (rủi ro FP cao hơn) |
220
-
221
- <details>
222
- <summary><strong>Mọi lệnh khác</strong> — phân loại test chập chờn, báo cáo, quản trị</summary>
223
-
224
- <br />
225
-
226
- | Lệnh | Chức năng |
227
- | ----------------------------------- | --------------------------------------------------------------------------- |
228
- | `mjolnir --classic` | Giao diện banner điểm từ trước khi có Trust Report |
229
- | `mjolnir explain verdict` | Vì sao kết luận của lần quét đã lưu lại như vậy |
230
- | `mjolnir triage ./test-results/` | Phân loại có hướng dẫn. Mỗi hàng kết thúc bằng một hành động tiếp theo. |
231
- | `mjolnir pw-report ./test-results/` | Tóm tắt lần chạy Playwright: số lần thử lại, test chập chờn, test chậm nhất |
232
- | `mjolnir doctor:playwright` | Quét sâu chỉ dành cho Playwright kèm Selector Health Score |
233
- | `mjolnir fix --dry-run` / `fix` | Tự động sửa an toàn, mỗi bản sửa được quét lại để chứng minh nó có hiệu lực |
234
- | `mjolnir baseline` / `diff` | Chụp nhanh các phát hiện, sau đó chỉ báo cáo cái mới hoặc tệ hơn |
235
- | `mjolnir impact --since <ref>` | Một commit đã đưa vào và giải quyết những gì |
236
- | `mjolnir summary` | Chú thích CI và tóm tắt step từ một báo cáo |
237
- | `mjolnir pr-comment` | Một bình luận PR có phạm vi, dạng Markdown |
238
- | `mjolnir debt` | Sổ nợ test kèm mô hình chi phí |
239
- | `mjolnir handover` | Bản đồ làm quen bộ test cho kỹ sư QA mới |
240
- | `mjolnir init` | Phát hiện framework, in danh sách kiểm tra thiết lập |
241
- | `mjolnir suppressions` | Liệt kê các phát hiện bị chặn, phục vụ quản trị |
242
- | `mjolnir rules --unmeasured` | Những quy tắc chạy dựa trên giả định, không phải đo lường |
243
- | `mjolnir rules --md` | Danh mục quy tắc đầy đủ (JSON hoặc Markdown) |
244
- | `mjolnir doctor` | Tự kiểm toán cơ sở quy tắc của chính Mjölnir |
245
- | `mjolnir create-rule <ID>` | Tạo khung cho một quy tắc mới và các fixture của nó |
246
- | `mjolnir stats` | Bộ đếm cục bộ mọi bản sửa từng thấy |
247
- | `mjolnir badge` | JSON cho endpoint shields.io và đoạn mã |
248
- | `mjolnir --cache` | Quét lại tăng dần qua bộ đệm kết luận cục bộ |
249
- | `mjolnir --format mermaid` | Sơ đồ kiến trúc test cho một bình luận PR |
250
-
251
- `mjolnir help <command>` in cách dùng, ví dụ và bước tiếp theo cho bất kỳ lệnh nào.
252
-
253
- </details>
254
-
255
- Yêu cầu **Node.js ≥ 22.18** trên Windows, macOS hoặc Linux. Muốn cài toàn cục? `npm i -g mjolnir-qa`. Mức tối thiểu này đến từ chuỗi công cụ build (tsdown nhắm tới nó và pipeline phát hành chạy smoke test trên nó); các dependency lúc chạy không cần gì hơn.
256
-
257
- <br />
258
-
259
- ## Mjölnir phát hiện gì
260
-
261
- <p align="center">
262
- <img src="assets/readme/stack.svg" alt="Hoạt động với stack của bạn: các ngôn ngữ, framework test và hệ thống CI mà các quy tắc bao phủ, lấy từ sổ đăng ký quy tắc." width="100%" />
263
- </p>
264
-
265
- **79 quy tắc** trong bốn nhóm — vệ sinh test, chất lượng test, Playwright và tính toàn vẹn CI — cho TypeScript và JavaScript, Python, Java, C# và YAML của GitHub Actions. Chúng bao phủ Playwright ở cả bốn binding, cùng pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest và Mocha, với mức hỗ trợ ban đầu cho Cypress và Selenium. Chín quy tắc trong số đó, để bạn hình dung:
266
-
267
- | ID | Quy tắc | Mức nghiêm trọng | Cấp |
268
- | ------------ | -------------------------------------------------------------------------- | ---------------- | ---------- |
269
- | QA-CI-001 | `continue-on-error` che giấu một cổng xác minh đang thất bại | error | quarantine |
270
- | QA-CI-009 | Mã thoát của test không được truyền đi (`\|` không có pipefail, chuỗi `;`) | error | extended |
271
- | QA-TEST-001 | Commit test bị focus (`.only`, `fit`) | error | quarantine |
272
- | QA-TEST-003 | Test không có assertion | error | quarantine |
273
- | QA-TQUAL-009 | Assertion trên promise không được await | error | quarantine |
274
- | QA-PW-002 | Assertion trên locator không được await | error | core |
275
- | QA-PW-004 | Selector CSS/XPath dễ vỡ | warning | quarantine |
276
- | QA-PY-002 | Test bị bỏ qua (`skip`, `xfail` không nghiêm ngặt) | warning | core |
277
- | QA-CS-103 | Phương thức test không có assertion | error | core |
278
-
279
- Danh mục đầy đủ được tạo từ sổ đăng ký, không bao giờ duy trì thủ công: `mjolnir rules --md`, [`docs/rules/`](docs/rules/), hoặc [hướng dẫn về những gì nó kiểm tra](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
280
-
281
- <details>
282
- <summary><strong>Mọi quy tắc được nhắc đến trong README này</strong>, trong một bảng</summary>
283
-
284
- <br />
285
-
286
- > Quy tắc `quarantine` chỉ chạy khi có `--strict` và không bao giờ chặn (bị giới hạn ở info). Mức nghiêm trọng hiển thị là mức do tác giả đặt.
287
-
288
- | ID | Nhóm | Quy tắc | Mức nghiêm trọng | Cấp |
289
- | ------------ | ---------- | ------------------------------------------------------------------ | ---------------- | ---------- |
290
- | QA-TEST-001 | Vệ sinh | Commit test bị focus (`.only`, `fit`) | error | quarantine |
291
- | QA-TEST-002 | Vệ sinh | Test bị bỏ qua. Nâng lên `error` nếu không có lý do được theo dõi. | warning | quarantine |
292
- | QA-TEST-003 | Vệ sinh | Test không có assertion | error | quarantine |
293
- | QA-TEST-004 | Vệ sinh | Sleep cố định (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
294
- | QA-TEST-006 | Vệ sinh | Lạm dụng thử lại để che giấu sự chập chờn | warning | quarantine |
295
- | QA-TEST-010 | Vệ sinh | Thân test rỗng | error | quarantine |
296
- | QA-TQUAL-002 | Chất lượng | Assertion hằng đúng | error | quarantine |
297
- | QA-TQUAL-009 | Chất lượng | Assertion trên promise không được await | error | quarantine |
298
- | QA-TQUAL-011 | Chất lượng | Test bị comment lại | warning | extended |
299
- | QA-PW-002 | Playwright | Assertion trên locator không được await | error | core |
300
- | QA-PW-003 | Playwright | Commit `page.pause()` / `test.only()` | error | core |
301
- | QA-PW-004 | Playwright | Selector CSS/XPath dễ vỡ | warning | quarantine |
302
- | QA-PW-123 | Playwright | URL môi trường bị viết cứng | warning | quarantine |
303
- | QA-PW-140 | Playwright | Chụp màn hình không có `maxDiffPixelRatio` | warning | core |
304
- | QA-CI-001 | CI | `continue-on-error` che giấu một cổng đang thất bại | error | quarantine |
305
- | QA-CI-002 | CI | `\|\| true` nuốt mất mã thoát | error | extended |
306
- | QA-CI-005 | CI | Báo cáo được dùng nhưng chưa từng được tạo | error | quarantine |
307
- | QA-CI-007 | CI | Lớp bọc thử lại quanh test | warning | extended |
308
- | QA-CI-008 | CI | Step luôn thành công che giấu thất bại | error | quarantine |
309
- | QA-CI-009 | CI | Mã thoát không được truyền đi (`\|` không có pipefail, chuỗi `;`) | error | extended |
310
- | QA-CI-010 | CI | Test bị bỏ qua ở nơi chúng phải chặn | error | quarantine |
311
- | QA-PY-002 | Python | Test bị bỏ qua (`skip`, `xfail` không nghiêm ngặt) | warning | core |
312
- | QA-PY-003 | Python | Hàm test không có assertion | error | quarantine |
313
- | QA-PY-005 | Python | `time.sleep()` trong test | warning | extended |
314
- | QA-PY-012 | Python | Assertion hằng đúng | error | quarantine |
315
- | QA-JV-101 | Java | Test bị vô hiệu hóa (`@Disabled`) | warning | core |
316
- | QA-JV-102 | Java | Sleep cố định (`Thread.sleep()`) | warning | extended |
317
- | QA-JV-103 | Java | Phương thức test không có assertion | error | extended |
318
- | QA-JV-105 | Java | Sleep cố định bằng `waitForTimeout()` của Playwright | warning | core |
319
- | QA-JV-106 | Java | Selector dễ vỡ thay vì locator theo vai trò | warning | quarantine |
320
- | QA-CS-101 | C# | Test bị bỏ qua (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
321
- | QA-CS-102 | C# | Sleep cố định (`Thread.Sleep` / `Task.Delay`) | warning | core |
322
- | QA-CS-103 | C# | Phương thức test không có assertion | error | core |
323
- | QA-CS-105 | C# | Sleep cố định bằng `WaitForTimeoutAsync()` | warning | extended |
324
- | QA-CS-106 | C# | Selector dễ vỡ thay vì locator theo vai trò | warning | quarantine |
325
-
326
- Python còn có QA-PY-001…012 (vệ sinh pytest) và QA-PY-101…108 (Playwright cho Python). Cypress và Selenium mỗi bên có một bộ khởi đầu gồm ba quy tắc.
327
-
328
- </details>
329
-
330
- Mỗi quy tắc được phát hành cùng một fixture must-fire **và** một fixture must-not-fire, và quy tắc nào kích hoạt trên chính fixture âm của nó thì không thể phát hành. Đó là tường lửa chống dương tính giả; `mjolnir doctor` thực thi nó trong CI của chính kho này.
331
-
332
- ### Selector Health Score
333
-
334
- `mjolnir doctor:playwright` chấm điểm mỗi locator theo cách nó tìm phần tử: theo cách người dùng tìm (vai trò, nhãn, văn bản), qua một hợp đồng rõ ràng (`data-testid`), hay nhờ một sự tình cờ về cấu trúc (chuỗi CSS, XPath). Mỗi tệp nhận điểm từ 0 đến 100:
335
-
336
- ```text
337
- ▍ SELECTOR HEALTH
338
-
339
- e2e/login.spec.ts
340
- [█████████████░░░░░░░] 65 / 100
341
- role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
342
-
343
- e2e/checkout.spec.ts
344
- [██████████████████░░] 88 / 100
345
- role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
346
- ```
347
-
348
- Điều này đo **độ bền, không phải độ đúng**. `.btn.btn-primary > div:nth-child(2)` qua hôm nay và sẽ tiếp tục qua cho đến khi ai đó động vào markup. Điểm thấp không bao giờ khẳng định test bị hỏng, chỉ nói rằng nó phụ thuộc vào markup mà không ai hứa giữ nguyên.
349
-
350
- <br />
351
-
352
- ## Điểm đáng tin
353
-
354
- <p align="center">
355
- <img src="assets/readme/score-gauge.svg" alt="Thang điểm đáng tin từ 0 đến 100, với một con trỏ quét qua mọi mức điểm: UNWORTHY dưới 50, NEEDS WORK từ 50 đến 79, WORTHY từ 80 đến 99, FORGED ở 100" width="720" />
356
- </p>
357
-
358
- <sub>Mọi mức điểm từ 0 đến 100, được đặt vị trí bởi `deriveScoreState` thật. Được tạo bởi `npm run docs:gauge` và được khóa chống sai lệch trong CI.</sub>
359
-
360
- | Điểm | Kết luận |
361
- | --------- | ----------------------------------------- |
362
- | `0 – 49` | **UNWORTHY** |
363
- | `50 – 79` | **NEEDS WORK** |
364
- | `80 – 99` | **WORTHY** |
365
- | `100` | **FORGED** |
366
- | `null` | **UNKNOWN**: không tìm thấy khai báo test |
367
-
368
- **Cách tính.** Mức nghiêm trọng đặt ra mức trừ cơ bản (`error −8`, `warning −3`, `info −1`) và mức bằng chứng chiết khấu nó: E2 trừ đủ, E1 trừ một nửa (làm tròn xuống), E0 không trừ. Tổng được chuẩn hóa theo quy mô bộ test, tức là trừ theo từng khai báo test chứ không theo tệp. Terminal in ra đúng những con số đã chiết khấu mà điểm đã dùng; không có mô hình thứ hai nào ẩn giấu. Chi tiết: [docs/SCORING.md](docs/SCORING.md) và [hướng dẫn chấm điểm](https://sergey-bar.github.io/Mjolnir/guide/scoring).
369
-
370
- **Điều mà 100 không có nghĩa.** Nó không có nghĩa là phần mềm đúng, bộ test đầy đủ, hay sản phẩm không có lỗi. Nó chỉ có nghĩa một điều: **không quy tắc nào mà Mjölnir đánh giá tạo ra mức trừ điểm trong lần quét này và với mô hình bằng chứng này.**
371
-
372
- <br />
373
-
374
- ## Mô hình bằng chứng
375
-
376
- Mỗi phát hiện mang hai nhãn: Mjölnir chắc chắn đến mức nào, và phát hiện đã được kiểm chứng đến đâu. Đó là khác biệt giữa một công cụ báo cáo mẫu và một công cụ bạn có thể dùng làm cổng cho một bản phát hành.
377
-
378
- **Chắc chắn đến mức nào — mức bằng chứng.**
379
-
380
- | Mức | Tên | Ý nghĩa | Trừ điểm |
381
- | ------ | ------------------- | ------------------------------------------------ | -------- |
382
- | **E2** | Chứng minh tất định | Lỗi hiện diện trong mã đúng như nó được viết | Đủ |
383
- | **E1** | Bằng chứng theo mẫu | Một mẫu gắn chặt với lỗi đã khớp | Một nửa |
384
- | **E0** | Quan sát | Đáng biết. Không phải khẳng định rằng có gì sai. | Không |
385
-
386
- Độ tin trong một lần phát hiện không phải là sức mạnh của chứng minh. Một quy tắc có thể chắc chắn rằng nó đã khớp đúng thứ nó tìm mà vẫn chỉ đang nhìn vào một phép suy đoán. Phát hiện E1 là để đọc và cân nhắc, không bao giờ áp dụng mù quáng, và ranh giới đó được đóng dấu trên phát hiện trong terminal, trong JSON và trong phần bàn giao cho tác tử.
387
-
388
- **Đã kiểm chứng đến đâu — mức tin cậy.** Phần lớn phát hiện đến từ việc đọc mã của bạn. Đưa cho Mjölnir báo cáo của một lần chạy test thật và nó có thể xác nhận rằng mã thực sự đã chạy.
389
-
390
- <p align="center">
391
- <img src="assets/readme/trust-ladder.svg" alt="Nấc thang tin cậy từ L0 đến L5. L0 đến L2 đến từ việc đọc mã; L3 đến L5 cần một báo cáo chạy thật, được đánh dấu bằng một chỗ đứt trên nấc thang." width="100%" />
392
- </p>
393
-
394
- | Mức | Nói đơn giản | Cần gì |
395
- | ------ | ---------------------- | --------------------------------------------------------- |
396
- | **L0** | Đã ghi nhận | Đọc mã |
397
- | **L1** | Trông giống vấn đề | Đọc mã: một mẫu đã khớp |
398
- | **L2** | Đã chứng minh trong mã | Đọc mã: lỗi mang tính cấu trúc |
399
- | **L3** | Tệp đã chạy | Báo cáo chạy cho thấy tệp của phát hiện đã được thực thi |
400
- | **L4** | Test đã chạy | Báo cáo chạy cho thấy test của phát hiện đã được thực thi |
401
- | **L5** | Lần chạy xác nhận | Chính kết quả của lần chạy xác nhận loại lỗi |
402
-
403
- Quét tĩnh dừng ở L2. Chỉ một báo cáo chạy thật (Playwright JSON, Jest hoặc Vitest JSON, JUnit XML) mới có thể nâng một phát hiện lên L3 hoặc cao hơn, nên một phát hiện chưa từng được thấy chạy sẽ không bao giờ có thể khẳng định là nó đã chạy. Định nghĩa: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
404
-
405
- ### Bao nhiêu phần trong số này đã được đo
406
-
407
- **74 trên 79 quy tắc có tỷ lệ dương tính giả được đo trên mã OSS thật** (mỗi quy tắc ít nhất 10 phát hiện được phân loại thủ công; xem [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). 5 quy tắc còn lại phát hành dựa trên ước tính của tác giả và nói rõ điều đó, từng quy tắc một, trong `mjolnir explain`. `mjolnir rules --unmeasured` liệt kê chúng, và phần chân của mỗi lần quét cho biết bao nhiêu quy tắc thực sự _đã kích hoạt_ đã được đo.
408
-
409
- Các tỷ lệ vẫn công khai kể cả khi chúng tệ. QA-TEST-001 (một `.only` bị commit) cho kết quả kiểm toán kém trên các kho thật và vì thế nằm trong quarantine. Con số hiện tại của mọi quy tắc, kể cả QA-PW-141, nằm trong báo cáo kiểm toán.
410
-
411
- ### Cấp tin cậy của quy tắc
412
-
413
- Các cấp theo tỷ lệ dương tính giả đã đo, không theo ý kiến:
414
-
415
- | Cấp | FP đã đo | Hành vi |
416
- | -------------- | -------------------------------- | ------------------------------------------------------- |
417
- | **core** | ≤ 10% | Báo cáo mặc định, có chặn |
418
- | **extended** | ≤ 30% | Báo cáo mặc định, độ tin thấp hơn |
419
- | **quarantine** | > 30% hoặc được khai báo rõ ràng | Chỉ với `--strict`, giới hạn ở info, không bao giờ chặn |
420
- | _chưa đo_ | n < 10 | Không thể nâng lên core cho đến khi được đo |
421
-
422
- Dải FP chỉ có thể hạ cấp một bậc — chúng không bao giờ nâng cấp một quy tắc ra khỏi `quarantine` nếu nó đã được khai báo rõ ràng ở đó. Một quy tắc bị quarantined rõ ràng vẫn ở quarantine bất kể tỷ lệ FP đã đo được.
423
-
424
- Nâng cấp, hạ cấp và độ trưởng thành theo ngôn ngữ: [vòng đời quy tắc](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
425
-
426
- ### Vì sao đây không phải một linter
427
-
428
- Linter cho bạn biết mã có tuân theo quy tắc hay không. Mjölnir cho bạn biết việc xác minh của bạn có đáng tin hay không.
429
-
430
- | | Linter (ESLint, SonarQube) | Công cụ đo độ phủ | Review mã bằng AI | **Mjölnir** |
431
- | ---------------------------------------------------------------- | :------------------------: | :---------------: | :---------------: | :---------------------: |
432
- | Chấm điểm **hệ thống xác minh**, không phải mã sản phẩm | Không | Không | Không | Có |
433
- | Tính toàn vẹn của workflow CI (`continue-on-error`, `\|\| true`) | Không | Không | chỉ phần diff | Có |
434
- | Chấm độ bền của locator Playwright (Selector Health) | Không | Không | Không | Có |
435
- | Đọc dữ liệu chạy thật để đưa ra kết luận `TRUE-FLAKE` | Không | Không | Không | Có |
436
- | Công bố tỷ lệ dương tính giả đã đo cho từng quy tắc | Không | Không | Không | Có |
437
- | Đánh dấu test không có assertion | Có\* | Không | đôi khi | Có |
438
- | Bắt các sleep cố định (`waitForTimeout`, `time.sleep`) | Có\* | Không | đôi khi | Có |
439
- | Tất định (cùng đầu vào, cùng đầu ra) | Có | Có | Không | Có |
440
- | Chi phí mỗi lần quét | miễn phí | miễn phí | token | **bằng không** (cục bộ) |
441
-
442
- <sub>\*Được bao phủ bởi `eslint-plugin-jest` và `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) và bởi các quy tắc assertion riêng của SonarQube. Các cột mô tả hành vi mặc định khi xác minh bộ test; plugin, gói trả phí và quy tắc tùy chỉnh sẽ làm thay đổi một số câu trả lời. Đây là bản tóm tắt định vị, không phải benchmark.</sub>
443
-
444
- Hãy dùng cả review bằng AI. Nó nắm bắt sắc thái, ý định và lỗi thiết kế mà không mẫu nào tìm được. Mjölnir bắt được những gì review bằng AI bỏ sót vì trông có vẻ cố ý: một `.only` bị commit, một mã thoát bị nuốt, một `continue-on-error` trên job test. Những thứ đó cần quét, không cần suy luận.
445
-
446
- <br />
447
-
448
- ## Phân tích pháp chứng lúc chạy
449
-
450
- Phân tích tĩnh suy luận về mã chưa từng chạy. Phân tích pháp chứng đọc những gì thực sự đã xảy ra: Playwright JSON, Jest JSON, Vitest JSON và JUnit XML từ bất kỳ runner nào.
451
-
452
- ```bash
453
- mjolnir forensics ./test-results/
454
- ```
455
-
456
- ```text
457
- ▍ FLAKINESS LEADERBOARD
458
-
459
- 3 tests · 1 failed · 1 flaky · 1 retried
460
-
461
- TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
462
- ████████████████████ 6.0s · 2 attempts
463
- FAILING declines an expired card (e2e/checkout.spec.ts)
464
- ████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
465
- ```
466
-
467
- `TRUE-FLAKE` không có nghĩa là test đã được thử lại. Nó có nghĩa là test **đã thất bại ít nhất một lần thử rồi kết thúc với màu xanh**: một lần qua may mắn, bị đánh dấu bất kể dấu tích cuối cùng nói gì. `mjolnir triage` biến lịch sử đó thành một đề xuất cách ly, và `mjolnir pw-report` tóm tắt một lần chạy. Chính những báo cáo chạy này là thứ nâng phát hiện lên mức tin cậy L3 trở lên.
468
-
469
- <br />
470
-
471
- ## Tính toàn vẹn CI
472
-
473
- Một test có thể qua trong khi pipeline bao quanh nó không thể thất bại. Mjölnir cũng đọc các workflow: `continue-on-error`, `|| true`, mã thoát không bao giờ được truyền đi, step luôn thành công, báo cáo được dùng nhưng chưa từng được tạo, và cổng bị bỏ qua đúng ở những sự kiện lẽ ra phải chặn. Mỗi phát hiện nêu tên job, step và dòng, và mang mức bằng chứng riêng.
474
-
475
- Tạo workflow PR, mặc định mang tính tư vấn:
476
-
477
- ```bash
478
- mjolnir ci install
479
- ```
480
-
481
- Hoặc thêm action trên Marketplace vào một workflow bạn đã có:
482
-
483
- ```yaml
484
- - uses: Sergey-Bar/Mjolnir@v3
485
- with:
486
- scope: changed
487
- fail-on: error
488
- ```
489
-
490
- Ghim `@v3` để theo dòng phiên bản chính, hoặc một tag chính xác (`@v0.5.32`) để có cổng tái lập được. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) đề cập đến Marketplace, Smithery và các sổ đăng ký MCP.
491
-
492
- Để đưa phát hiện vào GitHub Code Scanning, hãy tải lên SARIF (yêu cầu `security-events: write` ở phạm vi workflow hoặc job):
493
-
494
- ```yaml
495
- - run: npx mjolnir-qa@3.0.0 --format sarif > mjolnir.sarif
496
- continue-on-error: true
497
- - uses: github/codeql-action/upload-sarif@v3
498
- if: ${{ !cancelled() }}
499
- with:
500
- sarif_file: mjolnir.sarif
501
- ```
502
-
503
- Trên GitLab, `--format codequality` ghi báo cáo Code Quality mà widget MR và chú thích diff đọc ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Thiết lập trình soạn thảo và pipeline: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
504
-
505
- ### Quy trách nhiệm theo phạm vi thay đổi
506
-
507
- ```bash
508
- npx mjolnir-qa@3.0.0 --scope changed
509
- ```
510
-
511
- Phát hiện được quy về các dòng mà nhánh của bạn đã thêm, đo so với **merge-base**. Phạm vi là cùng tập tệp mà một lần quét đầy đủ phát hiện (spec TS/JS và cấu hình adapter, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), cộng thêm các thay đổi chưa commit và chưa theo dõi, nên nó hoạt động cả trước khi bạn commit. Nhánh gốc được xác định theo thứ tự `main → master → origin/main → origin/master → origin/HEAD`; ghi đè bằng `--base <ref>`.
512
-
513
- Khi không xác định được merge-base (clone nông, HEAD tách rời, mục tiêu nằm ngoài git), phát hiện sẽ quay về quy cho toàn bộ tệp **và báo cáo nói rõ điều đó.** Một sự quay về âm thầm sẽ chính là loại lỗi mà công cụ này tồn tại để bắt.
514
-
515
- <br />
516
-
517
- ## Tác tử AI
518
-
519
- Phát hiện chỉ có giá trị nếu có thứ gì đó hành động dựa trên chúng.
520
-
521
- ```text
522
- SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
523
- ```
524
-
525
- **AI viết bản sửa. Mjölnir xác minh nó.** Bằng chứng đến từ lần quét lại, không bao giờ đến từ báo cáo thành công của chính tác tử.
526
-
527
- | Lệnh | Tác tử nhận được gì |
528
- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529
- | `mjolnir mcp` | Một máy chủ [MCP](https://modelcontextprotocol.io) qua stdio. `scan`, `explain` và `diff` trở thành công cụ có thể gọi. |
530
- | `mjolnir handoff` | Một báo cáo `--json` đã lưu trở thành một kế hoạch Markdown tất định: đã phát hiện gì, ranh giới bằng chứng của từng phát hiện, những gì **không** được thay đổi, và cách xác minh. |
531
- | `mjolnir install` | Ghi vào các vị trí dành cho tác tử mà kho của bạn đã có (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`) để tác tử quét lại trước khi khẳng định là đã xong. |
532
-
533
- Thêm vào một client có CLI riêng:
534
-
535
- ```bash
536
- claude mcp add mjolnir -- npx -y mjolnir-qa@3.0.0 mcp
537
- ```
538
-
539
- Hoặc vào bất kỳ client nào nhận khối `mcpServers`:
540
-
541
- ```json
542
- {
543
- "mcpServers": {
544
- "mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@3.0.0", "mcp"] }
545
- }
546
- }
547
- ```
548
-
549
- **Lan can bảo vệ quan trọng hơn sự tiện lợi.** Mỗi phát hiện trong phần bàn giao mang ranh giới của nó. **E2** nói _tất định: kiểm tra vị trí và áp dụng bản sửa_. **E1** nói _CẦN XÁC NHẬN: chỉ riêng quan sát không chứng minh được lỗi_. Một tác tử sửa E1 một cách mù quáng, chặn một quy tắc, hoặc sửa một quy tắc để nâng điểm đang làm đúng điều mà công cụ này tồn tại để bắt, nên phần bàn giao nói rõ điều đó trong prompt, ngay cạnh phát hiện.
550
-
551
- <br />
552
-
553
- ## Tin cậy và bảo mật
554
-
555
- **Ưu tiên cục bộ, không thu thập dữ liệu sử dụng.** Không có API nào có khả năng truy cập mạng (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) tồn tại ở bất kỳ đâu trong `src/`, và [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) sẽ làm build thất bại nếu có một cái xuất hiện. Nó cũng cấm `eval` và `new Function`. Quét mã không đáng tin không bao giờ thực thi nó: phân tích tĩnh đọc văn bản nguồn, còn phân tích pháp chứng phân tích các tệp báo cáo đã có sẵn trên đĩa.
556
-
557
- Hai lưu ý: bản thân `npx` tải gói xuống trước khi bất cứ thứ gì chạy, và cam kết này áp dụng cho `src/`, không bao gồm plugin của bên thứ ba.
558
-
559
- **Plugin không chạy trong sandbox.** Plugin JS (`mjolnir-rules/*.mjs`, hoặc các gói npm liệt kê dưới `"plugins"`) chạy với toàn quyền của Node, cùng mô hình tin cậy như plugin của ESLint hay Vitest. Việc tải chúng phải được bật **cho từng lần quét**: không có `--enable-plugins` (hoặc `MJOLNIR_ENABLE_PLUGINS=1`) thì mã nguồn của chúng không bao giờ được tải, và một thông báo trên stderr liệt kê những gì đã bị bỏ qua. Manifest quy tắc dạng JSON không thực thi mã, và các tiền tố ID của quy tắc core được giữ riêng để plugin không thể mạo danh chúng. Báo cáo lỗ hổng qua [SECURITY.md](SECURITY.md).
560
-
561
- **Nó tự chạy trên chính mình.** Một công cụ tin cậy xác minh chẳng có chỗ đứng nếu chính nó không thể được xác minh. Mỗi lần chạy CI đều quét kho này bằng bản build mà chính lần chạy đó tạo ra. Cổng thất bại với bất kỳ phát hiện nào ở mức error, và cả khi lần quét là **một phần** hoặc có **quy tắc bị sập**, vì một lần tự quét bị cắt cụt mà không báo cáo gì chính là màu xanh giả mà dự án này tồn tại để bắt. `mjolnir doctor` kiểm toán lại cơ sở quy tắc trong cùng lần chạy (tường lửa fixture, tính trung thực của các cấp, trần của cấp core), và một kiểm tra có kết quả INCONCLUSIVE sẽ thất bại y như một kiểm tra thất bại. Cả hai báo cáo được tải lên dưới dạng artifact của build.
562
-
563
- ### Mã thoát và hợp đồng máy
564
-
565
- Đã đóng băng, nên bạn có thể xây logic CI dựa trên chúng:
566
-
567
- | Mã thoát | Ý nghĩa |
568
- | -------- | ---------------------------------------------------------------------- |
569
- | `0` | Sạch: không có phát hiện ở mức cổng hoặc cao hơn |
570
- | `1` | Có phát hiện ở mức cổng hoặc cao hơn |
571
- | `2` | Quét một phần (hết thời gian, tệp không đọc được). Không bao giờ chặn. |
572
- | `10` | Lỗi sử dụng (cờ sai, thiếu mục tiêu) |
573
- | `20` | Lỗi nội bộ |
574
-
575
- `2` được cố ý tách biệt khỏi `0`: một lần quét chưa hoàn tất không phải là "không tìm thấy gì". Nó chỉ chưa tìm xong.
576
-
577
- Mọi thứ mà máy tiêu thụ (kết quả công cụ MCP, `--json`, SARIF 2.1) đều đến từ một kết quả chuẩn duy nhất theo một schema có phiên bản và **chỉ mở rộng bằng cách bổ sung** (`schemaVersion: 1`, `contractVersion: 1`), nên không bên tiêu thụ nào phải dựng lại ý nghĩa từ văn bản đã hiển thị. Xem [hợp đồng máy](docs/machine-contract.md). ID quy tắc (`QA-<FAMILY>-NNN`) không thể thay đổi sau khi phát hành và không bao giờ được dùng lại.
578
-
579
- <br />
580
-
581
- ## Những điều Mjölnir không thể cho bạn biết
582
-
583
- - **Nó không chạy test của bạn.** Một lần quét sạch không phải là một bộ test đang qua.
584
- - **Nó không thể cho bạn biết một assertion là _sai_.** `expect(total).toBe(41)` trông vẫn khỏe mạnh. Mjölnir tìm những test _không thể thất bại_ và những pipeline _không thể chuyển đỏ_, không phải những test kiểm tra sai thứ.
585
- - **Nó không chứng minh tính đúng đắn nghiệp vụ.** Không có gì ở đây nói rằng sản phẩm của bạn làm đúng điều mà yêu cầu đặt ra.
586
- - **Điểm 100 không phải bằng chứng của một bộ test tốt.** Bộ test của bạn có bao phủ rủi ro thực tế hay không là một câu hỏi khác, và công cụ này không trả lời câu hỏi đó.
587
- - **5 trên 79 quy tắc phát hành dựa trên ước tính**, không phải tỷ lệ đã đo. Mỗi quy tắc đều nói rõ điều đó trên phát hiện của chính nó.
588
- - **E1 không phải E2.** Phát hiện theo suy đoán đáng để đọc, không đáng để áp dụng mù quáng.
589
- - **Một kho rỗng nhận điểm `null`, không bao giờ là 100.**
590
- - **Một tệp tên `*.spec.ts` không có khai báo test không được tính là độ phủ.** Một kho mà các tệp spec duy nhất chỉ chứa import hoặc kiểu (không có lời gọi `it`/`test` nào) nhận điểm `null`, không phải 100.
591
-
592
- <br />
593
-
594
- ## Tài liệu
595
-
596
- Trang tài liệu đầy đủ ở <https://sergey-bar.github.io/Mjolnir/>.
597
-
598
- | Tài liệu | Nội dung |
599
- | ------------------------------------------------------ | ----------------------------------------------------------- |
600
- | [docs/SCORING.md](docs/SCORING.md) | Chuẩn hóa điểm và trọng số bằng chứng |
601
- | [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Bộ từ vựng chuẩn: một từ cho một khái niệm |
602
- | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Tỷ lệ dương tính giả đã đo và phương pháp |
603
- | [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Trạng thái quy tắc, cấp, chặn, ngừng hỗ trợ |
604
- | [docs/VERSIONING.md](docs/VERSIONING.md) | Chính sách semver, giao diện đóng băng, chu kỳ ngừng hỗ trợ |
605
- | [docs/machine-contract.md](docs/machine-contract.md) | Kết quả chuẩn mà máy đọc được |
606
- | [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Đầu ra SARIF và thiết lập trình soạn thảo hoặc CI |
607
- | [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: báo cáo Code Quality, công thức cho MR, cổng |
608
- | [docs/rules/](docs/rules/) | Danh mục được tạo cho từng quy tắc |
609
- | [CONTRIBUTING.md](CONTRIBUTING.md) | Thiết lập môi trường phát triển và quy trình đóng góp |
610
- | [SUPPORT.md](SUPPORT.md) | Nơi hỏi, báo cáo và nhận trợ giúp |
611
- | [SECURITY.md](SECURITY.md) | Báo cáo lỗ hổng |
612
- | [CHANGELOG.md](CHANGELOG.md) | Lịch sử phát hành |
613
-
614
- ### Trạng thái
615
-
616
- **Phiên bản 1.** Schema JSON và mã thoát là những hợp đồng đã đóng băng. TypeScript và Python có độ phủ đã đo rộng nhất. Java và C# mới hơn; hãy đọc chúng qua [bảng độ trưởng thành](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). Những gì sắp tới, không có ngày tháng bịa đặt: [lộ trình công khai](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
617
-
618
- ### Đóng góp
619
-
620
- Quy tắc mới là đóng góp đầu tiên dễ nhất. Một lệnh duy nhất tạo khung cho quy tắc cùng các fixture must-fire **và** must-not-fire của nó. Quy tắc được tạo cố ý thất bại trên chính các fixture của nó cho đến khi logic phát hiện thật được viết, vì một bản nháp được phát hành là một quy tắc chưa ai đo:
621
-
622
- ```bash
623
- mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
624
- ```
625
-
626
- Thiết lập môi trường phát triển, các lệnh cổng thường trực, cùng các luật anti-creep và tường lửa fixture có trong [CONTRIBUTING.md](CONTRIBUTING.md).
627
-
628
- <br />
629
-
630
- <div align="center">
631
-
632
- <img src="assets/readme/closing.svg" alt="Chạy nó trên kho của bạn." width="100%" />
633
-
634
- ```bash
635
- npx mjolnir-qa@3.0.0
636
- ```
637
-
638
- [Đọc hướng dẫn](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Trang tài liệu](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
639
-
640
- <br />
641
-
642
- Đừng hỏi test có qua hay không.<br />
643
- Hãy hỏi bằng chứng có chứng minh rằng chúng xứng đáng được tin hay không.
644
-
645
- <sub>Được xây dựng bởi [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Giấy phép MIT</sub>
646
-
647
- </div>