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/README.ja.md CHANGED
@@ -1,394 +1,431 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/readme/logo.png" alt="Mjölnir — Verification Trust Engine" width="800" />
3
+ <img src="assets/readme/hero.svg" alt="Mjölnir。テストは何が通ったかを教えてくれる。Mjölnir は何を信頼できるかを教えてくれる。" width="100%" />
4
4
 
5
- ### あなたのテストは嘘をついています。私たちが証明します。
5
+ <br />
6
6
 
7
- **QA 向け Verification Trust Engine。** Mjölnir はテストスイートと CI
8
- パイプラインを監査し、信頼性スコアを報告し、信頼がどこで壊れているかを
9
- 正確に示します。
7
+ Mjölnir は、失敗しようがないテストと赤くなりようがないパイプラインを見つけ出し、<br />
8
+ 結果をどこまで信頼できるかを、すべての点に証拠を添えてスコアリングします。
10
9
 
11
- [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=C19A34&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
12
- [![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)
13
- [![license](https://img.shields.io/badge/license-MIT-C19A34.svg?style=flat-square&labelColor=0A1119)](LICENSE)
14
- [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-37ABBD.svg?style=flat-square&labelColor=0A1119)](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
- > 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-08.
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
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
- [何をチェックするか](#-mjölnir-がチェックするもの) ·
29
- [スコアリング](#スコアの仕組み) ·
30
- [CI](#-ci-統合) · [設定](#設定) ·
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
- <img src="assets/readme/demo.svg" alt="デモリポジトリに対する Mjölnir の完全な --verbose レポート: WORTHINESS 75/100 NEEDS WORK、カテゴリ別の診断内訳、FIX THIS FIRST リスト、そして CI・Playwright・テスト衛生・Python ルール全体にわたるルール ID と行番号付きの各検出" width="900" />
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>`npx mjolnir-qa ./examples/demo-repo --verbose` の完全な出力を、
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
- 1. Mjölnir は Playwright のスペック、その設定、CI ワークフロー、
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
- ### 検出を 1 つ、クローズアップ
106
+ どの検出結果も 4 つの問いに答えます。どこにあるのか、Mjölnir はどれだけ確信しているのか、そのルールはどれくらいの頻度で誤るのか、そしてどう直すのか。
62
107
 
63
- 上の最初の検出に対して `mjolnir explain QA-CI-001` を実行すると:
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
- ▚ QA-CI-001 — continue-on-error masks a failing verification gate
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
- Measured FP: not yet measured — this rule ships on assumption (see docs/FP-AUDIT.md)
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
- on this workflow cannot be trusted.
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
- これが価値の単位です。スタイルへの指摘ではなく、あなたの CI が
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
- ```bash
94
- npx mjolnir-qa@latest
155
+ Docs: mjolnir rules --md (full catalog, this rule included)
95
156
  ```
96
157
 
97
- **CI では、製品は 1 コマンドです。** ブランチが触ったものだけをスキャン
98
- し、新しい問題があれば非ゼロで終了します:
158
+ これが価値の単位です。CI が、得てもいない成功を報告している箇所がひとつあるということ。
159
+
160
+ <br />
161
+
162
+ ## クイックスタート
99
163
 
100
164
  ```bash
101
- npx mjolnir-qa@latest --scope changed
165
+ npx mjolnir-qa@latest
102
166
  ```
103
167
 
104
- それを PR チェックに放り込む——`mjolnir ci install` がワークフローを
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
- <details>
118
- <summary><strong>何かが flaky なとき</strong></summary>
170
+ CI では、ブランチが持ち込んだものだけをスキャンしましょう。そうすれば、レガシーなスイートが最初の pull request を埋もれさせることはありません。
119
171
 
120
- | コマンド | 何をするか |
121
- | ----------------------------------- | ----------------------------------------------------- |
122
- | `mjolnir forensics ./test-results/` | 実際の実行データ → `TRUE-FLAKE` 判定、`FLAKY.md` |
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
- </details>
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>たまに / レポート系</strong></summary>
131
-
132
- | コマンド | 何をするか |
133
- | ------------------------------- | ----------------------------------------------------- |
134
- | `mjolnir fix --dry-run` / `fix` | 証拠付きの安全な自動修正 |
135
- | `mjolnir baseline` / `diff` | 検出のスナップショットを取り、以後は新規/悪化のみ報告 |
136
- | `mjolnir impact --since <ref>` | 以前のコミット以降に何が変わったか |
137
- | `mjolnir debt` | コストモデル付きのテスト負債台帳 |
138
- | `mjolnir handover` | 新しい QA 向けのスイートオンボーディングマップ |
139
- | `mjolnir stats` | これまでに見た修正のローカル累計カウンタ |
140
- | `mjolnir badge` | shields.io エンドポイント JSON + スニペット |
141
- | `mjolnir rules --md` | 完全なルールカタログ(JSON または Markdown) |
142
- | `mjolnir doctor` | Mjölnir 自身のルールベースの自己監査 |
143
- | `mjolnir create-rule <ID>` | 新しいルール + フィクスチャのスキャフォールド |
144
- | `mjolnir --format mermaid` | PR コメント用のテストアーキテクチャ図 |
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
- お好みなら `npx` の代わりにグローバルインストールを:
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
- - **QA / SDET** — e2e または統合スイートを所有し、スイートが生成する
157
- 緑のチェックマークが本当に値するものかの証拠を必要としている人。
158
- - **プラットフォーム / DevEx チーム** — CI の完全性とリリースゲートに
159
- 責任を持つ人々。`continue-on-error` が赤いパイプラインを静かに緑に
160
- 塗り替えないことを気にする人々。
161
- - **OSS メンテナ** — ローカルでも CI でも、ネットワーク呼び出しゼロで
162
- 動く安価で常時有効な検証ゲートを求めている人。
230
+ ## Mjölnir が検出するもの
163
231
 
164
- ---
165
-
166
- ## 🔨 Mjölnir がチェックするもの
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
- すべてのルールは must-fire **と** must-not-fire のフィクスチャを備えて
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>テスト衛生</strong></summary>
185
-
186
- | ID | ルール | Severity |
187
- | ----------- | -------------------------------------------------------- | -------- |
188
- | QA-TEST-001 | コミットされたフォーカステスト(`.only`、`fit`) | error |
189
- | QA-TEST-002 | 根拠のないままスキップされたテスト | error |
190
- | QA-TEST-002 | 記録済みの根拠つきでスキップされたテスト | warning |
191
- | QA-TEST-003 | アサーションのないテスト | error |
192
- | QA-TEST-004 | ハードな sleep(`waitForTimeout`、`sleep()`、`delay()`) | warning |
193
- | QA-TEST-006 | flakiness を隠すリトライの濫用 | warning |
194
- | QA-TEST-010 | 空のテスト本体 | error |
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
- <details>
199
- <summary><strong>テスト品質</strong></summary>
301
+ どのルールも must-fire **と** must-not-fire の fixture を備えてリリースされ、自分自身のネガティブ fixture で発火するルールはリリースできません。これが誤検知ファイアウォールです。`mjolnir doctor` がこのリポジトリ自身の CI でそれを強制しています。
200
302
 
201
- | ID | ルール | Severity |
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
- </details>
305
+ `mjolnir doctor:playwright` は、各 locator が要素をどう見つけるかで評価します。ユーザーと同じ方法か(ロール、ラベル、テキスト)、明示的な契約か(`data-testid`)、構造上の偶然か(CSS の連結、XPath)。各ファイルに 0〜100 のスコアが付きます。
208
306
 
209
- <details>
210
- <summary><strong>Playwright 🎭</strong></summary>
307
+ ```text
308
+ ▍ SELECTOR HEALTH
211
309
 
212
- | ID | ルール | Severity |
213
- | --------- | --------------------------------------------- | -------- |
214
- | QA-PW-002 | await されていないロケータアサーション | error |
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
- </details>
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
- <details>
222
- <summary><strong>CI 完全性</strong></summary>
223
-
224
- | ID | ルール | Severity |
225
- | --------- | ---------------------------------------------------------------- | -------- |
226
- | QA-CI-001 | `continue-on-error` が失敗をマスクする | error |
227
- | QA-CI-002 | `\|\| true` が終了コードを呑み込む | error |
228
- | QA-CI-005 | レポートが消費されるのに生成されない | error |
229
- | QA-CI-007 | テストを包むリトライラッパー | warning |
230
- | QA-CI-008 | 常に成功するステップが失敗をマスクする | error |
231
- | QA-CI-009 | テストの終了コードが伝播しない(pipefail なしの `\|`、`;` 連結) | error |
232
- | QA-CI-010 | ブロックすべき場所でテストがスキップされる(skip-on-PR ガード) | error |
319
+ これが測るのは**正しさではなく耐久性**です。`.btn.btn-primary > div:nth-child(2)` は今日は通り、誰かがマークアップに触れるまで通り続けます。低いスコアはテストが壊れていると主張するものではなく、誰も維持を約束していないマークアップに依存していることを示すだけです。
233
320
 
234
- </details>
321
+ <br />
235
322
 
236
- <details>
237
- <summary><strong>Python / pytest 🐍</strong></summary>
323
+ ## 信頼度スコア
238
324
 
239
- | ID | ルール | Severity |
240
- | --------- | ------------------------------------------------ | -------- |
241
- | QA-PY-002 | スキップされたテスト(`skip`、非厳格な `xfail`) | warning |
242
- | QA-PY-003 | アサーションのないテスト関数 | error |
243
- | QA-PY-005 | テスト内の `time.sleep()` | warning |
244
- | QA-PY-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
- Python ルールは合計 20 本(QA-PY-001…012 pytest 衛生 + QA-PY-101…108 Playwright-Python)。
329
+ <sub>0 から 100 までのすべてのスコアを、実際の `deriveScoreState` で配置したもの。`npm run docs:gauge` で生成され、CI でずれがないよう固定されています。</sub>
247
330
 
248
- </details>
331
+ | スコア | 判定 |
332
+ | --------- | ------------------------------------- |
333
+ | `0 – 49` | **UNWORTHY** |
334
+ | `50 – 79` | **NEEDS WORK** |
335
+ | `80 – 99` | **WORTHY** |
336
+ | `100` | **FORGED** |
337
+ | `null` | **UNKNOWN**:テスト宣言が見つからない |
249
338
 
250
- <details>
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
- | ID | ルール | Severity |
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
- </details>
343
+ <br />
262
344
 
263
- <details>
264
- <summary><strong>C# / .NET — NUnit · xUnit · MSTest 🟣</strong></summary>
345
+ ## 証拠モデル
265
346
 
266
- | ID | ルール | Severity |
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
- </details>
349
+ **どれだけ確かか — 証拠レベル。**
275
350
 
276
- > 完全なライブカタログ——各ルールのティア、confidence、false-positive
277
- > リスク、オートフィックス対応状況——はレジストリから生成されます:
278
- >
279
- > ```bash
280
- > mjolnir rules --md
281
- > ```
282
- >
283
- > ルールごとのページは [`docs/rules/`](docs/rules/) にあります。
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/terminal-hero.svg" alt="Mjölnir のターミナル出力——WORTHINESS 75/100 NEEDS WORK、カテゴリ別の診断内訳と FIX THIS FIRST リスト" width="820" />
362
+ <img src="assets/readme/trust-ladder.svg" alt="L0 から L5 までの信頼のはしご。L0〜L2 はコードを読むことから得られ、L3〜L5 には実際の実行レポートが必要です。はしごの切れ目がその境目を示しています。" width="100%" />
325
363
  </p>
326
364
 
327
- <sub>`npm run docs:hero` で再生成されます。
328
- [`tests/hero-asset-reproducibility.spec.ts`](tests/hero-asset-reproducibility.spec.ts)
329
- は、成果物がレポーターが実際に印字するものから逸れたら CI を落とします。</sub>
365
+ | レベル | わかりやすく言うと | 必要なもの |
366
+ | ------ | -------------------- | -------------------------------------------------------------- |
367
+ | **L0** | 記録済み | コードを読む |
368
+ | **L1** | 問題らしく見える | コードを読む:パターンが一致 |
369
+ | **L2** | コードで証明済み | コードを読む:欠陥は構造的 |
370
+ | **L3** | ファイルが実行された | 実行レポートが、検出結果のファイルが実行されたことを示している |
371
+ | **L4** | テストが実行された | 実行レポートが、検出結果のテストが実行されたことを示している |
372
+ | **L5** | 実行結果が一致 | 実行自体の結果が欠陥のクラスを裏付けている |
330
373
 
331
- スコアは透過的です: **error −8、warning −3、info −1**、その後スイートの
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
- | Score | 判定 |
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
- ほとんどのルールは **E1** です。「we prove it」という標語はこの仕組みを
355
- 指します: E2 の検出は構造的な証明であり、E1 の検出は適切に位置づけられた
356
- 警告であって、形式的な証明ではありません。
384
+ ティアは意見ではなく、実測の誤検知率に従います。
357
385
 
358
- 空のリポジトリは `null` を返します。偽の 100 を決して返しません —
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
- ## 🎭 Selector Health Score
395
+ 昇格、降格、言語ごとの成熟度:[ルールのライフサイクル](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle)。
364
396
 
365
- Playwright スイート向けの看板指標——あなたのロケータはどれだけ丈夫か:
397
+ ### なぜこれは linter ではないのか
366
398
 
367
- ```text
368
- ▚ SELECTOR HEALTH — e2e/checkout.spec.ts
399
+ linter は、コードがルールに従っているかを教えてくれます。Mjölnir は、あなたの検証が信頼できるかを教えてくれます。
369
400
 
370
- [█████████████████░░░] 83 / 100
371
- role/text: 2 · testid: 1 · css-chains: 1 ⚠ · xpath: 0
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
- ロールベースのロケータは満点です。CSS クラスチェーンと XPath はスコアを
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
- 静的な flakiness 検出は当てずっぽうです。Mjölnir は**実際の実行データ**を
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
- ▚ FLAKINESS LEADERBOARD
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
- 2 回目以降の試行でしか通らないテストは、通るテストではありません——
402
- 運の良いテストです。最終的な緑のチェックマークにかかわらず、
403
- `TRUE-FLAKE` としてフラグが立ちます。
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
- ## ⚡ Mjölnir はまた別のリンタではありません
446
+ PR workflow を生成します(デフォルトは助言的):
447
+
448
+ ```bash
449
+ mjolnir ci install
450
+ ```
408
451
 
409
- リンタはコードがルールに従っているかを教えます。Mjölnir は、あなたの
410
- 検証が信頼できるかを教えます。
452
+ または、既存の workflow に Marketplace の action を追加します:
411
453
 
412
- | | ESLint / SonarQube | カバレッジツール | 手動レビュー | **Mjölnir** |
413
- | ----------------------------------------------------------- | :----------------: | :--------------: | :----------: | :---------: |
414
- | CI ワークフローの完全性(`continue-on-error`、`\|\| true`) | ❌ | ❌ | まれ | ✅ |
415
- | 1 ツールで複数言語(TS、Python、Java、C#) | ❌ | ❌ | ❌ | ✅ |
416
- | Playwright ロケータの耐性を評価(Selector Health) | ❌ | ❌ | まれ | ✅ |
417
- | 実質的なアサーションのないテストを検出 | ✅(プラグイン)\* | ❌ | ときどき | ✅ |
418
- | ハードな sleep を検出(`waitForTimeout`、`time.sleep`) | ✅(プラグイン)\* | ❌ | ときどき | ✅ |
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
- \*`eslint-plugin-jest`(`expect-expect`)と
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
- | | Playwright retry reporter | Allure / ReportPortal | **Mjölnir forensics** |
428
- | ----------------------------------------------- | :-----------------------: | :-------------------: | :-------------------: |
429
- | `TRUE-FLAKE` 判定のために実際の実行データを読む | 一部\* | 一部(タグ) | ✅ |
430
- | 実行履歴からの flaky トリアージレポート | ❌ | ✅ | ✅ |
431
- | 静的な信頼性スコアと統合 | ❌ | ❌ | ✅ |
478
+ ```bash
479
+ npx mjolnir-qa@latest --scope changed
480
+ ```
432
481
 
433
- \*Playwright はリトライを内部で追跡しますが、判定ラベルつきの独立した
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
- ## 🤖 なぜ AI コードレビューだけでは足りないのか
486
+ <br />
439
487
 
440
- 問題も層も違います。AI レビューは diff の中の怪しいテスト変更を
441
- 見つけられますが、検証システム全体が信頼に値すると証明はできません——
442
- しかも見るのはあなたが見せた diff だけです。
488
+ ## AI エージェント
443
489
 
444
- | | AI コードレビュー(Copilot など) | **Mjölnir** |
445
- | ------------------------------------- | :-------------------------------: | :------------------------------------: |
446
- | スキャンごとのコスト | トークン(diff サイズで増える) | **ゼロ**(ローカル、インストール済み) |
447
- | スイート全体 + すべての CI 設定を見る | あなたが見せた PR diff のみ | **毎回すべて** |
448
- | 決定論的(同じ入力 → 同じ出力) | ❌(非決定論的) | **✅** |
449
- | 数か月眠っていたパターンを検出 | コンテキストにある場合のみ | **✅**(全ファイルをスキャン) |
450
- | 実行間で検出を記憶 | ❌(セッション間の記憶なし) | **✅**(baseline + diff) |
451
- | 人間のトリガーなしで動く | PR またはプロンプトが必要 | **✅**(CI フック、数秒で実行) |
490
+ 検出結果に価値があるのは、何かがそれに基づいて動くときだけです。
452
491
 
453
- **両方使いましょう。** AI は、どんな正規表現も見つけられないニュアンス、
454
- 意図、設計上の欠陥を捉えます。Mjölnir は、「意図的」に見えるがゆえに
455
- AI が見逃す構造的パターンを捉えます——コミットされた `.only`、呑み込まれた
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
- ## 🤖 CI 統合
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
- 1 コマンドで PR ワークフローを生成します——既定ではアドバイザリ、
464
- 決してブロックしません:
504
+ 独自の CLI を持つクライアントに追加する場合:
465
505
 
466
506
  ```bash
467
- mjolnir ci install
507
+ claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
468
508
  ```
469
509
 
470
- または SARIF 経由で GitHub Code Scanning にネイティブに接続します:
510
+ または、`mcpServers` ブロックを受け付ける任意のクライアントに:
471
511
 
472
- ```yaml
473
- - run: npx mjolnir-qa@latest --format sarif > mjolnir.sarif
474
- - uses: github/codeql-action/upload-sarif@v3
475
- with:
476
- sarif_file: mjolnir.sarif
512
+ ```json
513
+ {
514
+ "mcpServers": {
515
+ "mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@latest", "mcp"] }
516
+ }
517
+ }
477
518
  ```
478
519
 
479
- SARIF のエディタ・パイプライン設定:
480
- [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md)。
520
+ **利便性よりもガードレールが大事です**。引き継ぎに含まれるどの検出結果も、その境界を伴っています。**E2** は _決定論的:場所を確認して修正を適用_ と伝えます。**E1** は _確認が必要:観察だけでは欠陥は証明されない_ と伝えます。E1 を盲目的に直したり、ルールを抑制したり、スコアを上げるためにルールを書き換えたりするエージェントは、まさにこのツールが捉えるために存在することをしているのです。だから引き継ぎは、プロンプトの中で、検出結果のすぐ隣でそう伝えます。
481
521
 
482
- ### changed-scope のカバレッジ
522
+ <br />
483
523
 
484
- `--scope changed` は、`main` とのマージベースに対してブランチが追加した
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
- Mjölnir はゼロ設定です。リポジトリルートの任意の `mjolnir.config.json`
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
- ```json
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
- - **`.mjolnirignore`** — パス除外のための素朴な gitignore 風ファイル、
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
- <details>
602
- <summary>ツリーを展開</summary>
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
- </details>
548
+ 機械が消費するもの(MCP ツールの結果、`--json`、SARIF 2.1)はすべて、バージョン管理された**追加のみ**のスキーマ(`schemaVersion: 1`、`contractVersion: 1`)に基づく単一の正規結果から生成されます。そのため、どの利用者もレンダリングされたテキストから意味を組み立て直す必要はありません。[マシン契約](docs/machine-contract.md) を参照してください。ルール ID(`QA-<FAMILY>-NNN`)は一度リリースされると変更されず、再利用されることもありません。
625
549
 
626
- - **ルールは純粋関数です** — `(SourceFileContext) → Finding[]`、I/O なし、
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
- **v0.5.x · オープンベータ。** JSON スキーマと終了コードは凍結された契約
654
- です。TypeScript と Python が最も広い実測カバレッジを持ち、Java と C# は
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
- 新しいルールが最も簡単な最初の貢献です — 1 コマンドでルールとその
663
- must-fire **と** must-not-fire フィクスチャをスキャフォールドします
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
- **Star ⭐ · Watch 👀 · Contribute 🤝**
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>