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.ja.md
CHANGED
|
@@ -1,394 +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) | 日本語 | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](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) | 日本語 | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
25
30
|
|
|
26
|
-
[
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
[ドキュメント](#-ドキュメント)
|
|
31
|
+
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-15.
|
|
32
|
+
|
|
33
|
+
<!-- Source hash: 3541b09e8d04 -->
|
|
34
|
+
|
|
35
|
+
</details>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
<br />
|
|
40
|
+
|
|
41
|
+
## 緑のチェックは主張であって、証明ではない
|
|
42
|
+
|
|
43
|
+
緑のチェックが意味するのは、パイプラインが失敗しなかったということだけです。テストが実行されたことも、テストが失敗し得たことも意味しません。次のどれもが緑のまま通ります。
|
|
44
|
+
|
|
45
|
+
- コミットされた `.only` によって、900 件ではなく 3 件のテストしか実行されなかった
|
|
46
|
+
- ゲートとなるはずの job に付いた `continue-on-error: true`
|
|
47
|
+
- テストコマンドの後ろの `|| true`
|
|
48
|
+
- 何もアサートしない、あるいは本体が空のテスト
|
|
49
|
+
- 本当の失敗を運のいい成功に変えてしまうリトライのラッパー
|
|
50
|
+
- workflow がアップロードしているのに、一度も生成されていないレポート
|
|
51
|
+
- 競合状態を固定の sleep でかろうじて支えている箇所
|
|
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`、空のテスト、リトライの悪用 — は検疫ティアに属します。`--strict` の下でのみ実行され、`info` 重要度に制限されます:フラグを立てますが、決してゲートを閉じません。デフォルトのスキャン(`--strict` なしの `npx mjolnir-qa@latest`)はコアおよび拡張ルールのみをカバーします。アドバイザリレイヤーも欲しい場合は `--strict` を追加してください。
|
|
62
|
+
|
|
63
|
+
Mjölnir は、テストスイート、CI workflow、そして手元にあれば実際の実行レポートを読みます。テストを実行することも、依存関係をインストールすることも、スキャン対象のコードを実行することもありません。そして証拠がないときは、確信をでっち上げずにそう伝えます。
|
|
64
|
+
|
|
65
|
+
| 状況 | Mjölnir の報告内容 |
|
|
66
|
+
| -------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
67
|
+
| テスト宣言が見つからない | スコアは `null` で、**UNKNOWN** と表示されます。でっち上げの 100 には決してなりません。 |
|
|
68
|
+
| ベースラインや比較可能なリビジョンがない | **UNKNOWN** とし、理由を明示します。0 と仮定することは決してありません。 |
|
|
69
|
+
| スキャンが途中で打ち切られた(時間制限、読み取れないファイル) | **PARTIAL**、終了コード `2`。クリーンとして提示することは決してありません。 |
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="assets/readme/how-it-works.svg" alt="Mjölnir の仕組み。テストスイートと CI パイプラインを静的に読み、実際の実行レポートがあればそれも読みます。各検出結果を証拠レベルと信頼レベルで重み付けし(L3〜L5 に到達できるのは実際の実行だけです)、検出結果、信頼度スコア、そして凍結された終了コードに基づく CI ゲートを出力します。エージェントのループでは、AI が修正を書き、Mjölnir が再スキャンしてそれを証明します。" width="880" />
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<sub>このページのために構成し、等倍で表示しています。`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
|
+
## 動作を見る
|
|
80
|
+
|
|
81
|
+
CI workflow を持つ小さな Playwright スイート、[`examples/demo-repo`](examples/demo-repo) の実際のスキャンです。点数がどこで失われたかはこちら:
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<img src="assets/readme/terminal-hero.svg" alt="Mjölnir の減点内訳:WORTHINESS 80/100 WORTHY、カテゴリ別スコア、重大度別の減点ボックス、そして FIX THIS FIRST リスト" width="520" />
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
<sub>`npm run docs:hero` により実際のスキャンから生成され、CI でずれがないよう固定されています。同じスキャンの完全な `--verbose` レポートは [`demo.svg`](assets/readme/demo.svg)(`npm run docs:demo`)です。</sub>
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>動画で見る</strong> — スキャン、それが出力する修正、そして修正を証明する再スキャン</summary>
|
|
36
91
|
|
|
37
|
-
|
|
92
|
+
<br />
|
|
38
93
|
|
|
39
94
|
<p align="center">
|
|
40
|
-
<
|
|
95
|
+
<a href="assets/video/mjolnir-demo.mp4">
|
|
96
|
+
<img src="assets/video/mjolnir-demo-poster.png" alt="デモ録画の 1 フレーム:ターミナルウィンドウで npx mjolnir-qa@latest がデモリポジトリをスキャンしている様子" width="900" />
|
|
97
|
+
</a>
|
|
41
98
|
</p>
|
|
42
99
|
|
|
43
|
-
<sub>`
|
|
44
|
-
本物のレポーターで描画したもの——何ひとつ省いていません。
|
|
45
|
-
`npm run docs:demo` で再生成します。
|
|
46
|
-
[`tests/demo-asset-reproducibility.spec.ts`](tests/demo-asset-reproducibility.spec.ts)
|
|
47
|
-
は、成果物がツールの出力から逸れたら CI を落とします。</sub>
|
|
100
|
+
<sub>`npm run docs:video` により実際のスキャンから 1 フレームずつレンダリングしたもので、画面録画ではありません。フレームを選ぶと [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4) が開きます。</sub>
|
|
48
101
|
|
|
49
|
-
|
|
102
|
+
</details>
|
|
50
103
|
|
|
51
|
-
|
|
52
|
-
Python テストファイルを検出しました——4 言語/フォーマットを 1
|
|
53
|
-
パスで。
|
|
54
|
-
2. スイートへの信頼を弱める証拠を見つけました——ジョブをマスクする
|
|
55
|
-
`continue-on-error`、終了コードを呑み込む `|| true`、ハードな
|
|
56
|
-
sleep、壊れやすいセレクタ、ハードコードされたステージング URL、
|
|
57
|
-
`networkidle` 待ち。
|
|
58
|
-
3. それぞれをルール ID・場所・修正方法を備えた具体的な検出に——そして
|
|
59
|
-
PR にゲートをかけられる単一のスコアに変換しました。
|
|
104
|
+
### ひとつの検出結果を詳しく見る
|
|
60
105
|
|
|
61
|
-
|
|
106
|
+
どの検出結果も 4 つの問いに答えます。どこにあるのか、Mjölnir はどれだけ確信しているのか、そのルールはどれくらいの頻度で誤るのか、そしてどう直すのか。
|
|
62
107
|
|
|
63
|
-
|
|
108
|
+
<p align="center">
|
|
109
|
+
<img src="assets/readme/finding-anatomy.svg" alt="デモスキャンの最初の検出結果を、ターミナルが出力するとおりに示し、4 つの部分に印を付けたもの:場所、確信度、ルールの誤りやすさ、修正方法。" width="100%" />
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
`mjolnir explain QA-CI-001` は、ルールの信頼記録をまるごと出力します。実測の誤検知率と、その率によって得たティアも含まれます。
|
|
64
113
|
|
|
65
114
|
```text
|
|
66
|
-
|
|
115
|
+
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
67
116
|
|
|
68
117
|
Severity: error
|
|
69
118
|
Confidence: high
|
|
119
|
+
Tier: quarantine
|
|
70
120
|
Evidence: E2
|
|
71
|
-
|
|
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
|
|
72
126
|
|
|
73
127
|
WHAT WAS FOUND (real detector output, not a mockup)
|
|
74
128
|
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
75
129
|
|
|
76
130
|
WHY IT MATTERS
|
|
77
|
-
This job can fail every day and CI will still show green. The checkmark
|
|
78
|
-
|
|
131
|
+
This job can fail every day and CI will still show green. The checkmark on
|
|
132
|
+
this workflow cannot be trusted.
|
|
79
133
|
|
|
80
134
|
HOW TO FIX
|
|
81
135
|
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
82
|
-
```
|
|
83
136
|
|
|
84
|
-
|
|
85
|
-
「通った」と告げているのに実際には通っていない箇所です。
|
|
137
|
+
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
86
138
|
|
|
87
|
-
|
|
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
|
|
88
146
|
|
|
89
|
-
|
|
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.
|
|
90
150
|
|
|
91
|
-
|
|
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.
|
|
92
154
|
|
|
93
|
-
|
|
94
|
-
npx mjolnir-qa@latest
|
|
155
|
+
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
95
156
|
```
|
|
96
157
|
|
|
97
|
-
|
|
98
|
-
|
|
158
|
+
これが価値の単位です。CI が、得てもいない成功を報告している箇所がひとつあるということ。
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## クイックスタート
|
|
99
163
|
|
|
100
164
|
```bash
|
|
101
|
-
npx mjolnir-qa@latest
|
|
165
|
+
npx mjolnir-qa@latest
|
|
102
166
|
```
|
|
103
167
|
|
|
104
|
-
|
|
105
|
-
書き出します——それだけです。ほかはすべてオプションです。
|
|
106
|
-
|
|
107
|
-
| コマンド | 何をするか |
|
|
108
|
-
| ----------------------------------- | ----------------------------------------------------- |
|
|
109
|
-
| `mjolnir` | リポジトリ全体のスキャン + 信頼性スコア |
|
|
110
|
-
| `mjolnir --scope changed` | ブランチが導入したものだけ——CI 形態 |
|
|
111
|
-
| `mjolnir ci install` | アドバイザリな PR ワークフローを生成 |
|
|
112
|
-
| `mjolnir explain QA-CI-001` | 何 / なぜ / 修正方法 + 1 ルールの実測 FP 率 |
|
|
113
|
-
| `mjolnir rules --unmeasured` | 測定ではなく仮定で動いているルール |
|
|
114
|
-
| `mjolnir --json` / `--format sarif` | 機械可読 / GitHub Code Scanning |
|
|
115
|
-
| `mjolnir --strict` | 隔離層(quarantine)のルールも実行(FP リスクが高い) |
|
|
168
|
+
カレントディレクトリをスキャンし、Trust Report を出力します。何が見つかったか、どこまで信頼できるか、その理由、次に何をすべきか。ゲート以上のものが何も見つからなければ `0` で終了します。
|
|
116
169
|
|
|
117
|
-
|
|
118
|
-
<summary><strong>何かが flaky なとき</strong></summary>
|
|
170
|
+
CI では、ブランチが持ち込んだものだけをスキャンしましょう。そうすれば、レガシーなスイートが最初の pull request を埋もれさせることはありません。
|
|
119
171
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
| `mjolnir triage ./test-results/` | 実行履歴からの隔離提案 |
|
|
124
|
-
| `mjolnir pw-report ./test-results/` | Playwright 実行サマリー——リトライ / flake / 最遅 |
|
|
125
|
-
| `mjolnir doctor:playwright` | Playwright 専用の深いスキャン + Selector Health Score |
|
|
172
|
+
```bash
|
|
173
|
+
npx mjolnir-qa@latest --scope changed
|
|
174
|
+
```
|
|
126
175
|
|
|
127
|
-
|
|
176
|
+
`mjolnir ci install` はこれを GitHub Actions の workflow として書き出します。メジャータグ `v1` に固定した [action](https://github.com/Sergey-Bar/Mjolnir#readme) を使います(`--no-action` を付ければ素の `npx`)。ブロックすべきだとあなたが決めるまで、助言的な扱いのままです。
|
|
177
|
+
|
|
178
|
+
| コマンド | 内容 |
|
|
179
|
+
| ----------------------------------- | ----------------------------------------------------------------- |
|
|
180
|
+
| `mjolnir` | Trust Report:判定、確信度、次のアクション |
|
|
181
|
+
| `mjolnir --scope changed` | ブランチが持ち込んだものだけ(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 リスクは高め) |
|
|
128
191
|
|
|
129
192
|
<details>
|
|
130
|
-
<summary><strong
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
| `mjolnir
|
|
137
|
-
| `mjolnir
|
|
138
|
-
| `mjolnir
|
|
139
|
-
| `mjolnir
|
|
140
|
-
| `mjolnir
|
|
141
|
-
| `mjolnir
|
|
142
|
-
| `mjolnir
|
|
143
|
-
| `mjolnir
|
|
144
|
-
| `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` | shields.io のエンドポイント JSON とスニペット |
|
|
219
|
+
| `mjolnir --cache` | ローカルの判定キャッシュによる差分再スキャン |
|
|
220
|
+
| `mjolnir --format mermaid` | PR コメント用のテストアーキテクチャ図 |
|
|
221
|
+
|
|
222
|
+
`mjolnir help <command>` は、どのコマンドについても使い方、例、次のステップを出力します。
|
|
145
223
|
|
|
146
224
|
</details>
|
|
147
225
|
|
|
148
|
-
|
|
149
|
-
`npm i -g mjolnir-qa`。Node.js ≥ 22.18 が必要です。Windows、macOS、
|
|
150
|
-
Linux で動作します。
|
|
151
|
-
|
|
152
|
-
---
|
|
226
|
+
Windows、macOS、Linux 上で **Node.js ≥ 22.18** が必要です。グローバルにインストールしたい場合は `npm i -g mjolnir-qa`。この下限はビルドツールチェーンに由来します(tsdown がこれをターゲットにし、リリースパイプラインがこれに対してスモークテストを行います)。実行時の依存関係はそれ以上を必要としません。
|
|
153
227
|
|
|
154
|
-
|
|
228
|
+
<br />
|
|
155
229
|
|
|
156
|
-
|
|
157
|
-
緑のチェックマークが本当に値するものかの証拠を必要としている人。
|
|
158
|
-
- **プラットフォーム / DevEx チーム** — CI の完全性とリリースゲートに
|
|
159
|
-
責任を持つ人々。`continue-on-error` が赤いパイプラインを静かに緑に
|
|
160
|
-
塗り替えないことを気にする人々。
|
|
161
|
-
- **OSS メンテナ** — ローカルでも CI でも、ネットワーク呼び出しゼロで
|
|
162
|
-
動く安価で常時有効な検証ゲートを求めている人。
|
|
230
|
+
## Mjölnir が検出するもの
|
|
163
231
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
232
|
+
<p align="center">
|
|
233
|
+
<img src="assets/readme/stack.svg" alt="あなたのスタックで動きます:ルールがカバーする言語、テストフレームワーク、CI システム(ルールレジストリより)。" width="100%" />
|
|
234
|
+
</p>
|
|
167
235
|
|
|
168
|
-
|
|
169
|
-
| --- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
170
|
-
| ⚖️ | **信頼性スコア** — ひとつの数字、透過的な減点テーブル、ブラックボックスなし |
|
|
171
|
-
| 🎭 | **Selector Health Score** — 合格率だけでなく、Playwright ロケータを評価する |
|
|
172
|
-
| 🔬 | **ランタイムフォレンジクス** — 実際の Playwright/JUnit 実行データを読み、静的な推測ではなく `TRUE-FLAKE` を捉える |
|
|
173
|
-
| 🚨 | **CI 完全性ルール** — `continue-on-error`、`\|\| true`、その他の偽グリーンの手口を検出する |
|
|
174
|
-
| 🐍 | **4 つの Playwright バインディングすべて** — TypeScript、Python、Java、C#/.NET — さらに pytest、JUnit/TestNG、CI ワークフロー |
|
|
175
|
-
| 🔒 | **ローカルファースト** — スキャン中のネットワーク呼び出しゼロ、テレメトリゼロ、数秒で実行 |
|
|
236
|
+
4 つのファミリー(テストの衛生、テストの品質、Playwright、CI の整合性)にわたる **79 のルール**が、TypeScript と JavaScript、Python、Java、C#、GitHub Actions の YAML を対象とします。Playwright は 4 つのバインディングすべてに対応し、さらに pytest、JUnit、TestNG、NUnit、xUnit、MSTest、Jest、Vitest、Mocha をカバーし、Cypress と Selenium には入門レベルの対応があります。雰囲気をつかむために、そのうち 9 つを示します。
|
|
176
237
|
|
|
177
|
-
|
|
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 | アサーションのないテスト | error | quarantine |
|
|
244
|
+
| QA-TQUAL-009 | await されていない promise のアサーション | error | quarantine |
|
|
245
|
+
| QA-PW-002 | await されていない locator のアサーション | error | core |
|
|
246
|
+
| QA-PW-004 | 壊れやすい CSS/XPath セレクター | warning | quarantine |
|
|
247
|
+
| QA-PY-002 | スキップされたテスト(`skip`、strict でない `xfail`) | warning | core |
|
|
248
|
+
| QA-CS-103 | アサーションのないテストメソッド | error | core |
|
|
178
249
|
|
|
179
|
-
|
|
180
|
-
出荷されます。自分自身のネガティブフィクスチャで発火するルールは出荷
|
|
181
|
-
できません——それが false-positive の防火壁です。
|
|
250
|
+
完全なカタログはレジストリから生成され、手作業で保守されることはありません:`mjolnir rules --md`、[`docs/rules/`](docs/rules/)、または [チェック内容ガイド](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks)。
|
|
182
251
|
|
|
183
252
|
<details>
|
|
184
|
-
<summary><strong
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
|
191
|
-
|
|
|
192
|
-
| QA-TEST-
|
|
193
|
-
| QA-TEST-
|
|
194
|
-
| QA-TEST-
|
|
253
|
+
<summary><strong>この README に登場するすべてのルール</strong>を 1 つの表に</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 | 衛生 | アサーションのないテスト | error | quarantine |
|
|
264
|
+
| QA-TEST-004 | 衛生 | 固定の sleep(`waitForTimeout`、`sleep()`、`delay()`) | warning | extended |
|
|
265
|
+
| QA-TEST-006 | 衛生 | 不安定さを隠すリトライの乱用 | warning | quarantine |
|
|
266
|
+
| QA-TEST-010 | 衛生 | 空のテスト本体 | error | quarantine |
|
|
267
|
+
| QA-TQUAL-002 | 品質 | トートロジー的なアサーション | error | quarantine |
|
|
268
|
+
| QA-TQUAL-009 | 品質 | await されていない promise のアサーション | error | quarantine |
|
|
269
|
+
| QA-TQUAL-011 | 品質 | コメントアウトされたテスト | warning | extended |
|
|
270
|
+
| QA-PW-002 | Playwright | await されていない locator のアサーション | error | core |
|
|
271
|
+
| QA-PW-003 | Playwright | `page.pause()` / `test.only()` がコミットされている | error | core |
|
|
272
|
+
| QA-PW-004 | Playwright | 壊れやすい CSS/XPath セレクター | warning | quarantine |
|
|
273
|
+
| QA-PW-123 | Playwright | ハードコードされた環境 URL | warning | quarantine |
|
|
274
|
+
| QA-PW-140 | Playwright | `maxDiffPixelRatio` のないスクリーンショット | warning | core |
|
|
275
|
+
| QA-CI-001 | CI | `continue-on-error` が失敗しているゲートを覆い隠している | error | quarantine |
|
|
276
|
+
| QA-CI-002 | CI | `\|\| true` が終了コードを握りつぶす | error | extended |
|
|
277
|
+
| QA-CI-005 | CI | レポートが使われているのに生成されていない | error | quarantine |
|
|
278
|
+
| QA-CI-007 | CI | テストを包むリトライのラッパー | warning | extended |
|
|
279
|
+
| QA-CI-008 | CI | 常に成功する step が失敗を覆い隠している | error | quarantine |
|
|
280
|
+
| QA-CI-009 | CI | 終了コードが伝播されない(pipefail なしの `\|`、`;` での連結) | error | extended |
|
|
281
|
+
| QA-CI-010 | CI | ブロックすべき場面でテストがスキップされている | error | quarantine |
|
|
282
|
+
| QA-PY-002 | Python | スキップされたテスト(`skip`、strict でない `xfail`) | warning | core |
|
|
283
|
+
| QA-PY-003 | Python | アサーションのないテスト関数 | error | quarantine |
|
|
284
|
+
| QA-PY-005 | Python | テスト内の `time.sleep()` | warning | extended |
|
|
285
|
+
| QA-PY-012 | Python | トートロジー的なアサーション | error | quarantine |
|
|
286
|
+
| QA-JV-101 | Java | 無効化されたテスト(`@Disabled`) | warning | core |
|
|
287
|
+
| QA-JV-102 | Java | 固定の sleep(`Thread.sleep()`) | warning | extended |
|
|
288
|
+
| QA-JV-103 | Java | アサーションのないテストメソッド | error | extended |
|
|
289
|
+
| QA-JV-105 | Java | Playwright の `waitForTimeout()` による固定の sleep | warning | core |
|
|
290
|
+
| QA-JV-106 | Java | ロールベースの locator ではなく壊れやすいセレクター | warning | quarantine |
|
|
291
|
+
| QA-CS-101 | C# | スキップされたテスト(`[Ignore]`、`[Fact(Skip=)]`) | warning | core |
|
|
292
|
+
| QA-CS-102 | C# | 固定の sleep(`Thread.Sleep` / `Task.Delay`) | warning | core |
|
|
293
|
+
| QA-CS-103 | C# | アサーションのないテストメソッド | error | core |
|
|
294
|
+
| QA-CS-105 | C# | `WaitForTimeoutAsync()` による固定の sleep | warning | extended |
|
|
295
|
+
| QA-CS-106 | C# | ロールベースの locator ではなく壊れやすいセレクター | warning | quarantine |
|
|
296
|
+
|
|
297
|
+
Python には QA-PY-001…012(pytest の衛生)と QA-PY-101…108(Python 版 Playwright)もあります。Cypress と Selenium にはそれぞれ 3 つのルールからなるスターターセットがあります。
|
|
195
298
|
|
|
196
299
|
</details>
|
|
197
300
|
|
|
198
|
-
|
|
199
|
-
<summary><strong>テスト品質</strong></summary>
|
|
301
|
+
どのルールも must-fire **と** must-not-fire の fixture を備えてリリースされ、自分自身のネガティブ fixture で発火するルールはリリースできません。これが誤検知ファイアウォールです。`mjolnir doctor` がこのリポジトリ自身の CI でそれを強制しています。
|
|
200
302
|
|
|
201
|
-
|
|
202
|
-
| ------------ | --------------------------------------- | -------- |
|
|
203
|
-
| QA-TQUAL-002 | トートロジカルなアサーション | error |
|
|
204
|
-
| QA-TQUAL-009 | await されていない promise アサーション | error |
|
|
205
|
-
| QA-TQUAL-011 | コメントアウトされたテスト | warning |
|
|
303
|
+
### Selector Health Score
|
|
206
304
|
|
|
207
|
-
|
|
305
|
+
`mjolnir doctor:playwright` は、各 locator が要素をどう見つけるかで評価します。ユーザーと同じ方法か(ロール、ラベル、テキスト)、明示的な契約か(`data-testid`)、構造上の偶然か(CSS の連結、XPath)。各ファイルに 0〜100 のスコアが付きます。
|
|
208
306
|
|
|
209
|
-
|
|
210
|
-
|
|
307
|
+
```text
|
|
308
|
+
▍ SELECTOR HEALTH
|
|
211
309
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
| QA-PW-003 | コミットされた `page.pause()` / `test.only()` | error |
|
|
216
|
-
| QA-PW-004 | 脆弱な CSS/XPath セレクタ | warning |
|
|
217
|
-
| QA-PW-123 | ハードコードされた環境 URL | warning |
|
|
310
|
+
e2e/login.spec.ts
|
|
311
|
+
[█████████████░░░░░░░] 65 / 100
|
|
312
|
+
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
218
313
|
|
|
219
|
-
|
|
314
|
+
e2e/checkout.spec.ts
|
|
315
|
+
[██████████████████░░] 88 / 100
|
|
316
|
+
role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
317
|
+
```
|
|
220
318
|
|
|
221
|
-
|
|
222
|
-
<summary><strong>CI 完全性</strong></summary>
|
|
223
|
-
|
|
224
|
-
| ID | ルール | Severity |
|
|
225
|
-
| --------- | ---------------------------------------------------------------- | -------- |
|
|
226
|
-
| QA-CI-001 | `continue-on-error` が失敗をマスクする | error |
|
|
227
|
-
| QA-CI-002 | `\|\| true` が終了コードを呑み込む | error |
|
|
228
|
-
| QA-CI-005 | レポートが消費されるのに生成されない | error |
|
|
229
|
-
| QA-CI-007 | テストを包むリトライラッパー | warning |
|
|
230
|
-
| QA-CI-008 | 常に成功するステップが失敗をマスクする | error |
|
|
231
|
-
| QA-CI-009 | テストの終了コードが伝播しない(pipefail なしの `\|`、`;` 連結) | error |
|
|
232
|
-
| QA-CI-010 | ブロックすべき場所でテストがスキップされる(skip-on-PR ガード) | error |
|
|
319
|
+
これが測るのは**正しさではなく耐久性**です。`.btn.btn-primary > div:nth-child(2)` は今日は通り、誰かがマークアップに触れるまで通り続けます。低いスコアはテストが壊れていると主張するものではなく、誰も維持を約束していないマークアップに依存していることを示すだけです。
|
|
233
320
|
|
|
234
|
-
|
|
321
|
+
<br />
|
|
235
322
|
|
|
236
|
-
|
|
237
|
-
<summary><strong>Python / pytest 🐍</strong></summary>
|
|
323
|
+
## 信頼度スコア
|
|
238
324
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
| QA-PY-003 | アサーションのないテスト関数 | error |
|
|
243
|
-
| QA-PY-005 | テスト内の `time.sleep()` | warning |
|
|
244
|
-
| QA-PY-012 | トートロジカルなアサーション | error |
|
|
325
|
+
<p align="center">
|
|
326
|
+
<img src="assets/readme/score-gauge.svg" alt="0 から 100 までの信頼度スケール。マーカーがすべてのスコアを走査します:50 未満は UNWORTHY、50〜79 は NEEDS WORK、80〜99 は WORTHY、100 は FORGED" width="720" />
|
|
327
|
+
</p>
|
|
245
328
|
|
|
246
|
-
|
|
329
|
+
<sub>0 から 100 までのすべてのスコアを、実際の `deriveScoreState` で配置したもの。`npm run docs:gauge` で生成され、CI でずれがないよう固定されています。</sub>
|
|
247
330
|
|
|
248
|
-
|
|
331
|
+
| スコア | 判定 |
|
|
332
|
+
| --------- | ------------------------------------- |
|
|
333
|
+
| `0 – 49` | **UNWORTHY** |
|
|
334
|
+
| `50 – 79` | **NEEDS WORK** |
|
|
335
|
+
| `80 – 99` | **WORTHY** |
|
|
336
|
+
| `100` | **FORGED** |
|
|
337
|
+
| `null` | **UNKNOWN**:テスト宣言が見つからない |
|
|
249
338
|
|
|
250
|
-
|
|
251
|
-
<summary><strong>Java / JUnit · TestNG ☕</strong></summary>
|
|
339
|
+
**計算方法**。重大度が基本の減点を決め(`error −8`、`warning −3`、`info −1`)、証拠レベルがそれを割り引きます。E2 は満額、E1 は半分(切り捨て)、E0 はゼロです。合計はスイートの規模で正規化され、ファイル単位ではなくテスト宣言あたりの減点になります。ターミナルに表示されるのは、スコアが使ったのと同じ割引後の数値です。隠れた第二のモデルはありません。詳細:[docs/SCORING.md](docs/SCORING.md) と [スコアリングガイド](https://sergey-bar.github.io/Mjolnir/guide/scoring)。
|
|
252
340
|
|
|
253
|
-
|
|
254
|
-
| --------- | ---------------------------------------------- | -------- |
|
|
255
|
-
| QA-JV-101 | 無効化されたテスト(`@Disabled`) | warning |
|
|
256
|
-
| QA-JV-102 | ハードな sleep(`Thread.sleep()`) | warning |
|
|
257
|
-
| QA-JV-103 | アサーションのないテストメソッド | error |
|
|
258
|
-
| QA-JV-105 | Playwright のハードな sleep `waitForTimeout()` | warning |
|
|
259
|
-
| QA-JV-106 | role ロケータの代わりの脆弱なセレクタ | warning |
|
|
341
|
+
**100 が意味しないこと**。ソフトウェアが正しいことも、スイートが十分であることも、製品に欠陥がないことも意味しません。意味するのはただひとつ:**このスキャンとこの証拠モデルのもとで、Mjölnir が評価したルールのどれも減点を生まなかった**ということです。
|
|
260
342
|
|
|
261
|
-
|
|
343
|
+
<br />
|
|
262
344
|
|
|
263
|
-
|
|
264
|
-
<summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
|
|
345
|
+
## 証拠モデル
|
|
265
346
|
|
|
266
|
-
|
|
267
|
-
| --------- | --------------------------------------------------- | -------- |
|
|
268
|
-
| QA-CS-101 | スキップされたテスト(`[Ignore]`、`[Fact(Skip=)]`) | warning |
|
|
269
|
-
| QA-CS-102 | ハードな sleep(`Thread.Sleep` / `Task.Delay`) | warning |
|
|
270
|
-
| QA-CS-103 | アサーションのないテストメソッド | error |
|
|
271
|
-
| QA-CS-105 | ハードな sleep `WaitForTimeoutAsync()` | warning |
|
|
272
|
-
| QA-CS-106 | role ロケータの代わりの脆弱なセレクタ | warning |
|
|
347
|
+
どの検出結果にも 2 つのラベルが付きます。Mjölnir がどれだけ確信しているか、そしてその検出結果がどこまで確認されたか。これが、パターンを報告するだけのツールと、リリースの判断を委ねられるツールとの違いです。
|
|
273
348
|
|
|
274
|
-
|
|
349
|
+
**どれだけ確かか — 証拠レベル。**
|
|
275
350
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
### どれだけが測定されているか
|
|
286
|
-
|
|
287
|
-
**99 ルールのうち 78 ルールが、実際の OSS コードに対して測定された
|
|
288
|
-
false-positive 率を備えています**(各ルールにつき手作業で分類された
|
|
289
|
-
検出 ≥ 10 件。[docs/FP-AUDIT.md](docs/FP-AUDIT.md) 参照)。残り 21 ルール
|
|
290
|
-
は作者の推定で出荷されます。すべてのスキャンのフッターは、_発火した_
|
|
291
|
-
ルールのうちいくつが測定済みかを教えてくれます。`mjolnir rules --unmeasured`
|
|
292
|
-
は未測定のものを列挙します。各ルールの `mjolnir explain` ページはその
|
|
293
|
-
それゆえ隔離されています。この数字を増やすことが、プロジェクトの継続的
|
|
294
|
-
な仕事です。
|
|
295
|
-
|
|
296
|
-
### ルールのティアと言語ごとの成熟度
|
|
297
|
-
|
|
298
|
-
すべてのルールは、**測定された** false-positive 率に基づいて `core`、
|
|
299
|
-
`extended`、`quarantine` のいずれかに割り当てられます:
|
|
300
|
-
|
|
301
|
-
| ティア | 意味 | 既定のスキャン | `--strict` |
|
|
302
|
-
| ------------ | ------------------------------- | :------------: | :--------: |
|
|
303
|
-
| `core` | 実測 FP ≤ 10 % | ✅ | ✅ |
|
|
304
|
-
| `extended` | 実測 FP ≤ 30 % | ✅ | ✅ |
|
|
305
|
-
| `quarantine` | 30 % 超、または未測定(n < 10) | ❌ | ✅ |
|
|
306
|
-
|
|
307
|
-
| 言語 | アダプタ | 現在のカバレッジ |
|
|
308
|
-
| --------------- | -------------- | ---------------------------------------------- |
|
|
309
|
-
| TypeScript / JS | コンパイラ AST | 最も広く、最も測定済み——主に `core`/`extended` |
|
|
310
|
-
| Python / pytest | 正規表現層 | 広範、コーパス監査済み——主に `core`/`extended` |
|
|
311
|
-
| Java | 正規表現層 | より新しい——主に `extended`/`quarantine` |
|
|
312
|
-
| C# / .NET | 正規表現層 | より新しい——主に `extended`/`quarantine` |
|
|
313
|
-
|
|
314
|
-
TypeScript と Python が最も広い測定済みカバレッジを持ちます。Java と
|
|
315
|
-
C# は出荷済みでドキュメントもあり、実際のコンシューマスイート(バインディング
|
|
316
|
-
ライブラリ自身のテストではなく)が監査されるまでは、ヘッドラインの数字から
|
|
317
|
-
外れています。
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
## スコアの仕組み
|
|
351
|
+
| レベル | 名称 | 意味 | 減点 |
|
|
352
|
+
| ------ | ------------------ | ---------------------------------------------------------- | ---- |
|
|
353
|
+
| **E2** | 決定論的な証明 | 書かれたとおりのコードに欠陥が存在する | 満額 |
|
|
354
|
+
| **E1** | パターンによる証拠 | 欠陥と強く結びついたパターンが一致した | 半分 |
|
|
355
|
+
| **E0** | 観察 | 知っておく価値あり。何かが間違っているという主張ではない。 | ゼロ |
|
|
356
|
+
|
|
357
|
+
検出の確信度は、証明の強さとは別物です。ルールは探していたものに一致したと確信していても、実際にはヒューリスティックを見ているだけかもしれません。E1 の検出結果は読んで判断するためのものであり、盲目的に適用するものではありません。この境界は、ターミナル、JSON、そしてエージェントへの引き継ぎのすべてで、検出結果に明記されています。
|
|
358
|
+
|
|
359
|
+
**どこまで確認されたか — 信頼レベル**。ほとんどの検出結果はコードを読むことから得られます。実際のテスト実行のレポートを Mjölnir に渡せば、コードが本当に実行されたことを確認できます。
|
|
322
360
|
|
|
323
361
|
<p align="center">
|
|
324
|
-
<img src="assets/readme/
|
|
362
|
+
<img src="assets/readme/trust-ladder.svg" alt="L0 から L5 までの信頼のはしご。L0〜L2 はコードを読むことから得られ、L3〜L5 には実際の実行レポートが必要です。はしごの切れ目がその境目を示しています。" width="100%" />
|
|
325
363
|
</p>
|
|
326
364
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
365
|
+
| レベル | わかりやすく言うと | 必要なもの |
|
|
366
|
+
| ------ | -------------------- | -------------------------------------------------------------- |
|
|
367
|
+
| **L0** | 記録済み | コードを読む |
|
|
368
|
+
| **L1** | 問題らしく見える | コードを読む:パターンが一致 |
|
|
369
|
+
| **L2** | コードで証明済み | コードを読む:欠陥は構造的 |
|
|
370
|
+
| **L3** | ファイルが実行された | 実行レポートが、検出結果のファイルが実行されたことを示している |
|
|
371
|
+
| **L4** | テストが実行された | 実行レポートが、検出結果のテストが実行されたことを示している |
|
|
372
|
+
| **L5** | 実行結果が一致 | 実行自体の結果が欠陥のクラスを裏付けている |
|
|
330
373
|
|
|
331
|
-
|
|
332
|
-
露出度(テスト宣言あたりの減点)で正規化します。証拠で重みづけされた減点は、
|
|
333
|
-
弱いシグナルほど安いことを意味します。ターミナルはスコアが使うのと同じ
|
|
334
|
-
割引後の数字を表示します——ブラックボックスはありません。完全な方法論は
|
|
335
|
-
[docs/SCORING.md](docs/SCORING.md)。
|
|
374
|
+
静的スキャンは L2 で止まります。検出結果を L3 以上に引き上げられるのは実際の実行レポート(Playwright JSON、Jest または Vitest JSON、JUnit XML)だけです。したがって、実行されている様子が一度も確認されていない検出結果が、実行されたと主張することはありません。定義:[docs/TERMINOLOGY.md](docs/TERMINOLOGY.md)。
|
|
336
375
|
|
|
337
|
-
|
|
376
|
+
### どれだけが実測されているか
|
|
338
377
|
|
|
339
|
-
|
|
340
|
-
| ------- | ---------------- |
|
|
341
|
-
| ≥ 80 | ✓ **WORTHY** |
|
|
342
|
-
| 50 – 79 | ⚠ **NEEDS WORK** |
|
|
343
|
-
| < 50 | ✖ **UNWORTHY** |
|
|
378
|
+
**79 のルールのうち 74 は、実際の OSS コードに対して測定した誤検知率を持っています**(それぞれ手作業で分類した検出結果が 10 件以上。[docs/FP-AUDIT.md](docs/FP-AUDIT.md) を参照)。残りの 5 つは作成者の見積もりでリリースされており、`mjolnir explain` の中でルールごとにそう明記しています。`mjolnir rules --unmeasured` がそれらを一覧表示し、各スキャンのフッターは、実際に*発火した*ルールのうちいくつが実測済みかを報告します。
|
|
344
379
|
|
|
345
|
-
|
|
346
|
-
決めます:
|
|
380
|
+
率が悪くても公開したままにします。QA-TEST-001(コミットされた `.only`)は実際のリポジトリでの監査結果が悪く、そのため quarantine に置かれています。QA-PW-141 を含む各ルールの最新の数値は監査に載っています。
|
|
347
381
|
|
|
348
|
-
|
|
349
|
-
| ------ | ---------------------------- | ----------------- | ----------------------------------------------------------- |
|
|
350
|
-
| E2 | 決定論的な欠陥 | 全額減点 | コミットされた `.only` — 構造的に証明可能 |
|
|
351
|
-
| E1 | ヒューリスティックなパターン | 半分の減点 | 正規表現で見つかった `sleep()` — 強いシグナル、証明ではない |
|
|
352
|
-
| E0 | 観察 | ゼロ(info のみ) | 報告されるが CI をゲートすることも減点することもない |
|
|
382
|
+
### ルールの信頼ティア
|
|
353
383
|
|
|
354
|
-
|
|
355
|
-
指します: E2 の検出は構造的な証明であり、E1 の検出は適切に位置づけられた
|
|
356
|
-
警告であって、形式的な証明ではありません。
|
|
384
|
+
ティアは意見ではなく、実測の誤検知率に従います。
|
|
357
385
|
|
|
358
|
-
|
|
359
|
-
|
|
386
|
+
| ティア | 実測 FP | 動作 |
|
|
387
|
+
| -------------- | ---------------------------------- | ------------------------------------------------ |
|
|
388
|
+
| **core** | ≤ 10% | デフォルトのレポート、ゲートになる |
|
|
389
|
+
| **extended** | ≤ 30% | デフォルトのレポート、確信度は低め |
|
|
390
|
+
| **quarantine** | > 30% または明示的に宣言されたもの | `--strict` のみ、info が上限、ゲートにはならない |
|
|
391
|
+
| _未測定_ | n < 10 | 測定されるまで core に昇格できない |
|
|
360
392
|
|
|
361
|
-
|
|
393
|
+
FP バンドはティアを降格することしかできません — 明示的に `quarantine` に宣言されたルールをそこから昇格させることはありません。明示的に quarantine に置かれたルールは、測定された FP 率に関係なく quarantine のままです。
|
|
362
394
|
|
|
363
|
-
|
|
395
|
+
昇格、降格、言語ごとの成熟度:[ルールのライフサイクル](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle)。
|
|
364
396
|
|
|
365
|
-
|
|
397
|
+
### なぜこれは linter ではないのか
|
|
366
398
|
|
|
367
|
-
|
|
368
|
-
▚ SELECTOR HEALTH — e2e/checkout.spec.ts
|
|
399
|
+
linter は、コードがルールに従っているかを教えてくれます。Mjölnir は、あなたの検証が信頼できるかを教えてくれます。
|
|
369
400
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
401
|
+
| | linter(ESLint、SonarQube) | カバレッジツール | AI コードレビュー | **Mjölnir** |
|
|
402
|
+
| -------------------------------------------------------- | :-------------------------: | :--------------: | :---------------: | :------------------: |
|
|
403
|
+
| 製品コードではなく、**検証の仕組み**をスコアリングする | いいえ | いいえ | いいえ | はい |
|
|
404
|
+
| CI workflow の整合性(`continue-on-error`、`\|\| true`) | いいえ | いいえ | diff のみ | はい |
|
|
405
|
+
| Playwright の locator の耐久性を評価(Selector Health) | いいえ | いいえ | いいえ | はい |
|
|
406
|
+
| 実際の実行データを読んで `TRUE-FLAKE` を判定 | いいえ | いいえ | いいえ | はい |
|
|
407
|
+
| ルールごとの実測誤検知率を公開 | いいえ | いいえ | いいえ | はい |
|
|
408
|
+
| アサーションのないテストを検出 | はい\* | いいえ | 場合による | はい |
|
|
409
|
+
| 固定の sleep を検出(`waitForTimeout`、`time.sleep`) | はい\* | いいえ | 場合による | はい |
|
|
410
|
+
| 決定論的(同じ入力なら同じ出力) | はい | はい | いいえ | はい |
|
|
411
|
+
| スキャンあたりのコスト | 無料 | 無料 | トークン | **ゼロ**(ローカル) |
|
|
412
|
+
|
|
413
|
+
<sub>\*`eslint-plugin-jest` と `eslint-plugin-playwright`(`expect-expect`、`no-wait-for-timeout`)、および SonarQube 独自のアサーションルールでカバーされます。各列は、テストスイートを検証する際のデフォルトの挙動を示しています。プラグイン、有料プラン、カスタムルールによって一部の答えは変わります。これはポジショニングの概要であって、ベンチマークではありません。</sub>
|
|
373
414
|
|
|
374
|
-
|
|
375
|
-
沈めます——どの振る舞いが退行したかを告げずに、あらゆる DOM リファクタで
|
|
376
|
-
壊れるからです。
|
|
415
|
+
AI レビューも併用してください。AI レビューは、どんなパターンにも見つけられないニュアンス、意図、設計上の欠陥を捉えます。Mjölnir が捉えるのは、意図的に見えるために AI レビューが見落とすものです:コミットされた `.only`、握りつぶされた終了コード、テストの job に付いた `continue-on-error`。こうしたものに必要なのは推論ではなくスキャンです。
|
|
377
416
|
|
|
378
|
-
|
|
417
|
+
<br />
|
|
379
418
|
|
|
380
|
-
##
|
|
419
|
+
## 実行時フォレンジック
|
|
381
420
|
|
|
382
|
-
|
|
383
|
-
読みます——あらゆるランナーの Playwright JSON レポートと JUnit XML
|
|
384
|
-
です:
|
|
421
|
+
静的解析は、一度も実行されていないコードについて推論します。フォレンジックは、実際に何が起きたかを読みます:どのランナーのものでも、Playwright JSON、Jest JSON、Vitest JSON、JUnit XML に対応します。
|
|
385
422
|
|
|
386
423
|
```bash
|
|
387
424
|
mjolnir forensics ./test-results/
|
|
388
425
|
```
|
|
389
426
|
|
|
390
427
|
```text
|
|
391
|
-
|
|
428
|
+
▍ FLAKINESS LEADERBOARD
|
|
392
429
|
|
|
393
430
|
3 tests · 1 failed · 1 flaky · 1 retried
|
|
394
431
|
|
|
@@ -398,291 +435,184 @@ FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
|
398
435
|
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
399
436
|
```
|
|
400
437
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
438
|
+
`TRUE-FLAKE` は、テストがリトライされたという意味ではありません。そのテストが**少なくとも 1 回の試行で失敗し、その後緑で終わった**という意味です:運による成功であり、最終的なチェックが何を示していても検出されます。`mjolnir triage` はその履歴を隔離の提案に変え、`mjolnir pw-report` は実行を要約します。検出結果を信頼レベル L3 以上に引き上げるのも、これと同じ実行レポートです。
|
|
439
|
+
|
|
440
|
+
<br />
|
|
441
|
+
|
|
442
|
+
## CI の整合性
|
|
404
443
|
|
|
405
|
-
|
|
444
|
+
テストが通っていても、それを取り巻くパイプラインが失敗しようがない、ということがあります。Mjölnir は workflow も読みます:`continue-on-error`、`|| true`、伝播されない終了コード、常に成功する step、使われているのに生成されないレポート、そしてブロックすべきイベントでスキップされるゲート。各検出結果は job、step、行を示し、それぞれの証拠レベルを持ちます。
|
|
406
445
|
|
|
407
|
-
|
|
446
|
+
PR workflow を生成します(デフォルトは助言的):
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
mjolnir ci install
|
|
450
|
+
```
|
|
408
451
|
|
|
409
|
-
|
|
410
|
-
検証が信頼できるかを教えます。
|
|
452
|
+
または、既存の workflow に Marketplace の action を追加します:
|
|
411
453
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
454
|
+
```yaml
|
|
455
|
+
- uses: Sergey-Bar/Mjolnir@v1
|
|
456
|
+
with:
|
|
457
|
+
scope: changed
|
|
458
|
+
fail-on: error
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
メジャーラインに追従するなら `@v1` を、再現可能なゲートにするなら正確なタグ(`@v0.5.32`)を固定してください。[docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) では Marketplace、Smithery、MCP レジストリについて説明しています。
|
|
462
|
+
|
|
463
|
+
検出結果を GitHub Code Scanning に送るには、SARIF をアップロードします(workflow または job スコープで `security-events: write` が必要):
|
|
464
|
+
|
|
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
|
+
```
|
|
420
473
|
|
|
421
|
-
|
|
422
|
-
`eslint-plugin-playwright`(`expect-expect`、`no-wait-for-timeout`)が
|
|
423
|
-
それぞれのフレームワーク向けにこれをカバーしています。
|
|
474
|
+
GitLab では、`--format codequality` が MR ウィジェットと diff のアノテーションが読む Code Quality レポートを書き出します([docs/GITLAB-CI.md](docs/GITLAB-CI.md))。エディターとパイプラインの設定:[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md)。
|
|
424
475
|
|
|
425
|
-
|
|
476
|
+
### 変更範囲への帰属
|
|
426
477
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
| 実行履歴からの flaky トリアージレポート | ❌ | ✅ | ✅ |
|
|
431
|
-
| 静的な信頼性スコアと統合 | ❌ | ❌ | ✅ |
|
|
478
|
+
```bash
|
|
479
|
+
npx mjolnir-qa@latest --scope changed
|
|
480
|
+
```
|
|
432
481
|
|
|
433
|
-
|
|
434
|
-
flakiness レポートは生成しません。
|
|
482
|
+
検出結果は、ブランチが追加した行に、**merge-base** を基準として帰属されます。範囲は完全スキャンが見つけるのと同じファイル集合(TS/JS の spec とアダプターの設定、`test_*.py`、`*Test.java`、`*Tests.cs`、`.github/workflows/*.yml`)に、未コミットおよび未追跡の変更を加えたものなので、コミット前でも使えます。ベースは `main → master → origin/main → origin/master → origin/HEAD` の順で解決され、`--base <ref>` で上書きできます。
|
|
435
483
|
|
|
436
|
-
|
|
484
|
+
merge-base を解決できない場合(シャロークローン、detached HEAD、git 外の対象)、検出結果はファイル全体への帰属にフォールバックし、**レポートにもそう明記されます**。黙ってフォールバックすることこそ、このツールが捉えるために存在する種類の欠陥だからです。
|
|
437
485
|
|
|
438
|
-
|
|
486
|
+
<br />
|
|
439
487
|
|
|
440
|
-
|
|
441
|
-
見つけられますが、検証システム全体が信頼に値すると証明はできません——
|
|
442
|
-
しかも見るのはあなたが見せた diff だけです。
|
|
488
|
+
## AI エージェント
|
|
443
489
|
|
|
444
|
-
|
|
445
|
-
| ------------------------------------- | :-------------------------------: | :------------------------------------: |
|
|
446
|
-
| スキャンごとのコスト | トークン(diff サイズで増える) | **ゼロ**(ローカル、インストール済み) |
|
|
447
|
-
| スイート全体 + すべての CI 設定を見る | あなたが見せた PR diff のみ | **毎回すべて** |
|
|
448
|
-
| 決定論的(同じ入力 → 同じ出力) | ❌(非決定論的) | **✅** |
|
|
449
|
-
| 数か月眠っていたパターンを検出 | コンテキストにある場合のみ | **✅**(全ファイルをスキャン) |
|
|
450
|
-
| 実行間で検出を記憶 | ❌(セッション間の記憶なし) | **✅**(baseline + diff) |
|
|
451
|
-
| 人間のトリガーなしで動く | PR またはプロンプトが必要 | **✅**(CI フック、数秒で実行) |
|
|
490
|
+
検出結果に価値があるのは、何かがそれに基づいて動くときだけです。
|
|
452
491
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
終了コード、テストジョブ上の `continue-on-error`。これらは推論を要する
|
|
457
|
-
バグではなく、スキャンを要する事実です。
|
|
492
|
+
```text
|
|
493
|
+
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
494
|
+
```
|
|
458
495
|
|
|
459
|
-
|
|
496
|
+
**AI が修正を書き、Mjölnir がそれを検証します**。証明は再スキャンから得られるのであって、エージェント自身の成功報告から得られるのではありません。
|
|
460
497
|
|
|
461
|
-
|
|
498
|
+
| コマンド | エージェントが受け取るもの |
|
|
499
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
500
|
+
| `mjolnir mcp` | stdio 経由の [MCP](https://modelcontextprotocol.io) サーバー。`scan`、`explain`、`diff` が呼び出し可能なツールになります。 |
|
|
501
|
+
| `mjolnir handoff` | 保存した `--json` レポートが、決定論的な Markdown の計画になります:何が検出されたか、検出結果ごとの証拠の境界、何を変えては**いけない**か、どう検証するか。 |
|
|
502
|
+
| `mjolnir install` | リポジトリに既にあるエージェント用の場所(`.claude/`、`.cursor/`、`.kilo/`、`AGENTS.md`)に書き込み、エージェントが完了を宣言する前に再スキャンするようにします。 |
|
|
462
503
|
|
|
463
|
-
|
|
464
|
-
決してブロックしません:
|
|
504
|
+
独自の CLI を持つクライアントに追加する場合:
|
|
465
505
|
|
|
466
506
|
```bash
|
|
467
|
-
mjolnir
|
|
507
|
+
claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
|
|
468
508
|
```
|
|
469
509
|
|
|
470
|
-
|
|
510
|
+
または、`mcpServers` ブロックを受け付ける任意のクライアントに:
|
|
471
511
|
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
512
|
+
```json
|
|
513
|
+
{
|
|
514
|
+
"mcpServers": {
|
|
515
|
+
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
|
|
516
|
+
}
|
|
517
|
+
}
|
|
477
518
|
```
|
|
478
519
|
|
|
479
|
-
|
|
480
|
-
[docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md)。
|
|
520
|
+
**利便性よりもガードレールが大事です**。引き継ぎに含まれるどの検出結果も、その境界を伴っています。**E2** は _決定論的:場所を確認して修正を適用_ と伝えます。**E1** は _確認が必要:観察だけでは欠陥は証明されない_ と伝えます。E1 を盲目的に直したり、ルールを抑制したり、スコアを上げるためにルールを書き換えたりするエージェントは、まさにこのツールが捉えるために存在することをしているのです。だから引き継ぎは、プロンプトの中で、検出結果のすぐ隣でそう伝えます。
|
|
481
521
|
|
|
482
|
-
|
|
522
|
+
<br />
|
|
483
523
|
|
|
484
|
-
|
|
485
|
-
行に検出を帰属させます。テストファイル(`*.spec.*`、`*.test.*`)に加え、
|
|
486
|
-
diff 内の GitHub ワークフローファイルと Playwright 設定をカバーします。
|
|
487
|
-
マージベースを解決できない場合——シャロークローン、detached HEAD、
|
|
488
|
-
git 以外のターゲット、既定ブランチの違い——正直に劣化します: 検出は
|
|
489
|
-
ファイル全体への帰属に戻り、レポートはその旨を述べます。ベース参照は
|
|
490
|
-
`--base <ref>` で上書きできます。
|
|
524
|
+
## 信頼とセキュリティ
|
|
491
525
|
|
|
492
|
-
|
|
526
|
+
**ローカルファースト、テレメトリーゼロ**。ネットワークにアクセスできる API(`fetch`、`http`、`https`、`net`、`dns`、`dgram`、WebSocket)は `src/` のどこにも存在せず、もし現れれば [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) がビルドを失敗させます。`eval` と `new Function` も禁止しています。信頼できないコードをスキャンしても、それを実行することはありません:静的解析はソーステキストを読み、フォレンジックはディスク上に既にあるレポートファイルを解析します。
|
|
493
527
|
|
|
494
|
-
|
|
528
|
+
注意点が 2 つあります:`npx` 自体は何かが実行される前にパッケージを取得します。また、この保証が対象とするのは `src/` であり、サードパーティのプラグインは含みません。
|
|
495
529
|
|
|
496
|
-
|
|
497
|
-
(または `.mjolnir.json`)で重大度、ゲーティング、スコープを調整
|
|
498
|
-
できます——検出の意味論は決して変えません。
|
|
530
|
+
**プラグインはサンドボックス化されていません**。JS プラグイン(`mjolnir-rules/*.mjs`、または `"plugins"` に列挙された npm パッケージ)は Node の完全な権限で実行されます。ESLint や Vitest のプラグインと同じ信頼モデルです。読み込みは**スキャンごと**のオプトインです:`--enable-plugins`(または `MJOLNIR_ENABLE_PLUGINS=1`)がなければ、そのソースは決して読み込まれず、stderr の通知がスキップされたものを一覧表示します。JSON のルールマニフェストはコードを実行せず、コアのルール ID の接頭辞は予約されているため、プラグインがコアのルールになりすますことはできません。脆弱性は [SECURITY.md](SECURITY.md) から報告してください。
|
|
499
531
|
|
|
500
|
-
|
|
501
|
-
| ------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
502
|
-
| `exclude` | `string[]` | 追加の ignore グロブ(gitignore のサブセット)、内蔵デフォルトの上に重ねる |
|
|
503
|
-
| `gate` | `"advisory" \| "error" \| "warning"` | どの重大度が非ゼロで終了するか(既定 `error`; `advisory` は決してブロックしない) |
|
|
504
|
-
| `severityOverrides` | `{ "<RULE-ID>": severity }` | リポジトリに合わせてルールの検出を再ランク付けする |
|
|
505
|
-
| `ignore` | `IgnoreEntry[]` | 検出を抑制する — **`reason` が必須**; エントリは 90 日で失効します(明示的な `expires` 日付、または未記入の場合は設定ファイルの最終更新時刻) |
|
|
506
|
-
| `plugins` | `string[]` | サードパーティのルールパッケージ([信頼モデル](#信頼モデル) 参照) |
|
|
532
|
+
**自分自身にも実行します**。検証の信頼エンジンは、それ自体が検証可能でなければ立場がありません。すべての CI 実行は、その同じ実行が生成したビルドでこのリポジトリをスキャンします。ゲートは、重大度 error の検出結果があれば失敗し、**部分的な**スキャンや**クラッシュしたルール**でも失敗します。何も報告しない途中で打ち切られたセルフスキャンこそ、このプロジェクトが捉えるために存在する偽りの緑だからです。`mjolnir doctor` は同じ実行の中でルールベースを再監査し(fixture ファイアウォール、ティアの誠実さ、core ティアの上限)、INCONCLUSIVE となったチェックは失敗したチェックとまったく同じように失敗します。両方のレポートがビルドのアーティファクトとしてアップロードされます。
|
|
507
533
|
|
|
508
|
-
|
|
509
|
-
{
|
|
510
|
-
"gate": "error",
|
|
511
|
-
"exclude": ["legacy/**"],
|
|
512
|
-
"severityOverrides": { "QA-PW-141": "warning" },
|
|
513
|
-
"ignore": [
|
|
514
|
-
{
|
|
515
|
-
"ruleId": "QA-TEST-004",
|
|
516
|
-
"files": ["e2e/legacy-login.spec.ts"],
|
|
517
|
-
"reason": "Third-party widget needs a settle delay; tracked in JIRA-4821",
|
|
518
|
-
"expires": "2026-12-31"
|
|
519
|
-
}
|
|
520
|
-
]
|
|
521
|
-
}
|
|
522
|
-
```
|
|
534
|
+
### 終了コードとマシン契約
|
|
523
535
|
|
|
524
|
-
|
|
525
|
-
`exclude` と同じ方言です。マシン単位のノイズにはこちらを; リストが
|
|
526
|
-
残りの設定とともにバージョン管理に入るべきなら `exclude` を。
|
|
527
|
-
- **CLI 上書き** — `--strict`(隔離層のルールを含める)、`--width <cols>` と
|
|
528
|
-
`--ascii` / `--no-ascii`(ターミナル描画)、`--tone blunt`
|
|
529
|
-
(より直接的なメッセージ)、`--max-duration <sec>`(時間制限つき部分
|
|
530
|
-
スキャン)。
|
|
531
|
-
- ルール抑制と非推奨のライフサイクル:
|
|
532
|
-
[docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md)。
|
|
533
|
-
|
|
534
|
-
`ignore` エントリは、単独のコマンド `mjolnir suppressions` も駆動します。
|
|
535
|
-
これは現在中断されているものと、各エントリの失効時期を一覧表示します。
|
|
536
|
-
|
|
537
|
-
---
|
|
538
|
-
|
|
539
|
-
## 📐 終了コードと契約
|
|
540
|
-
|
|
541
|
-
凍結済み — その上に CI ロジックを構築しても安全です:
|
|
542
|
-
|
|
543
|
-
| 終了コード | 意味 |
|
|
544
|
-
| ---------- | ---------------------------------------------------------------------- |
|
|
545
|
-
| `0` | クリーン — ゲート以上の検出なし |
|
|
546
|
-
| `1` | ゲート以上の検出あり |
|
|
547
|
-
| `2` | 部分スキャン(時間予算の消尽、読めないファイル)— 決してブロックしない |
|
|
548
|
-
| `10` | 使用方法の誤り(不正なフラグ、ターゲット欠落) |
|
|
549
|
-
| `20` | 内部エラー |
|
|
550
|
-
|
|
551
|
-
JSON/SARIF レポートは `schemaVersion: 1` です。ルール ID
|
|
552
|
-
(`QA-<FAMILY>-NNN`)は出荷後は不変であり、決して再利用されません。
|
|
553
|
-
|
|
554
|
-
---
|
|
555
|
-
|
|
556
|
-
## 信頼モデル
|
|
557
|
-
|
|
558
|
-
- **ローカルファースト** — スキャン中のネットワーク呼び出しゼロ。常に。
|
|
559
|
-
テレメトリゼロ。
|
|
560
|
-
- **偽の証明をしない** — 「検証済み」より「不明」と言うことを選びます。
|
|
561
|
-
空のリポジトリは `score: null` を受け取り、偽の 100 は決して返しません。
|
|
562
|
-
- **部分的な正直さ** — 分析が中断されたら、出力がその旨を述べます。
|
|
563
|
-
完了していないのに「complete」とは決して言いません。
|
|
564
|
-
- **FP 防火壁** — 検出はコメント/文字列を除いたコードビュー上で動作
|
|
565
|
-
します(TypeScript ルールはコンパイラ AST を使用): 散文コメント内や
|
|
566
|
-
ドキュメント例の文字列にあるパターンはドキュメントであり、検出では
|
|
567
|
-
ありません。
|
|
568
|
-
- **測定、断言にあらず** — 実際の OSS コードからの false-positive 率を
|
|
569
|
-
持つルールだけがヘッドラインのティアに出荷されます
|
|
570
|
-
([どれだけが測定されているか](#どれだけが測定されているか) 参照)。
|
|
571
|
-
スキャンのフッターと `mjolnir rules --unmeasured` がどれがどれかを
|
|
572
|
-
教えます。
|
|
573
|
-
- **プラグインの信頼と実行ゲート** — プラグインは `"plugins"` の下で宣言された npm
|
|
574
|
-
パッケージです; JS モジュールは `mjolnir-rules/*.mjs` に置かれます。
|
|
575
|
-
**サンドボックスはありません**: プラグインコードは
|
|
576
|
-
完全な Node 権限で動作し、ESLint や Vitest のプラグインと同じ信頼
|
|
577
|
-
モデルです。そのため、コード実行は**スキャンごとにオプトイン**です:
|
|
578
|
-
`--enable-plugins` を渡すか(`MJOLNIR_ENABLE_PLUGINS=1` を設定するか)、
|
|
579
|
-
そうでなければソースはロードされません — 目立つ stderr の通知が、
|
|
580
|
-
スキップされたものを正確に列挙します。信頼できないコードをスキャンしても、
|
|
581
|
-
それが実行されることはありません。JSON ルールマニフェスト
|
|
582
|
-
(`mjolnir-rules/*.json`)は影響を受けません: 正規表現パターンを宣言し、
|
|
583
|
-
設計上コードを一切実行しません。コアルール ID の接頭辞は予約されており、
|
|
584
|
-
なりすまし防止のためプラグインおよび外部ルールからは拒否されます。
|
|
585
|
-
- **ワークスペースローカルの外部ルール**(フォルダベース、ネットワーク
|
|
586
|
-
ゼロ)— スキャン対象の隣にある `mjolnir-rules/` ディレクトリがカスタム
|
|
587
|
-
ルールを読み込みます: JSON ファイルは正規表現パターンを宣言し(コードは
|
|
588
|
-
実行されません)、`.mjs`/`.js` モジュールは `rules` をエクスポート
|
|
589
|
-
します(プラグインと同じ完全な Node 信頼)。外部ルールはコアと同じ
|
|
590
|
-
信頼メタデータを持ちます; コアティアに出荷されることは決してありません
|
|
591
|
-
(コアにはコーパスサイドカーからの実測 FP 率が必要です — 宣言された
|
|
592
|
-
`tier: "core"` は `extended` にクランプされます)、ティア上限に従い、
|
|
593
|
-
ドリフトの検査を受けます: `mjolnir rules --md --external` は読み込んだ
|
|
594
|
-
ファイルからカタログを描画し(出所 `external`)、マトリクスジェネレータは
|
|
595
|
-
`--external <root>` を受け付けます。
|
|
596
|
-
|
|
597
|
-
---
|
|
598
|
-
|
|
599
|
-
## 🏗️ アーキテクチャ
|
|
536
|
+
凍結されているので、これを前提に CI のロジックを組めます:
|
|
600
537
|
|
|
601
|
-
|
|
602
|
-
|
|
538
|
+
| 終了コード | 意味 |
|
|
539
|
+
| ---------- | ------------------------------------------------------------------------------ |
|
|
540
|
+
| `0` | クリーン:ゲート以上の検出結果なし |
|
|
541
|
+
| `1` | ゲート以上の検出結果あり |
|
|
542
|
+
| `2` | 部分的なスキャン(時間制限に到達、読み取れないファイル)。ブロックはしません。 |
|
|
543
|
+
| `10` | 使い方の誤り(不正なフラグ、対象の指定漏れ) |
|
|
544
|
+
| `20` | 内部エラー |
|
|
603
545
|
|
|
604
|
-
|
|
605
|
-
mjolnir/
|
|
606
|
-
├── src/
|
|
607
|
-
│ ├── engine/ # LanguageAdapter interface + rule runner
|
|
608
|
-
│ ├── adapters/ # typescript · python · java · csharp · github-actions
|
|
609
|
-
│ ├── rules/ # rules across 8 families + the measured-FP table
|
|
610
|
-
│ ├── playwright/ # Selector Health Score engine
|
|
611
|
-
│ ├── discovery/ # workspace, frameworks, ignore resolution
|
|
612
|
-
│ ├── scope/ # git merge-base changed-scope engine
|
|
613
|
-
│ ├── scorer/ # transparent deduction table + prioritization
|
|
614
|
-
│ ├── reporter/ # terminal · JSON · SARIF 2.1 · Mermaid
|
|
615
|
-
│ ├── forensics/ # run-data ingestion · flake verdicts · triage
|
|
616
|
-
│ ├── config/ # mjolnir.config.json + suppressions
|
|
617
|
-
│ ├── plugins/ # third-party rule loading (no sandbox)
|
|
618
|
-
│ └── commands/ # every subcommand
|
|
619
|
-
└── tests/
|
|
620
|
-
├── fixtures/ # must-fire / must-not-fire per rule
|
|
621
|
-
└── golden/ # frozen score regression locks
|
|
622
|
-
```
|
|
546
|
+
`2` は意図的に `0` と区別されています:終わらなかったスキャンは「何も見つからなかった」のではありません。まだ探し終わっていないのです。
|
|
623
547
|
|
|
624
|
-
|
|
548
|
+
機械が消費するもの(MCP ツールの結果、`--json`、SARIF 2.1)はすべて、バージョン管理された**追加のみ**のスキーマ(`schemaVersion: 1`、`contractVersion: 1`)に基づく単一の正規結果から生成されます。そのため、どの利用者もレンダリングされたテキストから意味を組み立て直す必要はありません。[マシン契約](docs/machine-contract.md) を参照してください。ルール ID(`QA-<FAMILY>-NNN`)は一度リリースされると変更されず、再利用されることもありません。
|
|
625
549
|
|
|
626
|
-
|
|
627
|
-
グローバルなし。新しいエコシステム = 1 つのアダプタ + そのルール。
|
|
628
|
-
- **TypeScript/Playwright はコンパイラ AST を使用します**(ts-morph)。
|
|
629
|
-
Python、Java、C# はコメント/文字列をマスクした共有正規表現層上で動作
|
|
630
|
-
します。
|
|
631
|
-
- Java と C# 向けの tree-sitter WASM AST 層は存在し、次の精度ステップ
|
|
632
|
-
ですが、まだ同期スキャンパイプラインには組み込まれていません。
|
|
550
|
+
<br />
|
|
633
551
|
|
|
634
|
-
|
|
552
|
+
## Mjölnir が教えてくれないこと
|
|
635
553
|
|
|
636
|
-
|
|
554
|
+
- **テストは実行しません**。スキャンがクリーンでも、スイートが通るとは限りません。
|
|
555
|
+
- **アサーションが*間違っている*ことは教えてくれません**。`expect(total).toBe(41)` は健全に見えます。Mjölnir が見つけるのは*失敗しようがない*テストと*赤くなりようがない*パイプラインであって、間違ったものを確認しているテストではありません。
|
|
556
|
+
- **ビジネス上の正しさは証明しません**。ここにあるものは何ひとつ、製品が要件どおりに動くことを示しません。
|
|
557
|
+
- **100 は良いスイートの証明ではありません**。スイートが本当のリスクをカバーしているかどうかは別の問いであり、このツールはそれに答えません。
|
|
558
|
+
- **79 のルールのうち 5 つは見積もりでリリースされています**。実測値ではありません。それぞれ自分の検出結果にそう明記しています。
|
|
559
|
+
- **E1 は E2 ではありません**。ヒューリスティックな検出結果は読む価値はあっても、盲目的に適用する価値はありません。
|
|
560
|
+
- **空のリポジトリのスコアは `null` であり、決して 100 にはなりません。**
|
|
561
|
+
- **テスト宣言のない `*.spec.ts` という名前のファイルは、カバレッジとして数えられません**。spec ファイルが import や型しか含まない(`it`/`test` の呼び出しがゼロの)リポジトリのスコアは、100 ではなく `null` です。
|
|
637
562
|
|
|
638
|
-
|
|
639
|
-
| ------------------------------------------------------ | ------------------------------------- |
|
|
640
|
-
| [docs/SCORING.md](docs/SCORING.md) | スコアの正規化 + 証拠の重み付け |
|
|
641
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | 実測 false-positive 率 + 手法 |
|
|
642
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | ルール状態、抑制、非推奨化 |
|
|
643
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | SARIF 出力 + エディタ/CI 設定 |
|
|
644
|
-
| [docs/rules/](docs/rules/) | 生成されたルールごとのカタログ |
|
|
645
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | 開発環境 + コントリビューションフロー |
|
|
646
|
-
| [CHANGELOG.md](CHANGELOG.md) | リリース履歴 |
|
|
647
|
-
| [SECURITY.md](SECURITY.md) | 脆弱性の報告 |
|
|
563
|
+
<br />
|
|
648
564
|
|
|
649
|
-
|
|
565
|
+
## ドキュメント
|
|
650
566
|
|
|
651
|
-
|
|
567
|
+
完全なドキュメントサイトは <https://sergey-bar.github.io/Mjolnir/> にあります。
|
|
652
568
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
[
|
|
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) | リリース履歴 |
|
|
657
584
|
|
|
658
|
-
|
|
585
|
+
### ステータス
|
|
659
586
|
|
|
660
|
-
|
|
587
|
+
**バージョン 1**。JSON スキーマと終了コードは凍結された契約です。TypeScript と Python は最も幅広い実測カバレッジを持っています。Java と C# は比較的新しいので、[成熟度の表](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle) と合わせて見てください。今後の予定(日付をでっち上げることはしません):[公開ロードマップ](https://sergey-bar.github.io/Mjolnir/reference/roadmap)。
|
|
661
588
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
失敗します — スタブは出荷できません):
|
|
589
|
+
### コントリビューション
|
|
590
|
+
|
|
591
|
+
新しいルールは、最も取り組みやすい最初のコントリビューションです。コマンドひとつで、must-fire **と** must-not-fire の fixture 付きでルールの雛形が作られます。生成されたルールは、実際の検出ロジックが書かれるまで、わざと自分の fixture で失敗します。そのままリリースされたスタブは、誰も測定していないルールだからです。
|
|
666
592
|
|
|
667
593
|
```bash
|
|
668
594
|
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
669
595
|
```
|
|
670
596
|
|
|
671
|
-
|
|
672
|
-
防火壁の法則は [CONTRIBUTING.md](CONTRIBUTING.md) にあります。
|
|
597
|
+
開発環境のセットアップ、常設ゲートのコマンド、anti-creep と fixture ファイアウォールの法則は [CONTRIBUTING.md](CONTRIBUTING.md) にあります。
|
|
673
598
|
|
|
674
|
-
|
|
599
|
+
<br />
|
|
675
600
|
|
|
676
601
|
<div align="center">
|
|
677
602
|
|
|
678
|
-
|
|
603
|
+
<img src="assets/readme/closing.svg" alt="あなたのリポジトリで試してみてください。" width="100%" />
|
|
679
604
|
|
|
680
605
|
```bash
|
|
681
606
|
npx mjolnir-qa@latest
|
|
682
607
|
```
|
|
683
608
|
|
|
684
|
-
|
|
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
|
+
そのテストが信頼に値すると証拠が示しているかを問おう。
|
|
685
615
|
|
|
686
|
-
[Sergey Bar](https://www.linkedin.com/in/sergeybar/)
|
|
616
|
+
<sub>制作:[Sergey Bar](https://www.linkedin.com/in/sergeybar/) · MIT ライセンス</sub>
|
|
687
617
|
|
|
688
618
|
</div>
|